1440a403fSchristos /* tc-s390.c -- Assemble for the S390
2*b88e3e88Schristos    Copyright (C) 2000-2020 Free Software Foundation, Inc.
3440a403fSchristos    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
4440a403fSchristos 
5440a403fSchristos    This file is part of GAS, the GNU Assembler.
6440a403fSchristos 
7440a403fSchristos    GAS is free software; you can redistribute it and/or modify
8440a403fSchristos    it under the terms of the GNU General Public License as published by
9440a403fSchristos    the Free Software Foundation; either version 3, or (at your option)
10440a403fSchristos    any later version.
11440a403fSchristos 
12440a403fSchristos    GAS is distributed in the hope that it will be useful,
13440a403fSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14440a403fSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15440a403fSchristos    GNU General Public License for more details.
16440a403fSchristos 
17440a403fSchristos    You should have received a copy of the GNU General Public License
18440a403fSchristos    along with GAS; see the file COPYING.  If not, write to the Free
19440a403fSchristos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20440a403fSchristos    02110-1301, USA.  */
21440a403fSchristos 
22440a403fSchristos #include "as.h"
23440a403fSchristos #include "safe-ctype.h"
24440a403fSchristos #include "subsegs.h"
25440a403fSchristos #include "dwarf2dbg.h"
26440a403fSchristos #include "dw2gencfi.h"
27440a403fSchristos 
28440a403fSchristos #include "opcode/s390.h"
29440a403fSchristos #include "elf/s390.h"
30440a403fSchristos 
31440a403fSchristos /* The default architecture.  */
32440a403fSchristos #ifndef DEFAULT_ARCH
33440a403fSchristos #define DEFAULT_ARCH "s390"
34440a403fSchristos #endif
35440a403fSchristos static const char *default_arch = DEFAULT_ARCH;
36440a403fSchristos /* Either 32 or 64, selects file format.  */
37440a403fSchristos static int s390_arch_size = 0;
38440a403fSchristos 
39440a403fSchristos /* If no -march option was given default to the highest available CPU.
40440a403fSchristos    Since with S/390 a newer CPU always supports everything from its
41440a403fSchristos    predecessors this will accept every valid asm input.  */
42440a403fSchristos static unsigned int current_cpu = S390_OPCODE_MAXCPU - 1;
4306324dcfSchristos /* All facilities are enabled by default.  */
4406324dcfSchristos static unsigned int current_flags = S390_INSTR_FLAG_FACILITY_MASK;
4506324dcfSchristos /* The mode mask default is picked in init_default_arch depending on
4606324dcfSchristos    the current cpu.  */
47440a403fSchristos static unsigned int current_mode_mask = 0;
48440a403fSchristos 
49440a403fSchristos /* Set to TRUE if the highgprs flag in the ELF header needs to be set
50440a403fSchristos    for the output file.  */
51440a403fSchristos static bfd_boolean set_highgprs_p = FALSE;
52440a403fSchristos 
53440a403fSchristos /* Whether to use user friendly register names. Default is TRUE.  */
54440a403fSchristos #ifndef TARGET_REG_NAMES_P
55440a403fSchristos #define TARGET_REG_NAMES_P TRUE
56440a403fSchristos #endif
57440a403fSchristos 
58440a403fSchristos static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
59440a403fSchristos 
60440a403fSchristos /* Set to TRUE if we want to warn about zero base/index registers.  */
61440a403fSchristos static bfd_boolean warn_areg_zero = FALSE;
62440a403fSchristos 
63440a403fSchristos /* Generic assembler global variables which must be defined by all
64440a403fSchristos    targets.  */
65440a403fSchristos 
66440a403fSchristos const char comment_chars[] = "#";
67440a403fSchristos 
68440a403fSchristos /* Characters which start a comment at the beginning of a line.  */
69440a403fSchristos const char line_comment_chars[] = "#";
70440a403fSchristos 
71440a403fSchristos /* Characters which may be used to separate multiple commands on a
72440a403fSchristos    single line.  */
73440a403fSchristos const char line_separator_chars[] = ";";
74440a403fSchristos 
75440a403fSchristos /* Characters which are used to indicate an exponent in a floating
76440a403fSchristos    point number.  */
77440a403fSchristos const char EXP_CHARS[] = "eE";
78440a403fSchristos 
79440a403fSchristos /* Characters which mean that a number is a floating point constant,
80440a403fSchristos    as in 0d1.0.  */
81440a403fSchristos const char FLT_CHARS[] = "dD";
82440a403fSchristos 
83440a403fSchristos /* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
84440a403fSchristos int s390_cie_data_alignment;
85440a403fSchristos 
86440a403fSchristos /* The target specific pseudo-ops which we support.  */
87440a403fSchristos 
88440a403fSchristos /* Define the prototypes for the pseudo-ops */
89440a403fSchristos static void s390_byte (int);
90440a403fSchristos static void s390_elf_cons (int);
91440a403fSchristos static void s390_bss (int);
92440a403fSchristos static void s390_insn (int);
93440a403fSchristos static void s390_literals (int);
94440a403fSchristos static void s390_machine (int);
95440a403fSchristos static void s390_machinemode (int);
96440a403fSchristos 
97440a403fSchristos const pseudo_typeS md_pseudo_table[] =
98440a403fSchristos {
99440a403fSchristos   { "align",        s_align_bytes,      0 },
100440a403fSchristos   /* Pseudo-ops which must be defined.  */
101440a403fSchristos   { "bss",          s390_bss,           0 },
102440a403fSchristos   { "insn",         s390_insn,          0 },
103440a403fSchristos   /* Pseudo-ops which must be overridden.  */
104440a403fSchristos   { "byte",	    s390_byte,	        0 },
105440a403fSchristos   { "short",        s390_elf_cons,      2 },
106440a403fSchristos   { "long",	    s390_elf_cons,	4 },
107440a403fSchristos   { "quad",         s390_elf_cons,      8 },
108440a403fSchristos   { "ltorg",        s390_literals,      0 },
109440a403fSchristos   { "string",       stringer,           8 + 1 },
110440a403fSchristos   { "machine",      s390_machine,       0 },
111440a403fSchristos   { "machinemode",  s390_machinemode,   0 },
112440a403fSchristos   { NULL,	    NULL,		0 }
113440a403fSchristos };
114440a403fSchristos 
115440a403fSchristos /* Given NAME, find the register number associated with that name, return
116440a403fSchristos    the integer value associated with the given name or -1 on failure.  */
117440a403fSchristos 
118440a403fSchristos static int
reg_name_search(const char * name)119440a403fSchristos reg_name_search (const char *name)
120440a403fSchristos {
121440a403fSchristos   int val = -1;
122440a403fSchristos 
123440a403fSchristos   if (strcasecmp (name, "lit") == 0)
124440a403fSchristos     return 13;
125440a403fSchristos 
126440a403fSchristos   if (strcasecmp (name, "sp") == 0)
127440a403fSchristos     return 15;
128440a403fSchristos 
129440a403fSchristos   if (name[0] != 'a' && name[0] != 'c' && name[0] != 'f'
130440a403fSchristos       && name[0] != 'r' && name[0] != 'v')
131440a403fSchristos     return -1;
132440a403fSchristos 
133440a403fSchristos   if (ISDIGIT (name[1]))
134440a403fSchristos     {
135440a403fSchristos       val = name[1] - '0';
136440a403fSchristos       if (ISDIGIT (name[2]))
137440a403fSchristos 	val = val * 10 + name[2] - '0';
138440a403fSchristos     }
139440a403fSchristos 
140440a403fSchristos   if ((name[0] != 'v' && val > 15) || val > 31)
141440a403fSchristos     val = -1;
142440a403fSchristos 
143440a403fSchristos   return val;
144440a403fSchristos }
145440a403fSchristos 
146440a403fSchristos 
147440a403fSchristos /*
148440a403fSchristos  * Summary of register_name().
149440a403fSchristos  *
150440a403fSchristos  * in:	Input_line_pointer points to 1st char of operand.
151440a403fSchristos  *
152440a403fSchristos  * out:	A expressionS.
153440a403fSchristos  *      The operand may have been a register: in this case, X_op == O_register,
154440a403fSchristos  *      X_add_number is set to the register number, and truth is returned.
155440a403fSchristos  *	Input_line_pointer->(next non-blank) char after operand, or is in its
156440a403fSchristos  *      original state.
157440a403fSchristos  */
158440a403fSchristos 
159440a403fSchristos static bfd_boolean
register_name(expressionS * expressionP)160440a403fSchristos register_name (expressionS *expressionP)
161440a403fSchristos {
162440a403fSchristos   int reg_number;
163440a403fSchristos   char *name;
164440a403fSchristos   char *start;
165440a403fSchristos   char c;
166440a403fSchristos 
167440a403fSchristos   /* Find the spelling of the operand.  */
168440a403fSchristos   start = name = input_line_pointer;
169440a403fSchristos   if (name[0] == '%' && ISALPHA (name[1]))
170440a403fSchristos     name = ++input_line_pointer;
171440a403fSchristos   else
172440a403fSchristos     return FALSE;
173440a403fSchristos 
174440a403fSchristos   c = get_symbol_name (&name);
175440a403fSchristos   reg_number = reg_name_search (name);
176440a403fSchristos 
177440a403fSchristos   /* Put back the delimiting char.  */
178440a403fSchristos   (void) restore_line_pointer (c);
179440a403fSchristos 
180440a403fSchristos   /* Look to see if it's in the register table.  */
181440a403fSchristos   if (reg_number >= 0)
182440a403fSchristos     {
183440a403fSchristos       expressionP->X_op = O_register;
184440a403fSchristos       expressionP->X_add_number = reg_number;
185440a403fSchristos 
186440a403fSchristos       /* Make the rest nice.  */
187440a403fSchristos       expressionP->X_add_symbol = NULL;
188440a403fSchristos       expressionP->X_op_symbol = NULL;
189440a403fSchristos       return TRUE;
190440a403fSchristos     }
191440a403fSchristos 
192440a403fSchristos   /* Reset the line as if we had not done anything.  */
193440a403fSchristos   input_line_pointer = start;
194440a403fSchristos   return FALSE;
195440a403fSchristos }
196440a403fSchristos 
197440a403fSchristos /* Local variables.  */
198440a403fSchristos 
199440a403fSchristos /* Opformat hash table.  */
200440a403fSchristos static struct hash_control *s390_opformat_hash;
201440a403fSchristos 
202440a403fSchristos /* Opcode hash table.  */
203440a403fSchristos static struct hash_control *s390_opcode_hash = NULL;
204440a403fSchristos 
205440a403fSchristos /* Flags to set in the elf header */
206440a403fSchristos static flagword s390_flags = 0;
207440a403fSchristos 
208440a403fSchristos symbolS *GOT_symbol;		/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */
209440a403fSchristos 
210440a403fSchristos #ifndef WORKING_DOT_WORD
211440a403fSchristos int md_short_jump_size = 4;
212440a403fSchristos int md_long_jump_size = 4;
213440a403fSchristos #endif
214440a403fSchristos 
215440a403fSchristos const char *md_shortopts = "A:m:kVQ:";
216440a403fSchristos struct option md_longopts[] = {
217440a403fSchristos   {NULL, no_argument, NULL, 0}
218440a403fSchristos };
219440a403fSchristos size_t md_longopts_size = sizeof (md_longopts);
220440a403fSchristos 
221440a403fSchristos /* Initialize the default opcode arch and word size from the default
222440a403fSchristos    architecture name if not specified by an option.  */
223440a403fSchristos static void
init_default_arch(void)224440a403fSchristos init_default_arch (void)
225440a403fSchristos {
226440a403fSchristos   if (strcmp (default_arch, "s390") == 0)
227440a403fSchristos     {
228440a403fSchristos       if (s390_arch_size == 0)
229440a403fSchristos 	s390_arch_size = 32;
230440a403fSchristos     }
231440a403fSchristos   else if (strcmp (default_arch, "s390x") == 0)
232440a403fSchristos     {
233440a403fSchristos       if (s390_arch_size == 0)
234440a403fSchristos 	s390_arch_size = 64;
235440a403fSchristos     }
236440a403fSchristos   else
237440a403fSchristos     as_fatal (_("Invalid default architecture, broken assembler."));
238440a403fSchristos 
239440a403fSchristos   if (current_mode_mask == 0)
240440a403fSchristos     {
241440a403fSchristos       /* Default to z/Architecture mode if the CPU supports it.  */
242440a403fSchristos       if (current_cpu < S390_OPCODE_Z900)
243440a403fSchristos 	current_mode_mask = 1 << S390_OPCODE_ESA;
244440a403fSchristos       else
245440a403fSchristos 	current_mode_mask = 1 << S390_OPCODE_ZARCH;
246440a403fSchristos     }
247440a403fSchristos }
248440a403fSchristos 
249440a403fSchristos /* Called by TARGET_FORMAT.  */
250440a403fSchristos const char *
s390_target_format(void)251440a403fSchristos s390_target_format (void)
252440a403fSchristos {
253440a403fSchristos   /* We don't get a chance to initialize anything before we're called,
254440a403fSchristos      so handle that now.  */
255440a403fSchristos   init_default_arch ();
256440a403fSchristos 
257440a403fSchristos   return s390_arch_size == 64 ? "elf64-s390" : "elf32-s390";
258440a403fSchristos }
259440a403fSchristos 
260440a403fSchristos /* Map a cpu string ARG as given with -march= or .machine to the respective
261440a403fSchristos    enum s390_opcode_cpu_val value.  If ALLOW_EXTENSIONS is TRUE, the cpu name
262440a403fSchristos    can be followed by a list of cpu facility flags each beginning with the
263440a403fSchristos    character '+'.  The active cpu flags are returned through *RET_FLAGS.
264440a403fSchristos    In case of an error, S390_OPCODE_MAXCPU is returned.  */
265440a403fSchristos 
266440a403fSchristos static unsigned int
s390_parse_cpu(const char * arg,unsigned int * ret_flags,bfd_boolean allow_extensions)267440a403fSchristos s390_parse_cpu (const char *         arg,
268440a403fSchristos 		unsigned int * ret_flags,
269440a403fSchristos 		bfd_boolean    allow_extensions)
270440a403fSchristos {
271440a403fSchristos   static struct
272440a403fSchristos   {
273440a403fSchristos     const char * name;
27406324dcfSchristos     unsigned int name_len;
27506324dcfSchristos     const char * alt_name;
27606324dcfSchristos     unsigned int alt_name_len;
277440a403fSchristos     unsigned int flags;
278440a403fSchristos   } cpu_table[S390_OPCODE_MAXCPU] =
279440a403fSchristos   {
28006324dcfSchristos     { STRING_COMMA_LEN ("g5"), STRING_COMMA_LEN ("arch3"), 0 },
28106324dcfSchristos     { STRING_COMMA_LEN ("g6"), STRING_COMMA_LEN (""), 0 },
28206324dcfSchristos     { STRING_COMMA_LEN ("z900"), STRING_COMMA_LEN ("arch5"), 0 },
28306324dcfSchristos     { STRING_COMMA_LEN ("z990"), STRING_COMMA_LEN ("arch6"), 0 },
28406324dcfSchristos     { STRING_COMMA_LEN ("z9-109"), STRING_COMMA_LEN (""), 0 },
28506324dcfSchristos     { STRING_COMMA_LEN ("z9-ec"), STRING_COMMA_LEN ("arch7"), 0 },
28606324dcfSchristos     { STRING_COMMA_LEN ("z10"), STRING_COMMA_LEN ("arch8"), 0 },
28706324dcfSchristos     { STRING_COMMA_LEN ("z196"), STRING_COMMA_LEN ("arch9"), 0 },
28806324dcfSchristos     { STRING_COMMA_LEN ("zEC12"), STRING_COMMA_LEN ("arch10"),
28906324dcfSchristos       S390_INSTR_FLAG_HTM },
29006324dcfSchristos     { STRING_COMMA_LEN ("z13"), STRING_COMMA_LEN ("arch11"),
29106324dcfSchristos       S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX },
29206324dcfSchristos     { STRING_COMMA_LEN ("z14"), STRING_COMMA_LEN ("arch12"),
293*b88e3e88Schristos       S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX },
294*b88e3e88Schristos     { STRING_COMMA_LEN ("z15"), STRING_COMMA_LEN ("arch13"),
29506324dcfSchristos       S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX }
296440a403fSchristos   };
297440a403fSchristos   static struct
298440a403fSchristos   {
299440a403fSchristos     const char * name;
300440a403fSchristos     unsigned int mask;
301440a403fSchristos     bfd_boolean  on;
302440a403fSchristos   } cpu_flags[] =
303440a403fSchristos   {
304440a403fSchristos     { "htm",   S390_INSTR_FLAG_HTM, TRUE },
305440a403fSchristos     { "nohtm", S390_INSTR_FLAG_HTM, FALSE },
306440a403fSchristos     { "vx",    S390_INSTR_FLAG_VX, TRUE },
307440a403fSchristos     { "novx",  S390_INSTR_FLAG_VX, FALSE }
308440a403fSchristos   };
309440a403fSchristos   unsigned int icpu;
310440a403fSchristos   char *ilp_bak;
311440a403fSchristos 
312440a403fSchristos   icpu = S390_OPCODE_MAXCPU;
313440a403fSchristos   if (strncmp (arg, "all", 3) == 0 && (arg[3] == 0 || arg[3] == '+'))
314440a403fSchristos     {
315440a403fSchristos       icpu = S390_OPCODE_MAXCPU - 1;
316440a403fSchristos       arg += 3;
317440a403fSchristos     }
318440a403fSchristos   else
319440a403fSchristos     {
320440a403fSchristos       for (icpu = 0; icpu < S390_OPCODE_MAXCPU; icpu++)
321440a403fSchristos 	{
32206324dcfSchristos 	  unsigned int l, l_alt;
323440a403fSchristos 
32406324dcfSchristos 	  l = cpu_table[icpu].name_len;
32506324dcfSchristos 
326440a403fSchristos 	  if (strncmp (arg, cpu_table[icpu].name, l) == 0
327440a403fSchristos 	      && (arg[l] == 0 || arg[l] == '+'))
328440a403fSchristos 	    {
329440a403fSchristos 	      arg += l;
330440a403fSchristos 	      break;
331440a403fSchristos 	    }
33206324dcfSchristos 
33306324dcfSchristos 	  l_alt = cpu_table[icpu].alt_name_len;
33406324dcfSchristos 
33506324dcfSchristos 	  if (l_alt > 0
33606324dcfSchristos 	      && strncmp (arg, cpu_table[icpu].alt_name, l_alt) == 0
33706324dcfSchristos 	      && (arg[l_alt] == 0 || arg[l_alt] == '+'))
33806324dcfSchristos 	    {
33906324dcfSchristos 	      arg += l_alt;
34006324dcfSchristos 	      break;
341440a403fSchristos 	    }
342440a403fSchristos 	}
34306324dcfSchristos     }
34406324dcfSchristos 
34506324dcfSchristos   if (icpu == S390_OPCODE_MAXCPU)
34606324dcfSchristos     return S390_OPCODE_MAXCPU;
347440a403fSchristos 
348440a403fSchristos   ilp_bak = input_line_pointer;
349440a403fSchristos   if (icpu != S390_OPCODE_MAXCPU)
350440a403fSchristos     {
351440a403fSchristos       input_line_pointer = (char *) arg;
352440a403fSchristos       *ret_flags = (cpu_table[icpu].flags & S390_INSTR_FLAG_FACILITY_MASK);
353440a403fSchristos 
354440a403fSchristos       while (*input_line_pointer == '+' && allow_extensions)
355440a403fSchristos 	{
356440a403fSchristos 	  unsigned int iflag;
357440a403fSchristos 	  char *sym;
358440a403fSchristos 	  char c;
359440a403fSchristos 
360440a403fSchristos 	  input_line_pointer++;
361440a403fSchristos 	  c = get_symbol_name (&sym);
362440a403fSchristos 	  for (iflag = 0; iflag < ARRAY_SIZE (cpu_flags); iflag++)
363440a403fSchristos 	    {
364440a403fSchristos 	      if (strcmp (sym, cpu_flags[iflag].name) == 0)
365440a403fSchristos 		{
366440a403fSchristos 		  if (cpu_flags[iflag].on)
367440a403fSchristos 		    *ret_flags |= cpu_flags[iflag].mask;
368440a403fSchristos 		  else
369440a403fSchristos 		    *ret_flags &= ~cpu_flags[iflag].mask;
370440a403fSchristos 		  break;
371440a403fSchristos 		}
372440a403fSchristos 	    }
373440a403fSchristos 	  if (iflag == ARRAY_SIZE (cpu_flags))
374440a403fSchristos 	    as_bad (_("no such machine extension `%s'"), sym - 1);
375440a403fSchristos 	  *input_line_pointer = c;
376440a403fSchristos 	  if (iflag == ARRAY_SIZE (cpu_flags))
377440a403fSchristos 	    break;
378440a403fSchristos 	}
379440a403fSchristos     }
380440a403fSchristos 
381440a403fSchristos   SKIP_WHITESPACE ();
382440a403fSchristos 
383440a403fSchristos   if (*input_line_pointer != 0 && *input_line_pointer != '\n')
384440a403fSchristos     {
385440a403fSchristos       as_bad (_("junk at end of machine string, first unrecognized character"
386440a403fSchristos 		" is `%c'"), *input_line_pointer);
387440a403fSchristos       icpu = S390_OPCODE_MAXCPU;
388440a403fSchristos     }
389440a403fSchristos   input_line_pointer = ilp_bak;
390440a403fSchristos 
391440a403fSchristos   return icpu;
392440a403fSchristos }
393440a403fSchristos 
394440a403fSchristos int
md_parse_option(int c,const char * arg)395440a403fSchristos md_parse_option (int c, const char *arg)
396440a403fSchristos {
397440a403fSchristos   switch (c)
398440a403fSchristos     {
399440a403fSchristos       /* -k: Ignore for FreeBSD compatibility.  */
400440a403fSchristos     case 'k':
401440a403fSchristos       break;
402440a403fSchristos     case 'm':
403440a403fSchristos       if (arg != NULL && strcmp (arg, "regnames") == 0)
404440a403fSchristos 	reg_names_p = TRUE;
405440a403fSchristos 
406440a403fSchristos       else if (arg != NULL && strcmp (arg, "no-regnames") == 0)
407440a403fSchristos 	reg_names_p = FALSE;
408440a403fSchristos 
409440a403fSchristos       else if (arg != NULL && strcmp (arg, "warn-areg-zero") == 0)
410440a403fSchristos 	warn_areg_zero = TRUE;
411440a403fSchristos 
412440a403fSchristos       else if (arg != NULL && strcmp (arg, "31") == 0)
413440a403fSchristos 	s390_arch_size = 32;
414440a403fSchristos 
415440a403fSchristos       else if (arg != NULL && strcmp (arg, "64") == 0)
416440a403fSchristos 	s390_arch_size = 64;
417440a403fSchristos 
418440a403fSchristos       else if (arg != NULL && strcmp (arg, "esa") == 0)
419440a403fSchristos 	current_mode_mask = 1 << S390_OPCODE_ESA;
420440a403fSchristos 
421440a403fSchristos       else if (arg != NULL && strcmp (arg, "zarch") == 0)
422440a403fSchristos 	{
423440a403fSchristos 	  if (s390_arch_size == 32)
424440a403fSchristos 	    set_highgprs_p = TRUE;
425440a403fSchristos 	  current_mode_mask = 1 << S390_OPCODE_ZARCH;
426440a403fSchristos 	}
427440a403fSchristos 
428440a403fSchristos       else if (arg != NULL && strncmp (arg, "arch=", 5) == 0)
429440a403fSchristos 	{
430440a403fSchristos 	  current_cpu = s390_parse_cpu (arg + 5, &current_flags, FALSE);
431440a403fSchristos 	  if (current_cpu == S390_OPCODE_MAXCPU)
432440a403fSchristos 	    {
433440a403fSchristos 	      as_bad (_("invalid switch -m%s"), arg);
434440a403fSchristos 	      return 0;
435440a403fSchristos 	    }
436440a403fSchristos 	}
437440a403fSchristos 
438440a403fSchristos       else
439440a403fSchristos 	{
440440a403fSchristos 	  as_bad (_("invalid switch -m%s"), arg);
441440a403fSchristos 	  return 0;
442440a403fSchristos 	}
443440a403fSchristos       break;
444440a403fSchristos 
445440a403fSchristos     case 'A':
446440a403fSchristos       /* Option -A is deprecated. Still available for compatibility.  */
447440a403fSchristos       if (arg != NULL && strcmp (arg, "esa") == 0)
448440a403fSchristos 	current_cpu = S390_OPCODE_G5;
449440a403fSchristos       else if (arg != NULL && strcmp (arg, "esame") == 0)
450440a403fSchristos 	current_cpu = S390_OPCODE_Z900;
451440a403fSchristos       else
452440a403fSchristos 	as_bad (_("invalid architecture -A%s"), arg);
453440a403fSchristos       break;
454440a403fSchristos 
455440a403fSchristos       /* -V: SVR4 argument to print version ID.  */
456440a403fSchristos     case 'V':
457440a403fSchristos       print_version_id ();
458440a403fSchristos       break;
459440a403fSchristos 
460440a403fSchristos       /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
461440a403fSchristos 	 should be emitted or not.  FIXME: Not implemented.  */
462440a403fSchristos     case 'Q':
463440a403fSchristos       break;
464440a403fSchristos 
465440a403fSchristos     default:
466440a403fSchristos       return 0;
467440a403fSchristos     }
468440a403fSchristos 
469440a403fSchristos   return 1;
470440a403fSchristos }
471440a403fSchristos 
472440a403fSchristos void
md_show_usage(FILE * stream)473440a403fSchristos md_show_usage (FILE *stream)
474440a403fSchristos {
475440a403fSchristos   fprintf (stream, _("\
476440a403fSchristos         S390 options:\n\
477440a403fSchristos         -mregnames        Allow symbolic names for registers\n\
478440a403fSchristos         -mwarn-areg-zero  Warn about zero base/index registers\n\
479440a403fSchristos         -mno-regnames     Do not allow symbolic names for registers\n\
480440a403fSchristos         -m31              Set file format to 31 bit format\n\
481440a403fSchristos         -m64              Set file format to 64 bit format\n"));
482440a403fSchristos   fprintf (stream, _("\
483440a403fSchristos         -V                print assembler version number\n\
484440a403fSchristos         -Qy, -Qn          ignored\n"));
485440a403fSchristos }
486440a403fSchristos 
487440a403fSchristos /* Generate the hash table mapping mnemonics to struct s390_opcode.
488440a403fSchristos    This table is built at startup and whenever the CPU level is
489440a403fSchristos    changed using .machine.  */
490440a403fSchristos 
491440a403fSchristos static void
s390_setup_opcodes(void)492440a403fSchristos s390_setup_opcodes (void)
493440a403fSchristos {
494440a403fSchristos   const struct s390_opcode *op;
495440a403fSchristos   const struct s390_opcode *op_end;
496440a403fSchristos   bfd_boolean dup_insn = FALSE;
497440a403fSchristos   const char *retval;
498440a403fSchristos 
499440a403fSchristos   if (s390_opcode_hash != NULL)
500440a403fSchristos     hash_die (s390_opcode_hash);
501440a403fSchristos 
502440a403fSchristos   /* Insert the opcodes into a hash table.  */
503440a403fSchristos   s390_opcode_hash = hash_new ();
504440a403fSchristos 
505440a403fSchristos   op_end = s390_opcodes + s390_num_opcodes;
506440a403fSchristos   for (op = s390_opcodes; op < op_end; op++)
507440a403fSchristos     {
508440a403fSchristos       int use_opcode;
509440a403fSchristos 
510440a403fSchristos       while (op < op_end - 1 && strcmp(op->name, op[1].name) == 0)
511440a403fSchristos 	{
512440a403fSchristos           if (op->min_cpu <= current_cpu && (op->modes & current_mode_mask))
513440a403fSchristos 	    break;
514440a403fSchristos 	  op++;
515440a403fSchristos         }
516440a403fSchristos 
517440a403fSchristos       if ((op->modes & current_mode_mask) == 0)
518440a403fSchristos 	use_opcode = 0;
519440a403fSchristos       else if ((op->flags & S390_INSTR_FLAG_FACILITY_MASK) == 0)
520440a403fSchristos 	{
521440a403fSchristos 	  /* Opcodes that do not belong to a specific facility are enabled if
522440a403fSchristos 	     present in the selected cpu.  */
523440a403fSchristos 	  use_opcode = (op->min_cpu <= current_cpu);
524440a403fSchristos 	}
525440a403fSchristos       else
526440a403fSchristos 	{
527440a403fSchristos 	  unsigned int f;
528440a403fSchristos 
529440a403fSchristos 	  /* Opcodes of a specific facility are enabled if the facility is
530440a403fSchristos 	     enabled.  Note: only some facilities are represented as flags.  */
531440a403fSchristos 	  f = (op->flags & S390_INSTR_FLAG_FACILITY_MASK);
532440a403fSchristos 	  use_opcode = ((f & current_flags) == f);
533440a403fSchristos 	}
534440a403fSchristos       if (use_opcode)
535440a403fSchristos 	{
536440a403fSchristos 	  retval = hash_insert (s390_opcode_hash, op->name, (void *) op);
537440a403fSchristos 	  if (retval != (const char *) NULL)
538440a403fSchristos 	    {
539440a403fSchristos 	      as_bad (_("Internal assembler error for instruction %s"),
540440a403fSchristos 		      op->name);
541440a403fSchristos 	      dup_insn = TRUE;
542440a403fSchristos 	    }
543440a403fSchristos 	}
544440a403fSchristos 
545440a403fSchristos       while (op < op_end - 1 && strcmp (op->name, op[1].name) == 0)
546440a403fSchristos 	op++;
547440a403fSchristos     }
548440a403fSchristos 
549440a403fSchristos   if (dup_insn)
550440a403fSchristos     abort ();
551440a403fSchristos }
552440a403fSchristos 
553440a403fSchristos /* This function is called when the assembler starts up.  It is called
554440a403fSchristos    after the options have been parsed and the output file has been
555440a403fSchristos    opened.  */
556440a403fSchristos 
557440a403fSchristos void
md_begin(void)558440a403fSchristos md_begin (void)
559440a403fSchristos {
560440a403fSchristos   const struct s390_opcode *op;
561440a403fSchristos   const struct s390_opcode *op_end;
562440a403fSchristos   const char *retval;
563440a403fSchristos 
564440a403fSchristos   /* Give a warning if the combination -m64-bit and -Aesa is used.  */
565440a403fSchristos   if (s390_arch_size == 64 && current_cpu < S390_OPCODE_Z900)
566440a403fSchristos     as_warn (_("The 64 bit file format is used without esame instructions."));
567440a403fSchristos 
568440a403fSchristos   s390_cie_data_alignment = -s390_arch_size / 8;
569440a403fSchristos 
570440a403fSchristos   /* Set the ELF flags if desired.  */
571440a403fSchristos   if (s390_flags)
572440a403fSchristos     bfd_set_private_flags (stdoutput, s390_flags);
573440a403fSchristos 
574440a403fSchristos   /* Insert the opcode formats into a hash table.  */
575440a403fSchristos   s390_opformat_hash = hash_new ();
576440a403fSchristos 
577440a403fSchristos   op_end = s390_opformats + s390_num_opformats;
578440a403fSchristos   for (op = s390_opformats; op < op_end; op++)
579440a403fSchristos     {
580440a403fSchristos       retval = hash_insert (s390_opformat_hash, op->name, (void *) op);
581440a403fSchristos       if (retval != (const char *) NULL)
582440a403fSchristos 	as_bad (_("Internal assembler error for instruction format %s"),
583440a403fSchristos 		op->name);
584440a403fSchristos     }
585440a403fSchristos 
586440a403fSchristos   s390_setup_opcodes ();
587440a403fSchristos 
588440a403fSchristos   record_alignment (text_section, 2);
589440a403fSchristos   record_alignment (data_section, 2);
590440a403fSchristos   record_alignment (bss_section, 2);
591440a403fSchristos }
592440a403fSchristos 
593440a403fSchristos /* Called after all assembly has been done.  */
594440a403fSchristos void
s390_md_end(void)595440a403fSchristos s390_md_end (void)
596440a403fSchristos {
597440a403fSchristos   if (s390_arch_size == 64)
598440a403fSchristos     bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_64);
599440a403fSchristos   else
600440a403fSchristos     bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_31);
601440a403fSchristos }
602440a403fSchristos 
603440a403fSchristos /* Insert an operand value into an instruction.  */
604440a403fSchristos 
605440a403fSchristos static void
s390_insert_operand(unsigned char * insn,const struct s390_operand * operand,offsetT val,const char * file,unsigned int line)606440a403fSchristos s390_insert_operand (unsigned char *insn,
607440a403fSchristos 		     const struct s390_operand *operand,
608440a403fSchristos 		     offsetT val,
609440a403fSchristos 		     const char *file,
610440a403fSchristos 		     unsigned int line)
611440a403fSchristos {
612440a403fSchristos   addressT uval;
613440a403fSchristos   int offset;
614440a403fSchristos 
615440a403fSchristos   if (operand->flags & (S390_OPERAND_SIGNED|S390_OPERAND_PCREL))
616440a403fSchristos     {
617440a403fSchristos       offsetT min, max;
618440a403fSchristos 
619440a403fSchristos       max = ((offsetT) 1 << (operand->bits - 1)) - 1;
620440a403fSchristos       min = - ((offsetT) 1 << (operand->bits - 1));
621440a403fSchristos       /* Halve PCREL operands.  */
622440a403fSchristos       if (operand->flags & S390_OPERAND_PCREL)
623440a403fSchristos 	val >>= 1;
624440a403fSchristos       /* Check for underflow / overflow.  */
625440a403fSchristos       if (val < min || val > max)
626440a403fSchristos 	{
627440a403fSchristos 	  const char *err =
628440a403fSchristos 	    _("operand out of range (%s not between %ld and %ld)");
629440a403fSchristos 	  char buf[100];
630440a403fSchristos 
631440a403fSchristos 	  if (operand->flags & S390_OPERAND_PCREL)
632440a403fSchristos 	    {
633440a403fSchristos 	      val <<= 1;
634440a403fSchristos 	      min <<= 1;
635440a403fSchristos 	      max <<= 1;
636440a403fSchristos 	    }
637440a403fSchristos 	  sprint_value (buf, val);
638440a403fSchristos 	  if (file == (char *) NULL)
639440a403fSchristos 	    as_bad (err, buf, (int) min, (int) max);
640440a403fSchristos 	  else
641440a403fSchristos 	    as_bad_where (file, line, err, buf, (int) min, (int) max);
642440a403fSchristos 	  return;
643440a403fSchristos 	}
644440a403fSchristos       /* val is ok, now restrict it to operand->bits bits.  */
645440a403fSchristos       uval = (addressT) val & ((((addressT) 1 << (operand->bits-1)) << 1) - 1);
646440a403fSchristos       /* val is restrict, now check for special case.  */
647440a403fSchristos       if (operand->bits == 20 && operand->shift == 20)
648440a403fSchristos         uval = (uval >> 12) | ((uval & 0xfff) << 8);
649440a403fSchristos     }
650440a403fSchristos   else
651440a403fSchristos     {
652440a403fSchristos       addressT min, max;
653440a403fSchristos 
654440a403fSchristos       max = (((addressT) 1 << (operand->bits - 1)) << 1) - 1;
655440a403fSchristos       min = (offsetT) 0;
656440a403fSchristos       uval = (addressT) val;
657440a403fSchristos 
658440a403fSchristos       /* Vector register operands have an additional bit in the RXB
659440a403fSchristos 	 field.  */
660440a403fSchristos       if (operand->flags & S390_OPERAND_VR)
661440a403fSchristos 	max = (max << 1) | 1;
662440a403fSchristos 
663440a403fSchristos       /* Length x in an instructions has real length x+1.  */
664440a403fSchristos       if (operand->flags & S390_OPERAND_LENGTH)
665440a403fSchristos 	uval--;
666440a403fSchristos       /* Check for underflow / overflow.  */
667440a403fSchristos       if (uval < min || uval > max)
668440a403fSchristos 	{
669440a403fSchristos 	  if (operand->flags & S390_OPERAND_LENGTH)
670440a403fSchristos 	    {
671440a403fSchristos 	      uval++;
672440a403fSchristos 	      min++;
673440a403fSchristos 	      max++;
674440a403fSchristos 	    }
675440a403fSchristos 
676440a403fSchristos 	  as_bad_value_out_of_range (_("operand"), uval, (offsetT) min, (offsetT) max, file, line);
677440a403fSchristos 
678440a403fSchristos 	  return;
679440a403fSchristos 	}
680440a403fSchristos     }
681440a403fSchristos 
682440a403fSchristos   if (operand->flags & S390_OPERAND_VR)
683440a403fSchristos     {
684440a403fSchristos       /* Insert the extra bit into the RXB field.  */
685440a403fSchristos       switch (operand->shift)
686440a403fSchristos 	{
687440a403fSchristos 	case 8:
688440a403fSchristos 	  insn[4] |= (uval & 0x10) >> 1;
689440a403fSchristos 	  break;
690440a403fSchristos 	case 12:
691440a403fSchristos 	  insn[4] |= (uval & 0x10) >> 2;
692440a403fSchristos 	  break;
693440a403fSchristos 	case 16:
694440a403fSchristos 	  insn[4] |= (uval & 0x10) >> 3;
695440a403fSchristos 	  break;
696440a403fSchristos 	case 32:
697440a403fSchristos 	  insn[4] |= (uval & 0x10) >> 4;
698440a403fSchristos 	  break;
699440a403fSchristos 	}
700440a403fSchristos       uval &= 0xf;
701440a403fSchristos     }
702440a403fSchristos 
703440a403fSchristos   if (operand->flags & S390_OPERAND_OR1)
704440a403fSchristos     uval |= 1;
705440a403fSchristos   if (operand->flags & S390_OPERAND_OR2)
706440a403fSchristos     uval |= 2;
707440a403fSchristos   if (operand->flags & S390_OPERAND_OR8)
708440a403fSchristos     uval |= 8;
709440a403fSchristos 
710440a403fSchristos   /* Duplicate the operand at bit pos 12 to 16.  */
711440a403fSchristos   if (operand->flags & S390_OPERAND_CP16)
712440a403fSchristos     {
713440a403fSchristos       /* Copy VR operand at bit pos 12 to bit pos 16.  */
714440a403fSchristos       insn[2] |= uval << 4;
715440a403fSchristos       /* Copy the flag in the RXB field.  */
716440a403fSchristos       insn[4] |= (insn[4] & 4) >> 1;
717440a403fSchristos     }
718440a403fSchristos 
719440a403fSchristos   /* Insert fragments of the operand byte for byte.  */
720440a403fSchristos   offset = operand->shift + operand->bits;
721440a403fSchristos   uval <<= (-offset) & 7;
722440a403fSchristos   insn += (offset - 1) / 8;
723440a403fSchristos   while (uval != 0)
724440a403fSchristos     {
725440a403fSchristos       *insn-- |= uval;
726440a403fSchristos       uval >>= 8;
727440a403fSchristos     }
728440a403fSchristos }
729440a403fSchristos 
730440a403fSchristos struct map_tls
731440a403fSchristos   {
732440a403fSchristos     const char *string;
733440a403fSchristos     int length;
734440a403fSchristos     bfd_reloc_code_real_type reloc;
735440a403fSchristos   };
736440a403fSchristos 
737440a403fSchristos /* Parse tls marker and return the desired relocation.  */
738440a403fSchristos static bfd_reloc_code_real_type
s390_tls_suffix(char ** str_p,expressionS * exp_p)739440a403fSchristos s390_tls_suffix (char **str_p, expressionS *exp_p)
740440a403fSchristos {
741440a403fSchristos   static struct map_tls mapping[] =
742440a403fSchristos   {
743440a403fSchristos     { "tls_load", 8, BFD_RELOC_390_TLS_LOAD },
744440a403fSchristos     { "tls_gdcall", 10, BFD_RELOC_390_TLS_GDCALL  },
745440a403fSchristos     { "tls_ldcall", 10, BFD_RELOC_390_TLS_LDCALL  },
746440a403fSchristos     { NULL,  0, BFD_RELOC_UNUSED }
747440a403fSchristos   };
748440a403fSchristos   struct map_tls *ptr;
749440a403fSchristos   char *orig_line;
750440a403fSchristos   char *str;
751440a403fSchristos   char *ident;
752440a403fSchristos   int len;
753440a403fSchristos 
754440a403fSchristos   str = *str_p;
755440a403fSchristos   if (*str++ != ':')
756440a403fSchristos     return BFD_RELOC_UNUSED;
757440a403fSchristos 
758440a403fSchristos   ident = str;
759440a403fSchristos   while (ISIDNUM (*str))
760440a403fSchristos     str++;
761440a403fSchristos   len = str - ident;
762440a403fSchristos   if (*str++ != ':')
763440a403fSchristos     return BFD_RELOC_UNUSED;
764440a403fSchristos 
765440a403fSchristos   orig_line = input_line_pointer;
766440a403fSchristos   input_line_pointer = str;
767440a403fSchristos   expression (exp_p);
768440a403fSchristos   str = input_line_pointer;
769440a403fSchristos   if (&input_line_pointer != str_p)
770440a403fSchristos     input_line_pointer = orig_line;
771440a403fSchristos 
772440a403fSchristos   if (exp_p->X_op != O_symbol)
773440a403fSchristos     return BFD_RELOC_UNUSED;
774440a403fSchristos 
775440a403fSchristos   for (ptr = &mapping[0]; ptr->length > 0; ptr++)
776440a403fSchristos     if (len == ptr->length
777440a403fSchristos 	&& strncasecmp (ident, ptr->string, ptr->length) == 0)
778440a403fSchristos       {
779440a403fSchristos 	/* Found a matching tls suffix.  */
780440a403fSchristos 	*str_p = str;
781440a403fSchristos 	return ptr->reloc;
782440a403fSchristos       }
783440a403fSchristos   return BFD_RELOC_UNUSED;
784440a403fSchristos }
785440a403fSchristos 
786440a403fSchristos /* Structure used to hold suffixes.  */
787440a403fSchristos typedef enum
788440a403fSchristos   {
789440a403fSchristos     ELF_SUFFIX_NONE = 0,
790440a403fSchristos     ELF_SUFFIX_GOT,
791440a403fSchristos     ELF_SUFFIX_PLT,
792440a403fSchristos     ELF_SUFFIX_GOTENT,
793440a403fSchristos     ELF_SUFFIX_GOTOFF,
794440a403fSchristos     ELF_SUFFIX_GOTPLT,
795440a403fSchristos     ELF_SUFFIX_PLTOFF,
796440a403fSchristos     ELF_SUFFIX_TLS_GD,
797440a403fSchristos     ELF_SUFFIX_TLS_GOTIE,
798440a403fSchristos     ELF_SUFFIX_TLS_IE,
799440a403fSchristos     ELF_SUFFIX_TLS_LDM,
800440a403fSchristos     ELF_SUFFIX_TLS_LDO,
801440a403fSchristos     ELF_SUFFIX_TLS_LE
802440a403fSchristos   }
803440a403fSchristos elf_suffix_type;
804440a403fSchristos 
805440a403fSchristos struct map_bfd
806440a403fSchristos   {
807440a403fSchristos     const char *string;
808440a403fSchristos     int length;
809440a403fSchristos     elf_suffix_type suffix;
810440a403fSchristos   };
811440a403fSchristos 
812440a403fSchristos 
813440a403fSchristos /* Parse @got/@plt/@gotoff. and return the desired relocation.  */
814440a403fSchristos static elf_suffix_type
s390_elf_suffix(char ** str_p,expressionS * exp_p)815440a403fSchristos s390_elf_suffix (char **str_p, expressionS *exp_p)
816440a403fSchristos {
817440a403fSchristos   static struct map_bfd mapping[] =
818440a403fSchristos   {
819440a403fSchristos     { "got", 3, ELF_SUFFIX_GOT  },
820440a403fSchristos     { "got12", 5, ELF_SUFFIX_GOT  },
821440a403fSchristos     { "plt", 3, ELF_SUFFIX_PLT  },
822440a403fSchristos     { "gotent", 6, ELF_SUFFIX_GOTENT },
823440a403fSchristos     { "gotoff", 6, ELF_SUFFIX_GOTOFF },
824440a403fSchristos     { "gotplt", 6, ELF_SUFFIX_GOTPLT },
825440a403fSchristos     { "pltoff", 6, ELF_SUFFIX_PLTOFF },
826440a403fSchristos     { "tlsgd", 5, ELF_SUFFIX_TLS_GD },
827440a403fSchristos     { "gotntpoff", 9, ELF_SUFFIX_TLS_GOTIE },
828440a403fSchristos     { "indntpoff", 9, ELF_SUFFIX_TLS_IE },
829440a403fSchristos     { "tlsldm", 6, ELF_SUFFIX_TLS_LDM },
830440a403fSchristos     { "dtpoff", 6, ELF_SUFFIX_TLS_LDO },
831440a403fSchristos     { "ntpoff", 6, ELF_SUFFIX_TLS_LE },
832440a403fSchristos     { NULL,  0, ELF_SUFFIX_NONE }
833440a403fSchristos   };
834440a403fSchristos 
835440a403fSchristos   struct map_bfd *ptr;
836440a403fSchristos   char *str = *str_p;
837440a403fSchristos   char *ident;
838440a403fSchristos   int len;
839440a403fSchristos 
840440a403fSchristos   if (*str++ != '@')
841440a403fSchristos     return ELF_SUFFIX_NONE;
842440a403fSchristos 
843440a403fSchristos   ident = str;
844440a403fSchristos   while (ISALNUM (*str))
845440a403fSchristos     str++;
846440a403fSchristos   len = str - ident;
847440a403fSchristos 
848440a403fSchristos   for (ptr = &mapping[0]; ptr->length > 0; ptr++)
849440a403fSchristos     if (len == ptr->length
850440a403fSchristos 	&& strncasecmp (ident, ptr->string, ptr->length) == 0)
851440a403fSchristos       {
852440a403fSchristos 	if (exp_p->X_add_number != 0)
853440a403fSchristos 	  as_warn (_("identifier+constant@%s means identifier@%s+constant"),
854440a403fSchristos 		   ptr->string, ptr->string);
855440a403fSchristos 	/* Now check for identifier@suffix+constant.  */
856440a403fSchristos 	if (*str == '-' || *str == '+')
857440a403fSchristos 	  {
858440a403fSchristos 	    char *orig_line = input_line_pointer;
859440a403fSchristos 	    expressionS new_exp;
860440a403fSchristos 
861440a403fSchristos 	    input_line_pointer = str;
862440a403fSchristos 	    expression (&new_exp);
863440a403fSchristos 
864440a403fSchristos 	    switch (new_exp.X_op)
865440a403fSchristos 	      {
866440a403fSchristos 	      case O_constant: /* X_add_number (a constant expression).  */
867440a403fSchristos 		exp_p->X_add_number += new_exp.X_add_number;
868440a403fSchristos 		str = input_line_pointer;
869440a403fSchristos 		break;
870440a403fSchristos 	      case O_symbol:   /* X_add_symbol + X_add_number.  */
871440a403fSchristos 		/* this case is used for e.g. xyz@PLT+.Label.  */
872440a403fSchristos 		exp_p->X_add_number += new_exp.X_add_number;
873440a403fSchristos 		exp_p->X_op_symbol = new_exp.X_add_symbol;
874440a403fSchristos 		exp_p->X_op = O_add;
875440a403fSchristos 		str = input_line_pointer;
876440a403fSchristos 		break;
877440a403fSchristos 	      case O_uminus:   /* (- X_add_symbol) + X_add_number.  */
878440a403fSchristos 		/* this case is used for e.g. xyz@PLT-.Label.  */
879440a403fSchristos 		exp_p->X_add_number += new_exp.X_add_number;
880440a403fSchristos 		exp_p->X_op_symbol = new_exp.X_add_symbol;
881440a403fSchristos 		exp_p->X_op = O_subtract;
882440a403fSchristos 		str = input_line_pointer;
883440a403fSchristos 		break;
884440a403fSchristos 	      default:
885440a403fSchristos 		break;
886440a403fSchristos 	      }
887440a403fSchristos 
888440a403fSchristos 	    /* If s390_elf_suffix has not been called with
889440a403fSchristos 	       &input_line_pointer as first parameter, we have
890440a403fSchristos 	       clobbered the input_line_pointer. We have to
891440a403fSchristos 	       undo that.  */
892440a403fSchristos 	    if (&input_line_pointer != str_p)
893440a403fSchristos 	      input_line_pointer = orig_line;
894440a403fSchristos 	  }
895440a403fSchristos 	*str_p = str;
896440a403fSchristos 	return ptr->suffix;
897440a403fSchristos       }
898440a403fSchristos 
899*b88e3e88Schristos   return ELF_SUFFIX_NONE;
900440a403fSchristos }
901440a403fSchristos 
902440a403fSchristos /* Structure used to hold a literal pool entry.  */
903440a403fSchristos struct s390_lpe
904440a403fSchristos   {
905440a403fSchristos     struct s390_lpe *next;
906440a403fSchristos     expressionS ex;
907440a403fSchristos     FLONUM_TYPE floatnum;     /* used if X_op == O_big && X_add_number <= 0 */
908440a403fSchristos     LITTLENUM_TYPE bignum[4]; /* used if X_op == O_big && X_add_number > 0  */
909440a403fSchristos     int nbytes;
910440a403fSchristos     bfd_reloc_code_real_type reloc;
911440a403fSchristos     symbolS *sym;
912440a403fSchristos   };
913440a403fSchristos 
914440a403fSchristos static struct s390_lpe *lpe_free_list = NULL;
915440a403fSchristos static struct s390_lpe *lpe_list = NULL;
916440a403fSchristos static struct s390_lpe *lpe_list_tail = NULL;
917440a403fSchristos static symbolS *lp_sym = NULL;
918440a403fSchristos static int lp_count = 0;
919440a403fSchristos static int lpe_count = 0;
920440a403fSchristos 
921440a403fSchristos static int
s390_exp_compare(expressionS * exp1,expressionS * exp2)922440a403fSchristos s390_exp_compare (expressionS *exp1, expressionS *exp2)
923440a403fSchristos {
924440a403fSchristos   if (exp1->X_op != exp2->X_op)
925440a403fSchristos     return 0;
926440a403fSchristos 
927440a403fSchristos   switch (exp1->X_op)
928440a403fSchristos     {
929440a403fSchristos     case O_constant:   /* X_add_number must be equal.  */
930440a403fSchristos     case O_register:
931440a403fSchristos       return exp1->X_add_number == exp2->X_add_number;
932440a403fSchristos 
933440a403fSchristos     case O_big:
934440a403fSchristos       as_bad (_("Can't handle O_big in s390_exp_compare"));
93506324dcfSchristos       return 0;
936440a403fSchristos 
937440a403fSchristos     case O_symbol:     /* X_add_symbol & X_add_number must be equal.  */
938440a403fSchristos     case O_symbol_rva:
939440a403fSchristos     case O_uminus:
940440a403fSchristos     case O_bit_not:
941440a403fSchristos     case O_logical_not:
942440a403fSchristos       return (exp1->X_add_symbol == exp2->X_add_symbol)
943440a403fSchristos 	&&   (exp1->X_add_number == exp2->X_add_number);
944440a403fSchristos 
945440a403fSchristos     case O_multiply:   /* X_add_symbol,X_op_symbol&X_add_number must be equal.  */
946440a403fSchristos     case O_divide:
947440a403fSchristos     case O_modulus:
948440a403fSchristos     case O_left_shift:
949440a403fSchristos     case O_right_shift:
950440a403fSchristos     case O_bit_inclusive_or:
951440a403fSchristos     case O_bit_or_not:
952440a403fSchristos     case O_bit_exclusive_or:
953440a403fSchristos     case O_bit_and:
954440a403fSchristos     case O_add:
955440a403fSchristos     case O_subtract:
956440a403fSchristos     case O_eq:
957440a403fSchristos     case O_ne:
958440a403fSchristos     case O_lt:
959440a403fSchristos     case O_le:
960440a403fSchristos     case O_ge:
961440a403fSchristos     case O_gt:
962440a403fSchristos     case O_logical_and:
963440a403fSchristos     case O_logical_or:
964440a403fSchristos       return (exp1->X_add_symbol == exp2->X_add_symbol)
965440a403fSchristos 	&&   (exp1->X_op_symbol  == exp2->X_op_symbol)
966440a403fSchristos 	&&   (exp1->X_add_number == exp2->X_add_number);
967440a403fSchristos     default:
968440a403fSchristos       return 0;
969440a403fSchristos     }
970440a403fSchristos }
971440a403fSchristos 
97206324dcfSchristos /* Test for @lit and if it's present make an entry in the literal pool and
973440a403fSchristos    modify the current expression to be an offset into the literal pool.  */
974440a403fSchristos static elf_suffix_type
s390_lit_suffix(char ** str_p,expressionS * exp_p,elf_suffix_type suffix)975440a403fSchristos s390_lit_suffix (char **str_p, expressionS *exp_p, elf_suffix_type suffix)
976440a403fSchristos {
977440a403fSchristos   bfd_reloc_code_real_type reloc;
978440a403fSchristos   char tmp_name[64];
979440a403fSchristos   char *str = *str_p;
980440a403fSchristos   char *ident;
981440a403fSchristos   struct s390_lpe *lpe;
982440a403fSchristos   int nbytes, len;
983440a403fSchristos 
984440a403fSchristos   if (*str++ != ':')
985440a403fSchristos     return suffix;       /* No modification.  */
986440a403fSchristos 
987440a403fSchristos   /* We look for a suffix of the form "@lit1", "@lit2", "@lit4" or "@lit8".  */
988440a403fSchristos   ident = str;
989440a403fSchristos   while (ISALNUM (*str))
990440a403fSchristos     str++;
991440a403fSchristos   len = str - ident;
992440a403fSchristos   if (len != 4 || strncasecmp (ident, "lit", 3) != 0
993440a403fSchristos       || (ident[3]!='1' && ident[3]!='2' && ident[3]!='4' && ident[3]!='8'))
994440a403fSchristos     return suffix;      /* no modification */
995440a403fSchristos   nbytes = ident[3] - '0';
996440a403fSchristos 
997440a403fSchristos   reloc = BFD_RELOC_UNUSED;
998440a403fSchristos   if (suffix == ELF_SUFFIX_GOT)
999440a403fSchristos     {
1000440a403fSchristos       if (nbytes == 2)
1001440a403fSchristos 	reloc = BFD_RELOC_390_GOT16;
1002440a403fSchristos       else if (nbytes == 4)
1003440a403fSchristos 	reloc = BFD_RELOC_32_GOT_PCREL;
1004440a403fSchristos       else if (nbytes == 8)
1005440a403fSchristos 	reloc = BFD_RELOC_390_GOT64;
1006440a403fSchristos     }
1007440a403fSchristos   else if (suffix == ELF_SUFFIX_PLT)
1008440a403fSchristos     {
1009440a403fSchristos       if (nbytes == 4)
1010440a403fSchristos 	reloc = BFD_RELOC_390_PLT32;
1011440a403fSchristos       else if (nbytes == 8)
1012440a403fSchristos 	reloc = BFD_RELOC_390_PLT64;
1013440a403fSchristos     }
1014440a403fSchristos 
1015440a403fSchristos   if (suffix != ELF_SUFFIX_NONE && reloc == BFD_RELOC_UNUSED)
1016440a403fSchristos     as_bad (_("Invalid suffix for literal pool entry"));
1017440a403fSchristos 
1018440a403fSchristos   /* Search the pool if the new entry is a duplicate.  */
1019440a403fSchristos   if (exp_p->X_op == O_big)
1020440a403fSchristos     {
1021440a403fSchristos       /* Special processing for big numbers.  */
1022440a403fSchristos       for (lpe = lpe_list; lpe != NULL; lpe = lpe->next)
1023440a403fSchristos 	{
1024440a403fSchristos 	  if (lpe->ex.X_op == O_big)
1025440a403fSchristos 	    {
1026440a403fSchristos 	      if (exp_p->X_add_number <= 0 && lpe->ex.X_add_number <= 0)
1027440a403fSchristos 		{
1028440a403fSchristos 		  if (memcmp (&generic_floating_point_number, &lpe->floatnum,
1029440a403fSchristos 			      sizeof (FLONUM_TYPE)) == 0)
1030440a403fSchristos 		    break;
1031440a403fSchristos 		}
1032440a403fSchristos 	      else if (exp_p->X_add_number == lpe->ex.X_add_number)
1033440a403fSchristos 		{
1034440a403fSchristos 		  if (memcmp (generic_bignum, lpe->bignum,
1035440a403fSchristos 			      sizeof (LITTLENUM_TYPE)*exp_p->X_add_number) == 0)
1036440a403fSchristos 		    break;
1037440a403fSchristos 		}
1038440a403fSchristos 	    }
1039440a403fSchristos 	}
1040440a403fSchristos     }
1041440a403fSchristos   else
1042440a403fSchristos     {
1043440a403fSchristos       /* Processing for 'normal' data types.  */
1044440a403fSchristos       for (lpe = lpe_list; lpe != NULL; lpe = lpe->next)
1045440a403fSchristos 	if (lpe->nbytes == nbytes && lpe->reloc == reloc
1046440a403fSchristos 	    && s390_exp_compare (exp_p, &lpe->ex) != 0)
1047440a403fSchristos 	  break;
1048440a403fSchristos     }
1049440a403fSchristos 
1050440a403fSchristos   if (lpe == NULL)
1051440a403fSchristos     {
1052440a403fSchristos       /* A new literal.  */
1053440a403fSchristos       if (lpe_free_list != NULL)
1054440a403fSchristos 	{
1055440a403fSchristos 	  lpe = lpe_free_list;
1056440a403fSchristos 	  lpe_free_list = lpe_free_list->next;
1057440a403fSchristos 	}
1058440a403fSchristos       else
1059440a403fSchristos 	{
1060440a403fSchristos 	  lpe = XNEW (struct s390_lpe);
1061440a403fSchristos 	}
1062440a403fSchristos 
1063440a403fSchristos       lpe->ex = *exp_p;
1064440a403fSchristos 
1065440a403fSchristos       if (exp_p->X_op == O_big)
1066440a403fSchristos 	{
1067440a403fSchristos 	  if (exp_p->X_add_number <= 0)
1068440a403fSchristos 	    lpe->floatnum = generic_floating_point_number;
1069440a403fSchristos 	  else if (exp_p->X_add_number <= 4)
1070440a403fSchristos 	    memcpy (lpe->bignum, generic_bignum,
1071440a403fSchristos 		    exp_p->X_add_number * sizeof (LITTLENUM_TYPE));
1072440a403fSchristos 	  else
1073440a403fSchristos 	    as_bad (_("Big number is too big"));
1074440a403fSchristos 	}
1075440a403fSchristos 
1076440a403fSchristos       lpe->nbytes = nbytes;
1077440a403fSchristos       lpe->reloc = reloc;
1078440a403fSchristos       /* Literal pool name defined ?  */
1079440a403fSchristos       if (lp_sym == NULL)
1080440a403fSchristos 	{
1081440a403fSchristos 	  sprintf (tmp_name, ".L\001%i", lp_count);
1082440a403fSchristos 	  lp_sym = symbol_make (tmp_name);
1083440a403fSchristos 	}
1084440a403fSchristos 
1085440a403fSchristos       /* Make name for literal pool entry.  */
1086440a403fSchristos       sprintf (tmp_name, ".L\001%i\002%i", lp_count, lpe_count);
1087440a403fSchristos       lpe_count++;
1088440a403fSchristos       lpe->sym = symbol_make (tmp_name);
1089440a403fSchristos 
1090440a403fSchristos       /* Add to literal pool list.  */
1091440a403fSchristos       lpe->next = NULL;
1092440a403fSchristos       if (lpe_list_tail != NULL)
1093440a403fSchristos 	{
1094440a403fSchristos 	  lpe_list_tail->next = lpe;
1095440a403fSchristos 	  lpe_list_tail = lpe;
1096440a403fSchristos 	}
1097440a403fSchristos       else
1098440a403fSchristos 	lpe_list = lpe_list_tail = lpe;
1099440a403fSchristos     }
1100440a403fSchristos 
1101440a403fSchristos   /* Now change exp_p to the offset into the literal pool.
110206324dcfSchristos      That's the expression: .L^Ax^By-.L^Ax   */
1103440a403fSchristos   exp_p->X_add_symbol = lpe->sym;
1104440a403fSchristos   exp_p->X_op_symbol = lp_sym;
1105440a403fSchristos   exp_p->X_op = O_subtract;
1106440a403fSchristos   exp_p->X_add_number = 0;
1107440a403fSchristos 
1108440a403fSchristos   *str_p = str;
1109440a403fSchristos 
1110440a403fSchristos   /* We change the suffix type to ELF_SUFFIX_NONE, because
1111440a403fSchristos      the difference of two local labels is just a number.  */
1112440a403fSchristos   return ELF_SUFFIX_NONE;
1113440a403fSchristos }
1114440a403fSchristos 
1115440a403fSchristos /* Like normal .long/.short/.word, except support @got, etc.
1116440a403fSchristos    clobbers input_line_pointer, checks end-of-line.  */
1117440a403fSchristos static void
s390_elf_cons(int nbytes)1118440a403fSchristos s390_elf_cons (int nbytes /* 1=.byte, 2=.word, 4=.long */)
1119440a403fSchristos {
1120440a403fSchristos   expressionS exp;
1121440a403fSchristos   elf_suffix_type suffix;
1122440a403fSchristos 
1123440a403fSchristos   if (is_it_end_of_statement ())
1124440a403fSchristos     {
1125440a403fSchristos       demand_empty_rest_of_line ();
1126440a403fSchristos       return;
1127440a403fSchristos     }
1128440a403fSchristos 
1129440a403fSchristos   do
1130440a403fSchristos     {
1131440a403fSchristos       expression (&exp);
1132440a403fSchristos 
1133440a403fSchristos       if (exp.X_op == O_symbol
1134440a403fSchristos 	  && *input_line_pointer == '@'
1135440a403fSchristos 	  && (suffix = s390_elf_suffix (&input_line_pointer, &exp)) != ELF_SUFFIX_NONE)
1136440a403fSchristos 	{
1137440a403fSchristos 	  bfd_reloc_code_real_type reloc;
1138440a403fSchristos 	  reloc_howto_type *reloc_howto;
1139440a403fSchristos 	  int size;
1140440a403fSchristos 	  char *where;
1141440a403fSchristos 
1142440a403fSchristos 	  if (nbytes == 2)
1143440a403fSchristos 	    {
1144440a403fSchristos 	      static bfd_reloc_code_real_type tab2[] =
1145440a403fSchristos 		{
1146440a403fSchristos 		  BFD_RELOC_UNUSED, 		/* ELF_SUFFIX_NONE  */
1147440a403fSchristos 		  BFD_RELOC_390_GOT16,		/* ELF_SUFFIX_GOT  */
1148440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_PLT  */
1149440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_GOTENT  */
1150440a403fSchristos 		  BFD_RELOC_16_GOTOFF,		/* ELF_SUFFIX_GOTOFF  */
1151440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_GOTPLT  */
1152440a403fSchristos 		  BFD_RELOC_390_PLTOFF16,	/* ELF_SUFFIX_PLTOFF  */
1153440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_TLS_GD  */
1154440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_TLS_GOTIE  */
1155440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_TLS_IE  */
1156440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_TLS_LDM  */
1157440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_TLS_LDO  */
1158440a403fSchristos 		  BFD_RELOC_UNUSED		/* ELF_SUFFIX_TLS_LE  */
1159440a403fSchristos 		};
1160440a403fSchristos 	      reloc = tab2[suffix];
1161440a403fSchristos 	    }
1162440a403fSchristos 	  else if (nbytes == 4)
1163440a403fSchristos 	    {
1164440a403fSchristos 	      static bfd_reloc_code_real_type tab4[] =
1165440a403fSchristos 		{
1166440a403fSchristos 		  BFD_RELOC_UNUSED, 		/* ELF_SUFFIX_NONE  */
1167440a403fSchristos 		  BFD_RELOC_32_GOT_PCREL,	/* ELF_SUFFIX_GOT  */
1168440a403fSchristos 		  BFD_RELOC_390_PLT32,		/* ELF_SUFFIX_PLT  */
1169440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_GOTENT  */
1170440a403fSchristos 		  BFD_RELOC_32_GOTOFF,		/* ELF_SUFFIX_GOTOFF  */
1171440a403fSchristos 		  BFD_RELOC_390_GOTPLT32,	/* ELF_SUFFIX_GOTPLT  */
1172440a403fSchristos 		  BFD_RELOC_390_PLTOFF32,	/* ELF_SUFFIX_PLTOFF  */
1173440a403fSchristos 		  BFD_RELOC_390_TLS_GD32,	/* ELF_SUFFIX_TLS_GD  */
1174440a403fSchristos 		  BFD_RELOC_390_TLS_GOTIE32,	/* ELF_SUFFIX_TLS_GOTIE  */
1175440a403fSchristos 		  BFD_RELOC_390_TLS_IE32,	/* ELF_SUFFIX_TLS_IE  */
1176440a403fSchristos 		  BFD_RELOC_390_TLS_LDM32,	/* ELF_SUFFIX_TLS_LDM  */
1177440a403fSchristos 		  BFD_RELOC_390_TLS_LDO32,	/* ELF_SUFFIX_TLS_LDO  */
1178440a403fSchristos 		  BFD_RELOC_390_TLS_LE32	/* ELF_SUFFIX_TLS_LE  */
1179440a403fSchristos 		};
1180440a403fSchristos 	      reloc = tab4[suffix];
1181440a403fSchristos 	    }
1182440a403fSchristos 	  else if (nbytes == 8)
1183440a403fSchristos 	    {
1184440a403fSchristos 	      static bfd_reloc_code_real_type tab8[] =
1185440a403fSchristos 		{
1186440a403fSchristos 		  BFD_RELOC_UNUSED, 		/* ELF_SUFFIX_NONE  */
1187440a403fSchristos 		  BFD_RELOC_390_GOT64,		/* ELF_SUFFIX_GOT  */
1188440a403fSchristos 		  BFD_RELOC_390_PLT64,		/* ELF_SUFFIX_PLT  */
1189440a403fSchristos 		  BFD_RELOC_UNUSED,		/* ELF_SUFFIX_GOTENT  */
1190440a403fSchristos 		  BFD_RELOC_390_GOTOFF64,	/* ELF_SUFFIX_GOTOFF  */
1191440a403fSchristos 		  BFD_RELOC_390_GOTPLT64,	/* ELF_SUFFIX_GOTPLT  */
1192440a403fSchristos 		  BFD_RELOC_390_PLTOFF64,	/* ELF_SUFFIX_PLTOFF  */
1193440a403fSchristos 		  BFD_RELOC_390_TLS_GD64,	/* ELF_SUFFIX_TLS_GD  */
1194440a403fSchristos 		  BFD_RELOC_390_TLS_GOTIE64,	/* ELF_SUFFIX_TLS_GOTIE  */
1195440a403fSchristos 		  BFD_RELOC_390_TLS_IE64,	/* ELF_SUFFIX_TLS_IE  */
1196440a403fSchristos 		  BFD_RELOC_390_TLS_LDM64,	/* ELF_SUFFIX_TLS_LDM  */
1197440a403fSchristos 		  BFD_RELOC_390_TLS_LDO64,	/* ELF_SUFFIX_TLS_LDO  */
1198440a403fSchristos 		  BFD_RELOC_390_TLS_LE64	/* ELF_SUFFIX_TLS_LE  */
1199440a403fSchristos 		};
1200440a403fSchristos 	      reloc = tab8[suffix];
1201440a403fSchristos 	    }
1202440a403fSchristos 	  else
1203440a403fSchristos 	    reloc = BFD_RELOC_UNUSED;
1204440a403fSchristos 
1205440a403fSchristos 	  if (reloc != BFD_RELOC_UNUSED
1206440a403fSchristos 	      && (reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc)))
1207440a403fSchristos 	    {
1208440a403fSchristos 	      size = bfd_get_reloc_size (reloc_howto);
1209440a403fSchristos 	      if (size > nbytes)
121006324dcfSchristos 		as_bad (ngettext ("%s relocations do not fit in %d byte",
121106324dcfSchristos 				  "%s relocations do not fit in %d bytes",
121206324dcfSchristos 				  nbytes),
1213440a403fSchristos 			reloc_howto->name, nbytes);
1214440a403fSchristos 	      where = frag_more (nbytes);
1215440a403fSchristos 	      md_number_to_chars (where, 0, size);
1216440a403fSchristos 	      /* To make fixup_segment do the pc relative conversion the
1217440a403fSchristos 		 pcrel parameter on the fix_new_exp call needs to be FALSE.  */
1218440a403fSchristos 	      fix_new_exp (frag_now, where - frag_now->fr_literal,
1219440a403fSchristos 			   size, &exp, FALSE, reloc);
1220440a403fSchristos 	    }
1221440a403fSchristos 	  else
1222440a403fSchristos 	    as_bad (_("relocation not applicable"));
1223440a403fSchristos 	}
1224440a403fSchristos       else
1225440a403fSchristos 	emit_expr (&exp, (unsigned int) nbytes);
1226440a403fSchristos     }
1227440a403fSchristos   while (*input_line_pointer++ == ',');
1228440a403fSchristos 
1229440a403fSchristos   input_line_pointer--;		/* Put terminator back into stream.  */
1230440a403fSchristos   demand_empty_rest_of_line ();
1231440a403fSchristos }
1232440a403fSchristos 
1233*b88e3e88Schristos /* Return true if all remaining operands in the opcode with
1234*b88e3e88Schristos    OPCODE_FLAGS can be skipped.  */
1235*b88e3e88Schristos static bfd_boolean
skip_optargs_p(unsigned int opcode_flags,const unsigned char * opindex_ptr)1236*b88e3e88Schristos skip_optargs_p (unsigned int opcode_flags, const unsigned char *opindex_ptr)
1237*b88e3e88Schristos {
1238*b88e3e88Schristos   if ((opcode_flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2))
1239*b88e3e88Schristos       && opindex_ptr[0] != '\0'
1240*b88e3e88Schristos       && opindex_ptr[1] == '\0')
1241*b88e3e88Schristos     return TRUE;
1242*b88e3e88Schristos 
1243*b88e3e88Schristos   if ((opcode_flags & S390_INSTR_FLAG_OPTPARM2)
1244*b88e3e88Schristos       && opindex_ptr[0] != '\0'
1245*b88e3e88Schristos       && opindex_ptr[1] != '\0'
1246*b88e3e88Schristos       && opindex_ptr[2] == '\0')
1247*b88e3e88Schristos     return TRUE;
1248*b88e3e88Schristos   return FALSE;
1249*b88e3e88Schristos }
1250*b88e3e88Schristos 
1251440a403fSchristos /* We need to keep a list of fixups.  We can't simply generate them as
1252440a403fSchristos    we go, because that would require us to first create the frag, and
1253440a403fSchristos    that would screw up references to ``.''.  */
1254440a403fSchristos 
1255440a403fSchristos struct s390_fixup
1256440a403fSchristos   {
1257440a403fSchristos     expressionS exp;
1258440a403fSchristos     int opindex;
1259440a403fSchristos     bfd_reloc_code_real_type reloc;
1260440a403fSchristos   };
1261440a403fSchristos 
1262440a403fSchristos #define MAX_INSN_FIXUPS (4)
1263440a403fSchristos 
1264440a403fSchristos /* This routine is called for each instruction to be assembled.  */
1265440a403fSchristos 
1266440a403fSchristos static char *
md_gather_operands(char * str,unsigned char * insn,const struct s390_opcode * opcode)1267440a403fSchristos md_gather_operands (char *str,
1268440a403fSchristos 		    unsigned char *insn,
1269440a403fSchristos 		    const struct s390_opcode *opcode)
1270440a403fSchristos {
1271440a403fSchristos   struct s390_fixup fixups[MAX_INSN_FIXUPS];
1272440a403fSchristos   const struct s390_operand *operand;
1273440a403fSchristos   const unsigned char *opindex_ptr;
1274440a403fSchristos   expressionS ex;
1275440a403fSchristos   elf_suffix_type suffix;
1276440a403fSchristos   bfd_reloc_code_real_type reloc;
1277440a403fSchristos   int skip_optional;
1278440a403fSchristos   char *f;
1279440a403fSchristos   int fc, i;
1280440a403fSchristos 
1281440a403fSchristos   while (ISSPACE (*str))
1282440a403fSchristos     str++;
1283440a403fSchristos 
1284440a403fSchristos   skip_optional = 0;
1285440a403fSchristos 
1286440a403fSchristos   /* Gather the operands.  */
1287440a403fSchristos   fc = 0;
1288440a403fSchristos   for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
1289440a403fSchristos     {
1290440a403fSchristos       char *hold;
1291440a403fSchristos 
1292440a403fSchristos       operand = s390_operands + *opindex_ptr;
1293440a403fSchristos 
129406324dcfSchristos       if ((opcode->flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2))
129506324dcfSchristos 	  && *str == '\0')
1296440a403fSchristos 	{
1297440a403fSchristos 	  /* Optional parameters might need to be ORed with a
1298440a403fSchristos 	     value so calling s390_insert_operand is needed.  */
1299440a403fSchristos 	  s390_insert_operand (insn, operand, 0, NULL, 0);
1300440a403fSchristos 	  break;
1301440a403fSchristos 	}
1302440a403fSchristos 
1303440a403fSchristos       if (skip_optional && (operand->flags & S390_OPERAND_INDEX))
1304440a403fSchristos 	{
1305440a403fSchristos 	  /* We do an early skip. For D(X,B) constructions the index
1306440a403fSchristos 	     register is skipped (X is optional). For D(L,B) the base
1307440a403fSchristos 	     register will be the skipped operand, because L is NOT
1308440a403fSchristos 	     optional.  */
1309440a403fSchristos 	  skip_optional = 0;
1310440a403fSchristos 	  continue;
1311440a403fSchristos 	}
1312440a403fSchristos 
1313440a403fSchristos       /* Gather the operand.  */
1314440a403fSchristos       hold = input_line_pointer;
1315440a403fSchristos       input_line_pointer = str;
1316440a403fSchristos 
1317440a403fSchristos       /* Parse the operand.  */
1318440a403fSchristos       if (! register_name (&ex))
1319440a403fSchristos 	expression (&ex);
1320440a403fSchristos 
1321440a403fSchristos       str = input_line_pointer;
1322440a403fSchristos       input_line_pointer = hold;
1323440a403fSchristos 
1324440a403fSchristos       /* Write the operand to the insn.  */
1325440a403fSchristos       if (ex.X_op == O_illegal)
1326440a403fSchristos 	as_bad (_("illegal operand"));
1327440a403fSchristos       else if (ex.X_op == O_absent)
1328440a403fSchristos 	{
1329440a403fSchristos 	  if (opindex_ptr[0] == '\0')
1330440a403fSchristos 	    break;
1331440a403fSchristos 	  as_bad (_("missing operand"));
1332440a403fSchristos 	}
1333440a403fSchristos       else if (ex.X_op == O_register || ex.X_op == O_constant)
1334440a403fSchristos 	{
1335440a403fSchristos 	  s390_lit_suffix (&str, &ex, ELF_SUFFIX_NONE);
1336440a403fSchristos 
1337440a403fSchristos 	  if (ex.X_op != O_register && ex.X_op != O_constant)
1338440a403fSchristos 	    {
1339440a403fSchristos 	      /* We need to generate a fixup for the
1340440a403fSchristos 		 expression returned by s390_lit_suffix.  */
1341440a403fSchristos 	      if (fc >= MAX_INSN_FIXUPS)
1342440a403fSchristos 		as_fatal (_("too many fixups"));
1343440a403fSchristos 	      fixups[fc].exp = ex;
1344440a403fSchristos 	      fixups[fc].opindex = *opindex_ptr;
1345440a403fSchristos 	      fixups[fc].reloc = BFD_RELOC_UNUSED;
1346440a403fSchristos 	      ++fc;
1347440a403fSchristos 	    }
1348440a403fSchristos 	  else
1349440a403fSchristos 	    {
1350440a403fSchristos 	      if ((operand->flags & S390_OPERAND_LENGTH)
1351440a403fSchristos 		  && ex.X_op != O_constant)
1352440a403fSchristos 		as_fatal (_("invalid length field specified"));
1353440a403fSchristos 	      if ((operand->flags & S390_OPERAND_INDEX)
1354440a403fSchristos 		  && ex.X_add_number == 0
1355440a403fSchristos 		  && warn_areg_zero)
1356440a403fSchristos 		as_warn (_("index register specified but zero"));
1357440a403fSchristos 	      if ((operand->flags & S390_OPERAND_BASE)
1358440a403fSchristos 		  && ex.X_add_number == 0
1359440a403fSchristos 		  && warn_areg_zero)
1360440a403fSchristos 		as_warn (_("base register specified but zero"));
1361440a403fSchristos 	      if ((operand->flags & S390_OPERAND_GPR)
1362440a403fSchristos 		  && (operand->flags & S390_OPERAND_REG_PAIR)
1363440a403fSchristos 		  && (ex.X_add_number & 1))
1364440a403fSchristos 		as_fatal (_("odd numbered general purpose register specified as "
1365440a403fSchristos 			    "register pair"));
1366440a403fSchristos 	      if ((operand->flags & S390_OPERAND_FPR)
1367440a403fSchristos 		  && (operand->flags & S390_OPERAND_REG_PAIR)
1368440a403fSchristos 		  && ex.X_add_number != 0 && ex.X_add_number != 1
1369440a403fSchristos 		  && ex.X_add_number != 4 && ex.X_add_number != 5
1370440a403fSchristos 		  && ex.X_add_number != 8 && ex.X_add_number != 9
1371440a403fSchristos 		  && ex.X_add_number != 12 && ex.X_add_number != 13)
1372440a403fSchristos 		as_fatal (_("invalid floating point register pair.  Valid fp "
1373440a403fSchristos 			    "register pair operands are 0, 1, 4, 5, 8, 9, "
1374440a403fSchristos 			    "12 or 13."));
1375440a403fSchristos 	      s390_insert_operand (insn, operand, ex.X_add_number, NULL, 0);
1376440a403fSchristos 	    }
1377440a403fSchristos 	}
1378440a403fSchristos       else
1379440a403fSchristos 	{
1380440a403fSchristos 	  suffix = s390_elf_suffix (&str, &ex);
1381440a403fSchristos 	  suffix = s390_lit_suffix (&str, &ex, suffix);
1382440a403fSchristos 	  reloc = BFD_RELOC_UNUSED;
1383440a403fSchristos 
1384440a403fSchristos 	  if (suffix == ELF_SUFFIX_GOT)
1385440a403fSchristos 	    {
1386440a403fSchristos 	      if ((operand->flags & S390_OPERAND_DISP) &&
1387440a403fSchristos 		  (operand->bits == 12))
1388440a403fSchristos 		reloc = BFD_RELOC_390_GOT12;
1389440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_DISP) &&
1390440a403fSchristos 		       (operand->bits == 20))
1391440a403fSchristos 		reloc = BFD_RELOC_390_GOT20;
1392440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_SIGNED)
1393440a403fSchristos 		       && (operand->bits == 16))
1394440a403fSchristos 		reloc = BFD_RELOC_390_GOT16;
1395440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_PCREL)
1396440a403fSchristos 		       && (operand->bits == 32))
1397440a403fSchristos 		reloc = BFD_RELOC_390_GOTENT;
1398440a403fSchristos 	    }
1399440a403fSchristos 	  else if (suffix == ELF_SUFFIX_PLT)
1400440a403fSchristos 	    {
1401440a403fSchristos 	      if ((operand->flags & S390_OPERAND_PCREL)
1402440a403fSchristos 		  && (operand->bits == 12))
1403440a403fSchristos 		reloc = BFD_RELOC_390_PLT12DBL;
1404440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_PCREL)
1405440a403fSchristos 		       && (operand->bits == 16))
1406440a403fSchristos 		reloc = BFD_RELOC_390_PLT16DBL;
1407440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_PCREL)
1408440a403fSchristos 		       && (operand->bits == 24))
1409440a403fSchristos 		reloc = BFD_RELOC_390_PLT24DBL;
1410440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_PCREL)
1411440a403fSchristos 		       && (operand->bits == 32))
1412440a403fSchristos 		reloc = BFD_RELOC_390_PLT32DBL;
1413440a403fSchristos 	    }
1414440a403fSchristos 	  else if (suffix == ELF_SUFFIX_GOTENT)
1415440a403fSchristos 	    {
1416440a403fSchristos 	      if ((operand->flags & S390_OPERAND_PCREL)
1417440a403fSchristos 		  && (operand->bits == 32))
1418440a403fSchristos 		reloc = BFD_RELOC_390_GOTENT;
1419440a403fSchristos 	    }
1420440a403fSchristos 	  else if (suffix == ELF_SUFFIX_GOTOFF)
1421440a403fSchristos 	    {
1422440a403fSchristos 	      if ((operand->flags & S390_OPERAND_SIGNED)
1423440a403fSchristos 		  && (operand->bits == 16))
1424440a403fSchristos 		reloc = BFD_RELOC_16_GOTOFF;
1425440a403fSchristos 	    }
1426440a403fSchristos 	  else if (suffix == ELF_SUFFIX_PLTOFF)
1427440a403fSchristos 	    {
1428440a403fSchristos 	      if ((operand->flags & S390_OPERAND_SIGNED)
1429440a403fSchristos 		  && (operand->bits == 16))
1430440a403fSchristos 		reloc = BFD_RELOC_390_PLTOFF16;
1431440a403fSchristos 	    }
1432440a403fSchristos 	  else if (suffix == ELF_SUFFIX_GOTPLT)
1433440a403fSchristos 	    {
1434440a403fSchristos 	      if ((operand->flags & S390_OPERAND_DISP)
1435440a403fSchristos 		  && (operand->bits == 12))
1436440a403fSchristos 		reloc = BFD_RELOC_390_GOTPLT12;
1437440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_SIGNED)
1438440a403fSchristos 		       && (operand->bits == 16))
1439440a403fSchristos 		reloc = BFD_RELOC_390_GOTPLT16;
1440440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_PCREL)
1441440a403fSchristos 		       && (operand->bits == 32))
1442440a403fSchristos 		reloc = BFD_RELOC_390_GOTPLTENT;
1443440a403fSchristos 	    }
1444440a403fSchristos 	  else if (suffix == ELF_SUFFIX_TLS_GOTIE)
1445440a403fSchristos 	    {
1446440a403fSchristos 	      if ((operand->flags & S390_OPERAND_DISP)
1447440a403fSchristos 		  && (operand->bits == 12))
1448440a403fSchristos 		reloc = BFD_RELOC_390_TLS_GOTIE12;
1449440a403fSchristos 	      else if ((operand->flags & S390_OPERAND_DISP)
1450440a403fSchristos 		       && (operand->bits == 20))
1451440a403fSchristos 		reloc = BFD_RELOC_390_TLS_GOTIE20;
1452440a403fSchristos 	    }
1453440a403fSchristos 	  else if (suffix == ELF_SUFFIX_TLS_IE)
1454440a403fSchristos 	    {
1455440a403fSchristos 	      if ((operand->flags & S390_OPERAND_PCREL)
1456440a403fSchristos 		       && (operand->bits == 32))
1457440a403fSchristos 		reloc = BFD_RELOC_390_TLS_IEENT;
1458440a403fSchristos 	    }
1459440a403fSchristos 
1460440a403fSchristos 	  if (suffix != ELF_SUFFIX_NONE && reloc == BFD_RELOC_UNUSED)
1461440a403fSchristos 	    as_bad (_("invalid operand suffix"));
1462440a403fSchristos 	  /* We need to generate a fixup of type 'reloc' for this
1463440a403fSchristos 	     expression.  */
1464440a403fSchristos 	  if (fc >= MAX_INSN_FIXUPS)
1465440a403fSchristos 	    as_fatal (_("too many fixups"));
1466440a403fSchristos 	  fixups[fc].exp = ex;
1467440a403fSchristos 	  fixups[fc].opindex = *opindex_ptr;
1468440a403fSchristos 	  fixups[fc].reloc = reloc;
1469440a403fSchristos 	  ++fc;
1470440a403fSchristos 	}
1471440a403fSchristos 
1472440a403fSchristos       /* Check the next character. The call to expression has advanced
1473440a403fSchristos 	 str past any whitespace.  */
1474440a403fSchristos       if (operand->flags & S390_OPERAND_DISP)
1475440a403fSchristos 	{
1476440a403fSchristos 	  /* After a displacement a block in parentheses can start.  */
1477440a403fSchristos 	  if (*str != '(')
1478440a403fSchristos 	    {
1479440a403fSchristos 	      /* Check if parenthesized block can be skipped. If the next
148006324dcfSchristos 		 operand is neither an optional operand nor a base register
1481440a403fSchristos 		 then we have a syntax error.  */
1482440a403fSchristos 	      operand = s390_operands + *(++opindex_ptr);
1483440a403fSchristos 	      if (!(operand->flags & (S390_OPERAND_INDEX|S390_OPERAND_BASE)))
1484440a403fSchristos 		as_bad (_("syntax error; missing '(' after displacement"));
1485440a403fSchristos 
1486440a403fSchristos 	      /* Ok, skip all operands until S390_OPERAND_BASE.  */
1487440a403fSchristos 	      while (!(operand->flags & S390_OPERAND_BASE))
1488440a403fSchristos 		operand = s390_operands + *(++opindex_ptr);
1489440a403fSchristos 
1490*b88e3e88Schristos 	      if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1]))
1491*b88e3e88Schristos 		continue;
1492*b88e3e88Schristos 
1493440a403fSchristos 	      /* If there is a next operand it must be separated by a comma.  */
1494440a403fSchristos 	      if (opindex_ptr[1] != '\0')
1495440a403fSchristos 		{
1496440a403fSchristos 		  if (*str != ',')
1497440a403fSchristos 		    {
1498440a403fSchristos 		      while (opindex_ptr[1] != '\0')
1499440a403fSchristos 			{
1500440a403fSchristos 			  operand = s390_operands + *(++opindex_ptr);
150106324dcfSchristos 			  as_bad (_("syntax error; expected ','"));
1502440a403fSchristos 			  break;
1503440a403fSchristos 			}
1504440a403fSchristos 		    }
1505440a403fSchristos 		  else
1506440a403fSchristos 		    str++;
1507440a403fSchristos 		}
1508440a403fSchristos 	    }
1509440a403fSchristos 	  else
1510440a403fSchristos 	    {
1511440a403fSchristos 	      /* We found an opening parentheses.  */
1512440a403fSchristos 	      str++;
1513440a403fSchristos 	      for (f = str; *f != '\0'; f++)
1514440a403fSchristos 		if (*f == ',' || *f == ')')
1515440a403fSchristos 		  break;
1516440a403fSchristos 	      /* If there is no comma until the closing parentheses OR
1517440a403fSchristos 		 there is a comma right after the opening parentheses,
1518440a403fSchristos 		 we have to skip optional operands.  */
1519440a403fSchristos 	      if (*f == ',' && f == str)
1520440a403fSchristos 		{
1521440a403fSchristos 		  /* comma directly after '(' ? */
1522440a403fSchristos 		  skip_optional = 1;
1523440a403fSchristos 		  str++;
1524440a403fSchristos 		}
1525440a403fSchristos 	      else
1526440a403fSchristos 		skip_optional = (*f != ',');
1527440a403fSchristos 	    }
1528440a403fSchristos 	}
1529440a403fSchristos       else if (operand->flags & S390_OPERAND_BASE)
1530440a403fSchristos 	{
153106324dcfSchristos 	  /* After the base register the parenthesised block ends.  */
1532440a403fSchristos 	  if (*str++ != ')')
1533440a403fSchristos 	    as_bad (_("syntax error; missing ')' after base register"));
1534440a403fSchristos 	  skip_optional = 0;
1535*b88e3e88Schristos 
1536*b88e3e88Schristos 	  if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1]))
1537*b88e3e88Schristos 	    continue;
1538*b88e3e88Schristos 
1539440a403fSchristos 	  /* If there is a next operand it must be separated by a comma.  */
1540440a403fSchristos 	  if (opindex_ptr[1] != '\0')
1541440a403fSchristos 	    {
1542440a403fSchristos 	      if (*str != ',')
1543440a403fSchristos 		{
1544440a403fSchristos 		  while (opindex_ptr[1] != '\0')
1545440a403fSchristos 		    {
1546440a403fSchristos 		      operand = s390_operands + *(++opindex_ptr);
154706324dcfSchristos 		      as_bad (_("syntax error; expected ','"));
1548440a403fSchristos 		      break;
1549440a403fSchristos 		    }
1550440a403fSchristos 		}
1551440a403fSchristos 	      else
1552440a403fSchristos 		str++;
1553440a403fSchristos 	    }
1554440a403fSchristos 	}
1555440a403fSchristos       else
1556440a403fSchristos 	{
1557440a403fSchristos 	  /* We can find an 'early' closing parentheses in e.g. D(L) instead
1558440a403fSchristos 	     of D(L,B).  In this case the base register has to be skipped.  */
1559440a403fSchristos 	  if (*str == ')')
1560440a403fSchristos 	    {
1561440a403fSchristos 	      operand = s390_operands + *(++opindex_ptr);
1562440a403fSchristos 
1563440a403fSchristos 	      if (!(operand->flags & S390_OPERAND_BASE))
1564440a403fSchristos 		as_bad (_("syntax error; ')' not allowed here"));
1565440a403fSchristos 	      str++;
1566440a403fSchristos 	    }
1567440a403fSchristos 
1568*b88e3e88Schristos 	  if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1]))
1569440a403fSchristos 	    continue;
1570440a403fSchristos 
1571440a403fSchristos 	  /* If there is a next operand it must be separated by a comma.  */
1572440a403fSchristos 	  if (opindex_ptr[1] != '\0')
1573440a403fSchristos 	    {
1574440a403fSchristos 	      if (*str != ',')
1575440a403fSchristos 		{
1576440a403fSchristos 		  while (opindex_ptr[1] != '\0')
1577440a403fSchristos 		    {
1578440a403fSchristos 		      operand = s390_operands + *(++opindex_ptr);
157906324dcfSchristos 		      as_bad (_("syntax error; expected ','"));
1580440a403fSchristos 		      break;
1581440a403fSchristos 		    }
1582440a403fSchristos 		}
1583440a403fSchristos 	      else
1584440a403fSchristos 		str++;
1585440a403fSchristos 	    }
1586440a403fSchristos 	}
1587440a403fSchristos     }
1588440a403fSchristos 
1589440a403fSchristos   while (ISSPACE (*str))
1590440a403fSchristos     ++str;
1591440a403fSchristos 
1592440a403fSchristos   /* Check for tls instruction marker.  */
1593440a403fSchristos   reloc = s390_tls_suffix (&str, &ex);
1594440a403fSchristos   if (reloc != BFD_RELOC_UNUSED)
1595440a403fSchristos     {
1596440a403fSchristos       /* We need to generate a fixup of type 'reloc' for this
1597440a403fSchristos 	 instruction.  */
1598440a403fSchristos       if (fc >= MAX_INSN_FIXUPS)
1599440a403fSchristos 	as_fatal (_("too many fixups"));
1600440a403fSchristos       fixups[fc].exp = ex;
1601440a403fSchristos       fixups[fc].opindex = -1;
1602440a403fSchristos       fixups[fc].reloc = reloc;
1603440a403fSchristos       ++fc;
1604440a403fSchristos     }
1605440a403fSchristos 
1606440a403fSchristos   if (*str != '\0')
1607440a403fSchristos     {
1608440a403fSchristos       char *linefeed;
1609440a403fSchristos 
1610440a403fSchristos       if ((linefeed = strchr (str, '\n')) != NULL)
1611440a403fSchristos 	*linefeed = '\0';
1612440a403fSchristos       as_bad (_("junk at end of line: `%s'"), str);
1613440a403fSchristos       if (linefeed != NULL)
1614440a403fSchristos 	*linefeed = '\n';
1615440a403fSchristos     }
1616440a403fSchristos 
1617440a403fSchristos   /* Write out the instruction.  */
1618440a403fSchristos   f = frag_more (opcode->oplen);
1619440a403fSchristos   memcpy (f, insn, opcode->oplen);
1620440a403fSchristos   dwarf2_emit_insn (opcode->oplen);
1621440a403fSchristos 
1622440a403fSchristos   /* Create any fixups.  At this point we do not use a
1623440a403fSchristos      bfd_reloc_code_real_type, but instead just use the
1624440a403fSchristos      BFD_RELOC_UNUSED plus the operand index.  This lets us easily
1625440a403fSchristos      handle fixups for any operand type, although that is admittedly
1626440a403fSchristos      not a very exciting feature.  We pick a BFD reloc type in
1627440a403fSchristos      md_apply_fix.  */
1628440a403fSchristos   for (i = 0; i < fc; i++)
1629440a403fSchristos     {
1630440a403fSchristos 
1631440a403fSchristos       if (fixups[i].opindex < 0)
1632440a403fSchristos 	{
1633440a403fSchristos 	  /* Create tls instruction marker relocation.  */
1634440a403fSchristos 	  fix_new_exp (frag_now, f - frag_now->fr_literal, opcode->oplen,
1635440a403fSchristos 		       &fixups[i].exp, 0, fixups[i].reloc);
1636440a403fSchristos 	  continue;
1637440a403fSchristos 	}
1638440a403fSchristos 
1639440a403fSchristos       operand = s390_operands + fixups[i].opindex;
1640440a403fSchristos 
1641440a403fSchristos       if (fixups[i].reloc != BFD_RELOC_UNUSED)
1642440a403fSchristos 	{
1643440a403fSchristos 	  reloc_howto_type *reloc_howto;
1644440a403fSchristos 	  fixS *fixP;
1645440a403fSchristos 	  int size;
1646440a403fSchristos 
1647440a403fSchristos 	  reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
1648440a403fSchristos 	  if (!reloc_howto)
1649440a403fSchristos 	    abort ();
1650440a403fSchristos 
1651440a403fSchristos 	  size = ((reloc_howto->bitsize - 1) / 8) + 1;
1652440a403fSchristos 
1653440a403fSchristos 	  if (size < 1 || size > 4)
1654440a403fSchristos 	    abort ();
1655440a403fSchristos 
1656440a403fSchristos 	  fixP = fix_new_exp (frag_now,
1657440a403fSchristos 			      f - frag_now->fr_literal + (operand->shift/8),
1658440a403fSchristos 			      size, &fixups[i].exp, reloc_howto->pc_relative,
1659440a403fSchristos 			      fixups[i].reloc);
1660440a403fSchristos 	  /* Turn off overflow checking in fixup_segment. This is necessary
1661440a403fSchristos 	     because fixup_segment will signal an overflow for large 4 byte
1662440a403fSchristos 	     quantities for GOT12 relocations.  */
1663440a403fSchristos 	  if (   fixups[i].reloc == BFD_RELOC_390_GOT12
1664440a403fSchristos 	      || fixups[i].reloc == BFD_RELOC_390_GOT20
1665440a403fSchristos 	      || fixups[i].reloc == BFD_RELOC_390_GOT16)
1666440a403fSchristos 	    fixP->fx_no_overflow = 1;
166706324dcfSchristos 
166806324dcfSchristos 	  if (operand->flags & S390_OPERAND_PCREL)
166906324dcfSchristos 	    fixP->fx_pcrel_adjust = operand->shift / 8;
1670440a403fSchristos 	}
1671440a403fSchristos       else
1672440a403fSchristos 	fix_new_exp (frag_now, f - frag_now->fr_literal, 4, &fixups[i].exp,
1673440a403fSchristos 		     (operand->flags & S390_OPERAND_PCREL) != 0,
1674440a403fSchristos 		     ((bfd_reloc_code_real_type)
1675440a403fSchristos 		      (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
1676440a403fSchristos     }
1677440a403fSchristos   return str;
1678440a403fSchristos }
1679440a403fSchristos 
1680440a403fSchristos /* This routine is called for each instruction to be assembled.  */
1681440a403fSchristos 
1682440a403fSchristos void
md_assemble(char * str)1683440a403fSchristos md_assemble (char *str)
1684440a403fSchristos {
1685440a403fSchristos   const struct s390_opcode *opcode;
1686440a403fSchristos   unsigned char insn[6];
1687440a403fSchristos   char *s;
1688440a403fSchristos 
1689440a403fSchristos   /* Get the opcode.  */
1690440a403fSchristos   for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
1691440a403fSchristos     ;
1692440a403fSchristos   if (*s != '\0')
1693440a403fSchristos     *s++ = '\0';
1694440a403fSchristos 
1695440a403fSchristos   /* Look up the opcode in the hash table.  */
1696440a403fSchristos   opcode = (struct s390_opcode *) hash_find (s390_opcode_hash, str);
1697440a403fSchristos   if (opcode == (const struct s390_opcode *) NULL)
1698440a403fSchristos     {
1699440a403fSchristos       as_bad (_("Unrecognized opcode: `%s'"), str);
1700440a403fSchristos       return;
1701440a403fSchristos     }
1702440a403fSchristos   else if (!(opcode->modes & current_mode_mask))
1703440a403fSchristos     {
1704440a403fSchristos       as_bad (_("Opcode %s not available in this mode"), str);
1705440a403fSchristos       return;
1706440a403fSchristos     }
1707440a403fSchristos   memcpy (insn, opcode->opcode, sizeof (insn));
1708440a403fSchristos   md_gather_operands (s, insn, opcode);
1709440a403fSchristos }
1710440a403fSchristos 
1711440a403fSchristos #ifndef WORKING_DOT_WORD
1712440a403fSchristos /* Handle long and short jumps. We don't support these */
1713440a403fSchristos void
md_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol)1714440a403fSchristos md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
1715440a403fSchristos      char *ptr;
1716440a403fSchristos      addressT from_addr, to_addr;
1717440a403fSchristos      fragS *frag;
1718440a403fSchristos      symbolS *to_symbol;
1719440a403fSchristos {
1720440a403fSchristos   abort ();
1721440a403fSchristos }
1722440a403fSchristos 
1723440a403fSchristos void
md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)1724440a403fSchristos md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
1725440a403fSchristos      char *ptr;
1726440a403fSchristos      addressT from_addr, to_addr;
1727440a403fSchristos      fragS *frag;
1728440a403fSchristos      symbolS *to_symbol;
1729440a403fSchristos {
1730440a403fSchristos   abort ();
1731440a403fSchristos }
1732440a403fSchristos #endif
1733440a403fSchristos 
1734440a403fSchristos void
s390_bss(int ignore ATTRIBUTE_UNUSED)1735440a403fSchristos s390_bss (int ignore ATTRIBUTE_UNUSED)
1736440a403fSchristos {
1737440a403fSchristos   /* We don't support putting frags in the BSS segment, we fake it
1738440a403fSchristos      by marking in_bss, then looking at s_skip for clues.  */
1739440a403fSchristos 
1740440a403fSchristos   subseg_set (bss_section, 0);
1741440a403fSchristos   demand_empty_rest_of_line ();
1742440a403fSchristos }
1743440a403fSchristos 
1744440a403fSchristos /* Pseudo-op handling.  */
1745440a403fSchristos 
1746440a403fSchristos void
s390_insn(int ignore ATTRIBUTE_UNUSED)1747440a403fSchristos s390_insn (int ignore ATTRIBUTE_UNUSED)
1748440a403fSchristos {
1749440a403fSchristos   expressionS exp;
1750440a403fSchristos   const struct s390_opcode *opformat;
1751440a403fSchristos   unsigned char insn[6];
1752440a403fSchristos   char *s;
1753440a403fSchristos 
1754440a403fSchristos   /* Get the opcode format.  */
1755440a403fSchristos   s = input_line_pointer;
1756440a403fSchristos   while (*s != '\0' && *s != ',' && ! ISSPACE (*s))
1757440a403fSchristos     s++;
1758440a403fSchristos   if (*s != ',')
1759440a403fSchristos     as_bad (_("Invalid .insn format\n"));
1760440a403fSchristos   *s++ = '\0';
1761440a403fSchristos 
1762440a403fSchristos   /* Look up the opcode in the hash table.  */
1763440a403fSchristos   opformat = (struct s390_opcode *)
1764440a403fSchristos     hash_find (s390_opformat_hash, input_line_pointer);
1765440a403fSchristos   if (opformat == (const struct s390_opcode *) NULL)
1766440a403fSchristos     {
1767440a403fSchristos       as_bad (_("Unrecognized opcode format: `%s'"), input_line_pointer);
1768440a403fSchristos       return;
1769440a403fSchristos     }
1770440a403fSchristos   input_line_pointer = s;
1771440a403fSchristos   expression (&exp);
1772440a403fSchristos   if (exp.X_op == O_constant)
1773440a403fSchristos     {
1774440a403fSchristos       if (   (   opformat->oplen == 6
1775440a403fSchristos 	      && (addressT) exp.X_add_number < (1ULL << 48))
1776440a403fSchristos 	  || (   opformat->oplen == 4
1777440a403fSchristos 	      && (addressT) exp.X_add_number < (1ULL << 32))
1778440a403fSchristos 	  || (   opformat->oplen == 2
1779440a403fSchristos 	      && (addressT) exp.X_add_number < (1ULL << 16)))
1780440a403fSchristos 	md_number_to_chars ((char *) insn, exp.X_add_number, opformat->oplen);
1781440a403fSchristos       else
1782440a403fSchristos 	as_bad (_("Invalid .insn format\n"));
1783440a403fSchristos     }
1784440a403fSchristos   else if (exp.X_op == O_big)
1785440a403fSchristos     {
1786440a403fSchristos       if (exp.X_add_number > 0
1787440a403fSchristos 	  && opformat->oplen == 6
1788440a403fSchristos 	  && generic_bignum[3] == 0)
1789440a403fSchristos 	{
1790440a403fSchristos 	  md_number_to_chars ((char *) insn, generic_bignum[2], 2);
1791440a403fSchristos 	  md_number_to_chars ((char *) &insn[2], generic_bignum[1], 2);
1792440a403fSchristos 	  md_number_to_chars ((char *) &insn[4], generic_bignum[0], 2);
1793440a403fSchristos 	}
1794440a403fSchristos       else
1795440a403fSchristos 	as_bad (_("Invalid .insn format\n"));
1796440a403fSchristos     }
1797440a403fSchristos   else
1798440a403fSchristos     as_bad (_("second operand of .insn not a constant\n"));
1799440a403fSchristos 
1800440a403fSchristos   if (strcmp (opformat->name, "e") != 0 && *input_line_pointer++ != ',')
1801440a403fSchristos     as_bad (_("missing comma after insn constant\n"));
1802440a403fSchristos 
1803440a403fSchristos   if ((s = strchr (input_line_pointer, '\n')) != NULL)
1804440a403fSchristos     *s = '\0';
1805440a403fSchristos   input_line_pointer = md_gather_operands (input_line_pointer, insn,
1806440a403fSchristos 					   opformat);
1807440a403fSchristos   if (s != NULL)
1808440a403fSchristos     *s = '\n';
1809440a403fSchristos   demand_empty_rest_of_line ();
1810440a403fSchristos }
1811440a403fSchristos 
1812440a403fSchristos /* The .byte pseudo-op.  This is similar to the normal .byte
1813440a403fSchristos    pseudo-op, but it can also take a single ASCII string.  */
1814440a403fSchristos 
1815440a403fSchristos static void
s390_byte(int ignore ATTRIBUTE_UNUSED)1816440a403fSchristos s390_byte (int ignore ATTRIBUTE_UNUSED)
1817440a403fSchristos {
1818440a403fSchristos   if (*input_line_pointer != '\"')
1819440a403fSchristos     {
1820440a403fSchristos       cons (1);
1821440a403fSchristos       return;
1822440a403fSchristos     }
1823440a403fSchristos 
1824440a403fSchristos   /* Gather characters.  A real double quote is doubled.  Unusual
1825440a403fSchristos      characters are not permitted.  */
1826440a403fSchristos   ++input_line_pointer;
1827440a403fSchristos   while (1)
1828440a403fSchristos     {
1829440a403fSchristos       char c;
1830440a403fSchristos 
1831440a403fSchristos       c = *input_line_pointer++;
1832440a403fSchristos 
1833440a403fSchristos       if (c == '\"')
1834440a403fSchristos 	{
1835440a403fSchristos 	  if (*input_line_pointer != '\"')
1836440a403fSchristos 	    break;
1837440a403fSchristos 	  ++input_line_pointer;
1838440a403fSchristos 	}
1839440a403fSchristos 
1840440a403fSchristos       FRAG_APPEND_1_CHAR (c);
1841440a403fSchristos     }
1842440a403fSchristos 
1843440a403fSchristos   demand_empty_rest_of_line ();
1844440a403fSchristos }
1845440a403fSchristos 
1846440a403fSchristos /* The .ltorg pseudo-op.This emits all literals defined since the last
1847440a403fSchristos    .ltorg or the invocation of gas. Literals are defined with the
1848440a403fSchristos    @lit suffix.  */
1849440a403fSchristos 
1850440a403fSchristos static void
s390_literals(int ignore ATTRIBUTE_UNUSED)1851440a403fSchristos s390_literals (int ignore ATTRIBUTE_UNUSED)
1852440a403fSchristos {
1853440a403fSchristos   struct s390_lpe *lpe;
1854440a403fSchristos 
1855440a403fSchristos   if (lp_sym == NULL || lpe_count == 0)
1856440a403fSchristos     return;     /* Nothing to be done.  */
1857440a403fSchristos 
1858440a403fSchristos   /* Emit symbol for start of literal pool.  */
1859440a403fSchristos   S_SET_SEGMENT (lp_sym, now_seg);
1860440a403fSchristos   S_SET_VALUE (lp_sym, (valueT) frag_now_fix ());
1861*b88e3e88Schristos   symbol_set_frag (lp_sym, frag_now);
1862440a403fSchristos 
1863440a403fSchristos   while (lpe_list)
1864440a403fSchristos     {
1865440a403fSchristos       lpe = lpe_list;
1866440a403fSchristos       lpe_list = lpe_list->next;
1867440a403fSchristos       S_SET_SEGMENT (lpe->sym, now_seg);
1868440a403fSchristos       S_SET_VALUE (lpe->sym, (valueT) frag_now_fix ());
1869*b88e3e88Schristos       symbol_set_frag (lpe->sym, frag_now);
1870440a403fSchristos 
1871440a403fSchristos       /* Emit literal pool entry.  */
1872440a403fSchristos       if (lpe->reloc != BFD_RELOC_UNUSED)
1873440a403fSchristos 	{
1874440a403fSchristos 	  reloc_howto_type *reloc_howto =
1875440a403fSchristos 	    bfd_reloc_type_lookup (stdoutput, lpe->reloc);
1876440a403fSchristos 	  int size = bfd_get_reloc_size (reloc_howto);
1877440a403fSchristos 	  char *where;
1878440a403fSchristos 
1879440a403fSchristos 	  if (size > lpe->nbytes)
188006324dcfSchristos 	    as_bad (ngettext ("%s relocations do not fit in %d byte",
188106324dcfSchristos 			      "%s relocations do not fit in %d bytes",
188206324dcfSchristos 			      lpe->nbytes),
1883440a403fSchristos 		    reloc_howto->name, lpe->nbytes);
1884440a403fSchristos 	  where = frag_more (lpe->nbytes);
1885440a403fSchristos 	  md_number_to_chars (where, 0, size);
1886440a403fSchristos 	  fix_new_exp (frag_now, where - frag_now->fr_literal,
1887440a403fSchristos 		       size, &lpe->ex, reloc_howto->pc_relative, lpe->reloc);
1888440a403fSchristos 	}
1889440a403fSchristos       else
1890440a403fSchristos 	{
1891440a403fSchristos 	  if (lpe->ex.X_op == O_big)
1892440a403fSchristos 	    {
1893440a403fSchristos 	      if (lpe->ex.X_add_number <= 0)
1894440a403fSchristos 		generic_floating_point_number = lpe->floatnum;
1895440a403fSchristos 	      else
1896440a403fSchristos 		memcpy (generic_bignum, lpe->bignum,
1897440a403fSchristos 			lpe->ex.X_add_number * sizeof (LITTLENUM_TYPE));
1898440a403fSchristos 	    }
1899440a403fSchristos 	  emit_expr (&lpe->ex, lpe->nbytes);
1900440a403fSchristos 	}
1901440a403fSchristos 
1902440a403fSchristos       lpe->next = lpe_free_list;
1903440a403fSchristos       lpe_free_list = lpe;
1904440a403fSchristos     }
1905440a403fSchristos   lpe_list_tail = NULL;
1906440a403fSchristos   lp_sym = NULL;
1907440a403fSchristos   lp_count++;
1908440a403fSchristos   lpe_count = 0;
1909440a403fSchristos }
1910440a403fSchristos 
1911440a403fSchristos #define MAX_HISTORY 100
1912440a403fSchristos 
1913440a403fSchristos /* The .machine pseudo op allows to switch to a different CPU level in
1914440a403fSchristos    the asm listing.  The current CPU setting can be stored on a stack
1915440a403fSchristos    with .machine push and restored with .machine pop.  */
1916440a403fSchristos 
1917440a403fSchristos static void
s390_machine(int ignore ATTRIBUTE_UNUSED)1918440a403fSchristos s390_machine (int ignore ATTRIBUTE_UNUSED)
1919440a403fSchristos {
1920440a403fSchristos   char *cpu_string;
1921440a403fSchristos   static struct cpu_history
1922440a403fSchristos   {
1923440a403fSchristos     unsigned int cpu;
1924440a403fSchristos     unsigned int flags;
1925440a403fSchristos   } *cpu_history;
1926440a403fSchristos   static int curr_hist;
1927440a403fSchristos 
1928440a403fSchristos   SKIP_WHITESPACE ();
1929440a403fSchristos 
1930440a403fSchristos   if (*input_line_pointer == '"')
1931440a403fSchristos     {
1932440a403fSchristos       int len;
1933440a403fSchristos       cpu_string = demand_copy_C_string (&len);
1934440a403fSchristos     }
1935440a403fSchristos   else
1936440a403fSchristos     {
1937440a403fSchristos       char c;
1938440a403fSchristos 
1939440a403fSchristos       cpu_string = input_line_pointer;
1940440a403fSchristos       do
1941440a403fSchristos 	{
1942440a403fSchristos 	  char * str;
1943440a403fSchristos 
1944440a403fSchristos 	  c = get_symbol_name (&str);
1945440a403fSchristos 	  c = restore_line_pointer (c);
1946440a403fSchristos 	  if (c == '+')
1947440a403fSchristos 	    ++ input_line_pointer;
1948440a403fSchristos 	}
1949440a403fSchristos       while (c == '+');
1950440a403fSchristos 
1951440a403fSchristos       c = *input_line_pointer;
1952440a403fSchristos       *input_line_pointer = 0;
1953440a403fSchristos       cpu_string = xstrdup (cpu_string);
1954440a403fSchristos       (void) restore_line_pointer (c);
1955440a403fSchristos     }
1956440a403fSchristos 
1957440a403fSchristos   if (cpu_string != NULL)
1958440a403fSchristos     {
1959440a403fSchristos       unsigned int new_cpu = current_cpu;
1960440a403fSchristos       unsigned int new_flags = current_flags;
1961440a403fSchristos 
1962440a403fSchristos       if (strcmp (cpu_string, "push") == 0)
1963440a403fSchristos 	{
1964440a403fSchristos 	  if (cpu_history == NULL)
1965440a403fSchristos 	    cpu_history = XNEWVEC (struct cpu_history, MAX_HISTORY);
1966440a403fSchristos 
1967440a403fSchristos 	  if (curr_hist >= MAX_HISTORY)
1968440a403fSchristos 	    as_bad (_(".machine stack overflow"));
1969440a403fSchristos 	  else
1970440a403fSchristos 	    {
1971440a403fSchristos 	      cpu_history[curr_hist].cpu = current_cpu;
1972440a403fSchristos 	      cpu_history[curr_hist].flags = current_flags;
1973440a403fSchristos 	      curr_hist++;
1974440a403fSchristos 	    }
1975440a403fSchristos 	}
1976440a403fSchristos       else if (strcmp (cpu_string, "pop") == 0)
1977440a403fSchristos 	{
1978440a403fSchristos 	  if (curr_hist <= 0)
1979440a403fSchristos 	    as_bad (_(".machine stack underflow"));
1980440a403fSchristos 	  else
1981440a403fSchristos 	    {
1982440a403fSchristos 	      curr_hist--;
1983440a403fSchristos 	      new_cpu = cpu_history[curr_hist].cpu;
1984440a403fSchristos 	      new_flags = cpu_history[curr_hist].flags;
1985440a403fSchristos 	    }
1986440a403fSchristos 	}
1987440a403fSchristos       else
1988440a403fSchristos 	new_cpu = s390_parse_cpu (cpu_string, &new_flags, TRUE);
1989440a403fSchristos 
1990440a403fSchristos       if (new_cpu == S390_OPCODE_MAXCPU)
1991440a403fSchristos 	as_bad (_("invalid machine `%s'"), cpu_string);
1992440a403fSchristos 
1993440a403fSchristos       if (new_cpu != current_cpu || new_flags != current_flags)
1994440a403fSchristos 	{
1995440a403fSchristos 	  current_cpu = new_cpu;
1996440a403fSchristos 	  current_flags = new_flags;
1997440a403fSchristos 	  s390_setup_opcodes ();
1998440a403fSchristos 	}
1999440a403fSchristos     }
2000440a403fSchristos 
2001440a403fSchristos   demand_empty_rest_of_line ();
2002440a403fSchristos }
2003440a403fSchristos 
2004440a403fSchristos /* The .machinemode pseudo op allows to switch to a different
2005440a403fSchristos    architecture mode in the asm listing.  The current architecture
2006440a403fSchristos    mode setting can be stored on a stack with .machinemode push and
2007440a403fSchristos    restored with .machinemode pop.  */
2008440a403fSchristos 
2009440a403fSchristos static void
s390_machinemode(int ignore ATTRIBUTE_UNUSED)2010440a403fSchristos s390_machinemode (int ignore ATTRIBUTE_UNUSED)
2011440a403fSchristos {
2012440a403fSchristos   char *mode_string;
2013440a403fSchristos   static unsigned int *mode_history;
2014440a403fSchristos   static int curr_hist;
2015440a403fSchristos 
2016440a403fSchristos   SKIP_WHITESPACE ();
2017440a403fSchristos 
2018440a403fSchristos   {
2019440a403fSchristos     char c;
2020440a403fSchristos 
2021440a403fSchristos     c = get_symbol_name (&mode_string);
2022440a403fSchristos     mode_string = xstrdup (mode_string);
2023440a403fSchristos     (void) restore_line_pointer (c);
2024440a403fSchristos   }
2025440a403fSchristos 
2026440a403fSchristos   if (mode_string != NULL)
2027440a403fSchristos     {
2028440a403fSchristos       unsigned int old_mode_mask = current_mode_mask;
2029440a403fSchristos       char *p;
2030440a403fSchristos 
2031440a403fSchristos       for (p = mode_string; *p != 0; p++)
2032440a403fSchristos 	*p = TOLOWER (*p);
2033440a403fSchristos 
2034440a403fSchristos       if (strcmp (mode_string, "push") == 0)
2035440a403fSchristos 	{
2036440a403fSchristos 	  if (mode_history == NULL)
2037440a403fSchristos 	    mode_history = XNEWVEC (unsigned int, MAX_HISTORY);
2038440a403fSchristos 
2039440a403fSchristos 	  if (curr_hist >= MAX_HISTORY)
2040440a403fSchristos 	    as_bad (_(".machinemode stack overflow"));
2041440a403fSchristos 	  else
2042440a403fSchristos 	    mode_history[curr_hist++] = current_mode_mask;
2043440a403fSchristos 	}
2044440a403fSchristos       else if (strcmp (mode_string, "pop") == 0)
2045440a403fSchristos 	{
2046440a403fSchristos 	  if (curr_hist <= 0)
2047440a403fSchristos 	    as_bad (_(".machinemode stack underflow"));
2048440a403fSchristos 	  else
2049440a403fSchristos 	    current_mode_mask = mode_history[--curr_hist];
2050440a403fSchristos 	}
2051440a403fSchristos       else
2052440a403fSchristos 	{
2053440a403fSchristos 	  if (strcmp (mode_string, "esa") == 0)
2054440a403fSchristos 	    current_mode_mask = 1 << S390_OPCODE_ESA;
2055440a403fSchristos 	  else if (strcmp (mode_string, "zarch") == 0)
2056440a403fSchristos 	    {
2057440a403fSchristos 	      if (s390_arch_size == 32)
2058440a403fSchristos 		set_highgprs_p = TRUE;
2059440a403fSchristos 	      current_mode_mask = 1 << S390_OPCODE_ZARCH;
2060440a403fSchristos 	    }
2061440a403fSchristos 	  else if (strcmp (mode_string, "zarch_nohighgprs") == 0)
2062440a403fSchristos 	    current_mode_mask = 1 << S390_OPCODE_ZARCH;
2063440a403fSchristos 	  else
2064440a403fSchristos 	    as_bad (_("invalid machine mode `%s'"), mode_string);
2065440a403fSchristos 	}
2066440a403fSchristos 
2067440a403fSchristos       if (current_mode_mask != old_mode_mask)
2068440a403fSchristos 	s390_setup_opcodes ();
2069440a403fSchristos     }
2070440a403fSchristos 
2071440a403fSchristos   demand_empty_rest_of_line ();
2072440a403fSchristos }
2073440a403fSchristos 
2074440a403fSchristos #undef MAX_HISTORY
2075440a403fSchristos 
2076440a403fSchristos const char *
md_atof(int type,char * litp,int * sizep)2077440a403fSchristos md_atof (int type, char *litp, int *sizep)
2078440a403fSchristos {
2079440a403fSchristos   return ieee_md_atof (type, litp, sizep, TRUE);
2080440a403fSchristos }
2081440a403fSchristos 
2082440a403fSchristos /* Align a section (I don't know why this is machine dependent).  */
2083440a403fSchristos 
2084440a403fSchristos valueT
md_section_align(asection * seg,valueT addr)2085440a403fSchristos md_section_align (asection *seg, valueT addr)
2086440a403fSchristos {
2087*b88e3e88Schristos   int align = bfd_section_alignment (seg);
2088440a403fSchristos 
2089440a403fSchristos   return ((addr + (1 << align) - 1) & -(1 << align));
2090440a403fSchristos }
2091440a403fSchristos 
2092440a403fSchristos /* We don't have any form of relaxing.  */
2093440a403fSchristos 
2094440a403fSchristos int
md_estimate_size_before_relax(fragS * fragp ATTRIBUTE_UNUSED,asection * seg ATTRIBUTE_UNUSED)2095440a403fSchristos md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
2096440a403fSchristos 			       asection *seg ATTRIBUTE_UNUSED)
2097440a403fSchristos {
2098440a403fSchristos   abort ();
2099440a403fSchristos   return 0;
2100440a403fSchristos }
2101440a403fSchristos 
2102440a403fSchristos /* Convert a machine dependent frag.  We never generate these.  */
2103440a403fSchristos 
2104440a403fSchristos void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,asection * sec ATTRIBUTE_UNUSED,fragS * fragp ATTRIBUTE_UNUSED)2105440a403fSchristos md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
2106440a403fSchristos 		 asection *sec ATTRIBUTE_UNUSED,
2107440a403fSchristos 		 fragS *fragp ATTRIBUTE_UNUSED)
2108440a403fSchristos {
2109440a403fSchristos   abort ();
2110440a403fSchristos }
2111440a403fSchristos 
2112440a403fSchristos symbolS *
md_undefined_symbol(char * name)2113440a403fSchristos md_undefined_symbol (char *name)
2114440a403fSchristos {
2115440a403fSchristos   if (*name == '_' && *(name + 1) == 'G'
2116440a403fSchristos       && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
2117440a403fSchristos     {
2118440a403fSchristos       if (!GOT_symbol)
2119440a403fSchristos 	{
2120440a403fSchristos 	  if (symbol_find (name))
2121440a403fSchristos 	    as_bad (_("GOT already in symbol table"));
2122440a403fSchristos 	  GOT_symbol = symbol_new (name, undefined_section,
2123440a403fSchristos 				   (valueT) 0, &zero_address_frag);
2124440a403fSchristos 	}
2125440a403fSchristos       return GOT_symbol;
2126440a403fSchristos     }
2127440a403fSchristos   return 0;
2128440a403fSchristos }
2129440a403fSchristos 
2130440a403fSchristos /* Functions concerning relocs.  */
2131440a403fSchristos 
2132440a403fSchristos /* The location from which a PC relative jump should be calculated,
2133440a403fSchristos    given a PC relative reloc.  */
2134440a403fSchristos 
2135440a403fSchristos long
md_pcrel_from_section(fixS * fixp,segT sec ATTRIBUTE_UNUSED)2136440a403fSchristos md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED)
2137440a403fSchristos {
2138440a403fSchristos   return fixp->fx_frag->fr_address + fixp->fx_where;
2139440a403fSchristos }
2140440a403fSchristos 
2141440a403fSchristos /* Here we decide which fixups can be adjusted to make them relative to
2142440a403fSchristos    the beginning of the section instead of the symbol.  Basically we need
2143440a403fSchristos    to make sure that the dynamic relocations are done correctly, so in
2144440a403fSchristos    some cases we force the original symbol to be used.  */
2145440a403fSchristos int
tc_s390_fix_adjustable(fixS * fixP)2146440a403fSchristos tc_s390_fix_adjustable (fixS *fixP)
2147440a403fSchristos {
214806324dcfSchristos   /* Don't adjust pc-relative references to merge sections.  */
214906324dcfSchristos   if (fixP->fx_pcrel
215006324dcfSchristos       && (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
2151440a403fSchristos     return 0;
215206324dcfSchristos 
2153440a403fSchristos   /* adjust_reloc_syms doesn't know about the GOT.  */
2154440a403fSchristos   if (   fixP->fx_r_type == BFD_RELOC_16_GOTOFF
2155440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_32_GOTOFF
2156440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOTOFF64
2157440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLTOFF16
2158440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLTOFF32
2159440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLTOFF64
2160440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLT12DBL
2161440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLT16DBL
2162440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLT24DBL
2163440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLT32
2164440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLT32DBL
2165440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_PLT64
2166440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOT12
2167440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOT20
2168440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOT16
2169440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_32_GOT_PCREL
2170440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOT64
2171440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOTENT
2172440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOTPLT12
2173440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOTPLT16
2174440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOTPLT20
2175440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOTPLT32
2176440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOTPLT64
2177440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_GOTPLTENT
2178440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_LOAD
2179440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_GDCALL
2180440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_LDCALL
2181440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_GD32
2182440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_GD64
2183440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_GOTIE12
2184440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_GOTIE20
2185440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_GOTIE32
2186440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_GOTIE64
2187440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_LDM32
2188440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_LDM64
2189440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_IE32
2190440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_IE64
2191440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_IEENT
2192440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_LE32
2193440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_LE64
2194440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_LDO32
2195440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_LDO64
2196440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_DTPMOD
2197440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_DTPOFF
2198440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_390_TLS_TPOFF
2199440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
2200440a403fSchristos       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
2201440a403fSchristos     return 0;
2202440a403fSchristos   return 1;
2203440a403fSchristos }
2204440a403fSchristos 
2205440a403fSchristos /* Return true if we must always emit a reloc for a type and false if
2206440a403fSchristos    there is some hope of resolving it at assembly time.  */
2207440a403fSchristos int
tc_s390_force_relocation(struct fix * fixp)2208440a403fSchristos tc_s390_force_relocation (struct fix *fixp)
2209440a403fSchristos {
2210440a403fSchristos   /* Ensure we emit a relocation for every reference to the global
2211440a403fSchristos      offset table or to the procedure link table.  */
2212440a403fSchristos   switch (fixp->fx_r_type)
2213440a403fSchristos     {
2214440a403fSchristos     case BFD_RELOC_390_GOT12:
2215440a403fSchristos     case BFD_RELOC_390_GOT20:
2216440a403fSchristos     case BFD_RELOC_32_GOT_PCREL:
2217440a403fSchristos     case BFD_RELOC_32_GOTOFF:
2218440a403fSchristos     case BFD_RELOC_390_GOTOFF64:
2219440a403fSchristos     case BFD_RELOC_390_PLTOFF16:
2220440a403fSchristos     case BFD_RELOC_390_PLTOFF32:
2221440a403fSchristos     case BFD_RELOC_390_PLTOFF64:
2222440a403fSchristos     case BFD_RELOC_390_GOTPC:
2223440a403fSchristos     case BFD_RELOC_390_GOT16:
2224440a403fSchristos     case BFD_RELOC_390_GOTPCDBL:
2225440a403fSchristos     case BFD_RELOC_390_GOT64:
2226440a403fSchristos     case BFD_RELOC_390_GOTENT:
2227440a403fSchristos     case BFD_RELOC_390_PLT32:
2228440a403fSchristos     case BFD_RELOC_390_PLT12DBL:
2229440a403fSchristos     case BFD_RELOC_390_PLT16DBL:
2230440a403fSchristos     case BFD_RELOC_390_PLT24DBL:
2231440a403fSchristos     case BFD_RELOC_390_PLT32DBL:
2232440a403fSchristos     case BFD_RELOC_390_PLT64:
2233440a403fSchristos     case BFD_RELOC_390_GOTPLT12:
2234440a403fSchristos     case BFD_RELOC_390_GOTPLT16:
2235440a403fSchristos     case BFD_RELOC_390_GOTPLT20:
2236440a403fSchristos     case BFD_RELOC_390_GOTPLT32:
2237440a403fSchristos     case BFD_RELOC_390_GOTPLT64:
2238440a403fSchristos     case BFD_RELOC_390_GOTPLTENT:
2239440a403fSchristos       return 1;
2240440a403fSchristos     default:
2241440a403fSchristos       break;
2242440a403fSchristos     }
2243440a403fSchristos 
2244440a403fSchristos   return generic_force_reloc (fixp);
2245440a403fSchristos }
2246440a403fSchristos 
2247440a403fSchristos /* Apply a fixup to the object code.  This is called for all the
2248440a403fSchristos    fixups we generated by the call to fix_new_exp, above.  In the call
2249440a403fSchristos    above we used a reloc code which was the largest legal reloc code
2250440a403fSchristos    plus the operand index.  Here we undo that to recover the operand
2251440a403fSchristos    index.  At this point all symbol values should be fully resolved,
2252440a403fSchristos    and we attempt to completely resolve the reloc.  If we can not do
2253440a403fSchristos    that, we determine the correct reloc code and put it back in the
2254440a403fSchristos    fixup.  */
2255440a403fSchristos 
2256440a403fSchristos void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)2257440a403fSchristos md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
2258440a403fSchristos {
2259440a403fSchristos   char *where;
2260440a403fSchristos   valueT value = *valP;
2261440a403fSchristos 
2262440a403fSchristos   where = fixP->fx_frag->fr_literal + fixP->fx_where;
2263440a403fSchristos 
2264440a403fSchristos   if (fixP->fx_subsy != NULL)
2265440a403fSchristos     as_bad_where (fixP->fx_file, fixP->fx_line,
2266440a403fSchristos 		  _("cannot emit relocation %s against subsy symbol %s"),
2267440a403fSchristos 		  bfd_get_reloc_code_name (fixP->fx_r_type),
2268440a403fSchristos 		  S_GET_NAME (fixP->fx_subsy));
2269440a403fSchristos 
2270440a403fSchristos   if (fixP->fx_addsy != NULL)
2271440a403fSchristos     {
2272440a403fSchristos       if (fixP->fx_pcrel)
2273440a403fSchristos 	value += fixP->fx_frag->fr_address + fixP->fx_where;
2274440a403fSchristos     }
2275440a403fSchristos   else
2276440a403fSchristos     fixP->fx_done = 1;
2277440a403fSchristos 
2278440a403fSchristos   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
2279440a403fSchristos     {
2280440a403fSchristos       const struct s390_operand *operand;
2281440a403fSchristos       int opindex;
2282440a403fSchristos 
2283440a403fSchristos       opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
2284440a403fSchristos       operand = &s390_operands[opindex];
2285440a403fSchristos 
2286440a403fSchristos       if (fixP->fx_done)
2287440a403fSchristos 	{
2288440a403fSchristos 	  /* Insert the fully resolved operand value.  */
2289440a403fSchristos 	  s390_insert_operand ((unsigned char *) where, operand,
2290440a403fSchristos 			       (offsetT) value, fixP->fx_file, fixP->fx_line);
2291440a403fSchristos 	  return;
2292440a403fSchristos 	}
2293440a403fSchristos 
2294440a403fSchristos       /* Determine a BFD reloc value based on the operand information.
2295440a403fSchristos 	 We are only prepared to turn a few of the operands into
2296440a403fSchristos 	 relocs.  */
2297440a403fSchristos       fixP->fx_offset = value;
2298440a403fSchristos       if (operand->bits == 12 && operand->shift == 20)
2299440a403fSchristos 	{
2300440a403fSchristos 	  fixP->fx_size = 2;
2301440a403fSchristos 	  fixP->fx_where += 2;
2302440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_390_12;
2303440a403fSchristos 	}
2304440a403fSchristos       else if (operand->bits == 12 && operand->shift == 36)
2305440a403fSchristos 	{
2306440a403fSchristos 	  fixP->fx_size = 2;
2307440a403fSchristos 	  fixP->fx_where += 4;
2308440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_390_12;
2309440a403fSchristos 	}
2310440a403fSchristos       else if (operand->bits == 20 && operand->shift == 20)
2311440a403fSchristos 	{
2312*b88e3e88Schristos 	  fixP->fx_size = 4;
2313440a403fSchristos 	  fixP->fx_where += 2;
2314440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_390_20;
2315440a403fSchristos 	}
2316440a403fSchristos       else if (operand->bits == 8 && operand->shift == 8)
2317440a403fSchristos 	{
2318440a403fSchristos 	  fixP->fx_size = 1;
2319440a403fSchristos 	  fixP->fx_where += 1;
2320440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_8;
2321440a403fSchristos 	}
2322440a403fSchristos       else if (operand->bits == 12 && operand->shift == 12
2323440a403fSchristos 	       && (operand->flags & S390_OPERAND_PCREL))
2324440a403fSchristos 	{
2325440a403fSchristos 	  fixP->fx_size = 2;
2326440a403fSchristos 	  fixP->fx_where += 1;
2327440a403fSchristos 	  fixP->fx_offset += 1;
232806324dcfSchristos 	  fixP->fx_pcrel_adjust = 1;
2329440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_390_PC12DBL;
2330440a403fSchristos 	}
2331440a403fSchristos       else if (operand->bits == 16 && operand->shift == 16)
2332440a403fSchristos 	{
2333440a403fSchristos 	  fixP->fx_size = 2;
2334440a403fSchristos 	  fixP->fx_where += 2;
2335440a403fSchristos 	  if (operand->flags & S390_OPERAND_PCREL)
2336440a403fSchristos 	    {
2337440a403fSchristos 	      fixP->fx_r_type = BFD_RELOC_390_PC16DBL;
2338440a403fSchristos 	      fixP->fx_offset += 2;
233906324dcfSchristos 	      fixP->fx_pcrel_adjust = 2;
2340440a403fSchristos 	    }
2341440a403fSchristos 	  else
2342440a403fSchristos 	    fixP->fx_r_type = BFD_RELOC_16;
2343440a403fSchristos 	}
234406324dcfSchristos       else if (operand->bits == 16 && operand->shift == 32
234506324dcfSchristos 	       && (operand->flags & S390_OPERAND_PCREL))
234606324dcfSchristos 	{
234706324dcfSchristos 	  fixP->fx_size = 2;
234806324dcfSchristos 	  fixP->fx_where += 4;
234906324dcfSchristos 	  fixP->fx_offset += 4;
235006324dcfSchristos 	  fixP->fx_pcrel_adjust = 4;
235106324dcfSchristos 	  fixP->fx_r_type = BFD_RELOC_390_PC16DBL;
235206324dcfSchristos 	}
2353440a403fSchristos       else if (operand->bits == 24 && operand->shift == 24
2354440a403fSchristos 	       && (operand->flags & S390_OPERAND_PCREL))
2355440a403fSchristos 	{
2356440a403fSchristos 	  fixP->fx_size = 3;
2357440a403fSchristos 	  fixP->fx_where += 3;
2358440a403fSchristos 	  fixP->fx_offset += 3;
235906324dcfSchristos 	  fixP->fx_pcrel_adjust = 3;
2360440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_390_PC24DBL;
2361440a403fSchristos 	}
2362440a403fSchristos       else if (operand->bits == 32 && operand->shift == 16
2363440a403fSchristos 	       && (operand->flags & S390_OPERAND_PCREL))
2364440a403fSchristos 	{
2365440a403fSchristos 	  fixP->fx_size = 4;
2366440a403fSchristos 	  fixP->fx_where += 2;
2367440a403fSchristos 	  fixP->fx_offset += 2;
236806324dcfSchristos 	  fixP->fx_pcrel_adjust = 2;
2369440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_390_PC32DBL;
2370440a403fSchristos 	}
2371440a403fSchristos       else
2372440a403fSchristos 	{
2373440a403fSchristos 	  const char *sfile;
2374440a403fSchristos 	  unsigned int sline;
2375440a403fSchristos 
2376440a403fSchristos 	  /* Use expr_symbol_where to see if this is an expression
2377440a403fSchristos 	     symbol.  */
2378440a403fSchristos 	  if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
2379440a403fSchristos 	    as_bad_where (fixP->fx_file, fixP->fx_line,
2380440a403fSchristos 			  _("unresolved expression that must be resolved"));
2381440a403fSchristos 	  else
2382440a403fSchristos 	    as_bad_where (fixP->fx_file, fixP->fx_line,
2383440a403fSchristos 			  _("unsupported relocation type"));
2384440a403fSchristos 	  fixP->fx_done = 1;
2385440a403fSchristos 	  return;
2386440a403fSchristos 	}
2387440a403fSchristos     }
2388440a403fSchristos   else
2389440a403fSchristos     {
2390440a403fSchristos       switch (fixP->fx_r_type)
2391440a403fSchristos 	{
2392440a403fSchristos 	case BFD_RELOC_8:
2393440a403fSchristos 	  if (fixP->fx_pcrel)
2394440a403fSchristos 	    abort ();
2395440a403fSchristos 	  if (fixP->fx_done)
2396440a403fSchristos 	    md_number_to_chars (where, value, 1);
2397440a403fSchristos 	  break;
2398440a403fSchristos 	case BFD_RELOC_390_12:
2399440a403fSchristos 	case BFD_RELOC_390_GOT12:
2400440a403fSchristos 	case BFD_RELOC_390_GOTPLT12:
2401440a403fSchristos 	case BFD_RELOC_390_PC12DBL:
2402440a403fSchristos 	case BFD_RELOC_390_PLT12DBL:
2403440a403fSchristos 	  if (fixP->fx_pcrel)
240406324dcfSchristos 	    value += fixP->fx_pcrel_adjust;
2405440a403fSchristos 
2406440a403fSchristos 	  if (fixP->fx_done)
2407440a403fSchristos 	    {
2408440a403fSchristos 	      unsigned short mop;
2409440a403fSchristos 
2410440a403fSchristos 	      if (fixP->fx_pcrel)
2411440a403fSchristos 		value >>= 1;
2412440a403fSchristos 
2413440a403fSchristos 	      mop = bfd_getb16 ((unsigned char *) where);
2414440a403fSchristos 	      mop |= (unsigned short) (value & 0xfff);
2415440a403fSchristos 	      bfd_putb16 ((bfd_vma) mop, (unsigned char *) where);
2416440a403fSchristos 	    }
2417440a403fSchristos 	  break;
2418440a403fSchristos 
2419440a403fSchristos 	case BFD_RELOC_390_20:
2420440a403fSchristos 	case BFD_RELOC_390_GOT20:
2421440a403fSchristos 	case BFD_RELOC_390_GOTPLT20:
2422440a403fSchristos 	  if (fixP->fx_done)
2423440a403fSchristos 	    {
2424440a403fSchristos 	      unsigned int mop;
2425440a403fSchristos 	      mop = bfd_getb32 ((unsigned char *) where);
2426440a403fSchristos 	      mop |= (unsigned int) ((value & 0xfff) << 8 |
2427440a403fSchristos 				     (value & 0xff000) >> 12);
2428440a403fSchristos 	      bfd_putb32 ((bfd_vma) mop, (unsigned char *) where);
2429440a403fSchristos 	    }
2430440a403fSchristos 	  break;
2431440a403fSchristos 
2432440a403fSchristos 	case BFD_RELOC_16:
2433440a403fSchristos 	case BFD_RELOC_GPREL16:
2434440a403fSchristos 	case BFD_RELOC_16_GOT_PCREL:
2435440a403fSchristos 	case BFD_RELOC_16_GOTOFF:
2436440a403fSchristos 	  if (fixP->fx_pcrel)
2437440a403fSchristos 	    as_bad_where (fixP->fx_file, fixP->fx_line,
2438440a403fSchristos 			  _("cannot emit PC relative %s relocation%s%s"),
2439440a403fSchristos 			  bfd_get_reloc_code_name (fixP->fx_r_type),
2440440a403fSchristos 			  fixP->fx_addsy != NULL ? " against " : "",
2441440a403fSchristos 			  (fixP->fx_addsy != NULL
2442440a403fSchristos 			   ? S_GET_NAME (fixP->fx_addsy)
2443440a403fSchristos 			   : ""));
2444440a403fSchristos 	  if (fixP->fx_done)
2445440a403fSchristos 	    md_number_to_chars (where, value, 2);
2446440a403fSchristos 	  break;
2447440a403fSchristos 	case BFD_RELOC_390_GOT16:
2448440a403fSchristos 	case BFD_RELOC_390_PLTOFF16:
2449440a403fSchristos 	case BFD_RELOC_390_GOTPLT16:
2450440a403fSchristos 	  if (fixP->fx_done)
2451440a403fSchristos 	    md_number_to_chars (where, value, 2);
2452440a403fSchristos 	  break;
2453440a403fSchristos 	case BFD_RELOC_390_PC16DBL:
2454440a403fSchristos 	case BFD_RELOC_390_PLT16DBL:
245506324dcfSchristos 	  value += fixP->fx_pcrel_adjust;
2456440a403fSchristos 	  if (fixP->fx_done)
2457440a403fSchristos 	    md_number_to_chars (where, (offsetT) value >> 1, 2);
2458440a403fSchristos 	  break;
2459440a403fSchristos 
2460440a403fSchristos 	case BFD_RELOC_390_PC24DBL:
2461440a403fSchristos 	case BFD_RELOC_390_PLT24DBL:
246206324dcfSchristos 	  value += fixP->fx_pcrel_adjust;
2463440a403fSchristos 	  if (fixP->fx_done)
2464440a403fSchristos 	    {
2465440a403fSchristos 	      unsigned int mop;
2466440a403fSchristos 	      value >>= 1;
2467440a403fSchristos 
2468440a403fSchristos 	      mop = bfd_getb32 ((unsigned char *) where - 1);
2469440a403fSchristos 	      mop |= (unsigned int) (value & 0xffffff);
2470440a403fSchristos 	      bfd_putb32 ((bfd_vma) mop, (unsigned char *) where - 1);
2471440a403fSchristos 	    }
2472440a403fSchristos 	  break;
2473440a403fSchristos 
2474440a403fSchristos 	case BFD_RELOC_32:
2475440a403fSchristos 	  if (fixP->fx_pcrel)
2476440a403fSchristos 	    fixP->fx_r_type = BFD_RELOC_32_PCREL;
2477440a403fSchristos 	  else
2478440a403fSchristos 	    fixP->fx_r_type = BFD_RELOC_32;
2479440a403fSchristos 	  if (fixP->fx_done)
2480440a403fSchristos 	    md_number_to_chars (where, value, 4);
2481440a403fSchristos 	  break;
2482440a403fSchristos 	case BFD_RELOC_32_PCREL:
2483440a403fSchristos 	case BFD_RELOC_32_BASEREL:
2484440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_32_PCREL;
2485440a403fSchristos 	  if (fixP->fx_done)
2486440a403fSchristos 	    md_number_to_chars (where, value, 4);
2487440a403fSchristos 	  break;
2488440a403fSchristos 	case BFD_RELOC_32_GOT_PCREL:
2489440a403fSchristos 	case BFD_RELOC_390_PLTOFF32:
2490440a403fSchristos 	case BFD_RELOC_390_PLT32:
2491440a403fSchristos 	case BFD_RELOC_390_GOTPLT32:
2492440a403fSchristos 	  if (fixP->fx_done)
2493440a403fSchristos 	    md_number_to_chars (where, value, 4);
2494440a403fSchristos 	  break;
2495440a403fSchristos 	case BFD_RELOC_390_PC32DBL:
2496440a403fSchristos 	case BFD_RELOC_390_PLT32DBL:
2497440a403fSchristos 	case BFD_RELOC_390_GOTPCDBL:
2498440a403fSchristos 	case BFD_RELOC_390_GOTENT:
2499440a403fSchristos 	case BFD_RELOC_390_GOTPLTENT:
250006324dcfSchristos 	  value += fixP->fx_pcrel_adjust;
2501440a403fSchristos 	  if (fixP->fx_done)
2502440a403fSchristos 	    md_number_to_chars (where, (offsetT) value >> 1, 4);
2503440a403fSchristos 	  break;
2504440a403fSchristos 
2505440a403fSchristos 	case BFD_RELOC_32_GOTOFF:
2506440a403fSchristos 	  if (fixP->fx_done)
2507440a403fSchristos 	    md_number_to_chars (where, value, sizeof (int));
2508440a403fSchristos 	  break;
2509440a403fSchristos 
2510440a403fSchristos 	case BFD_RELOC_390_GOTOFF64:
2511440a403fSchristos 	  if (fixP->fx_done)
2512440a403fSchristos 	    md_number_to_chars (where, value, 8);
2513440a403fSchristos 	  break;
2514440a403fSchristos 
2515440a403fSchristos 	case BFD_RELOC_390_GOT64:
2516440a403fSchristos 	case BFD_RELOC_390_PLTOFF64:
2517440a403fSchristos 	case BFD_RELOC_390_PLT64:
2518440a403fSchristos 	case BFD_RELOC_390_GOTPLT64:
2519440a403fSchristos 	  if (fixP->fx_done)
2520440a403fSchristos 	    md_number_to_chars (where, value, 8);
2521440a403fSchristos 	  break;
2522440a403fSchristos 
2523440a403fSchristos 	case BFD_RELOC_64:
2524440a403fSchristos 	  if (fixP->fx_pcrel)
2525440a403fSchristos 	    fixP->fx_r_type = BFD_RELOC_64_PCREL;
2526440a403fSchristos 	  else
2527440a403fSchristos 	    fixP->fx_r_type = BFD_RELOC_64;
2528440a403fSchristos 	  if (fixP->fx_done)
2529440a403fSchristos 	    md_number_to_chars (where, value, 8);
2530440a403fSchristos 	  break;
2531440a403fSchristos 
2532440a403fSchristos 	case BFD_RELOC_64_PCREL:
2533440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_64_PCREL;
2534440a403fSchristos 	  if (fixP->fx_done)
2535440a403fSchristos 	    md_number_to_chars (where, value, 8);
2536440a403fSchristos 	  break;
2537440a403fSchristos 
2538440a403fSchristos 	case BFD_RELOC_VTABLE_INHERIT:
2539440a403fSchristos 	case BFD_RELOC_VTABLE_ENTRY:
2540440a403fSchristos 	  fixP->fx_done = 0;
2541440a403fSchristos 	  return;
2542440a403fSchristos 
2543440a403fSchristos 	case BFD_RELOC_390_TLS_LOAD:
2544440a403fSchristos 	case BFD_RELOC_390_TLS_GDCALL:
2545440a403fSchristos 	case BFD_RELOC_390_TLS_LDCALL:
2546440a403fSchristos 	case BFD_RELOC_390_TLS_GD32:
2547440a403fSchristos 	case BFD_RELOC_390_TLS_GD64:
2548440a403fSchristos 	case BFD_RELOC_390_TLS_GOTIE12:
2549440a403fSchristos 	case BFD_RELOC_390_TLS_GOTIE20:
2550440a403fSchristos 	case BFD_RELOC_390_TLS_GOTIE32:
2551440a403fSchristos 	case BFD_RELOC_390_TLS_GOTIE64:
2552440a403fSchristos 	case BFD_RELOC_390_TLS_LDM32:
2553440a403fSchristos 	case BFD_RELOC_390_TLS_LDM64:
2554440a403fSchristos 	case BFD_RELOC_390_TLS_IE32:
2555440a403fSchristos 	case BFD_RELOC_390_TLS_IE64:
2556440a403fSchristos 	case BFD_RELOC_390_TLS_LE32:
2557440a403fSchristos 	case BFD_RELOC_390_TLS_LE64:
2558440a403fSchristos 	case BFD_RELOC_390_TLS_LDO32:
2559440a403fSchristos 	case BFD_RELOC_390_TLS_LDO64:
2560440a403fSchristos 	case BFD_RELOC_390_TLS_DTPMOD:
2561440a403fSchristos 	case BFD_RELOC_390_TLS_DTPOFF:
2562440a403fSchristos 	case BFD_RELOC_390_TLS_TPOFF:
2563440a403fSchristos 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
2564440a403fSchristos 	  /* Fully resolved at link time.  */
2565440a403fSchristos 	  break;
2566440a403fSchristos 	case BFD_RELOC_390_TLS_IEENT:
2567440a403fSchristos 	  /* Fully resolved at link time.  */
2568440a403fSchristos 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
2569440a403fSchristos 	  value += 2;
2570440a403fSchristos 	  break;
2571440a403fSchristos 
2572440a403fSchristos 	default:
2573440a403fSchristos 	  {
2574440a403fSchristos 	    const char *reloc_name = bfd_get_reloc_code_name (fixP->fx_r_type);
2575440a403fSchristos 
2576440a403fSchristos 	    if (reloc_name != NULL)
2577440a403fSchristos 	      as_fatal (_("Gas failure, reloc type %s\n"), reloc_name);
2578440a403fSchristos 	    else
2579440a403fSchristos 	      as_fatal (_("Gas failure, reloc type #%i\n"), fixP->fx_r_type);
2580440a403fSchristos 	  }
2581440a403fSchristos 	}
2582440a403fSchristos 
2583440a403fSchristos       fixP->fx_offset = value;
2584440a403fSchristos     }
2585440a403fSchristos }
2586440a403fSchristos 
2587440a403fSchristos /* Generate a reloc for a fixup.  */
2588440a403fSchristos 
2589440a403fSchristos arelent *
tc_gen_reloc(asection * seg ATTRIBUTE_UNUSED,fixS * fixp)2590440a403fSchristos tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
2591440a403fSchristos {
2592440a403fSchristos   bfd_reloc_code_real_type code;
2593440a403fSchristos   arelent *reloc;
2594440a403fSchristos 
2595440a403fSchristos   code = fixp->fx_r_type;
2596440a403fSchristos   if (GOT_symbol && fixp->fx_addsy == GOT_symbol)
2597440a403fSchristos     {
2598440a403fSchristos       if (   (s390_arch_size == 32 && code == BFD_RELOC_32_PCREL)
2599440a403fSchristos 	  || (s390_arch_size == 64 && code == BFD_RELOC_64_PCREL))
2600440a403fSchristos 	code = BFD_RELOC_390_GOTPC;
2601440a403fSchristos       if (code == BFD_RELOC_390_PC32DBL)
2602440a403fSchristos 	code = BFD_RELOC_390_GOTPCDBL;
2603440a403fSchristos     }
2604440a403fSchristos 
2605440a403fSchristos   reloc = XNEW (arelent);
2606440a403fSchristos   reloc->sym_ptr_ptr = XNEW (asymbol *);
2607440a403fSchristos   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2608440a403fSchristos   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
2609440a403fSchristos   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
2610440a403fSchristos   if (reloc->howto == NULL)
2611440a403fSchristos     {
2612440a403fSchristos       as_bad_where (fixp->fx_file, fixp->fx_line,
2613440a403fSchristos 		    _("cannot represent relocation type %s"),
2614440a403fSchristos 		    bfd_get_reloc_code_name (code));
2615440a403fSchristos       /* Set howto to a garbage value so that we can keep going.  */
2616440a403fSchristos       reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
2617440a403fSchristos       gas_assert (reloc->howto != NULL);
2618440a403fSchristos     }
2619440a403fSchristos   reloc->addend = fixp->fx_offset;
2620440a403fSchristos 
2621440a403fSchristos   return reloc;
2622440a403fSchristos }
2623440a403fSchristos 
2624440a403fSchristos void
s390_cfi_frame_initial_instructions(void)2625440a403fSchristos s390_cfi_frame_initial_instructions (void)
2626440a403fSchristos {
2627440a403fSchristos   cfi_add_CFA_def_cfa (15, s390_arch_size == 64 ? 160 : 96);
2628440a403fSchristos }
2629440a403fSchristos 
2630440a403fSchristos int
tc_s390_regname_to_dw2regnum(char * regname)2631440a403fSchristos tc_s390_regname_to_dw2regnum (char *regname)
2632440a403fSchristos {
2633440a403fSchristos   int regnum = -1;
2634440a403fSchristos 
2635440a403fSchristos   if (regname[0] != 'c' && regname[0] != 'a')
2636440a403fSchristos     {
2637440a403fSchristos       regnum = reg_name_search (regname);
2638440a403fSchristos       if (regname[0] == 'f' && regnum != -1)
2639440a403fSchristos         regnum += 16;
2640440a403fSchristos     }
2641440a403fSchristos   else if (strcmp (regname, "ap") == 0)
2642440a403fSchristos     regnum = 32;
2643440a403fSchristos   else if (strcmp (regname, "cc") == 0)
2644440a403fSchristos     regnum = 33;
2645440a403fSchristos   return regnum;
2646440a403fSchristos }
2647440a403fSchristos 
2648440a403fSchristos void
s390_elf_final_processing(void)2649440a403fSchristos s390_elf_final_processing (void)
2650440a403fSchristos {
2651440a403fSchristos   if (set_highgprs_p)
2652440a403fSchristos     elf_elfheader (stdoutput)->e_flags |= EF_S390_HIGH_GPRS;
2653440a403fSchristos }
2654