X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-s390.c;h=35b4a5b397b65fdb374a36db7ae9565247a1fcc5;hb=b7379eaddab00dc4ba9c9b98d8f603b9560366a1;hp=66b54ea8adb7050996293ded85d8925caf73fc31;hpb=6f2750feaf2827ef8a1a0a5b2f90c1e9a6cabbd1;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c index 66b54ea8ad..35b4a5b397 100644 --- a/gas/config/tc-s390.c +++ b/gas/config/tc-s390.c @@ -1,5 +1,5 @@ /* tc-s390.c -- Assemble for the S390 - Copyright (C) 2000-2016 Free Software Foundation, Inc. + Copyright (C) 2000-2019 Free Software Foundation, Inc. Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). This file is part of GAS, the GNU Assembler. @@ -22,7 +22,6 @@ #include "as.h" #include "safe-ctype.h" #include "subsegs.h" -#include "struc-symbol.h" #include "dwarf2dbg.h" #include "dw2gencfi.h" @@ -33,7 +32,7 @@ #ifndef DEFAULT_ARCH #define DEFAULT_ARCH "s390" #endif -static char *default_arch = DEFAULT_ARCH; +static const char *default_arch = DEFAULT_ARCH; /* Either 32 or 64, selects file format. */ static int s390_arch_size = 0; @@ -41,8 +40,11 @@ static int s390_arch_size = 0; Since with S/390 a newer CPU always supports everything from its predecessors this will accept every valid asm input. */ static unsigned int current_cpu = S390_OPCODE_MAXCPU - 1; +/* All facilities are enabled by default. */ +static unsigned int current_flags = S390_INSTR_FLAG_FACILITY_MASK; +/* The mode mask default is picked in init_default_arch depending on + the current cpu. */ 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. */ @@ -262,27 +264,35 @@ s390_target_format (void) In case of an error, S390_OPCODE_MAXCPU is returned. */ static unsigned int -s390_parse_cpu (char * arg, +s390_parse_cpu (const char * arg, unsigned int * ret_flags, bfd_boolean allow_extensions) { static struct { const char * name; - unsigned int len; + unsigned int name_len; + const char * alt_name; + unsigned int alt_name_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 } + { STRING_COMMA_LEN ("g5"), STRING_COMMA_LEN ("arch3"), 0 }, + { STRING_COMMA_LEN ("g6"), STRING_COMMA_LEN (""), 0 }, + { STRING_COMMA_LEN ("z900"), STRING_COMMA_LEN ("arch5"), 0 }, + { STRING_COMMA_LEN ("z990"), STRING_COMMA_LEN ("arch6"), 0 }, + { STRING_COMMA_LEN ("z9-109"), STRING_COMMA_LEN (""), 0 }, + { STRING_COMMA_LEN ("z9-ec"), STRING_COMMA_LEN ("arch7"), 0 }, + { STRING_COMMA_LEN ("z10"), STRING_COMMA_LEN ("arch8"), 0 }, + { STRING_COMMA_LEN ("z196"), STRING_COMMA_LEN ("arch9"), 0 }, + { STRING_COMMA_LEN ("zEC12"), STRING_COMMA_LEN ("arch10"), + S390_INSTR_FLAG_HTM }, + { STRING_COMMA_LEN ("z13"), STRING_COMMA_LEN ("arch11"), + S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX }, + { STRING_COMMA_LEN ("z14"), STRING_COMMA_LEN ("arch12"), + S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX }, + { STRING_COMMA_LEN ("z15"), STRING_COMMA_LEN ("arch13"), + S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX } }; static struct { @@ -309,22 +319,36 @@ s390_parse_cpu (char * arg, { for (icpu = 0; icpu < S390_OPCODE_MAXCPU; icpu++) { - unsigned int l; + unsigned int l, l_alt; + + l = cpu_table[icpu].name_len; - l = cpu_table[icpu].len; if (strncmp (arg, cpu_table[icpu].name, l) == 0 && (arg[l] == 0 || arg[l] == '+')) { arg += l; break; } + + l_alt = cpu_table[icpu].alt_name_len; + + if (l_alt > 0 + && strncmp (arg, cpu_table[icpu].alt_name, l_alt) == 0 + && (arg[l_alt] == 0 || arg[l_alt] == '+')) + { + arg += l_alt; + break; + } } } + if (icpu == S390_OPCODE_MAXCPU) + return S390_OPCODE_MAXCPU; + ilp_bak = input_line_pointer; if (icpu != S390_OPCODE_MAXCPU) { - input_line_pointer = arg; + input_line_pointer = (char *) arg; *ret_flags = (cpu_table[icpu].flags & S390_INSTR_FLAG_FACILITY_MASK); while (*input_line_pointer == '+' && allow_extensions) @@ -368,7 +392,7 @@ s390_parse_cpu (char * arg, } int -md_parse_option (int c, char *arg) +md_parse_option (int c, const char *arg) { switch (c) { @@ -582,7 +606,7 @@ static void s390_insert_operand (unsigned char *insn, const struct s390_operand *operand, offsetT val, - char *file, + const char *file, unsigned int line) { addressT uval; @@ -705,7 +729,7 @@ s390_insert_operand (unsigned char *insn, struct map_tls { - char *string; + const char *string; int length; bfd_reloc_code_real_type reloc; }; @@ -780,7 +804,7 @@ elf_suffix_type; struct map_bfd { - char *string; + const char *string; int length; elf_suffix_type suffix; }; @@ -908,6 +932,7 @@ s390_exp_compare (expressionS *exp1, expressionS *exp2) case O_big: as_bad (_("Can't handle O_big in s390_exp_compare")); + return 0; case O_symbol: /* X_add_symbol & X_add_number must be equal. */ case O_symbol_rva: @@ -944,7 +969,7 @@ s390_exp_compare (expressionS *exp1, expressionS *exp2) } } -/* Test for @lit and if its present make an entry in the literal pool and +/* Test for @lit and if it's present make an entry in the literal pool and modify the current expression to be an offset into the literal pool. */ static elf_suffix_type s390_lit_suffix (char **str_p, expressionS *exp_p, elf_suffix_type suffix) @@ -1032,7 +1057,7 @@ s390_lit_suffix (char **str_p, expressionS *exp_p, elf_suffix_type suffix) } else { - lpe = (struct s390_lpe *) xmalloc (sizeof (struct s390_lpe)); + lpe = XNEW (struct s390_lpe); } lpe->ex = *exp_p; @@ -1074,7 +1099,7 @@ s390_lit_suffix (char **str_p, expressionS *exp_p, elf_suffix_type suffix) } /* Now change exp_p to the offset into the literal pool. - Thats the expression: .L^Ax^By-.L^Ax */ + That's the expression: .L^Ax^By-.L^Ax */ exp_p->X_add_symbol = lpe->sym; exp_p->X_op_symbol = lp_sym; exp_p->X_op = O_subtract; @@ -1182,7 +1207,9 @@ s390_elf_cons (int nbytes /* 1=.byte, 2=.word, 4=.long */) { size = bfd_get_reloc_size (reloc_howto); if (size > nbytes) - as_bad (_("%s relocations do not fit in %d bytes"), + as_bad (ngettext ("%s relocations do not fit in %d byte", + "%s relocations do not fit in %d bytes", + nbytes), reloc_howto->name, nbytes); where = frag_more (nbytes); md_number_to_chars (where, 0, size); @@ -1203,6 +1230,24 @@ s390_elf_cons (int nbytes /* 1=.byte, 2=.word, 4=.long */) demand_empty_rest_of_line (); } +/* Return true if all remaining operands in the opcode with + OPCODE_FLAGS can be skipped. */ +static bfd_boolean +skip_optargs_p (unsigned int opcode_flags, const unsigned char *opindex_ptr) +{ + if ((opcode_flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2)) + && opindex_ptr[0] != '\0' + && opindex_ptr[1] == '\0') + return TRUE; + + if ((opcode_flags & S390_INSTR_FLAG_OPTPARM2) + && opindex_ptr[0] != '\0' + && opindex_ptr[1] != '\0' + && opindex_ptr[2] == '\0') + return TRUE; + return FALSE; +} + /* We need to keep a list of fixups. We can't simply generate them as we go, because that would require us to first create the frag, and that would screw up references to ``.''. */ @@ -1246,7 +1291,8 @@ md_gather_operands (char *str, operand = s390_operands + *opindex_ptr; - if ((opcode->flags & S390_INSTR_FLAG_OPTPARM) && *str == '\0') + if ((opcode->flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2)) + && *str == '\0') { /* Optional parameters might need to be ORed with a value so calling s390_insert_operand is needed. */ @@ -1280,19 +1326,6 @@ md_gather_operands (char *str, as_bad (_("illegal operand")); else if (ex.X_op == O_absent) { - /* No operands, check if all operands can be skipped. */ - while (*opindex_ptr != 0 && operand->flags & S390_OPERAND_OPTIONAL) - { - if (operand->flags & S390_OPERAND_DISP) - { - /* An optional displacement makes the whole D(X,B) - D(L,B) or D(B) block optional. */ - do { - operand = s390_operands + *(++opindex_ptr); - } while (!(operand->flags & S390_OPERAND_BASE)); - } - operand = s390_operands + *(++opindex_ptr); - } if (opindex_ptr[0] == '\0') break; as_bad (_("missing operand")); @@ -1444,7 +1477,7 @@ md_gather_operands (char *str, if (*str != '(') { /* Check if parenthesized block can be skipped. If the next - operand is neiter an optional operand nor a base register + operand is neither an optional operand nor a base register then we have a syntax error. */ operand = s390_operands + *(++opindex_ptr); if (!(operand->flags & (S390_OPERAND_INDEX|S390_OPERAND_BASE))) @@ -1454,6 +1487,9 @@ md_gather_operands (char *str, while (!(operand->flags & S390_OPERAND_BASE)) operand = s390_operands + *(++opindex_ptr); + if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1])) + continue; + /* If there is a next operand it must be separated by a comma. */ if (opindex_ptr[1] != '\0') { @@ -1462,9 +1498,7 @@ md_gather_operands (char *str, while (opindex_ptr[1] != '\0') { operand = s390_operands + *(++opindex_ptr); - if (operand->flags & S390_OPERAND_OPTIONAL) - continue; - as_bad (_("syntax error; expected ,")); + as_bad (_("syntax error; expected ','")); break; } } @@ -1494,10 +1528,14 @@ md_gather_operands (char *str, } else if (operand->flags & S390_OPERAND_BASE) { - /* After the base register the parenthesed block ends. */ + /* After the base register the parenthesised block ends. */ if (*str++ != ')') as_bad (_("syntax error; missing ')' after base register")); skip_optional = 0; + + if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1])) + continue; + /* If there is a next operand it must be separated by a comma. */ if (opindex_ptr[1] != '\0') { @@ -1506,9 +1544,7 @@ md_gather_operands (char *str, while (opindex_ptr[1] != '\0') { operand = s390_operands + *(++opindex_ptr); - if (operand->flags & S390_OPERAND_OPTIONAL) - continue; - as_bad (_("syntax error; expected ,")); + as_bad (_("syntax error; expected ','")); break; } } @@ -1529,7 +1565,7 @@ md_gather_operands (char *str, str++; } - if ((opcode->flags & S390_INSTR_FLAG_OPTPARM) && *str == '\0') + if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1])) continue; /* If there is a next operand it must be separated by a comma. */ @@ -1540,9 +1576,7 @@ md_gather_operands (char *str, while (opindex_ptr[1] != '\0') { operand = s390_operands + *(++opindex_ptr); - if (operand->flags & S390_OPERAND_OPTIONAL) - continue; - as_bad (_("syntax error; expected ,")); + as_bad (_("syntax error; expected ','")); break; } } @@ -1630,6 +1664,9 @@ md_gather_operands (char *str, || fixups[i].reloc == BFD_RELOC_390_GOT20 || fixups[i].reloc == BFD_RELOC_390_GOT16) fixP->fx_no_overflow = 1; + + if (operand->flags & S390_OPERAND_PCREL) + fixP->fx_pcrel_adjust = operand->shift / 8; } else fix_new_exp (frag_now, f - frag_now->fr_literal, 4, &fixups[i].exp, @@ -1821,7 +1858,7 @@ s390_literals (int ignore ATTRIBUTE_UNUSED) /* Emit symbol for start of literal pool. */ S_SET_SEGMENT (lp_sym, now_seg); S_SET_VALUE (lp_sym, (valueT) frag_now_fix ()); - lp_sym->sy_frag = frag_now; + symbol_set_frag (lp_sym, frag_now); while (lpe_list) { @@ -1829,7 +1866,7 @@ s390_literals (int ignore ATTRIBUTE_UNUSED) lpe_list = lpe_list->next; S_SET_SEGMENT (lpe->sym, now_seg); S_SET_VALUE (lpe->sym, (valueT) frag_now_fix ()); - lpe->sym->sy_frag = frag_now; + symbol_set_frag (lpe->sym, frag_now); /* Emit literal pool entry. */ if (lpe->reloc != BFD_RELOC_UNUSED) @@ -1840,7 +1877,9 @@ s390_literals (int ignore ATTRIBUTE_UNUSED) char *where; if (size > lpe->nbytes) - as_bad (_("%s relocations do not fit in %d bytes"), + as_bad (ngettext ("%s relocations do not fit in %d byte", + "%s relocations do not fit in %d bytes", + lpe->nbytes), reloc_howto->name, lpe->nbytes); where = frag_more (lpe->nbytes); md_number_to_chars (where, 0, size); @@ -1879,7 +1918,7 @@ static void s390_machine (int ignore ATTRIBUTE_UNUSED) { char *cpu_string; - static struct + static struct cpu_history { unsigned int cpu; unsigned int flags; @@ -1923,7 +1962,7 @@ s390_machine (int ignore ATTRIBUTE_UNUSED) if (strcmp (cpu_string, "push") == 0) { if (cpu_history == NULL) - cpu_history = xmalloc (MAX_HISTORY * sizeof (*cpu_history)); + cpu_history = XNEWVEC (struct cpu_history, MAX_HISTORY); if (curr_hist >= MAX_HISTORY) as_bad (_(".machine stack overflow")); @@ -1995,7 +2034,7 @@ s390_machinemode (int ignore ATTRIBUTE_UNUSED) if (strcmp (mode_string, "push") == 0) { if (mode_history == NULL) - mode_history = xmalloc (MAX_HISTORY * sizeof (*mode_history)); + mode_history = XNEWVEC (unsigned int, MAX_HISTORY); if (curr_hist >= MAX_HISTORY) as_bad (_(".machinemode stack overflow")); @@ -2034,7 +2073,7 @@ s390_machinemode (int ignore ATTRIBUTE_UNUSED) #undef MAX_HISTORY -char * +const char * md_atof (int type, char *litp, int *sizep) { return ieee_md_atof (type, litp, sizep, TRUE); @@ -2045,7 +2084,7 @@ md_atof (int type, char *litp, int *sizep) valueT md_section_align (asection *seg, valueT addr) { - int align = bfd_get_section_alignment (stdoutput, seg); + int align = bfd_section_alignment (seg); return ((addr + (1 << align) - 1) & -(1 << align)); } @@ -2106,9 +2145,11 @@ md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED) int tc_s390_fix_adjustable (fixS *fixP) { - /* Don't adjust references to merge sections. */ - if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0) + /* Don't adjust pc-relative references to merge sections. */ + if (fixP->fx_pcrel + && (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0) return 0; + /* adjust_reloc_syms doesn't know about the GOT. */ if ( fixP->fx_r_type == BFD_RELOC_16_GOTOFF || fixP->fx_r_type == BFD_RELOC_32_GOTOFF @@ -2268,7 +2309,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) } else if (operand->bits == 20 && operand->shift == 20) { - fixP->fx_size = 2; + fixP->fx_size = 4; fixP->fx_where += 2; fixP->fx_r_type = BFD_RELOC_390_20; } @@ -2284,6 +2325,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_size = 2; fixP->fx_where += 1; fixP->fx_offset += 1; + fixP->fx_pcrel_adjust = 1; fixP->fx_r_type = BFD_RELOC_390_PC12DBL; } else if (operand->bits == 16 && operand->shift == 16) @@ -2294,16 +2336,27 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { fixP->fx_r_type = BFD_RELOC_390_PC16DBL; fixP->fx_offset += 2; + fixP->fx_pcrel_adjust = 2; } else fixP->fx_r_type = BFD_RELOC_16; } + else if (operand->bits == 16 && operand->shift == 32 + && (operand->flags & S390_OPERAND_PCREL)) + { + fixP->fx_size = 2; + fixP->fx_where += 4; + fixP->fx_offset += 4; + fixP->fx_pcrel_adjust = 4; + fixP->fx_r_type = BFD_RELOC_390_PC16DBL; + } else if (operand->bits == 24 && operand->shift == 24 && (operand->flags & S390_OPERAND_PCREL)) { fixP->fx_size = 3; fixP->fx_where += 3; fixP->fx_offset += 3; + fixP->fx_pcrel_adjust = 3; fixP->fx_r_type = BFD_RELOC_390_PC24DBL; } else if (operand->bits == 32 && operand->shift == 16 @@ -2312,11 +2365,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_size = 4; fixP->fx_where += 2; fixP->fx_offset += 2; + fixP->fx_pcrel_adjust = 2; fixP->fx_r_type = BFD_RELOC_390_PC32DBL; } else { - char *sfile; + const char *sfile; unsigned int sline; /* Use expr_symbol_where to see if this is an expression @@ -2347,7 +2401,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_390_PC12DBL: case BFD_RELOC_390_PLT12DBL: if (fixP->fx_pcrel) - value++; + value += fixP->fx_pcrel_adjust; if (fixP->fx_done) { @@ -2398,14 +2452,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) break; case BFD_RELOC_390_PC16DBL: case BFD_RELOC_390_PLT16DBL: - value += 2; + value += fixP->fx_pcrel_adjust; if (fixP->fx_done) md_number_to_chars (where, (offsetT) value >> 1, 2); break; case BFD_RELOC_390_PC24DBL: case BFD_RELOC_390_PLT24DBL: - value += 3; + value += fixP->fx_pcrel_adjust; if (fixP->fx_done) { unsigned int mop; @@ -2443,7 +2497,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_390_GOTPCDBL: case BFD_RELOC_390_GOTENT: case BFD_RELOC_390_GOTPLTENT: - value += 2; + value += fixP->fx_pcrel_adjust; if (fixP->fx_done) md_number_to_chars (where, (offsetT) value >> 1, 4); break; @@ -2548,8 +2602,8 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) code = BFD_RELOC_390_GOTPCDBL; } - reloc = (arelent *) xmalloc (sizeof (arelent)); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + reloc = XNEW (arelent); + reloc->sym_ptr_ptr = XNEW (asymbol *); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; reloc->howto = bfd_reloc_type_lookup (stdoutput, code);