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, ¤t_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