forked from OSchip/llvm-project
ARM VFP assembly parsing and encoding for VCVT(float <--> fixed point).
rdar://10558523 llvm-svn: 147189
This commit is contained in:
parent
268d2599e0
commit
ea2319112f
|
@ -61,6 +61,22 @@ def vfp_f64imm : Operand<f64>,
|
||||||
let ParserMatchClass = FPImmOperand;
|
let ParserMatchClass = FPImmOperand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The VCVT to/from fixed-point instructions encode the 'fbits' operand
|
||||||
|
// (the number of fixed bits) differently than it appears in the assembly
|
||||||
|
// source. It's encoded as "Size - fbits" where Size is the size of the
|
||||||
|
// fixed-point representation (32 or 16) and fbits is the value appearing
|
||||||
|
// in the assembly source, an integer in [0,16] or (0,32], depending on size.
|
||||||
|
def fbits32_asm_operand : AsmOperandClass { let Name = "FBits32"; }
|
||||||
|
def fbits32 : Operand<i32> {
|
||||||
|
let PrintMethod = "printFBits32";
|
||||||
|
let ParserMatchClass = fbits32_asm_operand;
|
||||||
|
}
|
||||||
|
|
||||||
|
def fbits16_asm_operand : AsmOperandClass { let Name = "FBits16"; }
|
||||||
|
def fbits16 : Operand<i32> {
|
||||||
|
let PrintMethod = "printFBits16";
|
||||||
|
let ParserMatchClass = fbits16_asm_operand;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Load / store Instructions.
|
// Load / store Instructions.
|
||||||
|
@ -795,7 +811,7 @@ let Constraints = "$a = $dst" in {
|
||||||
// FP to Fixed-Point:
|
// FP to Fixed-Point:
|
||||||
|
|
||||||
def VTOSHS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 0,
|
def VTOSHS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 0,
|
||||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
(outs SPR:$dst), (ins SPR:$a, fbits16:$fbits),
|
||||||
IIC_fpCVTSI, "vcvt", ".s16.f32\t$dst, $a, $fbits", []> {
|
IIC_fpCVTSI, "vcvt", ".s16.f32\t$dst, $a, $fbits", []> {
|
||||||
// Some single precision VFP instructions may be executed on both NEON and
|
// Some single precision VFP instructions may be executed on both NEON and
|
||||||
// VFP pipelines on A8.
|
// VFP pipelines on A8.
|
||||||
|
@ -803,7 +819,7 @@ def VTOSHS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
def VTOUHS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 0,
|
def VTOUHS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 0,
|
||||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
(outs SPR:$dst), (ins SPR:$a, fbits16:$fbits),
|
||||||
IIC_fpCVTSI, "vcvt", ".u16.f32\t$dst, $a, $fbits", []> {
|
IIC_fpCVTSI, "vcvt", ".u16.f32\t$dst, $a, $fbits", []> {
|
||||||
// Some single precision VFP instructions may be executed on both NEON and
|
// Some single precision VFP instructions may be executed on both NEON and
|
||||||
// VFP pipelines on A8.
|
// VFP pipelines on A8.
|
||||||
|
@ -811,7 +827,7 @@ def VTOUHS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
def VTOSLS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 1,
|
def VTOSLS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 1,
|
||||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
(outs SPR:$dst), (ins SPR:$a, fbits32:$fbits),
|
||||||
IIC_fpCVTSI, "vcvt", ".s32.f32\t$dst, $a, $fbits", []> {
|
IIC_fpCVTSI, "vcvt", ".s32.f32\t$dst, $a, $fbits", []> {
|
||||||
// Some single precision VFP instructions may be executed on both NEON and
|
// Some single precision VFP instructions may be executed on both NEON and
|
||||||
// VFP pipelines on A8.
|
// VFP pipelines on A8.
|
||||||
|
@ -819,7 +835,7 @@ def VTOSLS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
def VTOULS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 1,
|
def VTOULS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 1,
|
||||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
(outs SPR:$dst), (ins SPR:$a, fbits32:$fbits),
|
||||||
IIC_fpCVTSI, "vcvt", ".u32.f32\t$dst, $a, $fbits", []> {
|
IIC_fpCVTSI, "vcvt", ".u32.f32\t$dst, $a, $fbits", []> {
|
||||||
// Some single precision VFP instructions may be executed on both NEON and
|
// Some single precision VFP instructions may be executed on both NEON and
|
||||||
// VFP pipelines on A8.
|
// VFP pipelines on A8.
|
||||||
|
@ -827,25 +843,25 @@ def VTOULS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
def VTOSHD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 0,
|
def VTOSHD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 0,
|
||||||
(outs DPR:$dst), (ins DPR:$a, i32imm:$fbits),
|
(outs DPR:$dst), (ins DPR:$a, fbits16:$fbits),
|
||||||
IIC_fpCVTDI, "vcvt", ".s16.f64\t$dst, $a, $fbits", []>;
|
IIC_fpCVTDI, "vcvt", ".s16.f64\t$dst, $a, $fbits", []>;
|
||||||
|
|
||||||
def VTOUHD : AVConv1XI<0b11101, 0b11, 0b1111, 0b1011, 0,
|
def VTOUHD : AVConv1XI<0b11101, 0b11, 0b1111, 0b1011, 0,
|
||||||
(outs DPR:$dst), (ins DPR:$a, i32imm:$fbits),
|
(outs DPR:$dst), (ins DPR:$a, fbits16:$fbits),
|
||||||
IIC_fpCVTDI, "vcvt", ".u16.f64\t$dst, $a, $fbits", []>;
|
IIC_fpCVTDI, "vcvt", ".u16.f64\t$dst, $a, $fbits", []>;
|
||||||
|
|
||||||
def VTOSLD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 1,
|
def VTOSLD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 1,
|
||||||
(outs DPR:$dst), (ins DPR:$a, i32imm:$fbits),
|
(outs DPR:$dst), (ins DPR:$a, fbits32:$fbits),
|
||||||
IIC_fpCVTDI, "vcvt", ".s32.f64\t$dst, $a, $fbits", []>;
|
IIC_fpCVTDI, "vcvt", ".s32.f64\t$dst, $a, $fbits", []>;
|
||||||
|
|
||||||
def VTOULD : AVConv1XI<0b11101, 0b11, 0b1111, 0b1011, 1,
|
def VTOULD : AVConv1XI<0b11101, 0b11, 0b1111, 0b1011, 1,
|
||||||
(outs DPR:$dst), (ins DPR:$a, i32imm:$fbits),
|
(outs DPR:$dst), (ins DPR:$a, fbits32:$fbits),
|
||||||
IIC_fpCVTDI, "vcvt", ".u32.f64\t$dst, $a, $fbits", []>;
|
IIC_fpCVTDI, "vcvt", ".u32.f64\t$dst, $a, $fbits", []>;
|
||||||
|
|
||||||
// Fixed-Point to FP:
|
// Fixed-Point to FP:
|
||||||
|
|
||||||
def VSHTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 0,
|
def VSHTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 0,
|
||||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
(outs SPR:$dst), (ins SPR:$a, fbits16:$fbits),
|
||||||
IIC_fpCVTIS, "vcvt", ".f32.s16\t$dst, $a, $fbits", []> {
|
IIC_fpCVTIS, "vcvt", ".f32.s16\t$dst, $a, $fbits", []> {
|
||||||
// Some single precision VFP instructions may be executed on both NEON and
|
// Some single precision VFP instructions may be executed on both NEON and
|
||||||
// VFP pipelines on A8.
|
// VFP pipelines on A8.
|
||||||
|
@ -853,7 +869,7 @@ def VSHTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
def VUHTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 0,
|
def VUHTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 0,
|
||||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
(outs SPR:$dst), (ins SPR:$a, fbits16:$fbits),
|
||||||
IIC_fpCVTIS, "vcvt", ".f32.u16\t$dst, $a, $fbits", []> {
|
IIC_fpCVTIS, "vcvt", ".f32.u16\t$dst, $a, $fbits", []> {
|
||||||
// Some single precision VFP instructions may be executed on both NEON and
|
// Some single precision VFP instructions may be executed on both NEON and
|
||||||
// VFP pipelines on A8.
|
// VFP pipelines on A8.
|
||||||
|
@ -861,7 +877,7 @@ def VUHTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
def VSLTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 1,
|
def VSLTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 1,
|
||||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
(outs SPR:$dst), (ins SPR:$a, fbits32:$fbits),
|
||||||
IIC_fpCVTIS, "vcvt", ".f32.s32\t$dst, $a, $fbits", []> {
|
IIC_fpCVTIS, "vcvt", ".f32.s32\t$dst, $a, $fbits", []> {
|
||||||
// Some single precision VFP instructions may be executed on both NEON and
|
// Some single precision VFP instructions may be executed on both NEON and
|
||||||
// VFP pipelines on A8.
|
// VFP pipelines on A8.
|
||||||
|
@ -869,7 +885,7 @@ def VSLTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
def VULTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 1,
|
def VULTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 1,
|
||||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
(outs SPR:$dst), (ins SPR:$a, fbits32:$fbits),
|
||||||
IIC_fpCVTIS, "vcvt", ".f32.u32\t$dst, $a, $fbits", []> {
|
IIC_fpCVTIS, "vcvt", ".f32.u32\t$dst, $a, $fbits", []> {
|
||||||
// Some single precision VFP instructions may be executed on both NEON and
|
// Some single precision VFP instructions may be executed on both NEON and
|
||||||
// VFP pipelines on A8.
|
// VFP pipelines on A8.
|
||||||
|
@ -877,19 +893,19 @@ def VULTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
def VSHTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 0,
|
def VSHTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 0,
|
||||||
(outs DPR:$dst), (ins DPR:$a, i32imm:$fbits),
|
(outs DPR:$dst), (ins DPR:$a, fbits16:$fbits),
|
||||||
IIC_fpCVTID, "vcvt", ".f64.s16\t$dst, $a, $fbits", []>;
|
IIC_fpCVTID, "vcvt", ".f64.s16\t$dst, $a, $fbits", []>;
|
||||||
|
|
||||||
def VUHTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 0,
|
def VUHTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 0,
|
||||||
(outs DPR:$dst), (ins DPR:$a, i32imm:$fbits),
|
(outs DPR:$dst), (ins DPR:$a, fbits16:$fbits),
|
||||||
IIC_fpCVTID, "vcvt", ".f64.u16\t$dst, $a, $fbits", []>;
|
IIC_fpCVTID, "vcvt", ".f64.u16\t$dst, $a, $fbits", []>;
|
||||||
|
|
||||||
def VSLTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 1,
|
def VSLTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 1,
|
||||||
(outs DPR:$dst), (ins DPR:$a, i32imm:$fbits),
|
(outs DPR:$dst), (ins DPR:$a, fbits32:$fbits),
|
||||||
IIC_fpCVTID, "vcvt", ".f64.s32\t$dst, $a, $fbits", []>;
|
IIC_fpCVTID, "vcvt", ".f64.s32\t$dst, $a, $fbits", []>;
|
||||||
|
|
||||||
def VULTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 1,
|
def VULTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 1,
|
||||||
(outs DPR:$dst), (ins DPR:$a, i32imm:$fbits),
|
(outs DPR:$dst), (ins DPR:$a, fbits32:$fbits),
|
||||||
IIC_fpCVTID, "vcvt", ".f64.u32\t$dst, $a, $fbits", []>;
|
IIC_fpCVTID, "vcvt", ".f64.u32\t$dst, $a, $fbits", []>;
|
||||||
|
|
||||||
} // End of 'let Constraints = "$a = $dst" in'
|
} // End of 'let Constraints = "$a = $dst" in'
|
||||||
|
|
|
@ -547,6 +547,20 @@ public:
|
||||||
bool isITCondCode() const { return Kind == k_CondCode; }
|
bool isITCondCode() const { return Kind == k_CondCode; }
|
||||||
bool isImm() const { return Kind == k_Immediate; }
|
bool isImm() const { return Kind == k_Immediate; }
|
||||||
bool isFPImm() const { return Kind == k_FPImmediate; }
|
bool isFPImm() const { return Kind == k_FPImmediate; }
|
||||||
|
bool isFBits16() const {
|
||||||
|
if (!isImm()) return false;
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
if (!CE) return false;
|
||||||
|
int64_t Value = CE->getValue();
|
||||||
|
return Value >= 0 && Value <= 16;
|
||||||
|
}
|
||||||
|
bool isFBits32() const {
|
||||||
|
if (!isImm()) return false;
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
if (!CE) return false;
|
||||||
|
int64_t Value = CE->getValue();
|
||||||
|
return Value >= 1 && Value <= 32;
|
||||||
|
}
|
||||||
bool isImm8s4() const {
|
bool isImm8s4() const {
|
||||||
if (!isImm()) return false;
|
if (!isImm()) return false;
|
||||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
@ -1351,6 +1365,18 @@ public:
|
||||||
addExpr(Inst, getImm());
|
addExpr(Inst, getImm());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addFBits16Operands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addFBits32Operands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
void addFPImmOperands(MCInst &Inst, unsigned N) const {
|
void addFPImmOperands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 1 && "Invalid number of operands!");
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
Inst.addOperand(MCOperand::CreateImm(getFPImm()));
|
Inst.addOperand(MCOperand::CreateImm(getFPImm()));
|
||||||
|
|
|
@ -1001,6 +1001,16 @@ void ARMInstPrinter::printRotImmOperand(const MCInst *MI, unsigned OpNum,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ARMInstPrinter::printFBits16(const MCInst *MI, unsigned OpNum,
|
||||||
|
raw_ostream &O) {
|
||||||
|
O << "#" << 16 - MI->getOperand(OpNum).getImm();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARMInstPrinter::printFBits32(const MCInst *MI, unsigned OpNum,
|
||||||
|
raw_ostream &O) {
|
||||||
|
O << "#" << 32 - MI->getOperand(OpNum).getImm();
|
||||||
|
}
|
||||||
|
|
||||||
void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
|
void ARMInstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
|
||||||
raw_ostream &O) {
|
raw_ostream &O) {
|
||||||
O << "[" << MI->getOperand(OpNum).getImm() << "]";
|
O << "[" << MI->getOperand(OpNum).getImm() << "]";
|
||||||
|
|
|
@ -128,6 +128,8 @@ public:
|
||||||
|
|
||||||
void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printPCLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printT2LdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printT2LdrLabelOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
|
void printFBits16(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
|
void printFBits32(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printVectorIndex(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printVectorIndex(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printVectorListOne(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printVectorListOne(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
void printVectorListTwo(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
void printVectorListTwo(const MCInst *MI, unsigned OpNum, raw_ostream &O);
|
||||||
|
|
|
@ -299,3 +299,15 @@
|
||||||
@ CHECK: vmov r4, s1 @ encoding: [0x90,0x4a,0x10,0xee]
|
@ CHECK: vmov r4, s1 @ encoding: [0x90,0x4a,0x10,0xee]
|
||||||
@ CHECK: vmov r5, s2 @ encoding: [0x10,0x5a,0x11,0xee]
|
@ CHECK: vmov r5, s2 @ encoding: [0x10,0x5a,0x11,0xee]
|
||||||
@ CHECK: vmov r6, s3 @ encoding: [0x90,0x6a,0x11,0xee]
|
@ CHECK: vmov r6, s3 @ encoding: [0x90,0x6a,0x11,0xee]
|
||||||
|
|
||||||
|
|
||||||
|
@ VCVT (between floating-point and fixed-point)
|
||||||
|
vcvt.f32.u32 s0, s0, #20
|
||||||
|
vcvt.f64.s32 d0, d0, #32
|
||||||
|
vcvt.f32.u16 s0, s0, #1
|
||||||
|
vcvt.f64.s16 d0, d0, #16
|
||||||
|
|
||||||
|
@ CHECK: vcvt.f32.u32 s0, s0, #20 @ encoding: [0xc6,0x0a,0xbb,0xee]
|
||||||
|
@ CHECK: vcvt.f64.s32 d0, d0, #32 @ encoding: [0xc0,0x0b,0xba,0xee]
|
||||||
|
@ CHECK: vcvt.f32.u16 s0, s0, #1 @ encoding: [0x67,0x0a,0xbb,0xee]
|
||||||
|
@ CHECK: vcvt.f64.s16 d0, d0, #16 @ encoding: [0x40,0x0b,0xba,0xee]
|
||||||
|
|
|
@ -581,6 +581,8 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||||
REG("VecListTwoQAllLanes");
|
REG("VecListTwoQAllLanes");
|
||||||
|
|
||||||
IMM("i32imm");
|
IMM("i32imm");
|
||||||
|
IMM("fbits16");
|
||||||
|
IMM("fbits32");
|
||||||
IMM("i32imm_hilo16");
|
IMM("i32imm_hilo16");
|
||||||
IMM("bf_inv_mask_imm");
|
IMM("bf_inv_mask_imm");
|
||||||
IMM("lsb_pos_imm");
|
IMM("lsb_pos_imm");
|
||||||
|
|
Loading…
Reference in New Issue