mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-03 17:31:50 +00:00
[ARMv8] Add support for the NEON instructions vmaxnm/vminnm.
This adds a new class for non-predicable NEON instructions and a new DecoderNamespace for v8 NEON instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186504 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
946dbd83df
commit
19c14abf1c
@ -180,10 +180,12 @@ let Properties = [IntrNoMem, Commutative] in {
|
||||
// Vector Maximum.
|
||||
def int_arm_neon_vmaxs : Neon_2Arg_Intrinsic;
|
||||
def int_arm_neon_vmaxu : Neon_2Arg_Intrinsic;
|
||||
def int_arm_neon_vmaxnm : Neon_2Arg_Intrinsic;
|
||||
|
||||
// Vector Minimum.
|
||||
def int_arm_neon_vmins : Neon_2Arg_Intrinsic;
|
||||
def int_arm_neon_vminu : Neon_2Arg_Intrinsic;
|
||||
def int_arm_neon_vminnm : Neon_2Arg_Intrinsic;
|
||||
|
||||
// Vector Reciprocal Step.
|
||||
def int_arm_neon_vrecps : Neon_2Arg_Intrinsic;
|
||||
|
@ -167,6 +167,8 @@ namespace {
|
||||
const { return 0; }
|
||||
unsigned NEONThumb2DupPostEncoder(const MachineInstr &MI,unsigned Val)
|
||||
const { return 0; }
|
||||
unsigned NEONThumb2V8PostEncoder(const MachineInstr &MI,unsigned Val)
|
||||
const { return 0; }
|
||||
unsigned VFPThumb2PostEncoder(const MachineInstr&MI, unsigned Val)
|
||||
const { return 0; }
|
||||
unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op)
|
||||
|
@ -1830,6 +1830,21 @@ class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
|
||||
let DecoderNamespace = "NEON";
|
||||
}
|
||||
|
||||
// Same as NeonI except it is not predicated
|
||||
class NeonInp<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
|
||||
InstrItinClass itin, string opc, string dt, string asm, string cstr,
|
||||
list<dag> pattern>
|
||||
: InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = iops;
|
||||
let AsmString = !strconcat(opc, ".", dt, "\t", asm);
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [HasNEON];
|
||||
let DecoderNamespace = "NEON";
|
||||
|
||||
let Inst{31-28} = 0b1111;
|
||||
}
|
||||
|
||||
class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
|
||||
dag oops, dag iops, InstrItinClass itin,
|
||||
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
||||
@ -2030,6 +2045,32 @@ class N3V<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6, bit op4,
|
||||
let Inst{5} = Vm{4};
|
||||
}
|
||||
|
||||
class N3Vnp<bits<5> op27_23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
||||
bit op4, dag oops, dag iops,Format f, InstrItinClass itin,
|
||||
string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy,
|
||||
SDPatternOperator IntOp, bit Commutable, list<dag> pattern>
|
||||
: NeonInp<oops, iops, AddrModeNone, IndexModeNone, f, itin, OpcodeStr,
|
||||
Dt, "$Vd, $Vn, $Vm", "", pattern> {
|
||||
bits<5> Vd;
|
||||
bits<5> Vn;
|
||||
bits<5> Vm;
|
||||
|
||||
// Encode instruction operands
|
||||
let Inst{22} = Vd{4};
|
||||
let Inst{15-12} = Vd{3-0};
|
||||
let Inst{19-16} = Vn{3-0};
|
||||
let Inst{7} = Vn{4};
|
||||
let Inst{5} = Vm{4};
|
||||
let Inst{3-0} = Vm{3-0};
|
||||
|
||||
// Encode constant bits
|
||||
let Inst{27-23} = op27_23;
|
||||
let Inst{21-20} = op21_20;
|
||||
let Inst{11-8} = op11_8;
|
||||
let Inst{6} = op6;
|
||||
let Inst{4} = op4;
|
||||
}
|
||||
|
||||
class N3VLane32<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
||||
bit op4, dag oops, dag iops, Format f, InstrItinClass itin,
|
||||
string opc, string dt, string asm, string cstr,
|
||||
|
@ -2541,6 +2541,16 @@ class N3VDInt<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op4,
|
||||
let TwoOperandAliasConstraint = "$Vn = $Vd";
|
||||
let isCommutable = Commutable;
|
||||
}
|
||||
|
||||
class N3VDIntnp<bits<5> op27_23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
||||
bit op4, Format f, InstrItinClass itin, string OpcodeStr,
|
||||
string Dt, ValueType ResTy, ValueType OpTy,
|
||||
SDPatternOperator IntOp, bit Commutable>
|
||||
: N3Vnp<op27_23, op21_20, op11_8, op6, op4,
|
||||
(outs DPR:$Vd), (ins DPR:$Vn, DPR:$Vm), f, itin, OpcodeStr, Dt,
|
||||
ResTy, OpTy, IntOp, Commutable,
|
||||
[(set DPR:$Vd, (ResTy (IntOp (OpTy DPR:$Vn), (OpTy DPR:$Vm))))]>;
|
||||
|
||||
class N3VDIntSL<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
string OpcodeStr, string Dt, ValueType Ty, SDPatternOperator IntOp>
|
||||
: N3VLane32<0, 1, op21_20, op11_8, 1, 0,
|
||||
@ -2552,6 +2562,7 @@ class N3VDIntSL<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
imm:$lane)))))]> {
|
||||
let isCommutable = 0;
|
||||
}
|
||||
|
||||
class N3VDIntSL16<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
string OpcodeStr, string Dt, ValueType Ty, SDPatternOperator IntOp>
|
||||
: N3VLane16<0, 1, op21_20, op11_8, 1, 0,
|
||||
@ -2584,6 +2595,16 @@ class N3VQInt<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op4,
|
||||
let TwoOperandAliasConstraint = "$Vn = $Vd";
|
||||
let isCommutable = Commutable;
|
||||
}
|
||||
|
||||
class N3VQIntnp<bits<5> op27_23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
||||
bit op4, Format f, InstrItinClass itin, string OpcodeStr,
|
||||
string Dt, ValueType ResTy, ValueType OpTy,
|
||||
SDPatternOperator IntOp, bit Commutable>
|
||||
: N3Vnp<op27_23, op21_20, op11_8, op6, op4,
|
||||
(outs QPR:$Vd), (ins QPR:$Vn, QPR:$Vm), f, itin, OpcodeStr, Dt,
|
||||
ResTy, OpTy, IntOp, Commutable,
|
||||
[(set QPR:$Vd, (ResTy (IntOp (OpTy QPR:$Vn), (OpTy QPR:$Vm))))]>;
|
||||
|
||||
class N3VQIntSL<bits<2> op21_20, bits<4> op11_8, InstrItinClass itin,
|
||||
string OpcodeStr, string Dt,
|
||||
ValueType ResTy, ValueType OpTy, SDPatternOperator IntOp>
|
||||
@ -4659,6 +4680,18 @@ def VMAXfq : N3VQInt<0, 0, 0b00, 0b1111, 0, N3RegFrm, IIC_VBINQ,
|
||||
"vmax", "f32",
|
||||
v4f32, v4f32, int_arm_neon_vmaxs, 1>;
|
||||
|
||||
// VMAXNM
|
||||
let PostEncoderMethod = "NEONThumb2V8PostEncoder", DecoderNamespace = "v8NEON" in {
|
||||
def VMAXNMND : N3VDIntnp<0b000110, 0b00, 0b1111, 0, 1,
|
||||
N3RegFrm, NoItinerary, "vmaxnm", "f32",
|
||||
v2f32, v2f32, int_arm_neon_vmaxnm, 1>,
|
||||
Requires<[HasV8, HasNEON]>;
|
||||
def VMAXNMNQ : N3VQIntnp<0b00110, 0b00, 0b1111, 1, 1,
|
||||
N3RegFrm, NoItinerary, "vmaxnm", "f32",
|
||||
v4f32, v4f32, int_arm_neon_vmaxnm, 1>,
|
||||
Requires<[HasV8, HasNEON]>;
|
||||
}
|
||||
|
||||
// VMIN : Vector Minimum
|
||||
defm VMINs : N3VInt_QHS<0, 0, 0b0110, 1, N3RegFrm,
|
||||
IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q,
|
||||
@ -4673,6 +4706,18 @@ def VMINfq : N3VQInt<0, 0, 0b10, 0b1111, 0, N3RegFrm, IIC_VBINQ,
|
||||
"vmin", "f32",
|
||||
v4f32, v4f32, int_arm_neon_vmins, 1>;
|
||||
|
||||
// VMINNM
|
||||
let PostEncoderMethod = "NEONThumb2V8PostEncoder", DecoderNamespace = "v8NEON" in {
|
||||
def VMINNMND : N3VDIntnp<0b00110, 0b10, 0b1111, 0, 1,
|
||||
N3RegFrm, NoItinerary, "vminnm", "f32",
|
||||
v2f32, v2f32, int_arm_neon_vminnm, 1>,
|
||||
Requires<[HasV8, HasNEON]>;
|
||||
def VMINNMNQ : N3VQIntnp<0b00110, 0b10, 0b1111, 1, 1,
|
||||
N3RegFrm, NoItinerary, "vminnm", "f32",
|
||||
v4f32, v4f32, int_arm_neon_vminnm, 1>,
|
||||
Requires<[HasV8, HasNEON]>;
|
||||
}
|
||||
|
||||
// Vector Pairwise Operations.
|
||||
|
||||
// VPADD : Vector Pairwise Add
|
||||
|
@ -499,7 +499,14 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
|
||||
}
|
||||
|
||||
MI.clear();
|
||||
result = decodeInstruction(DecoderTablev8NEON32, MI, insn, Address,
|
||||
this, STI);
|
||||
if (result != MCDisassembler::Fail) {
|
||||
Size = 4;
|
||||
return result;
|
||||
}
|
||||
|
||||
MI.clear();
|
||||
Size = 0;
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
@ -818,6 +825,17 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
|
||||
}
|
||||
}
|
||||
|
||||
MI.clear();
|
||||
uint32_t NEONv8Insn = insn32;
|
||||
NEONv8Insn &= 0xF3FFFFFF; // Clear bits 27-26
|
||||
result = decodeInstruction(DecoderTablev8NEON32, MI, NEONv8Insn, Address,
|
||||
this, STI);
|
||||
if (result != MCDisassembler::Fail) {
|
||||
Size = 4;
|
||||
return result;
|
||||
}
|
||||
|
||||
MI.clear();
|
||||
Size = 0;
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
|
@ -315,6 +315,8 @@ public:
|
||||
unsigned EncodedValue) const;
|
||||
unsigned NEONThumb2DupPostEncoder(const MCInst &MI,
|
||||
unsigned EncodedValue) const;
|
||||
unsigned NEONThumb2V8PostEncoder(const MCInst &MI,
|
||||
unsigned EncodedValue) const;
|
||||
|
||||
unsigned VFPThumb2PostEncoder(const MCInst &MI,
|
||||
unsigned EncodedValue) const;
|
||||
@ -389,6 +391,17 @@ unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
|
||||
return EncodedValue;
|
||||
}
|
||||
|
||||
/// Post-process encoded NEON v8 instructions, and rewrite them to Thumb2 form
|
||||
/// if we are in Thumb2.
|
||||
unsigned ARMMCCodeEmitter::NEONThumb2V8PostEncoder(const MCInst &MI,
|
||||
unsigned EncodedValue) const {
|
||||
if (isThumb2()) {
|
||||
EncodedValue |= 0xC000000; // Set bits 27-26
|
||||
}
|
||||
|
||||
return EncodedValue;
|
||||
}
|
||||
|
||||
/// VFPThumb2PostEncoder - Post-process encoded VFP instructions and rewrite
|
||||
/// them to their Thumb2 form if we are currently in Thumb2 mode.
|
||||
unsigned ARMMCCodeEmitter::
|
||||
|
Loading…
Reference in New Issue
Block a user