diff options
author | Jan Beulich <jbeulich@suse.com> | 2022-07-06 09:22:47 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2022-07-06 09:22:47 +0200 |
commit | f68697e82319687871943f949078ed334f188211 (patch) | |
tree | 41da297c91ac333d50f9d2d75a8e61186fea279d /gas | |
parent | ae89daecb1326742448fc359ddd64d127477cbc2 (diff) | |
download | gdb-f68697e82319687871943f949078ed334f188211.zip gdb-f68697e82319687871943f949078ed334f188211.tar.gz gdb-f68697e82319687871943f949078ed334f188211.tar.bz2 |
x86: introduce a state stack for .arch
When using just slightly non-trivial combinations of .arch, it can be
quite useful to be able to go back to prior state without needing to
re-invoke perhaps many earlier directives and without needing to invoke
perhaps many "negative" ones. Like some other architectures allow
saving (pushing) and restoring (popping) present/prior state.
For now require the same .code<N> to be in effect for ".arch pop" that
was in effect for the corresponding ".arch push".
Also change the global "no_cond_jump_promotion" to be bool, to match the
new struct field.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/config/tc-i386.c | 81 | ||||
-rw-r--r-- | gas/doc/c-i386.texi | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/arch-stk.l | 43 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/arch-stk.s | 34 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/i386.exp | 1 |
5 files changed, 159 insertions, 2 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index c11f052..d915b15 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -788,7 +788,7 @@ i386_cpu_flags cpu_arch_isa_flags; /* If set, conditional jumps are not automatically promoted to handle larger than a byte offset. */ -static unsigned int no_cond_jump_promotion = 0; +static bool no_cond_jump_promotion = false; /* Encode SSE instructions with VEX prefix. */ static unsigned int sse2avx; @@ -2660,6 +2660,20 @@ extend_cpu_sub_arch_name (const char *name) static void set_cpu_arch (int dummy ATTRIBUTE_UNUSED) { + typedef struct arch_stack_entry + { + const struct arch_stack_entry *prev; + const char *name; + char *sub_name; + i386_cpu_flags flags; + i386_cpu_flags isa_flags; + enum processor_type isa; + enum flag_code flag_code; + char stackop_size; + bool no_cond_jump_promotion; + } arch_stack_entry; + static const arch_stack_entry *arch_stack_top; + SKIP_WHITESPACE (); if (!is_end_of_line[(unsigned char) *input_line_pointer]) @@ -2703,6 +2717,67 @@ set_cpu_arch (int dummy ATTRIBUTE_UNUSED) j = ARRAY_SIZE (cpu_arch) + 1; } } + else if (strcmp (string, "push") == 0) + { + arch_stack_entry *top = XNEW (arch_stack_entry); + + top->name = cpu_arch_name; + if (cpu_sub_arch_name) + top->sub_name = xstrdup (cpu_sub_arch_name); + else + top->sub_name = NULL; + top->flags = cpu_arch_flags; + top->isa = cpu_arch_isa; + top->isa_flags = cpu_arch_isa_flags; + top->flag_code = flag_code; + top->stackop_size = stackop_size; + top->no_cond_jump_promotion = no_cond_jump_promotion; + + top->prev = arch_stack_top; + arch_stack_top = top; + + (void) restore_line_pointer (e); + demand_empty_rest_of_line (); + return; + } + else if (strcmp (string, "pop") == 0) + { + const arch_stack_entry *top = arch_stack_top; + + if (!top) + as_bad (_(".arch stack is empty")); + else if (top->flag_code != flag_code + || top->stackop_size != stackop_size) + { + static const unsigned int bits[] = { + [CODE_16BIT] = 16, + [CODE_32BIT] = 32, + [CODE_64BIT] = 64, + }; + + as_bad (_("this `.arch pop' requires `.code%u%s' to be in effect"), + bits[top->flag_code], + top->stackop_size == LONG_MNEM_SUFFIX ? "gcc" : ""); + } + else + { + arch_stack_top = top->prev; + + cpu_arch_name = top->name; + free (cpu_sub_arch_name); + cpu_sub_arch_name = top->sub_name; + cpu_arch_flags = top->flags; + cpu_arch_isa = top->isa; + cpu_arch_isa_flags = top->isa_flags; + no_cond_jump_promotion = top->no_cond_jump_promotion; + + XDELETE (top); + } + + (void) restore_line_pointer (e); + demand_empty_rest_of_line (); + return; + } for (; j < ARRAY_SIZE (cpu_arch); j++) { @@ -13660,6 +13735,10 @@ show_arch (FILE *stream, int ext, int check) { p = output_message (stream, p, message, start, &left, STRING_COMMA_LEN ("default")); + p = output_message (stream, p, message, start, &left, + STRING_COMMA_LEN ("push")); + p = output_message (stream, p, message, start, &left, + STRING_COMMA_LEN ("pop")); } for (j = 0; j < ARRAY_SIZE (cpu_arch); j++) diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi index 95fd8ec..c4a3967 100644 --- a/gas/doc/c-i386.texi +++ b/gas/doc/c-i386.texi @@ -1504,7 +1504,7 @@ directive enables a warning when gas detects an instruction that is not supported on the CPU specified. The choices for @var{cpu_type} are: @multitable @columnfractions .20 .20 .20 .20 -@item @samp{default} +@item @samp{default} @tab @samp{push} @tab @samp{pop} @item @samp{i8086} @tab @samp{i186} @tab @samp{i286} @tab @samp{i386} @item @samp{i486} @tab @samp{i586} @tab @samp{i686} @tab @samp{pentium} @item @samp{pentiumpro} @tab @samp{pentiumii} @tab @samp{pentiumiii} @tab @samp{pentium4} diff --git a/gas/testsuite/gas/i386/arch-stk.l b/gas/testsuite/gas/i386/arch-stk.l new file mode 100644 index 0000000..4b774cc --- /dev/null +++ b/gas/testsuite/gas/i386/arch-stk.l @@ -0,0 +1,43 @@ +.*: Assembler messages: +.*:3: Error:.*`cmovl'.* +.*:10: Error:.*`cmovg'.* +.*:17: Error:.*`cmovz'.* +.*:21: Error:.*`\.arch pop'.*`\.code32'.* +.*:28: Error:.*`\.arch pop'.*`\.code16gcc'.* +.*:32: Error:.*\.arch.*empty.* +GAS LISTING .* + + +[ ]*[0-9]*[ ]+\.text +[ ]*[0-9]*[ ]+start: +[ ]*[0-9]*[ ]+cmovl %eax, %ecx +[ ]*[0-9]*[ ]* +[ ]*[0-9]*[ ]+\.arch push +[ ]*[0-9]*[ ]+\.arch default +[ ]*[0-9]*[ ]+\?\?\?\? 0F4DC8[ ]+cmovnl %eax, %ecx +[ ]*[0-9]*[ ]* +[ ]*[0-9]*[ ]+\.arch pop +[ ]*[0-9]*[ ]+cmovg %eax, %ecx +[ ]*[0-9]*[ ]* +[ ]*[0-9]*[ ]+\.arch push +[ ]*[0-9]*[ ]+\.arch \.cmov +[ ]*[0-9]*[ ]+\?\?\?\? 0F4EC8[ ]+cmovng %eax, %ecx +[ ]*[0-9]*[ ]* +[ ]*[0-9]*[ ]+\.arch pop +[ ]*[0-9]*[ ]+cmovz %eax, %ecx +[ ]*[0-9]*[ ]* +[ ]*[0-9]*[ ]+\.arch push +[ ]*[0-9]*[ ]+\.code16 +[ ]*[0-9]*[ ]+\.arch pop +[ ]*[0-9]*[ ]+\.code32 +[ ]*[0-9]*[ ]+\.arch pop +[ ]*[0-9]*[ ]* +[ ]*[0-9]*[ ]+\.code16gcc +[ ]*[0-9]*[ ]+\.arch push +[ ]*[0-9]*[ ]+\.code32 +[ ]*[0-9]*[ ]+\.arch pop +[ ]*[0-9]*[ ]+\.code16gcc +[ ]*[0-9]*[ ]+\.arch pop +[ ]*[0-9]*[ ]* +[ ]*[0-9]*[ ]+\.arch pop +#pass diff --git a/gas/testsuite/gas/i386/arch-stk.s b/gas/testsuite/gas/i386/arch-stk.s new file mode 100644 index 0000000..3e7286d --- /dev/null +++ b/gas/testsuite/gas/i386/arch-stk.s @@ -0,0 +1,34 @@ + .text +start: + cmovl %eax, %ecx + + .arch push + .arch default + cmovnl %eax, %ecx + + .arch pop + cmovg %eax, %ecx + + .arch push + .arch .cmov + cmovng %eax, %ecx + + .arch pop + cmovz %eax, %ecx + + .arch push + .code16 + .arch pop + .code32 + .arch pop + + .code16gcc + .arch push + .code32 + .arch pop + .code16gcc + .arch pop + + .arch pop + + .end diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index de4eb1c..c7822c4 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -206,6 +206,7 @@ if [gas_32_check] then { run_dump_test "arch-13" run_dump_test "arch-14" run_list_test "arch-dflt" "-march=generic32 -al" + run_list_test "arch-stk" "-march=generic32 -al" run_dump_test "8087" run_dump_test "287" run_dump_test "387" |