From 42563acbd427b84bfc4cf3f9179043e66d2db7e7 Mon Sep 17 00:00:00 2001 From: Charlie Turner Date: Mon, 1 Dec 2014 08:33:28 +0000 Subject: [PATCH] Add ARM ERET and HVC virtualisation extension instructions. Patch by Matthew Wahab. Change-Id: Iad75f078fbaa4ecc7d7a4820ad9b3930679cbbbb git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222989 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrInfo.td | 27 ++++++++++++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 5 ++- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 4 +- test/MC/ARM/virtexts-arm.s | 42 +++++++++++++++++++ test/MC/Disassembler/ARM/virtexts-arm.txt | 41 ++++++++++++++++++ 5 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 test/MC/ARM/virtexts-arm.s create mode 100644 test/MC/Disassembler/ARM/virtexts-arm.txt diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index a34e3f312c8..a40f9bcd20b 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2387,6 +2387,33 @@ def RFEIB_UPD : RFEI<1, "rfeib\t$Rn!"> { 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. // diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 0e474c0e153..7dd300d048c 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5139,7 +5139,8 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic, 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 @@ getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst, 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 diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 0570084deb6..a51680c20da 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -269,7 +269,7 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O, // 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,8 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O, printInstruction(&NewMI, O); return; } + break; + } } printInstruction(MI, O); diff --git a/test/MC/ARM/virtexts-arm.s b/test/MC/ARM/virtexts-arm.s new file mode 100644 index 00000000000..a67a8fea5c6 --- /dev/null +++ b/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] + diff --git a/test/MC/Disassembler/ARM/virtexts-arm.txt b/test/MC/Disassembler/ARM/virtexts-arm.txt new file mode 100644 index 00000000000..a18466f2d66 --- /dev/null +++ b/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