diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h index 233706735e3..e76791921ee 100644 --- a/lib/Target/ARM/ARM.h +++ b/lib/Target/ARM/ARM.h @@ -90,6 +90,33 @@ inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) { } } +namespace ARM_MB { + // The Memory Barrier Option constants map directly to the 4-bit encoding of + // the option field for memory barrier operations. + enum MemBOpt { + ST = 14, + ISH = 11, + ISHST = 10, + NSH = 7, + NSHST = 6, + OSH = 3, + OSHST = 2 + }; + + inline static const char *MemBOptToString(unsigned val) { + switch (val) { + default: llvm_unreachable("Unknown memory opetion"); + case ST: return "st"; + case ISH: return "ish"; + case ISHST: return "ishst"; + case NSH: return "nsh"; + case NSHST: return "nshst"; + case OSH: return "osh"; + case OSHST: return "oshst"; + } + } +} // namespace ARM_MB + FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM, CodeGenOpt::Level OptLevel); diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index b09cd73176d..ded9800052e 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -122,6 +122,8 @@ namespace { const char *Modifier = 0); void printBitfieldInvMaskImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); + void printMemBOption(const MachineInstr *MI, int OpNum, + raw_ostream &O); void printSatShiftOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); @@ -671,6 +673,13 @@ ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op, O << "#" << lsb << ", #" << width; } +void +ARMAsmPrinter::printMemBOption(const MachineInstr *MI, int OpNum, + raw_ostream &O) { + unsigned val = MI->getOperand(OpNum).getImm(); + O << ARM_MB::MemBOptToString(val); +} + void ARMAsmPrinter::printSatShiftOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) { unsigned ShiftOp = MI->getOperand(OpNum).getImm(); diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index f058ee195f2..2e7757b0969 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2389,61 +2389,30 @@ def DSB_MCR : AInoP<(outs), (ins GPR:$zero), MiscFrm, NoItinerary, } } -// Helper class for multiclass MemB -- for disassembly only -class AMBI<string opc, string asm> - : AInoP<(outs), (ins), MiscFrm, NoItinerary, opc, asm, - [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM, HasV7]> { - let Inst{31-20} = 0xf57; +// Memory Barrier Operations Variants -- for disassembly only + +def memb_opt : Operand<i32> { + let PrintMethod = "printMemBOption"; } -multiclass MemB<bits<4> op7_4, string opc> { - - def st : AMBI<opc, "\tst"> { - let Inst{7-4} = op7_4; - let Inst{3-0} = 0b1110; - } - - def ish : AMBI<opc, "\tish"> { - let Inst{7-4} = op7_4; - let Inst{3-0} = 0b1011; - } - - def ishst : AMBI<opc, "\tishst"> { - let Inst{7-4} = op7_4; - let Inst{3-0} = 0b1010; - } - - def nsh : AMBI<opc, "\tnsh"> { - let Inst{7-4} = op7_4; - let Inst{3-0} = 0b0111; - } - - def nshst : AMBI<opc, "\tnshst"> { - let Inst{7-4} = op7_4; - let Inst{3-0} = 0b0110; - } - - def osh : AMBI<opc, "\tosh"> { - let Inst{7-4} = op7_4; - let Inst{3-0} = 0b0011; - } - - def oshst : AMBI<opc, "\toshst"> { - let Inst{7-4} = op7_4; - let Inst{3-0} = 0b0010; - } +class AMBI<bits<4> op7_4, string opc> + : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, opc, "\t$opt", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasDB]> { + let Inst{31-8} = 0xf57ff0; + let Inst{7-4} = op7_4; } // These DMB variants are for disassembly only. -defm DMB : MemB<0b0101, "dmb">; +def DMBvar : AMBI<0b0101, "dmb">; // These DSB variants are for disassembly only. -defm DSB : MemB<0b0100, "dsb">; +def DSBvar : AMBI<0b0100, "dsb">; // ISB has only full system option -- for disassembly only -def ISBsy : AMBI<"isb", ""> { - let Inst{7-4} = 0b0110; +def ISBsy : AInoP<(outs), (ins), MiscFrm, NoItinerary, "isb", "", []>, + Requires<[IsARM, HasDB]> { + let Inst{31-4} = 0xf57ff06; let Inst{3-0} = 0b1111; } diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp index f40da955041..b662289cd50 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp @@ -472,6 +472,12 @@ void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI, O << '#' << lsb << ", #" << width; } +void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum, + raw_ostream &O) { + unsigned val = MI->getOperand(OpNum).getImm(); + O << ARM_MB::MemBOptToString(val); +} + void ARMInstPrinter::printSatShiftOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O) { unsigned ShiftOp = MI->getOperand(OpNum).getImm(); diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h index 14d7ec93087..3eaa6f78823 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h @@ -57,6 +57,7 @@ public: void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); + void printMemBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printSatShiftOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O); diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index cb15cff734b..9637caaa578 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -2935,7 +2935,7 @@ static bool DisassembleNDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn, // A8.6.49 ISB static inline bool MemBarrierInstr(uint32_t insn) { unsigned op7_4 = slice(insn, 7, 4); - if (slice(insn, 31, 20) == 0xf57 && (op7_4 >= 4 && op7_4 <= 6)) + if (slice(insn, 31, 8) == 0xf57ff0 && (op7_4 >= 4 && op7_4 <= 6)) return true; return false; @@ -2992,8 +2992,15 @@ static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn, static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - if (MemBarrierInstr(insn)) + if (MemBarrierInstr(insn)) { + // DMBsy, DSBsy, and ISBsy instructions have zero operand and are taken care + // of within the generic ARMBasicMCBuilder::BuildIt() method. + // + // Inst{3-0} encodes the memory barrier option for the variants. + MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0))); + NumOpsAdded = 1; return true; + } switch (Opcode) { case ARM::CLREX: diff --git a/test/MC/Disassembler/arm-tests.txt b/test/MC/Disassembler/arm-tests.txt index bb5875d2f34..cca4f32a20c 100644 --- a/test/MC/Disassembler/arm-tests.txt +++ b/test/MC/Disassembler/arm-tests.txt @@ -21,6 +21,12 @@ # CHECK: dsb 0x4f 0xf0 0x7f 0xf5 +# CHECK: dsb st +0x4e 0xf0 0x7f 0xf5 + +# CHECK: isb +0x6f 0xf0 0x7f 0xf5 + # CHECK: ldclvc p5, cr15, [r8], #-0 0x00 0xf5 0x78 0x7c diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index a640a74d216..8706ed5426e 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -599,6 +599,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("cps_opt"); IMM("vfp_f64imm"); IMM("vfp_f32imm"); + IMM("memb_opt"); IMM("msr_mask"); IMM("neg_zero"); IMM("imm0_31");