Thumb assembly parsing and encoding for MUL.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138108 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2011-08-19 22:07:46 +00:00
parent cafe614035
commit 88ae2bc6d5
4 changed files with 57 additions and 5 deletions

View File

@ -1049,10 +1049,20 @@ def tMOVSr : T1I<(outs tGPR:$Rd), (ins tGPR:$Rm), IIC_iMOVr,
// Multiply register
let isCommutable = 1 in
def tMUL : // A8.6.105 T1
T1sItDPEncode<0b1101, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm),
IIC_iMUL32,
"mul", "\t$Rdn, $Rm, $Rdn",
[(set tGPR:$Rdn, (mul tGPR:$Rn, tGPR:$Rm))]>;
Thumb1sI<(outs tGPR:$Rd), (ins tGPR:$Rn, tGPR:$Rm), AddrModeNone, 2,
IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm", "$Rm = $Rd",
[(set tGPR:$Rd, (mul tGPR:$Rn, tGPR:$Rm))]>,
T1DataProcessing<0b1101> {
bits<3> Rd;
bits<3> Rn;
let Inst{5-3} = Rn;
let Inst{2-0} = Rd;
let AsmMatchConverter = "cvtThumbMultiply";
}
def : InstAlias<"mul${s}${p} $Rdm, $Rn", (tMUL tGPR:$Rdm, s_cc_out:$s, tGPR:$Rn,
pred:$p)>,
Requires<[IsThumb]>;
// Move inverse register
def tMVN : // A8.6.107

View File

@ -145,6 +145,8 @@ class ARMAsmParser : public MCTargetAsmParser {
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
bool validateInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
@ -2371,6 +2373,29 @@ cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
return true;
}
/// cvtThumbMultiple- 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::
cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// The second source operand must be the same register as the destination
// operand.
if (Operands.size() == 6 &&
((ARMOperand*)Operands[3])->getReg() !=
((ARMOperand*)Operands[5])->getReg()) {
Error(Operands[3]->getStartLoc(),
"destination register must match second source register");
return false;
}
((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Inst.addOperand(Inst.getOperand(0));
((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
return true;
}
/// Parse an ARM memory expression, return false if successful else return true
/// or an error. The first token must be a '[' when called.
@ -3220,7 +3245,8 @@ MatchAndEmitInstruction(SMLoc IDLoc,
case Match_MnemonicFail:
return Error(IDLoc, "invalid instruction");
case Match_ConversionFail:
return Error(IDLoc, "unable to convert operands to instruction");
// The converter function will have already emited a diagnostic.
return true;
case Match_RequiresITBlock:
return Error(IDLoc, "instruction only valid inside IT block");
case Match_RequiresV6:

View File

@ -321,3 +321,13 @@ _func:
@ CHECK: mov r3, r4 @ encoding: [0x23,0x46]
@ CHECK: movs r1, r3 @ encoding: [0x19,0x00]
@------------------------------------------------------------------------------
@ MUL
@------------------------------------------------------------------------------
muls r1, r2, r1
muls r3, r4
@ CHECK: muls r1, r2, r1 @ encoding: [0x51,0x43]
@ CHECK: muls r3, r4, r3 @ encoding: [0x63,0x43]

View File

@ -62,3 +62,9 @@ error: invalid operand for instruction
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: lsls r4, r5, #32
@ CHECK-ERRORS: ^
@ Mismatched source/destination operands for MUL instruction.
muls r1, r2, r3
@ CHECK-ERRORS: error: destination register must match second source register
@ CHECK-ERRORS: muls r1, r2, r3
@ CHECK-ERRORS: ^