From 242c9f4615feeee2fbdd1f29cd9a8e8ffd43c075 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 31 May 2013 15:55:51 +0000 Subject: [PATCH] ARM: add fstmx and fldmx instructions for assembly These instructions are deprecated oddities, but we still need to be able to disassemble (and reassemble) them if and when they're encountered. Patch by Amaury de la Vieuville. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183011 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrFormats.td | 30 +++++++++++++++--- lib/Target/ARM/ARMInstrVFP.td | 31 ++++++++++++++++++- .../ARM/Disassembler/ARMDisassembler.cpp | 17 ++++++++-- test/MC/ARM/simple-fp-encoding.s | 14 +++++++++ test/MC/Disassembler/ARM/fp-encoding.txt | 14 +++++++++ .../MC/Disassembler/ARM/invalid-FSTMX-arm.txt | 8 +++++ 6 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 67a6820932f..bd9a212928e 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/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/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 9c13c604638..824ffbf3386 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/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/test/MC/ARM/simple-fp-encoding.s b/test/MC/ARM/simple-fp-encoding.s index 2a226205a08..0561b449072 100644 --- a/test/MC/ARM/simple-fp-encoding.s +++ b/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/test/MC/Disassembler/ARM/fp-encoding.txt b/test/MC/Disassembler/ARM/fp-encoding.txt index 8dedf808c18..531793dbefb 100644 --- a/test/MC/Disassembler/ARM/fp-encoding.txt +++ b/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/test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt b/test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt new file mode 100644 index 00000000000..b81b4e8fb12 --- /dev/null +++ b/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