diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 6f0a18bf8dd..d4bf8cde9c9 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -521,6 +521,7 @@ def VMOVRRS : AVConv3I<0b11000101, 0b1010, // Some single precision VFP instructions may be executed on both NEON and VFP // pipelines. let D = VFPNeonDomain; + let DecoderMethod = "DecodeVMOVRRS"; } } // neverHasSideEffects @@ -559,6 +560,8 @@ def VMOVSRR : AVConv5I<0b11000100, 0b1010, // Some single precision VFP instructions may be executed on both NEON and VFP // pipelines. let D = VFPNeonDomain; + + let DecoderMethod = "DecodeVMOVSRR"; } // FMRDH: SPR -> GPR diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index ad1692ca3b8..db35c1891c0 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -175,6 +175,10 @@ static DecodeStatus DecodeVST3LN(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeVST4LN(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeVMOVSRR(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static DecodeStatus DecodeVMOVRRS(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); static DecodeStatus DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn, @@ -3195,3 +3199,44 @@ static DecodeStatus DecodeVST4LN(llvm::MCInst &Inst, unsigned Insn, return S; } +static DecodeStatus DecodeVMOVSRR(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + DecodeStatus S = Success; + unsigned Rt = fieldFromInstruction32(Insn, 12, 4); + unsigned Rt2 = fieldFromInstruction32(Insn, 16, 4); + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned pred = fieldFromInstruction32(Insn, 28, 4); + Rm |= fieldFromInstruction32(Insn, 5, 1) << 4; + + if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F) + CHECK(S, Unpredictable); + + CHECK(S, DecodeSPRRegisterClass(Inst, Rm , Address, Decoder)); + CHECK(S, DecodeSPRRegisterClass(Inst, Rm+1, Address, Decoder)); + CHECK(S, DecodeGPRRegisterClass(Inst, Rt , Address, Decoder)); + CHECK(S, DecodeGPRRegisterClass(Inst, Rt2 , Address, Decoder)); + CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder)); + + return S; +} + +static DecodeStatus DecodeVMOVRRS(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + DecodeStatus S = Success; + unsigned Rt = fieldFromInstruction32(Insn, 12, 4); + unsigned Rt2 = fieldFromInstruction32(Insn, 16, 4); + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned pred = fieldFromInstruction32(Insn, 28, 4); + Rm |= fieldFromInstruction32(Insn, 5, 1) << 4; + + if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F) + CHECK(S, Unpredictable); + + CHECK(S, DecodeGPRRegisterClass(Inst, Rt , Address, Decoder)); + CHECK(S, DecodeGPRRegisterClass(Inst, Rt2 , Address, Decoder)); + CHECK(S, DecodeSPRRegisterClass(Inst, Rm , Address, Decoder)); + CHECK(S, DecodeSPRRegisterClass(Inst, Rm+1, Address, Decoder)); + CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder)); + + return S; +} diff --git a/test/MC/Disassembler/ARM/neon.txt b/test/MC/Disassembler/ARM/neon.txt index 6068a38c3d3..4064ad84c32 100644 --- a/test/MC/Disassembler/ARM/neon.txt +++ b/test/MC/Disassembler/ARM/neon.txt @@ -1851,3 +1851,5 @@ 0x0d 0x03 0x80 0xf4 # CHECK: vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]! +0x3d 0x2a 0x5e 0x6c +# CHECK: vmovvs r2, lr, s29, s30