aboutsummaryrefslogtreecommitdiff
path: root/opcodes/i386-opc.h
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2023-08-11 10:04:49 +0200
committerJan Beulich <jbeulich@suse.com>2023-08-11 10:04:49 +0200
commit734dfd1cc966aff736eaeda68bfa4807ee4b50c1 (patch)
tree886eaf6a72d949950ce5aa63f17706f8297a2e19 /opcodes/i386-opc.h
parente416bd75c3fd471c1e0222a72b17f6c585b37e93 (diff)
downloadbinutils-734dfd1cc966aff736eaeda68bfa4807ee4b50c1.zip
binutils-734dfd1cc966aff736eaeda68bfa4807ee4b50c1.tar.gz
binutils-734dfd1cc966aff736eaeda68bfa4807ee4b50c1.tar.bz2
x86: pack CPU flags in opcode table
The table constantly growing in two dimensions (number of table entries times number of ISA extension flags) doesn't scale very well. Use a more compact representation: Only identifiers which need to combine with other identifiers retain individual flag bits. All others are combined into an enum, with a new helper added to transform the table entries into the original i386_cpu_flags layout. This way the table in the final binary shrinks by almost a third (the generated source code shrinks by about half), and isn't likely to grow again in that dimension any time soon. While moving the 3DNow! fields, drop the stray inner 'a' from their names.
Diffstat (limited to 'opcodes/i386-opc.h')
-rw-r--r--opcodes/i386-opc.h94
1 files changed, 61 insertions, 33 deletions
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 2844750..7bc4127 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -26,7 +26,7 @@
/* Position of cpu flags bitfiled. */
-enum
+enum i386_cpu
{
/* i186 or better required */
Cpu186 = 0,
@@ -52,10 +52,6 @@ enum
CpuSYSCALL,
/* Floating point support required */
Cpu8087,
- /* i287 support required */
- Cpu287,
- /* i387 support required */
- Cpu387,
/* i686 and floating point support required */
Cpu687,
/* SSE3 and floating point support required */
@@ -66,10 +62,6 @@ enum
CpuSSE,
/* SSE2 support required */
CpuSSE2,
- /* 3dnow! support required */
- Cpu3dnow,
- /* 3dnow! Extensions support required */
- Cpu3dnowA,
/* SSE3 support required */
CpuSSE3,
/* VIA PadLock required */
@@ -94,12 +86,8 @@ enum
CpuSSE4_1,
/* SSE4.2 support required */
CpuSSE4_2,
- /* AVX support required */
- CpuAVX,
/* AVX2 support required */
CpuAVX2,
- /* Intel AVX-512 Foundation Instructions support required */
- CpuAVX512F,
/* Intel AVX-512 Conflict Detection Instructions support required */
CpuAVX512CD,
/* Intel AVX-512 Exponential and Reciprocal Instructions support
@@ -107,8 +95,6 @@ enum
CpuAVX512ER,
/* Intel AVX-512 Prefetch Instructions support required */
CpuAVX512PF,
- /* Intel AVX-512 VL Instructions support required. */
- CpuAVX512VL,
/* Intel AVX-512 DQ Instructions support required. */
CpuAVX512DQ,
/* Intel AVX-512 BW Instructions support required. */
@@ -153,8 +139,6 @@ enum
CpuF16C,
/* Intel BMI2 support required */
CpuBMI2,
- /* HLE support required */
- CpuHLE,
/* RTM support required */
CpuRTM,
/* INVPCID Instructions required */
@@ -313,12 +297,33 @@ enum
/* RMPQUERY instruction required */
CpuRMPQUERY,
- /* NOTE: These last three items need to remain last and in this order. */
+ /* NOTE: These items, which can be combined with other ISA flags above, need
+ to remain second to last and in sync with CPU_FLAGS_COMMON. */
+ /* i287 support required */
+ Cpu287,
+ CpuAttrEnums = Cpu287,
+ /* i387 support required */
+ Cpu387,
+ /* 3dnow! support required */
+ Cpu3dnow,
+ /* 3dnow! Extensions support required */
+ Cpu3dnowA,
+ /* AVX support required */
+ CpuAVX,
+ /* HLE support required */
+ CpuHLE,
+ /* Intel AVX-512 Foundation Instructions support required */
+ CpuAVX512F,
+ /* Intel AVX-512 VL Instructions support required. */
+ CpuAVX512VL,
/* 64bit support required */
Cpu64,
/* Not supported in the 64bit mode */
CpuNo64,
+
+ /* NOTE: This item needs to remain last. */
+
/* The last bitfield in i386_cpu_flags. */
CpuMax = CpuNo64
};
@@ -328,9 +333,42 @@ enum
#define CpuNumOfBits \
(CpuNumOfUints * sizeof (unsigned int) * CHAR_BIT)
-/* If you get a compiler error for zero width of the unused field,
- comment it out. */
+#define CpuIsaBits 8
+#define CpuAttrNumOfUints \
+ ((CpuIsaBits + CpuMax - CpuAttrEnums) / sizeof (unsigned int) / CHAR_BIT + 1)
+#define CpuAttrNumOfBits \
+ (CpuAttrNumOfUints * sizeof (unsigned int) * CHAR_BIT)
+
+/* If you get a compiler error for zero width of an unused field,
+ comment the respective one out. */
#define CpuUnused (CpuMax + 1)
+#define CpuAttrUnused (CpuIsaBits + CpuMax + 1 - CpuAttrEnums)
+
+#define CPU_FLAGS_COMMON \
+ unsigned int cpu287:1, \
+ cpu387:1, \
+ cpu3dnow:1, \
+ cpu3dnowa:1, \
+ cpuavx:1, \
+ cpuhle:1, \
+ cpuavx512f:1, \
+ cpuavx512vl:1, \
+ /* NOTE: These two fields need to remain last and in this order. */ \
+ cpu64:1, \
+ cpuno64:1
+
+typedef union i386_cpu_attr
+{
+ struct
+ {
+ unsigned int isa:CpuIsaBits;
+ CPU_FLAGS_COMMON;
+#ifdef CpuAttrUnused
+ unsigned int unused:(CpuAttrNumOfBits - CpuAttrUnused);
+#endif
+ } bitfield;
+ unsigned int array[CpuAttrNumOfUints];
+} i386_cpu_attr;
/* We can check if an instruction is available with array instead
of bitfield. */
@@ -350,15 +388,11 @@ typedef union i386_cpu_flags
unsigned int cpunop:1;
unsigned int cpusyscall:1;
unsigned int cpu8087:1;
- unsigned int cpu287:1;
- unsigned int cpu387:1;
unsigned int cpu687:1;
unsigned int cpufisttp:1;
unsigned int cpummx:1;
unsigned int cpusse:1;
unsigned int cpusse2:1;
- unsigned int cpua3dnow:1;
- unsigned int cpua3dnowa:1;
unsigned int cpusse3:1;
unsigned int cpupadlock:1;
unsigned int cpusvme:1;
@@ -371,13 +405,10 @@ typedef union i386_cpu_flags
unsigned int cpumonitor:1;
unsigned int cpusse4_1:1;
unsigned int cpusse4_2:1;
- unsigned int cpuavx:1;
unsigned int cpuavx2:1;
- unsigned int cpuavx512f:1;
unsigned int cpuavx512cd:1;
unsigned int cpuavx512er:1;
unsigned int cpuavx512pf:1;
- unsigned int cpuavx512vl:1;
unsigned int cpuavx512dq:1;
unsigned int cpuavx512bw:1;
unsigned int cpuiamcu:1;
@@ -400,7 +431,6 @@ typedef union i386_cpu_flags
unsigned int cpurdrnd:1;
unsigned int cpuf16c:1;
unsigned int cpubmi2:1;
- unsigned int cpuhle:1;
unsigned int cpurtm:1;
unsigned int cpuinvpcid:1;
unsigned int cpuvmfunc:1;
@@ -480,9 +510,7 @@ typedef union i386_cpu_flags
unsigned int cputlbsync:1;
unsigned int cpusnp:1;
unsigned int cpurmpquery:1;
- /* NOTE: These last three fields need to remain last and in this order. */
- unsigned int cpu64:1;
- unsigned int cpuno64:1;
+ CPU_FLAGS_COMMON;
#ifdef CpuUnused
unsigned int unused:(CpuNumOfBits - CpuUnused);
#endif
@@ -972,8 +1000,8 @@ typedef struct insn_template
the same instruction */
i386_opcode_modifier opcode_modifier;
- /* cpu feature flags */
- i386_cpu_flags cpu_flags;
+ /* cpu feature attributes */
+ i386_cpu_attr cpu;
/* operand_types[i] describes the type of operand i. This is made
by OR'ing together all of the possible type masks. (e.g.