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
This commit is contained in:
Tim Northover 2013-05-31 15:55:51 +00:00
parent 4f3d7eea04
commit 242c9f4615
6 changed files with 106 additions and 8 deletions

View File

@ -1389,7 +1389,6 @@ class ADI5<bits<4> 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<bits<4> 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<dag oops, dag iops, InstrItinClass itin, string cstr,
}
// Load / store multiple
// Unknown precision
class AXXI4<dag oops, dag iops, IndexMode im,
string asm, string cstr, list<dag> pattern>
: VFPXI<oops, iops, AddrMode4, 4, im,
VFPLdStFrm, NoItinerary, asm, cstr, pattern> {
// 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<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: VFPXI<oops, iops, AddrMode4, 4, im,
@ -1449,14 +1469,15 @@ class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
let Inst{19-16} = Rn;
let Inst{22} = regs{12};
let Inst{15-12} = regs{11-8};
let Inst{7-0} = regs{7-0};
let Inst{7-1} = regs{7-1};
// TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-25} = 0b110;
let Inst{11-9} = 0b101;
let Inst{8} = 1; // Double precision
let Inst{0} = 0;
}
// Single Precision
class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
: VFPXI<oops, iops, AddrMode4, 4, im,
@ -1471,7 +1492,6 @@ class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
let Inst{15-12} = regs{12-9};
let Inst{7-0} = regs{7-0};
// TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-25} = 0b110;
let Inst{11-9} = 0b101;
let Inst{8} = 0; // Single precision

View File

@ -224,7 +224,36 @@ defm : VFPDTAnyInstAlias<"vpop${p}", "$r",
defm : VFPDTAnyInstAlias<"vpop${p}", "$r",
(VLDMDIA_UPD SP, pred:$p, dpr_reglist:$r)>;
// 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<string asm, bit L_bit> {
// 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.

View File

@ -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;

View File

@ -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]

View File

@ -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

View File

@ -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