aboutsummaryrefslogtreecommitdiff
path: root/opcodes/i386-gen.c
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-gen.c
parente416bd75c3fd471c1e0222a72b17f6c585b37e93 (diff)
downloadfsf-binutils-gdb-734dfd1cc966aff736eaeda68bfa4807ee4b50c1.zip
fsf-binutils-gdb-734dfd1cc966aff736eaeda68bfa4807ee4b50c1.tar.gz
fsf-binutils-gdb-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-gen.c')
-rw-r--r--opcodes/i386-gen.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 91c22c9..30430a2 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -774,21 +774,41 @@ add_isa_dependencies (bitfield *flags, const char *f, int value,
static void
output_cpu_flags (FILE *table, bitfield *flags, unsigned int size,
- int macro, const char *comma, const char *indent)
+ int macro, const char *comma, const char *indent, int lineno)
{
- unsigned int i;
+ unsigned int i = 0, j = 0;
memset (&active_cpu_flags, 0, sizeof(active_cpu_flags));
fprintf (table, "%s{ { ", indent);
- for (i = 0; i < size - 1; i++)
+ if (!macro)
{
- if (((i + 1) % 20) != 0)
+ for (j = ~0u; i < CpuAttrEnums; i++)
+ {
+ if (!flags[i].value)
+ continue;
+
+ if (j < ~0u)
+ fail ("%s: %d: invalid combination of CPU identifiers\n",
+ filename, lineno);
+ j = i;
+ active_cpu_flags.array[i / 32] |= 1U << (i % 32);
+ }
+
+ /* Write 0 to indicate "no associated flag". */
+ fprintf (table, "%u, ", j + 1);
+
+ j = 1;
+ }
+
+ for (; i < size - 1; i++, j++)
+ {
+ if (((j + 1) % 20) != 0)
fprintf (table, "%d, ", flags[i].value);
else
fprintf (table, "%d,", flags[i].value);
- if (((i + 1) % 20) == 0)
+ if (((j + 1) % 20) == 0)
{
/* We need \\ for macro. */
if (macro)
@@ -899,7 +919,7 @@ process_i386_cpu_flag (FILE *table, char *flag,
}
output_cpu_flags (table, flags, ARRAY_SIZE (flags), name != NULL,
- comma, indent);
+ comma, indent, lineno);
}
static void
@@ -2073,6 +2093,16 @@ main (int argc, char **argv)
fail ("%d unused bits in i386_cpu_flags.\n", c);
#endif
+ /* If this triggers, CpuIsaBits needs to be increased. */
+ static_assert (CpuAttrEnums <= (1u << CpuIsaBits));
+
+ /* Check the unused bitfield in i386_cpu_attr. */
+#ifndef CpuAttrUnused
+ c = CpuAttrNumOfBits - (CpuIsaBits + CpuMax + 1 - CpuAttrEnums);
+ if (c)
+ fail ("%d unused bits in i386_cpu_attr.\n", c);
+#endif
+
static_assert (ARRAY_SIZE (opcode_modifiers) == Opcode_Modifier_Num);
/* Check the unused bitfield in i386_operand_type. */