Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -2387,6 +2387,33 @@ let Inst{24-23} = 0b11; } +// Hypervisor Call is a system instruction +let isCall = 1 in { +def HVC : AInoP< (outs), (ins imm0_65535:$imm), BrFrm, NoItinerary, + "hvc", "\t$imm", []>, + Requires<[IsARM, HasVirtualization]> { + bits<16> imm; + + // Even though HVC isn't predicable, it's encoding includes a condition field. + // The instruction is undefined if the condition field is 0xf otherwise it is + // unpredictable if it isn't condition AL (0xe). + let Inst{31-28} = 0b1110; + let Unpredictable{31-28} = 0b1111; + let Inst{27-24} = 0b0001; + let Inst{23-20} = 0b0100; + let Inst{19-8} = imm{15-4}; + let Inst{7-4} = 0b0111; + let Inst{3-0} = imm{3-0}; +} +} + +// Return from exception in Hypervisor mode. +let isReturn = 1, isBarrier = 1, isTerminator = 1, Defs = [PC] in +def ERET : ABI<0b0001, (outs), (ins), NoItinerary, "eret", "", []>, + Requires<[IsARM, HasVirtualization]> { + let Inst{23-0} = 0b011000000000000001101110; +} + //===----------------------------------------------------------------------===// // Load / Store Instructions. // Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5139,7 +5139,8 @@ Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || - Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic.startswith("vsel")) + Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" || + Mnemonic.startswith("vsel")) return Mnemonic; // First, split out any predication code. Ignore mnemonics we know aren't @@ -5244,7 +5245,7 @@ Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" || Mnemonic == "vrintp" || - Mnemonic == "vrintm" || Mnemonic.startswith("aes") || + Mnemonic == "vrintm" || Mnemonic.startswith("aes") || Mnemonic == "hvc" || Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") || (FullInst.startswith("vmull") && FullInst.endswith(".p64"))) { // These mnemonics are never predicable Index: lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp =================================================================== --- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -269,7 +269,7 @@ // expressed as a GPRPair, so we have to manually merge them. // FIXME: We would really like to be able to tablegen'erate this. case ARM::LDREXD: case ARM::STREXD: - case ARM::LDAEXD: case ARM::STLEXD: + case ARM::LDAEXD: case ARM::STLEXD: { const MCRegisterClass& MRC = MRI.getRegClass(ARM::GPRRegClassID); bool isStore = Opcode == ARM::STREXD || Opcode == ARM::STLEXD; unsigned Reg = MI->getOperand(isStore ? 1 : 0).getReg(); @@ -290,6 +290,23 @@ printInstruction(&NewMI, O); return; } + break; + } + // B9.3.3 ERET (Thumb) + // For a target that has Virtualization Extensions, ERET is the preferred + // disassembly of SUBS PC, LR, #0 + case ARM::t2SUBS_PC_LR: { + if (MI->getNumOperands() == 3 && + MI->getOperand(0).isImm() && + MI->getOperand(0).getImm() == 0 && + (getAvailableFeatures() & ARM::FeatureVirtualization)) { + O << "\teret"; + printPredicateOperand(MI, 1, O); + printAnnotation(O, Annot); + return; + } + break; + } } printInstruction(MI, O); Index: test/MC/ARM/virtexts-arm.s =================================================================== --- /dev/null +++ test/MC/ARM/virtexts-arm.s @@ -0,0 +1,42 @@ +# RUN: llvm-mc -triple armv7 -mattr=virtualization -show-encoding %s | FileCheck %s --check-prefix=CHECK-ARM + + hvc #1 + hvc #7 + hvc #257 + hvc #65535 +# CHECK-ARM: [0x71,0x00,0x40,0xe1] +# CHECK-ARM: [0x77,0x00,0x40,0xe1] +# CHECK-ARM: [0x71,0x10,0x40,0xe1] +# CHECK-ARM: [0x7f,0xff,0x4f,0xe1] + + eret + ereteq + eretne + ereths + eretlo + eretmi + eretpl + eretvs + eretvc + erethi + eretls + eretge + eretlt + eretgt + eretle +# CHECK-ARM: [0x6e,0x00,0x60,0xe1] +# CHECK-ARM: [0x6e,0x00,0x60,0x01] +# CHECK-ARM: [0x6e,0x00,0x60,0x11] +# CHECK-ARM: [0x6e,0x00,0x60,0x21] +# CHECK-ARM: [0x6e,0x00,0x60,0x31] +# CHECK-ARM: [0x6e,0x00,0x60,0x41] +# CHECK-ARM: [0x6e,0x00,0x60,0x51] +# CHECK-ARM: [0x6e,0x00,0x60,0x61] +# CHECK-ARM: [0x6e,0x00,0x60,0x71] +# CHECK-ARM: [0x6e,0x00,0x60,0x81] +# CHECK-ARM: [0x6e,0x00,0x60,0x91] +# CHECK-ARM: [0x6e,0x00,0x60,0xa1] +# CHECK-ARM: [0x6e,0x00,0x60,0xb1] +# CHECK-ARM: [0x6e,0x00,0x60,0xc1] +# CHECK-ARM: [0x6e,0x00,0x60,0xd1] + Index: test/MC/Disassembler/ARM/virtexts-arm.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/ARM/virtexts-arm.txt @@ -0,0 +1,41 @@ +# RUN: llvm-mc -disassemble -triple armv7a -mcpu=cortex-a15 %s | FileCheck %s + +[0x71,0x00,0x40,0xe1] +[0x77,0x00,0x40,0xe1] +[0x71,0x10,0x40,0xe1] +[0x7f,0xff,0x4f,0xe1] +# CHECK: hvc #1 +# CHECK: hvc #7 +# CHECK: hvc #257 +# CHECK: hvc #65535 + +[0x6e,0x00,0x60,0xe1] +[0x6e,0x00,0x60,0x01] +[0x6e,0x00,0x60,0x11] +[0x6e,0x00,0x60,0x21] +[0x6e,0x00,0x60,0x31] +[0x6e,0x00,0x60,0x41] +[0x6e,0x00,0x60,0x51] +[0x6e,0x00,0x60,0x61] +[0x6e,0x00,0x60,0x71] +[0x6e,0x00,0x60,0x81] +[0x6e,0x00,0x60,0x91] +[0x6e,0x00,0x60,0xa1] +[0x6e,0x00,0x60,0xb1] +[0x6e,0x00,0x60,0xc1] +[0x6e,0x00,0x60,0xd1] +# CHECK: eret +# CHECK: ereteq +# CHECK: eretne +# CHECK: ereths +# CHECK: eretlo +# CHECK: eretmi +# CHECK: eretpl +# CHECK: eretvs +# CHECK: eretvc +# CHECK: erethi +# CHECK: eretls +# CHECK: eretge +# CHECK: eretlt +# CHECK: eretgt +# CHECK: eretle