Add assembly parsing support for "msr" and also fix its encoding. Also add

testcases for the disassembler to make sure it still works for "msr".



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125948 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bruno Cardoso Lopes 2011-02-18 19:45:59 +00:00
parent 6309b3e9be
commit 584bf7bb03
11 changed files with 237 additions and 48 deletions

View File

@ -161,6 +161,12 @@ def ProcIFlagsOperand : AsmOperandClass {
let ParserMethod = "tryParseProcIFlagsOperand";
}
def MSRMaskOperand : AsmOperandClass {
let Name = "MSRMask";
let SuperClasses = [];
let ParserMethod = "tryParseMSRMaskOperand";
}
// ARM imod and iflag operands, used only by the CPS instruction.
def imod_op : Operand<i32> {
let PrintMethod = "printCPSIMod";
@ -205,6 +211,7 @@ def cps_opt : Operand<i32> {
def msr_mask : Operand<i32> {
let PrintMethod = "printMSRMaskOperand";
let ParserMatchClass = MSRMaskOperand;
}
// A8.6.117, A8.6.118. Different instructions are generated for #0 and #-0.

View File

@ -3856,6 +3856,7 @@ def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>;
// Move between special register and ARM core register -- for disassembly only
//
// Move to ARM core register from Special Register
def MRS : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, cpsr",
[/* For disassembly only; pattern left blank */]> {
bits<4> Rd;
@ -3872,30 +3873,37 @@ def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary,"mrs","\t$Rd, spsr",
let Inst{7-4} = 0b0000;
}
def MSR : ABI<0b0001, (outs), (ins GPR:$src, msr_mask:$mask), NoItinerary,
"msr", "\tcpsr$mask, $src",
// Move from ARM core register to Special Register
//
// No need to have both system and application versions, the encodings are the
// same and the assembly parser has no way to distinguish between them. The mask
// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains
// the mask with the fields to be accessed in the special register.
def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary,
"msr", "\t$mask, $Rn",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0010;
let Inst{7-4} = 0b0000;
bits<5> mask;
bits<4> Rn;
let Inst{23} = 0;
let Inst{22} = mask{4}; // R bit
let Inst{21-20} = 0b10;
let Inst{19-16} = mask{3-0};
let Inst{15-12} = 0b1111;
let Inst{11-4} = 0b00000000;
let Inst{3-0} = Rn;
}
def MSRi : ABI<0b0011, (outs), (ins so_imm:$a, msr_mask:$mask), NoItinerary,
"msr", "\tcpsr$mask, $a",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0010;
let Inst{7-4} = 0b0000;
}
def MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask, so_imm:$a), NoItinerary,
"msr", "\t$mask, $a",
[/* For disassembly only; pattern left blank */]> {
bits<5> mask;
bits<12> a;
def MSRsys : ABI<0b0001, (outs), (ins GPR:$src, msr_mask:$mask), NoItinerary,
"msr", "\tspsr$mask, $src",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0110;
let Inst{7-4} = 0b0000;
}
def MSRsysi : ABI<0b0011, (outs), (ins so_imm:$a, msr_mask:$mask), NoItinerary,
"msr", "\tspsr$mask, $a",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0110;
let Inst{7-4} = 0b0000;
let Inst{23} = 0;
let Inst{22} = mask{4}; // R bit
let Inst{21-20} = 0b10;
let Inst{19-16} = mask{3-0};
let Inst{15-12} = 0b1111;
let Inst{11-0} = a;
}

View File

@ -3330,25 +3330,24 @@ def t2MRSsys : T2MRS<0b111100111111, 0b10, 0,
(outs rGPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, spsr",
[/* For disassembly only; pattern left blank */]>;
class T2MSR<bits<12> op31_20, bits<2> op15_14, bits<1> op12,
dag oops, dag iops, InstrItinClass itin,
string opc, string asm, list<dag> pattern>
: T2SpecialReg<op31_20, op15_14, op12, oops, iops, itin, opc, asm, pattern> {
// Move from ARM core register to Special Register
//
// No need to have both system and application versions, the encodings are the
// same and the assembly parser has no way to distinguish between them. The mask
// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains
// the mask with the fields to be accessed in the special register.
def t2MSR : T2SpecialReg<0b111100111000 /* op31-20 */, 0b10 /* op15-14 */,
0 /* op12 */, (outs), (ins msr_mask:$mask, rGPR:$Rn),
NoItinerary, "msr", "\t$mask, $Rn",
[/* For disassembly only; pattern left blank */]> {
bits<5> mask;
bits<4> Rn;
bits<4> mask;
let Inst{19-16} = Rn;
let Inst{11-8} = mask;
let Inst{20} = mask{4}; // R Bit
let Inst{13} = 0b0;
let Inst{11-8} = mask{3-0};
}
def t2MSR : T2MSR<0b111100111000, 0b10, 0,
(outs), (ins rGPR:$Rn, msr_mask:$mask), NoItinerary, "msr",
"\tcpsr$mask, $Rn",
[/* For disassembly only; pattern left blank */]>;
def t2MSRsys : T2MSR<0b111100111001, 0b10, 0,
(outs), (ins rGPR:$Rn, msr_mask:$mask), NoItinerary, "msr",
"\tspsr$mask, $Rn",
[/* For disassembly only; pattern left blank */]>;
//===----------------------------------------------------------------------===//
// Move between coprocessor and ARM core register -- for disassembly only
//

View File

@ -100,6 +100,8 @@ class ARMAsmParser : public TargetAsmParser {
SmallVectorImpl<MCParsedAsmOperand*> &);
OperandMatchResultTy tryParseProcIFlagsOperand(
SmallVectorImpl<MCParsedAsmOperand*> &);
OperandMatchResultTy tryParseMSRMaskOperand(
SmallVectorImpl<MCParsedAsmOperand*> &);
public:
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
@ -128,6 +130,7 @@ class ARMOperand : public MCParsedAsmOperand {
Immediate,
MemBarrierOpt,
Memory,
MSRMask,
ProcIFlags,
Register,
RegisterList,
@ -156,6 +159,10 @@ class ARMOperand : public MCParsedAsmOperand {
ARM_PROC::IFlags Val;
} IFlags;
struct {
unsigned Val;
} MMask;
struct {
const char *Data;
unsigned Length;
@ -222,6 +229,9 @@ public:
case Memory:
Mem = o.Mem;
break;
case MSRMask:
MMask = o.MMask;
break;
case ProcIFlags:
IFlags = o.IFlags;
}
@ -273,6 +283,11 @@ public:
return IFlags.Val;
}
unsigned getMSRMask() const {
assert(Kind == MSRMask && "Invalid access!");
return MMask.Val;
}
/// @name Memory Operand Accessors
/// @{
@ -347,6 +362,7 @@ public:
uint64_t Value = CE->getValue();
return ((Value & 0x3) == 0 && Value <= 124);
}
bool isMSRMask() const { return Kind == MSRMask; }
bool isProcIFlags() const { return Kind == ProcIFlags; }
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
@ -448,6 +464,11 @@ public:
Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
}
void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
}
void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
@ -584,6 +605,14 @@ public:
Op->EndLoc = S;
return Op;
}
static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
ARMOperand *Op = new ARMOperand(MSRMask);
Op->MMask.Val = MMask;
Op->StartLoc = S;
Op->EndLoc = S;
return Op;
}
};
} // end anonymous namespace.
@ -602,6 +631,9 @@ void ARMOperand::dump(raw_ostream &OS) const {
case CoprocReg:
OS << "<coprocessor register: " << getCoproc() << ">";
break;
case MSRMask:
OS << "<mask: " << getMSRMask() << ">";
break;
case Immediate:
getImm()->print(OS);
break;
@ -950,6 +982,69 @@ tryParseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
/// tryParseMSRMaskOperand - Try to parse mask flags from MSR instruction.
ARMAsmParser::OperandMatchResultTy ARMAsmParser::
tryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SMLoc S = Parser.getTok().getLoc();
const AsmToken &Tok = Parser.getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
StringRef Mask = Tok.getString();
// Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
size_t Start = 0, Next = Mask.find('_');
StringRef Flags = "";
StringRef SpecReg = Mask.slice(Start, Next);
if (Next != StringRef::npos)
Flags = Mask.slice(Next+1, Mask.size());
// FlagsVal contains the complete mask:
// 3-0: Mask
// 4: Special Reg (cpsr, apsr => 0; spsr => 1)
unsigned FlagsVal = 0;
if (SpecReg == "apsr") {
FlagsVal = StringSwitch<unsigned>(Flags)
.Case("nzcvq", 0x8) // same as CPSR_c
.Case("g", 0x4) // same as CPSR_s
.Case("nzcvqg", 0xc) // same as CPSR_fs
.Default(~0U);
if (FlagsVal == ~0U)
if (!Flags.empty())
return MatchOperand_NoMatch;
else
FlagsVal = 0; // No flag
} else if (SpecReg == "cpsr" || SpecReg == "spsr") {
for (int i = 0, e = Flags.size(); i != e; ++i) {
unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
.Case("c", 1)
.Case("x", 2)
.Case("s", 4)
.Case("f", 8)
.Default(~0U);
// If some specific flag is already set, it means that some letter is
// present more than once, this is not acceptable.
if (FlagsVal == ~0U || (FlagsVal & Flag))
return MatchOperand_NoMatch;
FlagsVal |= Flag;
}
} else // No match for special register.
return MatchOperand_NoMatch;
// Special register without flags are equivalent to "fc" flags.
if (!FlagsVal)
FlagsVal = 0x9;
// Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
if (SpecReg == "spsr")
FlagsVal |= 16;
Parser.Lex(); // Eat identifier token.
Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
return MatchOperand_Success;
}
/// Parse an ARM memory expression, return false if successful else return true
/// or an error. The first token must be a '[' when called.
///

View File

@ -720,25 +720,29 @@ static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
NumOpsAdded = 1;
return true;
}
// MSR and MSRsys take one GPR reg Rm, followed by the mask.
if (Opcode == ARM::MSR || Opcode == ARM::MSRsys) {
assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
// MSR take a mask, followed by one GPR reg Rm. The mask contains the R Bit in
// bit 4, and the special register fields in bits 3-0.
if (Opcode == ARM::MSR) {
assert(NumOps >= 1 && OpInfo[1].RegClass == ARM::GPRRegClassID &&
"Reg operand expected");
MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ |
slice(insn, 19, 16) /* Special Reg */ ));
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRm(insn))));
MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 16)));
NumOpsAdded = 2;
return true;
}
// MSRi and MSRsysi take one so_imm operand, followed by the mask.
if (Opcode == ARM::MSRi || Opcode == ARM::MSRsysi) {
// MSRi take a mask, followed by one so_imm operand. The mask contains the
// R Bit in bit 4, and the special register fields in bits 3-0.
if (Opcode == ARM::MSRi) {
MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ |
slice(insn, 19, 16) /* Special Reg */ ));
// SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0.
// A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}.
// See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot().
unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF;
unsigned Imm = insn & 0xFF;
MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot)));
MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 16)));
NumOpsAdded = 2;
return true;
}

View File

@ -1702,11 +1702,13 @@ static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode,
NumOpsAdded = 1;
return true;
}
// MSR and MSRsys take one GPR reg Rn, followed by the mask.
if (Opcode == ARM::t2MSR || Opcode == ARM::t2MSRsys || Opcode == ARM::t2BXJ) {
// MSR take a mask, followed by one GPR reg Rn. The mask contains the R Bit in
// bit 4, and the special register fields in bits 3-0.
if (Opcode == ARM::t2MSR) {
MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 20) << 4 /* R Bit */ |
slice(insn, 11, 8) /* Special Reg */));
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
decodeRn(insn))));
MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 8)));
NumOpsAdded = 2;
return true;
}

View File

@ -397,7 +397,14 @@ void ARMInstPrinter::printCPSIFlag(const MCInst *MI, unsigned OpNum,
void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNum);
unsigned Mask = Op.getImm();
unsigned SpecRegRBit = Op.getImm() >> 4;
unsigned Mask = Op.getImm() & 0xf;
if (SpecRegRBit)
O << "spsr";
else
O << "cpsr";
if (Mask) {
O << '_';
if (Mask & 8) O << 'f';

View File

@ -246,3 +246,39 @@
@ CHECK: cpsie if, #10 @ encoding: [0xca,0x00,0x0a,0xf1]
cpsie if, #10
@ CHECK: msr cpsr_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
msr apsr, r0
@ CHECK: msr cpsr_s, r0 @ encoding: [0x00,0xf0,0x24,0xe1]
msr apsr_g, r0
@ CHECK: msr cpsr_f, r0 @ encoding: [0x00,0xf0,0x28,0xe1]
msr apsr_nzcvq, r0
@ CHECK: msr cpsr_fs, r0 @ encoding: [0x00,0xf0,0x2c,0xe1]
msr apsr_nzcvqg, r0
@ CHECK: msr cpsr_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
msr cpsr_fc, r0
@ CHECK: msr cpsr_c, r0 @ encoding: [0x00,0xf0,0x21,0xe1]
msr cpsr_c, r0
@ CHECK: msr cpsr_x, r0 @ encoding: [0x00,0xf0,0x22,0xe1]
msr cpsr_x, r0
@ CHECK: msr cpsr_fc, r0 @ encoding: [0x00,0xf0,0x29,0xe1]
msr cpsr_fc, r0
@ CHECK: msr cpsr_fsx, r0 @ encoding: [0x00,0xf0,0x2e,0xe1]
msr cpsr_fsx, r0
@ CHECK: msr spsr_fc, r0 @ encoding: [0x00,0xf0,0x69,0xe1]
msr spsr_fc, r0
@ CHECK: msr spsr_fsxc, r0 @ encoding: [0x00,0xf0,0x6f,0xe1]
msr spsr_fsxc, r0
@ CHECK: msr cpsr_fsxc, r0 @ encoding: [0x00,0xf0,0x2f,0xe1]
msr cpsr_fsxc, r0

View File

@ -259,3 +259,28 @@
@ CHECK: cpsie.w if, #10 @ encoding: [0xaf,0xf3,0x6a,0x85]
cpsie.w if, #10
@ CHECK: msr cpsr_fc, r0 @ encoding: [0x80,0xf3,0x00,0x89]
msr apsr, r0
@ CHECK: msr cpsr_s, r0 @ encoding: [0x80,0xf3,0x00,0x84]
msr apsr_g, r0
@ CHECK: msr cpsr_f, r0 @ encoding: [0x80,0xf3,0x00,0x88]
msr apsr_nzcvq, r0
@ CHECK: msr cpsr_fs, r0 @ encoding: [0x80,0xf3,0x00,0x8c]
msr apsr_nzcvqg, r0
@ CHECK: msr cpsr_fc, r0 @ encoding: [0x80,0xf3,0x00,0x89]
msr cpsr_fc, r0
@ CHECK: msr cpsr_c, r0 @ encoding: [0x80,0xf3,0x00,0x81]
msr cpsr_c, r0
@ CHECK: msr cpsr_x, r0 @ encoding: [0x80,0xf3,0x00,0x82]
msr cpsr_x, r0
@ CHECK: msr cpsr_fc, r0 @ encoding: [0x80,0xf3,0x00,0x89]
msr cpsr_fc, r0
@ CHECK: msr cpsr_fsx, r0 @ encoding: [0x80,0xf3,0x00,0x8e]
msr cpsr_fsx, r0
@ CHECK: msr spsr_fc, r0 @ encoding: [0x90,0xf3,0x00,0x89]
msr spsr_fc, r0
@ CHECK: msr spsr_fsxc, r0 @ encoding: [0x90,0xf3,0x00,0x8f]
msr spsr_fsxc, r0
@ CHECK: msr cpsr_fsxc, r0 @ encoding: [0x80,0xf3,0x00,0x8f]
msr cpsr_fsxc, r0

View File

@ -127,3 +127,6 @@
# CHECK: cpsie if, #10
0xca 0x00 0x0a 0xf1
# CHECK: msr cpsr_fc, r0
0x00 0xf0 0x29 0xe1

View File

@ -115,3 +115,6 @@
# CHECK: cpsie aif
0x67 0xb6
# CHECK: msr cpsr_fc, r0
0x80 0xf3 0x00 0x89