ARM: enable decoding of pc-relative PLD/PLI

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184701 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Amaury de la Vieuville 2013-06-24 09:11:38 +00:00
parent 6bf3a05235
commit 0c9f0c047d
4 changed files with 180 additions and 46 deletions

View File

@ -1024,17 +1024,19 @@ multiclass T2I_ld<bit signed, bits<2> opcod, string opc,
def pci : T2Ipc <(outs target:$Rt), (ins t2ldrlabel:$addr), iii,
opc, ".w\t$Rt, $addr",
[(set target:$Rt, (opnode (ARMWrapper tconstpool:$addr)))]> {
bits<4> Rt;
bits<13> addr;
let isReMaterializable = 1;
let Inst{31-27} = 0b11111;
let Inst{26-25} = 0b00;
let Inst{24} = signed;
let Inst{23} = addr{12}; // add = (U == '1')
let Inst{22-21} = opcod;
let Inst{20} = 1; // load
let Inst{19-16} = 0b1111; // Rn
bits<4> Rt;
let Inst{15-12} = Rt{3-0};
bits<13> addr;
let Inst{23} = addr{12}; // add = (U == '1')
let Inst{11-0} = addr{11-0};
let DecoderMethod = "DecodeT2LoadLabel";
@ -1564,16 +1566,17 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
Sched<[WritePreLd]> {
let Inst{31-25} = 0b1111100;
let Inst{24} = instr;
let Inst{23} = 1;
let Inst{22} = 0;
let Inst{21} = write;
let Inst{20} = 1;
let Inst{15-12} = 0b1111;
bits<17> addr;
let addr{12} = 1; // add = TRUE
let Inst{19-16} = addr{16-13}; // Rn
let Inst{23} = addr{12}; // U
let Inst{11-0} = addr{11-0}; // imm12
let DecoderMethod = "DecodeT2LoadImm12";
}
def i8 : T2Ii8<(outs), (ins t2addrmode_negimm8:$addr), IIC_Preload, opc,
@ -1592,6 +1595,8 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
bits<13> addr;
let Inst{19-16} = addr{12-9}; // Rn
let Inst{7-0} = addr{7-0}; // imm8
let DecoderMethod = "DecodeT2LoadImm8";
}
def s : T2Iso<(outs), (ins t2addrmode_so_reg:$addr), IIC_Preload, opc,
@ -1605,7 +1610,7 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
let Inst{21} = write;
let Inst{20} = 1;
let Inst{15-12} = 0b1111;
let Inst{11-6} = 0000000;
let Inst{11-6} = 0b000000;
bits<10> addr;
let Inst{19-16} = addr{9-6}; // Rn
@ -1614,10 +1619,28 @@ multiclass T2Ipl<bits<1> write, bits<1> instr, string opc> {
let DecoderMethod = "DecodeT2LoadShift";
}
// FIXME: We should have a separate 'pci' variant here. As-is we represent
// it via the i12 variant, which it's related to, but that means we can
// represent negative immediates, which aren't legal for anything except
// the 'pci' case (Rn == 15).
// pci variant is very similar to i12, but supports negative offsets
// from the PC.
def pci : T2Iso<(outs), (ins t2ldrlabel:$addr), IIC_Preload, opc,
"\t$addr",
[(ARMPreload (ARMWrapper tconstpool:$addr),
(i32 write), (i32 instr))]>,
Sched<[WritePreLd]> {
let Inst{31-25} = 0b1111100;
let Inst{24} = instr;
let Inst{22} = 0;
let Inst{21} = write;
let Inst{20} = 1;
let Inst{19-16} = 0b1111;
let Inst{15-12} = 0b1111;
bits<13> addr;
let Inst{23} = addr{12}; // add = (U == '1')
let Inst{11-0} = addr{11-0}; // imm12
let DecoderMethod = "DecodeT2LoadLabel";
}
}
defm t2PLD : T2Ipl<0, 0, "pld">, Requires<[IsThumb2]>;

View File

@ -3199,38 +3199,51 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
unsigned Rt = fieldFromInstruction(Insn, 12, 4);
unsigned Rn = fieldFromInstruction(Insn, 16, 4);
if (Rn == 0xF) {
if (Rn == 15) {
switch (Inst.getOpcode()) {
case ARM::t2LDRBs:
Inst.setOpcode(ARM::t2LDRBpci);
break;
case ARM::t2LDRHs:
Inst.setOpcode(ARM::t2LDRHpci);
break;
case ARM::t2LDRSHs:
Inst.setOpcode(ARM::t2LDRSHpci);
break;
case ARM::t2LDRSBs:
Inst.setOpcode(ARM::t2LDRSBpci);
break;
case ARM::t2LDRs:
Inst.setOpcode(ARM::t2LDRpci);
break;
case ARM::t2PLDs: {
Inst.setOpcode(ARM::t2PLDi12);
Inst.addOperand(MCOperand::CreateReg(ARM::PC));
int imm = fieldFromInstruction(Insn, 0, 12);
if (!fieldFromInstruction(Insn, 23, 1)) imm *= -1;
Inst.addOperand(MCOperand::CreateImm(imm));
return S;
}
default:
return MCDisassembler::Fail;
case ARM::t2LDRBs:
Inst.setOpcode(ARM::t2LDRBpci);
break;
case ARM::t2LDRHs:
Inst.setOpcode(ARM::t2LDRHpci);
break;
case ARM::t2LDRSHs:
Inst.setOpcode(ARM::t2LDRSHpci);
break;
case ARM::t2LDRSBs:
Inst.setOpcode(ARM::t2LDRSBpci);
break;
case ARM::t2LDRs:
Inst.setOpcode(ARM::t2LDRpci);
break;
case ARM::t2PLDs:
Inst.setOpcode(ARM::t2PLDpci);
break;
case ARM::t2PLIs:
Inst.setOpcode(ARM::t2PLIpci);
break;
default:
return MCDisassembler::Fail;
}
return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
}
if (Rt == 15) {
switch (Inst.getOpcode()) {
case ARM::t2LDRSHs:
return MCDisassembler::Fail;
case ARM::t2LDRHs:
// FIXME: this instruction is only available with MP extensions,
// this should be checked first but we don't have access to the
// feature bits here.
Inst.setOpcode(ARM::t2PLDWs);
break;
default:
break;
}
}
switch (Inst.getOpcode()) {
case ARM::t2PLDs:
case ARM::t2PLDWs:
@ -3278,14 +3291,36 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
case ARM::t2LDRSHi8:
Inst.setOpcode(ARM::t2LDRSHpci);
break;
case ARM::t2PLDi8:
Inst.setOpcode(ARM::t2PLDpci);
break;
case ARM::t2PLIi8:
Inst.setOpcode(ARM::t2PLIpci);
break;
default:
return MCDisassembler::Fail;
}
return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
}
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
return MCDisassembler::Fail;
if (Rt == 15) {
switch (Inst.getOpcode()) {
case ARM::t2LDRSHi8:
return MCDisassembler::Fail;
default:
break;
}
}
switch (Inst.getOpcode()) {
case ARM::t2PLDi8:
case ARM::t2PLIi8:
break;
default:
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
return MCDisassembler::Fail;
}
if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder)))
return MCDisassembler::Fail;
return S;
@ -3317,14 +3352,39 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
case ARM::t2LDRSBi12:
Inst.setOpcode(ARM::t2LDRSBpci);
break;
case ARM::t2PLDi12:
Inst.setOpcode(ARM::t2PLDpci);
break;
case ARM::t2PLIi12:
Inst.setOpcode(ARM::t2PLIpci);
break;
default:
return MCDisassembler::Fail;
}
return DecodeT2LoadLabel(Inst, Insn, Address, Decoder);
}
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
return MCDisassembler::Fail;
if (Rt == 15) {
switch (Inst.getOpcode()) {
case ARM::t2LDRSHi12:
return MCDisassembler::Fail;
case ARM::t2LDRHi12:
Inst.setOpcode(ARM::t2PLDi12);
break;
default:
break;
}
}
switch (Inst.getOpcode()) {
case ARM::t2PLDi12:
case ARM::t2PLIi12:
break;
default:
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
return MCDisassembler::Fail;
}
if (!Check(S, DecodeT2AddrModeImm12(Inst, imm, Address, Decoder)))
return MCDisassembler::Fail;
return S;
@ -3377,11 +3437,27 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
unsigned U = fieldFromInstruction(Insn, 23, 1);
int imm = fieldFromInstruction(Insn, 0, 12);
// FIXME: detect and decode PLD properly
if (Inst.getOpcode() == ARM::t2LDRBpci && Rt == 15) {
Inst.setOpcode(ARM::t2PLDi12);
Inst.addOperand(MCOperand::CreateReg(ARM::PC));
} else {
if (Rt == 15) {
switch (Inst.getOpcode()) {
case ARM::t2LDRBpci:
case ARM::t2LDRHpci:
Inst.setOpcode(ARM::t2PLDpci);
break;
case ARM::t2LDRSBpci:
Inst.setOpcode(ARM::t2PLIpci);
break;
case ARM::t2LDRSHpci:
return MCDisassembler::Fail;
default:
break;
}
}
switch(Inst.getOpcode()) {
case ARM::t2PLDpci:
case ARM::t2PLIpci:
break;
default:
if (!Check(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder)))
return MCDisassembler::Fail;
}
@ -3528,7 +3604,10 @@ static DecodeStatus DecodeT2LdStPre(MCInst &Inst, unsigned Insn,
break;
case ARM::t2LDRSB_PRE:
case ARM::t2LDRSB_POST:
Inst.setOpcode(ARM::t2LDRSBpci);
if (Rt == 15)
Inst.setOpcode(ARM::t2PLIpci);
else
Inst.setOpcode(ARM::t2LDRSBpci);
break;
case ARM::t2LDRSH_PRE:
case ARM::t2LDRSH_POST:

View File

@ -0,0 +1,10 @@
# invalid LDRSHs Rt=PC
# RUN: echo "0x30 0xf9 0x00 0xf0" | llvm-mc -triple=thumbv7 -disassemble 2>&1 | FileCheck %s
# invalid LDRSHi8 Rt=PC
# RUN: echo "0x30 0xf9 0x00 0xfc" | llvm-mc -triple=thumbv7 -disassemble 2>&1 | FileCheck %s
# invalid LDRSHi12 Rt=PC
# RUN: echo "0xb0 0xf9 0x00 0xf0" | llvm-mc -triple=thumbv7 -disassemble 2>&1 | FileCheck %s
# CHECK: invalid instruction encoding

View File

@ -1303,6 +1303,17 @@
0x1d 0xf8 0x12 0xf0
0x1d 0xf8 0x02 0xf0
#------------------------------------------------------------------------------
# PLD(literal)
#------------------------------------------------------------------------------
# CHECK: pld [pc, #-0]
# CHECK: pld [pc, #455]
# CHECK: pld [pc, #0]
0x1f 0xf8 0x00 0xf0
0x9f 0xf8 0xc7 0xf1
0x9f 0xf8 0x00 0xf0
#------------------------------------------------------------------------------
# PLI(immediate)
#------------------------------------------------------------------------------
@ -1335,6 +1346,17 @@
0x1d 0xf9 0x12 0xf0
0x1d 0xf9 0x02 0xf0
#------------------------------------------------------------------------------
# PLI(literal)
#------------------------------------------------------------------------------
# CHECK: pli [pc, #-0]
# CHECK: pli [pc, #-328]
# CHECK: pli [pc, #0]
0x1f 0xf9 0x00 0xf0
0x1f 0xf9 0x48 0xf1
0x9f 0xf9 0x00 0xf0
#------------------------------------------------------------------------------
# QADD/QADD16/QADD8