forked from OSchip/llvm-project
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. llvm-svn: 183011
This commit is contained in:
parent
ab8128b01d
commit
4173e29a98
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue