diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 67a6820932fc..bd9a212928eb 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -1389,7 +1389,6 @@ class ADI5 opcod1, bits<2> opcod2, dag oops, dag iops, let Inst{15-12} = Dd{3-0}; let Inst{7-0} = addr{7-0}; // imm8 - // TODO: Mark the instructions with the appropriate subtarget info. let Inst{27-24} = opcod1; let Inst{21-20} = opcod2; let Inst{11-9} = 0b101; @@ -1415,7 +1414,6 @@ class ASI5 opcod1, bits<2> opcod2, dag oops, dag iops, let Inst{15-12} = Sd{4-1}; let Inst{7-0} = addr{7-0}; // imm8 - // TODO: Mark the instructions with the appropriate subtarget info. let Inst{27-24} = opcod1; let Inst{21-20} = opcod2; let Inst{11-9} = 0b101; @@ -1437,6 +1435,28 @@ class PseudoVFPLdStM pattern> + : VFPXI { + // Instruction operands. + bits<4> Rn; + bits<13> regs; + + // Encode instruction operands. + let Inst{19-16} = Rn; + let Inst{22} = 0; + let Inst{15-12} = regs{11-8}; + let Inst{7-1} = regs{7-1}; + + let Inst{27-25} = 0b110; + let Inst{11-8} = 0b1011; + let Inst{0} = 1; +} + +// Double precision class AXDI4 pattern> : VFPXI pattern> : VFPXI; -// FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores +// FLDMX, FSTMX - Load and store multiple unknown precision registers for +// pre-armv6 cores. +// These instruction are deprecated so we don't want them to get selected. +multiclass vfp_ldstx_mult { + // Unknown precision + def XIA : + AXXI4<(outs), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops), + IndexModeNone, !strconcat(asm, "iax${p}\t$Rn, $regs"), "", []> { + let Inst{24-23} = 0b01; // Increment After + let Inst{21} = 0; // No writeback + let Inst{20} = L_bit; + } + def XIA_UPD : + AXXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops), + IndexModeUpd, !strconcat(asm, "iax${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + let Inst{24-23} = 0b01; // Increment After + let Inst{21} = 1; // Writeback + let Inst{20} = L_bit; + } + def XDB_UPD : + AXXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops), + IndexModeUpd, !strconcat(asm, "dbx${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + let Inst{24-23} = 0b10; // Decrement Before + let Inst{21} = 1; + let Inst{20} = L_bit; + } +} + +defm FLDM : vfp_ldstx_mult<"fldm", 1>; +defm FSTM : vfp_ldstx_mult<"fstm", 0>; //===----------------------------------------------------------------------===// // FP Binary Operations. diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 9c13c604638d..824ffbf33863 100644 --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -1150,6 +1150,13 @@ static DecodeStatus DecodeSPRRegListOperand(MCInst &Inst, unsigned Val, unsigned Vd = fieldFromInstruction(Val, 8, 5); unsigned regs = fieldFromInstruction(Val, 0, 8); + // In case of unpredictable encoding, tweak the operands. + if (regs == 0 || (Vd + regs) > 32) { + regs = Vd + regs > 32 ? 32 - Vd : regs; + regs = std::max( 1u, regs); + S = MCDisassembler::SoftFail; + } + if (!Check(S, DecodeSPRRegisterClass(Inst, Vd, Address, Decoder))) return MCDisassembler::Fail; for (unsigned i = 0; i < (regs - 1); ++i) { @@ -1165,9 +1172,15 @@ static DecodeStatus DecodeDPRRegListOperand(MCInst &Inst, unsigned Val, DecodeStatus S = MCDisassembler::Success; unsigned Vd = fieldFromInstruction(Val, 8, 5); - unsigned regs = fieldFromInstruction(Val, 0, 8); + unsigned regs = fieldFromInstruction(Val, 1, 7); - regs = regs >> 1; + // In case of unpredictable encoding, tweak the operands. + if (regs == 0 || regs > 16 || (Vd + regs) > 32) { + regs = Vd + regs > 32 ? 32 - Vd : regs; + regs = std::max( 1u, regs); + regs = std::min(16u, regs); + S = MCDisassembler::SoftFail; + } if (!Check(S, DecodeDPRRegisterClass(Inst, Vd, Address, Decoder))) return MCDisassembler::Fail; diff --git a/llvm/test/MC/ARM/simple-fp-encoding.s b/llvm/test/MC/ARM/simple-fp-encoding.s index 2a226205a086..0561b4490721 100644 --- a/llvm/test/MC/ARM/simple-fp-encoding.s +++ b/llvm/test/MC/ARM/simple-fp-encoding.s @@ -289,6 +289,20 @@ vstmia r1, {s2,s3-s6,s7} vstmdb sp!, {q4-q7} + fldmiax r5!, {d0-d2} + fldmiaxeq r0, {d4,d5} + fldmdbxne r5!, {d4,d5,d6} +@ CHECK: fldmiax r5!, {d0, d1, d2} @ encoding: [0x07,0x0b,0xb5,0xec] +@ CHECK: fldmiaxeq r0, {d4, d5} @ encoding: [0x05,0x4b,0x90,0x0c] +@ CHECK: fldmdbxne r5!, {d4, d5, d6} @ encoding: [0x07,0x4b,0x35,0x1d] + + fstmiax r5!, {d0-d7} + fstmiaxeq r4, {d8,d9} + fstmdbxne r7!, {d2-d4} +@ CHECK: fstmiax r5!, {d0, d1, d2, d3, d4, d5, d6, d7} @ encoding: [0x11,0x0b,0xa5,0xec] +@ CHECK: fstmiaxeq r4, {d8, d9} @ encoding: [0x05,0x8b,0x84,0x0c] +@ CHECK: fstmdbxne r7!, {d2, d3, d4} @ encoding: [0x07,0x2b,0x27,0x1d] + @ CHECK: vcvtr.s32.f64 s0, d0 @ encoding: [0x40,0x0b,0xbd,0xee] @ CHECK: vcvtr.s32.f32 s0, s1 @ encoding: [0x60,0x0a,0xbd,0xee] @ CHECK: vcvtr.u32.f64 s0, d0 @ encoding: [0x40,0x0b,0xbc,0xee] diff --git a/llvm/test/MC/Disassembler/ARM/fp-encoding.txt b/llvm/test/MC/Disassembler/ARM/fp-encoding.txt index 8dedf808c180..531793dbefbb 100644 --- a/llvm/test/MC/Disassembler/ARM/fp-encoding.txt +++ b/llvm/test/MC/Disassembler/ARM/fp-encoding.txt @@ -221,6 +221,20 @@ # CHECK: vldmdbeq r5!, {s21, s22, s23} # CHECK: vldmdbeq r7!, {d14, d15, d16, d17} +0x0d 0x4b 0x96 0x0c +0x0f 0x3b 0xb7 0x0c +0x09 0x1b 0x38 0xed +# CHECK: fldmiaxeq r6, {d4, d5, d6, d7, d8, d9} +# CHECK: fldmiaxeq r7!, {d3, d4, d5, d6, d7, d8, d9} +# CHECK: fldmdbx r8!, {d1, d2, d3, d4} + +0x07 0x2b 0x83 0xec +0x05 0x5b 0xa3 0x0c +0x0f 0x3b 0x20 0x1d +# CHECK: fstmiax r3, {d2, d3, d4} +# CHECK: fstmiaxeq r3!, {d5, d6} +# CHECK: fstmdbxne r0!, {d3, d4, d5, d6, d7, d8, d9} + 0x04 0x7a 0xa6 0x0c 0x0c 0xfb 0xa4 0x0c 0x03 0xaa 0xf8 0x0c diff --git a/llvm/test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt b/llvm/test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt new file mode 100644 index 000000000000..b81b4e8fb129 --- /dev/null +++ b/llvm/test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt @@ -0,0 +1,8 @@ +# RUN: llvm-mc --disassemble %s -triple=armv7 2>&1 | FileCheck %s -check-prefix=CHECK-WARN +# RUN: llvm-mc --disassemble %s -triple=armv7 2>&1 | FileCheck %s + +# offset=1 +# CHECK-WARN: potentially undefined +# CHECK-WARN: 0x01 0xdb 0x84 0xec +# CHECK: fstmiax r4, {d13} +0x01 0xdb 0x84 0xec