invalid-LDR_PRE-arm.txt was already passing, but for the wrong reasons. We were failing to specify enough fixed bits of LDR_PRE/LDRB_PRE, resulting in decoding conflicts. Separate them into immediate vs. register versions, allowing us to specify the necessary fixed bits. This in turn results in the test being decoded properly, and being rejected as UNPREDICTABLE rather than a hard failure.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138653 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2011-08-26 20:43:14 +00:00
parent ae5ea6cab0
commit 9ab0f25fc1
7 changed files with 97 additions and 20 deletions

View File

@ -1321,11 +1321,11 @@ SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
bool Match = false;
if (LoadedVT == MVT::i32 &&
SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST_IMM;
Opcode = isPre ? ARM::LDR_PRE_IMM : ARM::LDR_POST_IMM;
Match = true;
} else if (LoadedVT == MVT::i32 &&
SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST_REG;
Opcode = isPre ? ARM::LDR_PRE_REG : ARM::LDR_POST_REG;
Match = true;
} else if (LoadedVT == MVT::i16 &&
@ -1343,10 +1343,10 @@ SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) {
} else {
if (SelectAddrMode2OffsetImm(N, LD->getOffset(), Offset, AMOpc)) {
Match = true;
Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST_IMM;
Opcode = isPre ? ARM::LDRB_PRE_IMM : ARM::LDRB_POST_IMM;
} else if (SelectAddrMode2OffsetReg(N, LD->getOffset(), Offset, AMOpc)) {
Match = true;
Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST_REG;
Opcode = isPre ? ARM::LDRB_PRE_REG : ARM::LDRB_POST_REG;
}
}
}

View File

@ -30,14 +30,16 @@ ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {
switch (Opc) {
default: break;
case ARM::LDR_PRE:
case ARM::LDR_PRE_IMM:
case ARM::LDR_PRE_REG:
case ARM::LDR_POST_IMM:
case ARM::LDR_POST_REG:
return ARM::LDRi12;
case ARM::LDRH_PRE:
case ARM::LDRH_POST:
return ARM::LDRH;
case ARM::LDRB_PRE:
case ARM::LDRB_PRE_IMM:
case ARM::LDRB_PRE_REG:
case ARM::LDRB_POST_IMM:
case ARM::LDRB_POST_REG:
return ARM::LDRBi12;

View File

@ -1997,19 +1997,28 @@ def LDRD : AI3ld<0b1101, 0, (outs GPR:$Rd, GPR:$dst2),
// Indexed loads
multiclass AI2_ldridx<bit isByte, string opc, InstrItinClass itin> {
def _PRE : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins addrmode2:$addr), IndexModePre, LdFrm, itin,
def _PRE_IMM : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins addrmode_imm12:$addr), IndexModePre, LdFrm, itin,
opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
// {17-14} Rn
// {13} reg vs. imm
// {12} isAdd
// {11-0} imm12/Rm
bits<18> addr;
let Inst{25} = addr{13};
bits<17> addr;
let Inst{25} = 0;
let Inst{23} = addr{12};
let Inst{19-16} = addr{17-14};
let Inst{19-16} = addr{16-13};
let Inst{11-0} = addr{11-0};
let DecoderMethod = "DecodeAddrMode2IdxInstruction";
let DecoderMethod = "DecodeLDRPreImm";
let AsmMatchConverter = "cvtLdWriteBackRegAddrModeImm12";
}
def _PRE_REG : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb),
(ins ldst_so_reg:$addr), IndexModePre, LdFrm, itin,
opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> {
bits<17> addr;
let Inst{25} = 1;
let Inst{23} = addr{12};
let Inst{19-16} = addr{16-13};
let Inst{11-0} = addr{11-0};
let Inst{4} = 0;
let DecoderMethod = "DecodeLDRPreReg";
let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
}

View File

@ -764,7 +764,7 @@ static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc,
ARM_AM::AddrOpc Mode) {
switch (Opc) {
case ARM::LDRi12:
return ARM::LDR_PRE;
return ARM::LDR_PRE_IMM;
case ARM::STRi12:
return ARM::STR_PRE_IMM;
case ARM::VLDRS:

View File

@ -127,6 +127,8 @@ class ARMAsmParser : public MCTargetAsmParser {
// Asm Match Converter Methods
bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
@ -2233,6 +2235,23 @@ cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
return true;
}
/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.
bool ARMAsmParser::
cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
// Create a writeback register dummy placeholder.
Inst.addOperand(MCOperand::CreateImm(0));
((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
return true;
}
/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
/// Needed here because the Asm Gen Matcher can't handle properly tied operands
/// when they refer multiple MIOperands inside a single one.

View File

@ -157,6 +157,10 @@ static DecodeStatus DecodeDoubleRegLoad(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDoubleRegStore(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeLDRPreImm(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeLDRPreReg(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSTRPreReg(llvm::MCInst &Inst, unsigned Insn,
@ -1055,8 +1059,6 @@ DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
case ARM::LDR_POST_REG:
case ARM::LDRB_POST_IMM:
case ARM::LDRB_POST_REG:
case ARM::LDR_PRE:
case ARM::LDRB_PRE:
case ARM::LDRBT_POST_REG:
case ARM::LDRBT_POST_IMM:
case ARM::LDRT_POST_REG:
@ -2756,6 +2758,51 @@ static DecodeStatus DecodeDoubleRegStore(llvm::MCInst &Inst, unsigned Insn,
return S;
}
static DecodeStatus DecodeLDRPreImm(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
unsigned imm = fieldFromInstruction32(Insn, 0, 12);
imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
unsigned pred = fieldFromInstruction32(Insn, 28, 4);
if (Rn == 0xF || Rn == Rt) CHECK(S, Unpredictable);
CHECK(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodeAddrModeImm12Operand(Inst, imm, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeLDRPreReg(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;
unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
unsigned imm = fieldFromInstruction32(Insn, 0, 12);
imm |= fieldFromInstruction32(Insn, 16, 4) << 13;
imm |= fieldFromInstruction32(Insn, 23, 1) << 12;
unsigned pred = fieldFromInstruction32(Insn, 28, 4);
unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
if (Rn == 0xF || Rn == Rt) CHECK(S, Unpredictable);
if (Rm == 0xF) CHECK(S, Unpredictable);
CHECK(S, DecodeGPRRegisterClass(Inst, Rt, Address, Decoder));
CHECK(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder));
CHECK(S, DecodeSORegMemOperand(Inst, imm, Address, Decoder));
CHECK(S, DecodePredicateOperand(Inst, pred, Address, Decoder));
return S;
}
static DecodeStatus DecodeSTRPreImm(llvm::MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
DecodeStatus S = Success;

View File

@ -1,4 +1,4 @@
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {potentially undefined instruction encoding}
# Opcode=165 Name=LDR_PRE Format=ARM_FORMAT_LDFRM(6)
# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0