diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2018-07-25 15:28:07 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2018-07-25 15:28:24 -0700 |
commit | 4a1b91eabbe77f4d906a0895121d76a0653c3cf3 (patch) | |
tree | 675d4da6c17c95157f9a312626af39ac098b27d6 /opcodes/i386-gen.c | |
parent | 506f5c41cab71dbc3e562ba367d2dc6b355b64a6 (diff) | |
download | gdb-4a1b91eabbe77f4d906a0895121d76a0653c3cf3.zip gdb-4a1b91eabbe77f4d906a0895121d76a0653c3cf3.tar.gz gdb-4a1b91eabbe77f4d906a0895121d76a0653c3cf3.tar.bz2 |
x86: Expand Broadcast to 3 bits
Expand Broadcast to 3 bits so that the number of bytes to broadcast
can be computed as 1 << (Broadcast - 1). Use it to simplify x86
assembler.
gas/
* config/tc-i386.c (Broadcast_Operation): Add bytes.
(build_evex_prefix): Use i.broadcast->bytes.
(match_broadcast_size): New function.
(check_VecOperands): Use the broadcast field to compute the
number of bytes to broadcast directly. Set i.broadcast->bytes.
Use match_broadcast_size.
opcodes/
* i386-gen.c (adjust_broadcast_modifier): New function.
(process_i386_opcode_modifier): Add an argument for operands.
Adjust the Broadcast value based on operands.
(output_i386_opcode): Pass operand_types to
process_i386_opcode_modifier.
(process_i386_opcodes): Pass NULL as operands to
process_i386_opcode_modifier.
* i386-opc.h (BYTE_BROADCAST): New.
(WORD_BROADCAST): Likewise.
(DWORD_BROADCAST): Likewise.
(QWORD_BROADCAST): Likewise.
(i386_opcode_modifier): Expand broadcast to 3 bits.
* i386-tbl.h: Regenerated.
Diffstat (limited to 'opcodes/i386-gen.c')
-rw-r--r-- | opcodes/i386-gen.c | 61 |
1 files changed, 57 insertions, 4 deletions
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c index 860d318..ee3a8d5 100644 --- a/opcodes/i386-gen.c +++ b/opcodes/i386-gen.c @@ -1023,8 +1023,58 @@ output_opcode_modifier (FILE *table, bitfield *modifier, unsigned int size) fprintf (table, "%d },\n", modifier[i].value); } +static int +adjust_broadcast_modifier (char **opnd) +{ + char *str, *next, *last, *op; + int bcst_type = INT_MAX; + + /* Skip the immediate operand. */ + op = opnd[0]; + if (strcasecmp(op, "Imm8") == 0) + op = opnd[1]; + + op = xstrdup (op); + last = op + strlen (op); + for (next = op; next && next < last; ) + { + str = next_field (next, '|', &next, last); + if (str) + { + if (strcasecmp(str, "Byte") == 0) + { + /* The smalest broadcast type, no need to check + further. */ + bcst_type = BYTE_BROADCAST; + break; + } + else if (strcasecmp(str, "Word") == 0) + { + if (bcst_type > WORD_BROADCAST) + bcst_type = WORD_BROADCAST; + } + else if (strcasecmp(str, "Dword") == 0) + { + if (bcst_type > DWORD_BROADCAST) + bcst_type = DWORD_BROADCAST; + } + else if (strcasecmp(str, "Qword") == 0) + { + if (bcst_type > QWORD_BROADCAST) + bcst_type = QWORD_BROADCAST; + } + } + } + free (op); + + if (bcst_type == INT_MAX) + fail (_("unknown broadcast operand: %s\n"), op); + + return bcst_type; +} + static void -process_i386_opcode_modifier (FILE *table, char *mod, int lineno) +process_i386_opcode_modifier (FILE *table, char *mod, char **opnd, int lineno) { char *str, *next, *last; bitfield modifiers [ARRAY_SIZE (opcode_modifiers)]; @@ -1042,7 +1092,10 @@ process_i386_opcode_modifier (FILE *table, char *mod, int lineno) str = next_field (next, '|', &next, last); if (str) { - set_bitfield (str, modifiers, 1, ARRAY_SIZE (modifiers), + int val = 1; + if (strcasecmp(str, "Broadcast") == 0) + val = adjust_broadcast_modifier (opnd); + set_bitfield (str, modifiers, val, ARRAY_SIZE (modifiers), lineno); if (strcasecmp(str, "IsString") == 0) active_isstring = 1; @@ -1201,7 +1254,7 @@ output_i386_opcode (FILE *table, const char *name, char *str, process_i386_cpu_flag (table, cpu_flags, 0, ",", " ", lineno); - process_i386_opcode_modifier (table, opcode_modifier, lineno); + process_i386_opcode_modifier (table, opcode_modifier, operand_types, lineno); fprintf (table, " { "); @@ -1394,7 +1447,7 @@ process_i386_opcodes (FILE *table) process_i386_cpu_flag (table, "0", 0, ",", " ", -1); - process_i386_opcode_modifier (table, "0", -1); + process_i386_opcode_modifier (table, "0", NULL, -1); fprintf (table, " { "); process_i386_operand_type (table, "0", stage_opcodes, "\t ", -1); |