diff options
author | Dominik Vogt <vogt@linux.vnet.ibm.com> | 2015-09-29 13:22:07 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-09-29 13:22:07 +0100 |
commit | 7ecc513a44095d614f10e89c67d9be5826abacf9 (patch) | |
tree | 150a49774f29ce8a95989942d9780c3edc10bf17 /gas | |
parent | 56e6cf80bd4be6dc95ed9b84b633e3c11ae8c86b (diff) | |
download | gdb-7ecc513a44095d614f10e89c67d9be5826abacf9.zip gdb-7ecc513a44095d614f10e89c67d9be5826abacf9.tar.gz gdb-7ecc513a44095d614f10e89c67d9be5826abacf9.tar.bz2 |
Add support for extensions in the .machine pseudoop on S/390, e.g. ".machine zEC12+nohtm+vx"
gas * doc/c-s390.texi: Add documentation.
Add missing code markup.
* config/tc-s390.c (current_flags): New static variable.
(s390_parse_cpu): Parse cpu flags a la "+nohtm" etc.
(s390_setup_opcodes): Use cpu flags to determine the set of opcodes.
Fix indentation.
(md_parse_option): Call s390_parse_cpu with the new signature.
(s390_machine): Likewise.
Keep track of current_flags.
Simplify code a bit.
undefine MAX_HISTORY at end of function.
(s390_machinemode): undefine MAX_HISTORY at end of function.
Update an error message.
tests * gas/s390/s390.exp: Add new tests.
* gas/s390/machine-parsing-1.s: New test file.
* gas/s390/machine-parsing-1.l: Likewise.
* gas/s390/machine-parsing-2.s: Likewise.
* gas/s390/machine-parsing-2.l: Likewise.
* gas/s390/machine-parsing-3.s: Likewise.
* gas/s390/machine-parsing-3.l: Likewise.
* gas/s390/machine-parsing-4.s: Likewise.
* gas/s390/machine-parsing-4.l: Likewise.
* gas/s390/machine-parsing-5.s: Likewise.
* gas/s390/machine-parsing-5.l: Likewise.
* gas/s390/machine-parsing-6.s: Likewise.
* gas/s390/machine-parsing-6.l: Likewise.
opcode * s390.h (S390_INSTR_FLAG_HTM): New flag.
(S390_INSTR_FLAG_VX): New flag.
(S390_INSTR_FLAG_FACILITY_MASK): New flag mask.
opcodes * s390-mkopc.c (main): Parse htm and vx flag.
* s390-opc.txt: Mark instructions from the hardware transactional
memory and vector facilities with the "htm"/"vx" flag.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 16 | ||||
-rw-r--r-- | gas/config/tc-s390.c | 221 | ||||
-rw-r--r-- | gas/doc/c-s390.texi | 30 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 16 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-1.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-1.s | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-2.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-2.s | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-3.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-3.s | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-4.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-4.s | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-5.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-5.s | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-6.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/machine-parsing-6.s | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/s390/s390.exp | 6 |
17 files changed, 267 insertions, 54 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index af99b96..5420973 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,19 @@ +2015-09-29 Dominik Vogt <vogt@linux.vnet.ibm.com> + + * doc/c-s390.texi: Add documentation. + Add missing code markup. + * config/tc-s390.c (current_flags): New static variable. + (s390_parse_cpu): Parse cpu flags a la "+nohtm" etc. + (s390_setup_opcodes): Use cpu flags to determine the set of opcodes. + Fix indentation. + (md_parse_option): Call s390_parse_cpu with the new signature. + (s390_machine): Likewise. + Keep track of current_flags. + Simplify code a bit. + undefine MAX_HISTORY at end of function. + (s390_machinemode): undefine MAX_HISTORY at end of function. + Update an error message. + 2015-08-11 Peter Zotov <whitequark@whitequark.org> PR ld/18759 diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c index 8d459b6..e217e56 100644 --- a/gas/config/tc-s390.c +++ b/gas/config/tc-s390.c @@ -42,6 +42,7 @@ static int s390_arch_size = 0; predecessors this will accept every valid asm input. */ static unsigned int current_cpu = S390_OPCODE_MAXCPU - 1; static unsigned int current_mode_mask = 0; +static unsigned int current_flags = 0; /* Set to TRUE if the highgprs flag in the ELF header needs to be set for the output file. */ @@ -254,37 +255,116 @@ s390_target_format (void) return s390_arch_size == 64 ? "elf64-s390" : "elf32-s390"; } -/* Map a CPU string as given with -march= or .machine to the - respective enum s390_opcode_cpu_val value. 0xffffffff is returned - in case of an error. */ +/* Map a cpu string ARG as given with -march= or .machine to the respective + enum s390_opcode_cpu_val value. If ALLOW_EXTENSIONS is TRUE, the cpu name + can be followed by a list of cpu facility flags each beginning with the + character '+'. The active cpu flags are returned through *RET_FLAGS. + In case of an error, S390_OPCODE_MAXCPU is returned. */ static unsigned int -s390_parse_cpu (char *arg) +s390_parse_cpu (char * arg, + unsigned int * ret_flags, + bfd_boolean allow_extensions) { - if (strcmp (arg, "g5") == 0) - return S390_OPCODE_G5; - else if (strcmp (arg, "g6") == 0) - return S390_OPCODE_G6; - else if (strcmp (arg, "z900") == 0) - return S390_OPCODE_Z900; - else if (strcmp (arg, "z990") == 0) - return S390_OPCODE_Z990; - else if (strcmp (arg, "z9-109") == 0) - return S390_OPCODE_Z9_109; - else if (strcmp (arg, "z9-ec") == 0) - return S390_OPCODE_Z9_EC; - else if (strcmp (arg, "z10") == 0) - return S390_OPCODE_Z10; - else if (strcmp (arg, "z196") == 0) - return S390_OPCODE_Z196; - else if (strcmp (arg, "zEC12") == 0) - return S390_OPCODE_ZEC12; - else if (strcmp (arg, "z13") == 0) - return S390_OPCODE_Z13; - else if (strcmp (arg, "all") == 0) - return S390_OPCODE_MAXCPU - 1; + static struct + { + const char * name; + unsigned int len; + unsigned int flags; + } cpu_table[S390_OPCODE_MAXCPU] = + { + { STRING_COMMA_LEN ("g5"), 0 }, + { STRING_COMMA_LEN ("g6"), 0 }, + { STRING_COMMA_LEN ("z900"), 0 }, + { STRING_COMMA_LEN ("z990"), 0 }, + { STRING_COMMA_LEN ("z9-109"), 0 }, + { STRING_COMMA_LEN ("z9-ec"), 0 }, + { STRING_COMMA_LEN ("z10"), 0 }, + { STRING_COMMA_LEN ("z196"), 0 }, + { STRING_COMMA_LEN ("zEC12"), S390_INSTR_FLAG_HTM }, + { STRING_COMMA_LEN ("z13"), S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX } + }; + static struct + { + const char * name; + unsigned int mask; + bfd_boolean on; + } cpu_flags[] = + { + { "htm", S390_INSTR_FLAG_HTM, TRUE }, + { "nohtm", S390_INSTR_FLAG_HTM, FALSE }, + { "vx", S390_INSTR_FLAG_VX, TRUE }, + { "novx", S390_INSTR_FLAG_VX, FALSE } + }; + unsigned int icpu; + char *ilp_bak; + + icpu = S390_OPCODE_MAXCPU; + if (strncmp (arg, "all", 3) == 0 && (arg[3] == 0 || arg[3] == '+')) + { + icpu = S390_OPCODE_MAXCPU - 1; + arg += 3; + } else - return -1; + { + for (icpu = 0; icpu < S390_OPCODE_MAXCPU; icpu++) + { + unsigned int l; + + l = cpu_table[icpu].len; + if (strncmp (arg, cpu_table[icpu].name, l) == 0 + && (arg[l] == 0 || arg[l] == '+')) + { + arg += l; + break; + } + } + } + + ilp_bak = input_line_pointer; + if (icpu != S390_OPCODE_MAXCPU) + { + input_line_pointer = arg; + *ret_flags = (cpu_table[icpu].flags & S390_INSTR_FLAG_FACILITY_MASK); + + while (*input_line_pointer == '+' && allow_extensions) + { + unsigned int iflag; + char *sym; + char c; + + input_line_pointer++; + c = get_symbol_name (&sym); + for (iflag = 0; iflag < ARRAY_SIZE (cpu_flags); iflag++) + { + if (strcmp (sym, cpu_flags[iflag].name) == 0) + { + if (cpu_flags[iflag].on) + *ret_flags |= cpu_flags[iflag].mask; + else + *ret_flags &= ~cpu_flags[iflag].mask; + break; + } + } + if (iflag == ARRAY_SIZE (cpu_flags)) + as_bad (_("no such machine extension `%s'"), sym - 1); + *input_line_pointer = c; + if (iflag == ARRAY_SIZE (cpu_flags)) + break; + } + } + + SKIP_WHITESPACE (); + + if (*input_line_pointer != 0 && *input_line_pointer != '\n') + { + as_bad (_("junk at end of machine string, first unrecognized character" + " is `%c'"), *input_line_pointer); + icpu = S390_OPCODE_MAXCPU; + } + input_line_pointer = ilp_bak; + + return icpu; } int @@ -323,9 +403,8 @@ md_parse_option (int c, char *arg) else if (arg != NULL && strncmp (arg, "arch=", 5) == 0) { - current_cpu = s390_parse_cpu (arg + 5); - - if (current_cpu == (unsigned int)-1) + current_cpu = s390_parse_cpu (arg + 5, ¤t_flags, FALSE); + if (current_cpu == S390_OPCODE_MAXCPU) { as_bad (_("invalid switch -m%s"), arg); return 0; @@ -402,6 +481,8 @@ s390_setup_opcodes (void) op_end = s390_opcodes + s390_num_opcodes; for (op = s390_opcodes; op < op_end; op++) { + int use_opcode; + while (op < op_end - 1 && strcmp(op->name, op[1].name) == 0) { if (op->min_cpu <= current_cpu && (op->modes & current_mode_mask)) @@ -409,7 +490,24 @@ s390_setup_opcodes (void) op++; } - if (op->min_cpu <= current_cpu && (op->modes & current_mode_mask)) + if ((op->modes & current_mode_mask) == 0) + use_opcode = 0; + else if ((op->flags & S390_INSTR_FLAG_FACILITY_MASK) == 0) + { + /* Opcodes that do not belong to a specific facility are enabled if + present in the selected cpu. */ + use_opcode = (op->min_cpu <= current_cpu); + } + else + { + unsigned int f; + + /* Opcodes of a specific facility are enabled if the facility is + enabled. Note: only some facilities are represented as flags. */ + f = (op->flags & S390_INSTR_FLAG_FACILITY_MASK); + use_opcode = ((f & current_flags) == f); + } + if (use_opcode) { retval = hash_insert (s390_opcode_hash, op->name, (void *) op); if (retval != (const char *) NULL) @@ -422,7 +520,7 @@ s390_setup_opcodes (void) while (op < op_end - 1 && strcmp (op->name, op[1].name) == 0) op++; - } + } if (dup_insn) abort (); @@ -1771,6 +1869,8 @@ s390_literals (int ignore ATTRIBUTE_UNUSED) lpe_count = 0; } +#define MAX_HISTORY 100 + /* The .machine pseudo op allows to switch to a different CPU level in the asm listing. The current CPU setting can be stored on a stack with .machine push and restored with .machine pop. */ @@ -1779,8 +1879,11 @@ static void s390_machine (int ignore ATTRIBUTE_UNUSED) { char *cpu_string; -#define MAX_HISTORY 100 - static unsigned int *cpu_history; + static struct + { + unsigned int cpu; + unsigned int flags; + } *cpu_history; static int curr_hist; SKIP_WHITESPACE (); @@ -1793,15 +1896,29 @@ s390_machine (int ignore ATTRIBUTE_UNUSED) else { char c; - c = get_symbol_name (&cpu_string); + + cpu_string = input_line_pointer; + do + { + char * str; + + c = get_symbol_name (&str); + c = restore_line_pointer (c); + if (c == '+') + ++ input_line_pointer; + } + while (c == '+'); + + c = *input_line_pointer; + *input_line_pointer = 0; cpu_string = xstrdup (cpu_string); (void) restore_line_pointer (c); } if (cpu_string != NULL) { - unsigned int old_cpu = current_cpu; - unsigned int new_cpu; + unsigned int new_cpu = current_cpu; + unsigned int new_flags = current_flags; if (strcmp (cpu_string, "push") == 0) { @@ -1811,22 +1928,35 @@ s390_machine (int ignore ATTRIBUTE_UNUSED) if (curr_hist >= MAX_HISTORY) as_bad (_(".machine stack overflow")); else - cpu_history[curr_hist++] = current_cpu; + { + cpu_history[curr_hist].cpu = current_cpu; + cpu_history[curr_hist].flags = current_flags; + curr_hist++; + } } else if (strcmp (cpu_string, "pop") == 0) { if (curr_hist <= 0) as_bad (_(".machine stack underflow")); else - current_cpu = cpu_history[--curr_hist]; + { + curr_hist--; + new_cpu = cpu_history[curr_hist].cpu; + new_flags = cpu_history[curr_hist].flags; + } } - else if ((new_cpu = s390_parse_cpu (cpu_string)) != (unsigned int)-1) - current_cpu = new_cpu; else + new_cpu = s390_parse_cpu (cpu_string, &new_flags, TRUE); + + if (new_cpu == S390_OPCODE_MAXCPU) as_bad (_("invalid machine `%s'"), cpu_string); - if (current_cpu != old_cpu) - s390_setup_opcodes (); + if (new_cpu != current_cpu || new_flags != current_flags) + { + current_cpu = new_cpu; + current_flags = new_flags; + s390_setup_opcodes (); + } } demand_empty_rest_of_line (); @@ -1841,7 +1971,6 @@ static void s390_machinemode (int ignore ATTRIBUTE_UNUSED) { char *mode_string; -#define MAX_HISTORY 100 static unsigned int *mode_history; static int curr_hist; @@ -1893,7 +2022,7 @@ s390_machinemode (int ignore ATTRIBUTE_UNUSED) else if (strcmp (mode_string, "zarch_nohighgprs") == 0) current_mode_mask = 1 << S390_OPCODE_ZARCH; else - as_bad (_("invalid machine `%s'"), mode_string); + as_bad (_("invalid machine mode `%s'"), mode_string); } if (current_mode_mask != old_mode_mask) @@ -1903,6 +2032,8 @@ s390_machinemode (int ignore ATTRIBUTE_UNUSED) demand_empty_rest_of_line (); } +#undef MAX_HISTORY + char * md_atof (int type, char *litp, int *sizep) { diff --git a/gas/doc/c-s390.texi b/gas/doc/c-s390.texi index ec36188..5a6e3a7 100644 --- a/gas/doc/c-s390.texi +++ b/gas/doc/c-s390.texi @@ -865,15 +865,27 @@ This directive causes the current contents of the literal pool to be dumped to the current location (@ref{s390 Literal Pool Entries}). @cindex @code{.machine} directive, s390 -@item .machine string -This directive allows you to change the machine for which code is -generated. @code{string} may be any of the @code{-march=} selection -options (without the -march=), @code{push}, or @code{pop}. -@code{.machine push} saves the currently selected cpu, which may be -restored with @code{.machine pop}. Be aware that the cpu string has -to be put into double quotes in case it contains characters not -appropriate for identifiers. So you have to write @code{"z9-109"} -instead of just @code{z9-109}. +@item .machine @var{STRING}[+@var{EXTENSION}]@dots{} + +This directive allows changing the machine for which code is +generated. @code{string} may be any of the @code{-march=} +selection options, or @code{push}, or @code{pop}. @code{.machine +push} saves the currently selected cpu, which may be restored with +@code{.machine pop}. Be aware that the cpu string has to be put +into double quotes in case it contains characters not appropriate +for identifiers. So you have to write @code{"z9-109"} instead of +just @code{z9-109}. Extensions can be specified after the cpu +name, separated by plus charaters. Valid extensions are: +@code{htm}, +@code{nohtm}, +@code{vx}, +@code{novx}. +They extend the basic instruction set with features from a higher +cpu level, or remove support for a feature from the given cpu +level. + +Example: @code{z13+nohtm} allows all instructions of the z13 cpu +except instructions from the HTM facility. @cindex @code{.machinemode} directive, s390 @item .machinemode string diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index c770a29..555f3f4 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2015-09-29 Dominik Vogt <vogt@linux.vnet.ibm.com> + + * gas/s390/s390.exp: Add new tests. + * gas/s390/machine-parsing-1.s: New test file. + * gas/s390/machine-parsing-1.l: Likewise. + * gas/s390/machine-parsing-2.s: Likewise. + * gas/s390/machine-parsing-2.l: Likewise. + * gas/s390/machine-parsing-3.s: Likewise. + * gas/s390/machine-parsing-3.l: Likewise. + * gas/s390/machine-parsing-4.s: Likewise. + * gas/s390/machine-parsing-4.l: Likewise. + * gas/s390/machine-parsing-5.s: Likewise. + * gas/s390/machine-parsing-5.l: Likewise. + * gas/s390/machine-parsing-6.s: Likewise. + * gas/s390/machine-parsing-6.l: Likewise. + 2015-09-28 Tom Rix <tom@bumblecow.com> * gas/ppc/e500-ill.s: New testcase for illegal ppc e500 ops. diff --git a/gas/testsuite/gas/s390/machine-parsing-1.l b/gas/testsuite/gas/s390/machine-parsing-1.l new file mode 100644 index 0000000..1a83ec8 --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-1.l @@ -0,0 +1,2 @@ +.*: Assembler messages: +.*:5: Error: invalid machine .foo.* diff --git a/gas/testsuite/gas/s390/machine-parsing-1.s b/gas/testsuite/gas/s390/machine-parsing-1.s new file mode 100644 index 0000000..ea402bc --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-1.s @@ -0,0 +1,5 @@ +.text +foo: + .machine z13 + .machine z13+vx+novx+htm+nohtm+vx+novx+htm+nohtm + .machine foo diff --git a/gas/testsuite/gas/s390/machine-parsing-2.l b/gas/testsuite/gas/s390/machine-parsing-2.l new file mode 100644 index 0000000..36c8518 --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-2.l @@ -0,0 +1,2 @@ +.*: Assembler messages: +.*:3: Error: junk at end of line, first unrecognized character is .[!].* diff --git a/gas/testsuite/gas/s390/machine-parsing-2.s b/gas/testsuite/gas/s390/machine-parsing-2.s new file mode 100644 index 0000000..8d3202d --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-2.s @@ -0,0 +1,3 @@ +.text +foo: + .machine z13! diff --git a/gas/testsuite/gas/s390/machine-parsing-3.l b/gas/testsuite/gas/s390/machine-parsing-3.l new file mode 100644 index 0000000..d92a58a --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-3.l @@ -0,0 +1,2 @@ +.*: Assembler messages: +.*:3: Error: no such machine extension .[+].* diff --git a/gas/testsuite/gas/s390/machine-parsing-3.s b/gas/testsuite/gas/s390/machine-parsing-3.s new file mode 100644 index 0000000..a8f7446 --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-3.s @@ -0,0 +1,3 @@ +.text +foo: + .machine z13+ diff --git a/gas/testsuite/gas/s390/machine-parsing-4.l b/gas/testsuite/gas/s390/machine-parsing-4.l new file mode 100644 index 0000000..a23a969 --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-4.l @@ -0,0 +1,2 @@ +.*: Assembler messages: +.*:3: Error: no such machine extension .[+]foo.* diff --git a/gas/testsuite/gas/s390/machine-parsing-4.s b/gas/testsuite/gas/s390/machine-parsing-4.s new file mode 100644 index 0000000..c712f45 --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-4.s @@ -0,0 +1,3 @@ +.text +foo: + .machine z13+foo diff --git a/gas/testsuite/gas/s390/machine-parsing-5.l b/gas/testsuite/gas/s390/machine-parsing-5.l new file mode 100644 index 0000000..36c8518 --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-5.l @@ -0,0 +1,2 @@ +.*: Assembler messages: +.*:3: Error: junk at end of line, first unrecognized character is .[!].* diff --git a/gas/testsuite/gas/s390/machine-parsing-5.s b/gas/testsuite/gas/s390/machine-parsing-5.s new file mode 100644 index 0000000..fa93df3 --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-5.s @@ -0,0 +1,3 @@ +.text +foo: + .machine z13+vx! diff --git a/gas/testsuite/gas/s390/machine-parsing-6.l b/gas/testsuite/gas/s390/machine-parsing-6.l new file mode 100644 index 0000000..d92a58a --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-6.l @@ -0,0 +1,2 @@ +.*: Assembler messages: +.*:3: Error: no such machine extension .[+].* diff --git a/gas/testsuite/gas/s390/machine-parsing-6.s b/gas/testsuite/gas/s390/machine-parsing-6.s new file mode 100644 index 0000000..511e81e --- /dev/null +++ b/gas/testsuite/gas/s390/machine-parsing-6.s @@ -0,0 +1,3 @@ +.text +foo: + .machine z13+vx+ diff --git a/gas/testsuite/gas/s390/s390.exp b/gas/testsuite/gas/s390/s390.exp index 734e86c..bd9dd7d 100644 --- a/gas/testsuite/gas/s390/s390.exp +++ b/gas/testsuite/gas/s390/s390.exp @@ -31,4 +31,10 @@ if [expr [istarget "s390-*-*"] || [istarget "s390x-*-*"]] then { run_dump_test "zarch-reloc" "{as -m64}" run_dump_test "zarch-operands" "{as -m64} {as -march=z9-109}" run_dump_test "zarch-machine" "{as -m64} {as -march=z900}" + run_list_test "machine-parsing-1" "" + run_list_test "machine-parsing-2" "" + run_list_test "machine-parsing-3" "" + run_list_test "machine-parsing-4" "" + run_list_test "machine-parsing-5" "" + run_list_test "machine-parsing-6" "" } |