[llvm] [X86][MC] Support encoding/decoding for JMPABS (PR #72835)
Shengchen Kan via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 20 00:33:43 PST 2023
https://github.com/KanRobert created https://github.com/llvm/llvm-project/pull/72835
None
>From 8154951e54cf4752a7791bfae09c0946399b32db Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Mon, 20 Nov 2023 16:32:09 +0800
Subject: [PATCH] [X86][MC] Support encoding/decoding for JMPABS
---
.../Support/X86DisassemblerDecoderCommon.h | 4 +++-
.../X86/Disassembler/X86Disassembler.cpp | 5 +++++
llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 9 ++++++---
.../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 2 ++
llvm/lib/Target/X86/X86InstrControl.td | 3 +++
llvm/lib/Target/X86/X86InstrFormats.td | 18 ++++++++++++++----
llvm/lib/Target/X86/X86InstrSSE.td | 2 +-
llvm/test/MC/Disassembler/X86/apx/jmpabs.txt | 10 ++++++++++
llvm/test/MC/X86/apx/jmpabs-att.s | 12 ++++++++++++
llvm/test/MC/X86/apx/jmpabs-intel.s | 8 ++++++++
llvm/utils/TableGen/X86DisassemblerTables.cpp | 3 +++
llvm/utils/TableGen/X86RecognizableInstr.cpp | 4 ++++
llvm/utils/TableGen/X86RecognizableInstr.h | 4 ++++
13 files changed, 75 insertions(+), 9 deletions(-)
create mode 100644 llvm/test/MC/Disassembler/X86/apx/jmpabs.txt
create mode 100644 llvm/test/MC/X86/apx/jmpabs-att.s
create mode 100644 llvm/test/MC/X86/apx/jmpabs-intel.s
diff --git a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
index 6e08fc6a0ccb650..f9089c4755444ab 100644
--- a/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
+++ b/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h
@@ -67,7 +67,8 @@ enum attributeBits {
ATTR_EVEXK = 0x1 << 10,
ATTR_EVEXKZ = 0x1 << 11,
ATTR_EVEXB = 0x1 << 12,
- ATTR_max = 0x1 << 13,
+ ATTR_REX2 = 0x1 << 13,
+ ATTR_max = 0x1 << 14,
};
// Combinations of the above attributes that are relevant to instruction
@@ -118,6 +119,7 @@ enum attributeBits {
ENUM_ENTRY(IC_64BIT_REXW_OPSIZE, 8, "The Dynamic Duo! Prefer over all " \
"else because this changes most " \
"operands' meaning") \
+ ENUM_ENTRY(IC_64BIT_REX2, 2, "requires a REX2 prefix") \
ENUM_ENTRY(IC_VEX, 1, "requires a VEX prefix") \
ENUM_ENTRY(IC_VEX_XS, 2, "requires VEX and the XS prefix") \
ENUM_ENTRY(IC_VEX_XD, 2, "requires VEX and the XD prefix") \
diff --git a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
index f738746ecd779bf..3e42499fe6be340 100644
--- a/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
+++ b/llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp
@@ -1257,6 +1257,11 @@ static int getInstructionID(struct InternalInstruction *insn,
attrMask &= ~ATTR_ADSIZE;
}
+ // Absolute jump need special handling
+ if (insn->rex2ExtensionPrefix[0] == 0xd5 && insn->opcodeType == ONEBYTE &&
+ insn->opcode == 0xA1)
+ attrMask |= ATTR_REX2;
+
if (insn->mode == MODE_16BIT) {
// JCXZ/JECXZ need special handling for 16-bit mode because the meaning
// of the AdSize prefix is inverted w.r.t. 32-bit mode.
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index 4c57009e3bc08bf..f6ae7c6fa715d77 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -966,9 +966,12 @@ namespace X86II {
NoTrackShift = EVEX_RCShift + 1,
NOTRACK = 1ULL << NoTrackShift,
- // Force VEX encoding
- ExplicitVEXShift = NoTrackShift + 1,
- ExplicitVEXPrefix = 1ULL << ExplicitVEXShift
+ // Force REX2/VEX/EVEX encoding
+ ExplicitOpPrefixShift = NoTrackShift + 1,
+ ExplicitREX2Prefix = 1ULL << ExplicitOpPrefixShift,
+ ExplicitVEXPrefix = 2ULL << ExplicitOpPrefixShift,
+ ExplicitEVEXPrefix = 3ULL << ExplicitOpPrefixShift,
+ ExplicitOpPrefix = 3ULL << ExplicitOpPrefixShift
};
/// \returns true if the instruction with given opcode is a prefix.
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index c17e7e183423804..05e33171956fb7a 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -1305,6 +1305,8 @@ PrefixKind X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
}
}
}
+ if (TSFlags & X86II::ExplicitREX2Prefix)
+ Prefix.setLowerBound(REX2);
switch (TSFlags & X86II::FormMask) {
default:
assert(!HasRegOp && "Unexpected form in emitREXPrefix!");
diff --git a/llvm/lib/Target/X86/X86InstrControl.td b/llvm/lib/Target/X86/X86InstrControl.td
index fd996603476d780..f086191767f5fa1 100644
--- a/llvm/lib/Target/X86/X86InstrControl.td
+++ b/llvm/lib/Target/X86/X86InstrControl.td
@@ -188,6 +188,9 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
}
}
+def JMPABS : Ii64<0xA1, RawFrm, (outs), (ins i64imm:$dst), "jmpabs\t$dst", []>,
+ ExplicitREX2Prefix, Requires<[In64BitMode]>, Sched<[WriteJumpLd]>;
+
// Loop instructions
let isBranch = 1, isTerminator = 1, SchedRW = [WriteJump] in {
def LOOP : Ii8PCRel<0xE2, RawFrm, (outs), (ins brtarget8:$dst), "loop\t$dst", []>;
diff --git a/llvm/lib/Target/X86/X86InstrFormats.td b/llvm/lib/Target/X86/X86InstrFormats.td
index 70ffd4175e1f145..adb6aa12a0628dc 100644
--- a/llvm/lib/Target/X86/X86InstrFormats.td
+++ b/llvm/lib/Target/X86/X86InstrFormats.td
@@ -271,8 +271,17 @@ class EVEX2VEXOverride<string VEXInstrName> {
// Prevent EVEX->VEX conversion from considering this instruction.
class NotEVEX2VEXConvertible { bit notEVEX2VEXConvertible = 1; }
-// Force the instruction to use VEX encoding.
-class ExplicitVEXPrefix { bit ExplicitVEXPrefix = 1; }
+// Force the instruction to use REX2/VEX/EVEX encoding.
+class ExplicitOpPrefix<bits<2> val> {
+ bits<2> Value = val;
+}
+def NoExplicitOpPrefix : ExplicitOpPrefix<0>;
+def ExplicitREX2 : ExplicitOpPrefix<1>;
+def ExplicitVEX : ExplicitOpPrefix<2>;
+def ExplicitEVEX : ExplicitOpPrefix<3>;
+class ExplicitREX2Prefix { ExplicitOpPrefix explicitOpPrefix = ExplicitREX2; }
+class ExplicitVEXPrefix { ExplicitOpPrefix explicitOpPrefix = ExplicitVEX; }
+class ExplicitEVEXPrefix { ExplicitOpPrefix explicitOpPrefix = ExplicitEVEX; }
class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
string AsmStr, Domain d = GenericDomain>
@@ -354,7 +363,8 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
string EVEX2VEXOverride = ?;
bit notEVEX2VEXConvertible = 0; // Prevent EVEX->VEX conversion.
- bit ExplicitVEXPrefix = 0; // Force the instruction to use VEX encoding.
+ ExplicitOpPrefix explicitOpPrefix = NoExplicitOpPrefix;
+ bits<2> explicitOpPrefixBits = explicitOpPrefix.Value;
// Force to check predicate before compress EVEX to VEX encoding.
bit checkVEXPredicate = 0;
// TSFlags layout should be kept in sync with X86BaseInfo.h.
@@ -381,7 +391,7 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
let TSFlags{47-45} = !if(!eq(CD8_Scale, 0), 0, !add(!logtwo(CD8_Scale), 1));
let TSFlags{48} = hasEVEX_RC;
let TSFlags{49} = hasNoTrackPrefix;
- let TSFlags{50} = ExplicitVEXPrefix;
+ let TSFlags{51-50} = explicitOpPrefixBits;
}
class PseudoI<dag oops, dag iops, list<dag> pattern>
diff --git a/llvm/lib/Target/X86/X86InstrSSE.td b/llvm/lib/Target/X86/X86InstrSSE.td
index 2ba1436946a286a..add24a061765014 100644
--- a/llvm/lib/Target/X86/X86InstrSSE.td
+++ b/llvm/lib/Target/X86/X86InstrSSE.td
@@ -7316,7 +7316,7 @@ defm VMASKMOVPD : avx_movmask_rm<0x2D, 0x2F, "vmaskmovpd",
// AVX_VNNI
//===----------------------------------------------------------------------===//
let Predicates = [HasAVXVNNI, NoVLX_Or_NoVNNI], Constraints = "$src1 = $dst",
- ExplicitVEXPrefix = 1, checkVEXPredicate = 1 in
+ explicitOpPrefix = ExplicitVEX, checkVEXPredicate = 1 in
multiclass avx_vnni_rm<bits<8> opc, string OpcodeStr, SDNode OpNode,
bit IsCommutable> {
let isCommutable = IsCommutable in
diff --git a/llvm/test/MC/Disassembler/X86/apx/jmpabs.txt b/llvm/test/MC/Disassembler/X86/apx/jmpabs.txt
new file mode 100644
index 000000000000000..a79dc6d5590a0eb
--- /dev/null
+++ b/llvm/test/MC/Disassembler/X86/apx/jmpabs.txt
@@ -0,0 +1,10 @@
+# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT
+# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL
+
+# ATT: jmpabs $1
+# INTEL: jmpabs 1
+0xd5,0x00,0xa1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+
+# ATT: jmpabs $72623859790382856
+# INTEL: jmpabs 72623859790382856
+0xd5,0x00,0xa1,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01
diff --git a/llvm/test/MC/X86/apx/jmpabs-att.s b/llvm/test/MC/X86/apx/jmpabs-att.s
new file mode 100644
index 000000000000000..5ce832e45857700
--- /dev/null
+++ b/llvm/test/MC/X86/apx/jmpabs-att.s
@@ -0,0 +1,12 @@
+# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s
+# RUN: not llvm-mc -triple i386 -show-encoding %s 2>&1 | FileCheck %s --check-prefix=ERROR
+
+# ERROR-COUNT-2: error:
+# ERROR-NOT: error:
+
+# CHECK: jmpabs $1
+# CHECK: encoding: [0xd5,0x00,0xa1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
+ jmpabs $1
+# CHECK: jmpabs $72623859790382856
+# CHECK: encoding: [0xd5,0x00,0xa1,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01]
+ jmpabs $72623859790382856
diff --git a/llvm/test/MC/X86/apx/jmpabs-intel.s b/llvm/test/MC/X86/apx/jmpabs-intel.s
new file mode 100644
index 000000000000000..c2b5815218a1356
--- /dev/null
+++ b/llvm/test/MC/X86/apx/jmpabs-intel.s
@@ -0,0 +1,8 @@
+# RUN: llvm-mc -triple x86_64 -show-encoding -x86-asm-syntax=intel -output-asm-variant=1 %s | FileCheck %s
+
+# CHECK: jmpabs 1
+# CHECK: encoding: [0xd5,0x00,0xa1,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
+ jmpabs 1
+# CHECK: jmpabs 72623859790382856
+# CHECK: encoding: [0xd5,0x00,0xa1,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01]
+ jmpabs 72623859790382856
diff --git a/llvm/utils/TableGen/X86DisassemblerTables.cpp b/llvm/utils/TableGen/X86DisassemblerTables.cpp
index ba51bf4858e19de..e8dffaa29c2e041 100644
--- a/llvm/utils/TableGen/X86DisassemblerTables.cpp
+++ b/llvm/utils/TableGen/X86DisassemblerTables.cpp
@@ -142,6 +142,7 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_64BIT_REXW_XS:
case IC_64BIT_REXW_OPSIZE:
case IC_64BIT_REXW_ADSIZE:
+ case IC_64BIT_REX2:
return false;
case IC_VEX:
return (VEX_LIG && WIG && inheritsFrom(child, IC_VEX_L_W)) ||
@@ -908,6 +909,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
o << "_B";
}
}
+ else if ((index & ATTR_64BIT) && (index & ATTR_REX2))
+ o << "IC_64BIT_REX2";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
o << "IC_64BIT_REXW_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index 962da623b1cadc7..bcfe7a749c09533 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -129,6 +129,8 @@ RecognizableInstrBase::RecognizableInstrBase(const CodeGenInstruction &insn) {
ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
CD8_Scale = byteFromRec(Rec, "CD8_Scale");
HasVEX_L = Rec->getValueAsBit("hasVEX_L");
+ ExplicitREX2Prefix =
+ byteFromRec(Rec, "explicitOpPrefixBits") == X86Local::ExplicitREX2;
EncodeRC = HasEVEX_B &&
(Form == X86Local::MRMDestReg || Form == X86Local::MRMSrcReg);
@@ -340,6 +342,8 @@ InstructionContext RecognizableInstr::insnContext() const {
insnContext = IC_64BIT_XD;
else if (OpPrefix == X86Local::XS)
insnContext = IC_64BIT_XS;
+ else if (ExplicitREX2Prefix)
+ insnContext = IC_64BIT_REX2;
else if (HasREX_W)
insnContext = IC_64BIT_REXW;
else
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.h b/llvm/utils/TableGen/X86RecognizableInstr.h
index 38bca87bfe614c3..d258ed21f46ab60 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.h
+++ b/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -155,6 +155,8 @@ namespace X86Local {
enum {
AdSize16 = 1, AdSize32 = 2, AdSize64 = 3
};
+
+ enum { ExplicitREX2 = 1 };
}
namespace X86Disassembler {
@@ -206,6 +208,8 @@ struct RecognizableInstrBase {
bool ForceDisassemble;
// The CD8_Scale field from the record
uint8_t CD8_Scale;
+ /// If explicitOpPrefix field from the record equals ExplicitREX2
+ bool ExplicitREX2Prefix;
/// \param insn The CodeGenInstruction to extract information from.
RecognizableInstrBase(const CodeGenInstruction &insn);
/// \returns true if this instruction should be emitted
More information about the llvm-commits
mailing list