2005-02-17 Paul Brook <paul@codesourcery.com>
[deliverable/binutils-gdb.git] / gas / config / tc-alpha.c
CommitLineData
252b5132 1/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU.
cc8a6dd0 2 Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
ae6063d4 3 2001, 2002, 2003 Free Software Foundation, Inc.
252b5132
RH
4 Contributed by Carnegie Mellon University, 1993.
5 Written by Alessandro Forin, based on earlier gas-1.38 target CPU files.
6 Modified by Ken Raeburn for gas-2.x and ECOFF support.
7 Modified by Richard Henderson for ELF support.
9de8d8f1 8 Modified by Klaus K"ampf for EVAX (OpenVMS/Alpha) support.
252b5132
RH
9
10 This file is part of GAS, the GNU Assembler.
11
12 GAS is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 GAS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with GAS; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26
27/*
28 * Mach Operating System
29 * Copyright (c) 1993 Carnegie Mellon University
30 * All Rights Reserved.
31 *
32 * Permission to use, copy, modify and distribute this software and its
33 * documentation is hereby granted, provided that both the copyright
34 * notice and this permission notice appear in all copies of the
35 * software, derivative works or modified versions, and any portions
36 * thereof, and that both notices appear in supporting documentation.
37 *
38 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
39 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
40 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41 *
42 * Carnegie Mellon requests users of this software to return to
43 *
44 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
45 * School of Computer Science
46 * Carnegie Mellon University
47 * Pittsburgh PA 15213-3890
48 *
49 * any improvements or extensions that they make and grant Carnegie the
50 * rights to redistribute these changes.
51 */
52
53#include "as.h"
54#include "subsegs.h"
43b4c25e 55#include "struc-symbol.h"
252b5132
RH
56#include "ecoff.h"
57
58#include "opcode/alpha.h"
59
60#ifdef OBJ_ELF
61#include "elf/alpha.h"
4dc7ead9 62#include "dwarf2dbg.h"
f37f01cf 63#include "dw2gencfi.h"
252b5132
RH
64#endif
65
3882b010 66#include "safe-ctype.h"
252b5132 67\f
11f45fb5 68/* Local types. */
252b5132 69
43b4c25e
MM
70#define TOKENIZE_ERROR -1
71#define TOKENIZE_ERROR_REPORT -2
72
252b5132
RH
73#define MAX_INSN_FIXUPS 2
74#define MAX_INSN_ARGS 5
75
11f45fb5
NC
76struct alpha_fixup
77{
252b5132
RH
78 expressionS exp;
79 bfd_reloc_code_real_type reloc;
80};
81
11f45fb5
NC
82struct alpha_insn
83{
252b5132
RH
84 unsigned insn;
85 int nfixups;
86 struct alpha_fixup fixups[MAX_INSN_FIXUPS];
19f78583 87 long sequence;
252b5132
RH
88};
89
11f45fb5
NC
90enum alpha_macro_arg
91 {
92 MACRO_EOA = 1,
93 MACRO_IR,
94 MACRO_PIR,
95 MACRO_OPIR,
96 MACRO_CPIR,
97 MACRO_FPR,
98 MACRO_EXP,
99 };
252b5132 100
11f45fb5
NC
101struct alpha_macro
102{
252b5132
RH
103 const char *name;
104 void (*emit) PARAMS ((const expressionS *, int, const PTR));
105 const PTR arg;
106 enum alpha_macro_arg argsets[16];
107};
108
1dab94dd 109/* Extra expression types. */
252b5132 110
446a06c9
MM
111#define O_pregister O_md1 /* O_register, in parentheses */
112#define O_cpregister O_md2 /* + a leading comma */
252b5132 113
3765b1be 114/* The alpha_reloc_op table below depends on the ordering of these. */
43b4c25e 115#define O_literal O_md3 /* !literal relocation */
19f78583
RH
116#define O_lituse_addr O_md4 /* !lituse_addr relocation */
117#define O_lituse_base O_md5 /* !lituse_base relocation */
118#define O_lituse_bytoff O_md6 /* !lituse_bytoff relocation */
119#define O_lituse_jsr O_md7 /* !lituse_jsr relocation */
3765b1be
RH
120#define O_lituse_tlsgd O_md8 /* !lituse_tlsgd relocation */
121#define O_lituse_tlsldm O_md9 /* !lituse_tlsldm relocation */
122#define O_gpdisp O_md10 /* !gpdisp relocation */
123#define O_gprelhigh O_md11 /* !gprelhigh relocation */
124#define O_gprellow O_md12 /* !gprellow relocation */
125#define O_gprel O_md13 /* !gprel relocation */
126#define O_samegp O_md14 /* !samegp relocation */
127#define O_tlsgd O_md15 /* !tlsgd relocation */
128#define O_tlsldm O_md16 /* !tlsldm relocation */
129#define O_gotdtprel O_md17 /* !gotdtprel relocation */
130#define O_dtprelhi O_md18 /* !dtprelhi relocation */
131#define O_dtprello O_md19 /* !dtprello relocation */
132#define O_dtprel O_md20 /* !dtprel relocation */
133#define O_gottprel O_md21 /* !gottprel relocation */
134#define O_tprelhi O_md22 /* !tprelhi relocation */
135#define O_tprello O_md23 /* !tprello relocation */
136#define O_tprel O_md24 /* !tprel relocation */
19f78583
RH
137
138#define DUMMY_RELOC_LITUSE_ADDR (BFD_RELOC_UNUSED + 1)
139#define DUMMY_RELOC_LITUSE_BASE (BFD_RELOC_UNUSED + 2)
140#define DUMMY_RELOC_LITUSE_BYTOFF (BFD_RELOC_UNUSED + 3)
141#define DUMMY_RELOC_LITUSE_JSR (BFD_RELOC_UNUSED + 4)
3765b1be
RH
142#define DUMMY_RELOC_LITUSE_TLSGD (BFD_RELOC_UNUSED + 5)
143#define DUMMY_RELOC_LITUSE_TLSLDM (BFD_RELOC_UNUSED + 6)
19f78583 144
3765b1be 145#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_tprel)
43b4c25e 146
11f45fb5 147/* Macros for extracting the type and number of encoded register tokens. */
252b5132
RH
148
149#define is_ir_num(x) (((x) & 32) == 0)
150#define is_fpr_num(x) (((x) & 32) != 0)
151#define regno(x) ((x) & 31)
152
11f45fb5 153/* Something odd inherited from the old assembler. */
252b5132
RH
154
155#define note_gpreg(R) (alpha_gprmask |= (1 << (R)))
156#define note_fpreg(R) (alpha_fprmask |= (1 << (R)))
157
158/* Predicates for 16- and 32-bit ranges */
159/* XXX: The non-shift version appears to trigger a compiler bug when
160 cross-assembling from x86 w/ gcc 2.7.2. */
161
162#if 1
163#define range_signed_16(x) \
bc805888 164 (((offsetT) (x) >> 15) == 0 || ((offsetT) (x) >> 15) == -1)
252b5132 165#define range_signed_32(x) \
bc805888 166 (((offsetT) (x) >> 31) == 0 || ((offsetT) (x) >> 31) == -1)
252b5132 167#else
32ff5c2e
KH
168#define range_signed_16(x) ((offsetT) (x) >= -(offsetT) 0x8000 && \
169 (offsetT) (x) <= (offsetT) 0x7FFF)
170#define range_signed_32(x) ((offsetT) (x) >= -(offsetT) 0x80000000 && \
171 (offsetT) (x) <= (offsetT) 0x7FFFFFFF)
252b5132
RH
172#endif
173
174/* Macros for sign extending from 16- and 32-bits. */
175/* XXX: The cast macros will work on all the systems that I care about,
176 but really a predicate should be found to use the non-cast forms. */
177
178#if 1
bc805888
KH
179#define sign_extend_16(x) ((short) (x))
180#define sign_extend_32(x) ((int) (x))
252b5132 181#else
bc805888
KH
182#define sign_extend_16(x) ((offsetT) (((x) & 0xFFFF) ^ 0x8000) - 0x8000)
183#define sign_extend_32(x) ((offsetT) (((x) & 0xFFFFFFFF) \
252b5132
RH
184 ^ 0x80000000) - 0x80000000)
185#endif
186
11f45fb5 187/* Macros to build tokens. */
252b5132 188
32ff5c2e 189#define set_tok_reg(t, r) (memset (&(t), 0, sizeof (t)), \
252b5132
RH
190 (t).X_op = O_register, \
191 (t).X_add_number = (r))
32ff5c2e 192#define set_tok_preg(t, r) (memset (&(t), 0, sizeof (t)), \
252b5132
RH
193 (t).X_op = O_pregister, \
194 (t).X_add_number = (r))
32ff5c2e 195#define set_tok_cpreg(t, r) (memset (&(t), 0, sizeof (t)), \
252b5132
RH
196 (t).X_op = O_cpregister, \
197 (t).X_add_number = (r))
32ff5c2e 198#define set_tok_freg(t, r) (memset (&(t), 0, sizeof (t)), \
252b5132 199 (t).X_op = O_register, \
66498417 200 (t).X_add_number = (r) + 32)
32ff5c2e 201#define set_tok_sym(t, s, a) (memset (&(t), 0, sizeof (t)), \
252b5132
RH
202 (t).X_op = O_symbol, \
203 (t).X_add_symbol = (s), \
204 (t).X_add_number = (a))
32ff5c2e 205#define set_tok_const(t, n) (memset (&(t), 0, sizeof (t)), \
252b5132
RH
206 (t).X_op = O_constant, \
207 (t).X_add_number = (n))
252b5132 208\f
11f45fb5 209/* Prototypes for all local functions. */
252b5132 210
19f78583 211static struct alpha_reloc_tag *get_alpha_reloc_tag PARAMS ((long));
a161fe53 212static void alpha_adjust_relocs PARAMS ((bfd *, asection *, PTR));
19f78583 213
252b5132
RH
214static int tokenize_arguments PARAMS ((char *, expressionS *, int));
215static const struct alpha_opcode *find_opcode_match
216 PARAMS ((const struct alpha_opcode *, const expressionS *, int *, int *));
217static const struct alpha_macro *find_macro_match
218 PARAMS ((const struct alpha_macro *, const expressionS *, int *));
219static unsigned insert_operand
220 PARAMS ((unsigned, const struct alpha_operand *, offsetT, char *, unsigned));
221static void assemble_insn
222 PARAMS ((const struct alpha_opcode *, const expressionS *, int,
19f78583 223 struct alpha_insn *, bfd_reloc_code_real_type));
252b5132
RH
224static void emit_insn PARAMS ((struct alpha_insn *));
225static void assemble_tokens_to_insn
226 PARAMS ((const char *, const expressionS *, int, struct alpha_insn *));
227static void assemble_tokens
228 PARAMS ((const char *, const expressionS *, int, int));
229
19f78583
RH
230static long load_expression
231 PARAMS ((int, const expressionS *, int *, expressionS *));
252b5132
RH
232
233static void emit_ldgp PARAMS ((const expressionS *, int, const PTR));
234static void emit_division PARAMS ((const expressionS *, int, const PTR));
235static void emit_lda PARAMS ((const expressionS *, int, const PTR));
236static void emit_ldah PARAMS ((const expressionS *, int, const PTR));
237static void emit_ir_load PARAMS ((const expressionS *, int, const PTR));
238static void emit_loadstore PARAMS ((const expressionS *, int, const PTR));
239static void emit_jsrjmp PARAMS ((const expressionS *, int, const PTR));
240static void emit_ldX PARAMS ((const expressionS *, int, const PTR));
241static void emit_ldXu PARAMS ((const expressionS *, int, const PTR));
242static void emit_uldX PARAMS ((const expressionS *, int, const PTR));
243static void emit_uldXu PARAMS ((const expressionS *, int, const PTR));
244static void emit_ldil PARAMS ((const expressionS *, int, const PTR));
245static void emit_stX PARAMS ((const expressionS *, int, const PTR));
246static void emit_ustX PARAMS ((const expressionS *, int, const PTR));
247static void emit_sextX PARAMS ((const expressionS *, int, const PTR));
248static void emit_retjcr PARAMS ((const expressionS *, int, const PTR));
249
250static void s_alpha_text PARAMS ((int));
251static void s_alpha_data PARAMS ((int));
252#ifndef OBJ_ELF
253static void s_alpha_comm PARAMS ((int));
254static void s_alpha_rdata PARAMS ((int));
255#endif
256#ifdef OBJ_ECOFF
257static void s_alpha_sdata PARAMS ((int));
258#endif
259#ifdef OBJ_ELF
260static void s_alpha_section PARAMS ((int));
261static void s_alpha_ent PARAMS ((int));
262static void s_alpha_end PARAMS ((int));
263static void s_alpha_mask PARAMS ((int));
264static void s_alpha_frame PARAMS ((int));
265static void s_alpha_prologue PARAMS ((int));
4dc7ead9
RH
266static void s_alpha_file PARAMS ((int));
267static void s_alpha_loc PARAMS ((int));
a8316fe2 268static void s_alpha_stab PARAMS ((int));
252b5132 269static void s_alpha_coff_wrapper PARAMS ((int));
f4b97536 270static void s_alpha_usepv PARAMS ((int));
252b5132
RH
271#endif
272#ifdef OBJ_EVAX
273static void s_alpha_section PARAMS ((int));
274#endif
275static void s_alpha_gprel32 PARAMS ((int));
276static void s_alpha_float_cons PARAMS ((int));
277static void s_alpha_proc PARAMS ((int));
278static void s_alpha_set PARAMS ((int));
279static void s_alpha_base PARAMS ((int));
280static void s_alpha_align PARAMS ((int));
281static void s_alpha_stringer PARAMS ((int));
282static void s_alpha_space PARAMS ((int));
19f78583
RH
283static void s_alpha_ucons PARAMS ((int));
284static void s_alpha_arch PARAMS ((int));
252b5132
RH
285
286static void create_literal_section PARAMS ((const char *, segT *, symbolS **));
287#ifndef OBJ_ELF
288static void select_gp_value PARAMS ((void));
289#endif
290static void alpha_align PARAMS ((int, char *, symbolS *, int));
252b5132
RH
291\f
292/* Generic assembler global variables which must be defined by all
293 targets. */
294
295/* Characters which always start a comment. */
296const char comment_chars[] = "#";
297
298/* Characters which start a comment at the beginning of a line. */
299const char line_comment_chars[] = "#";
300
301/* Characters which may be used to separate multiple commands on a
302 single line. */
303const char line_separator_chars[] = ";";
304
305/* Characters which are used to indicate an exponent in a floating
306 point number. */
307const char EXP_CHARS[] = "eE";
308
309/* Characters which mean that a number is a floating point constant,
310 as in 0d1.0. */
252b5132
RH
311/* XXX: Do all of these really get used on the alpha?? */
312char FLT_CHARS[] = "rRsSfFdDxXpP";
252b5132
RH
313
314#ifdef OBJ_EVAX
315const char *md_shortopts = "Fm:g+1h:HG:";
316#else
317const char *md_shortopts = "Fm:gG:";
318#endif
319
11f45fb5
NC
320struct option md_longopts[] =
321 {
252b5132 322#define OPTION_32ADDR (OPTION_MD_BASE)
11f45fb5 323 { "32addr", no_argument, NULL, OPTION_32ADDR },
66498417 324#define OPTION_RELAX (OPTION_32ADDR + 1)
11f45fb5 325 { "relax", no_argument, NULL, OPTION_RELAX },
252b5132 326#ifdef OBJ_ELF
66498417
KH
327#define OPTION_MDEBUG (OPTION_RELAX + 1)
328#define OPTION_NO_MDEBUG (OPTION_MDEBUG + 1)
11f45fb5
NC
329 { "mdebug", no_argument, NULL, OPTION_MDEBUG },
330 { "no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG },
252b5132 331#endif
11f45fb5
NC
332 { NULL, no_argument, NULL, 0 }
333 };
252b5132 334
bc805888 335size_t md_longopts_size = sizeof (md_longopts);
252b5132
RH
336\f
337#ifdef OBJ_EVAX
338#define AXP_REG_R0 0
339#define AXP_REG_R16 16
340#define AXP_REG_R17 17
341#undef AXP_REG_T9
342#define AXP_REG_T9 22
343#undef AXP_REG_T10
344#define AXP_REG_T10 23
345#undef AXP_REG_T11
346#define AXP_REG_T11 24
347#undef AXP_REG_T12
348#define AXP_REG_T12 25
349#define AXP_REG_AI 25
350#undef AXP_REG_FP
351#define AXP_REG_FP 29
352
353#undef AXP_REG_GP
354#define AXP_REG_GP AXP_REG_PV
355#endif /* OBJ_EVAX */
356
11f45fb5 357/* The cpu for which we are generating code. */
252b5132
RH
358static unsigned alpha_target = AXP_OPCODE_BASE;
359static const char *alpha_target_name = "<all>";
360
11f45fb5 361/* The hash table of instruction opcodes. */
252b5132
RH
362static struct hash_control *alpha_opcode_hash;
363
11f45fb5 364/* The hash table of macro opcodes. */
252b5132
RH
365static struct hash_control *alpha_macro_hash;
366
367#ifdef OBJ_ECOFF
11f45fb5 368/* The $gp relocation symbol. */
252b5132
RH
369static symbolS *alpha_gp_symbol;
370
371/* XXX: what is this, and why is it exported? */
372valueT alpha_gp_value;
373#endif
374
11f45fb5 375/* The current $gp register. */
252b5132
RH
376static int alpha_gp_register = AXP_REG_GP;
377
11f45fb5 378/* A table of the register symbols. */
252b5132
RH
379static symbolS *alpha_register_table[64];
380
11f45fb5 381/* Constant sections, or sections of constants. */
252b5132
RH
382#ifdef OBJ_ECOFF
383static segT alpha_lita_section;
252b5132
RH
384#endif
385#ifdef OBJ_EVAX
386static segT alpha_link_section;
387static segT alpha_ctors_section;
388static segT alpha_dtors_section;
389#endif
390static segT alpha_lit8_section;
391
1dab94dd 392/* Symbols referring to said sections. */
252b5132
RH
393#ifdef OBJ_ECOFF
394static symbolS *alpha_lita_symbol;
252b5132
RH
395#endif
396#ifdef OBJ_EVAX
397static symbolS *alpha_link_symbol;
398static symbolS *alpha_ctors_symbol;
399static symbolS *alpha_dtors_symbol;
400#endif
401static symbolS *alpha_lit8_symbol;
402
11f45fb5 403/* Literal for .litX+0x8000 within .lita. */
252b5132 404#ifdef OBJ_ECOFF
252b5132
RH
405static offsetT alpha_lit8_literal;
406#endif
407
11f45fb5 408/* Is the assembler not allowed to use $at? */
252b5132
RH
409static int alpha_noat_on = 0;
410
11f45fb5 411/* Are macros enabled? */
252b5132
RH
412static int alpha_macros_on = 1;
413
11f45fb5 414/* Are floats disabled? */
252b5132
RH
415static int alpha_nofloats_on = 0;
416
11f45fb5 417/* Are addresses 32 bit? */
252b5132
RH
418static int alpha_addr32_on = 0;
419
420/* Symbol labelling the current insn. When the Alpha gas sees
421 foo:
422 .quad 0
423 and the section happens to not be on an eight byte boundary, it
424 will align both the symbol and the .quad to an eight byte boundary. */
425static symbolS *alpha_insn_label;
426
427/* Whether we should automatically align data generation pseudo-ops.
428 .align 0 will turn this off. */
429static int alpha_auto_align_on = 1;
430
431/* The known current alignment of the current section. */
432static int alpha_current_align;
433
434/* These are exported to ECOFF code. */
435unsigned long alpha_gprmask, alpha_fprmask;
436
437/* Whether the debugging option was seen. */
438static int alpha_debug;
439
440#ifdef OBJ_ELF
441/* Whether we are emitting an mdebug section. */
a8316fe2 442int alpha_flag_mdebug = -1;
252b5132
RH
443#endif
444
445/* Don't fully resolve relocations, allowing code movement in the linker. */
446static int alpha_flag_relax;
447
448/* What value to give to bfd_set_gp_size. */
449static int g_switch_value = 8;
450
451#ifdef OBJ_EVAX
452/* Collect information about current procedure here. */
453static struct {
454 symbolS *symbol; /* proc pdesc symbol */
455 int pdsckind;
456 int framereg; /* register for frame pointer */
457 int framesize; /* size of frame */
458 int rsa_offset;
459 int ra_save;
460 int fp_save;
461 long imask;
462 long fmask;
463 int type;
464 int prologue;
465} alpha_evax_proc;
466
467static int alpha_flag_hash_long_names = 0; /* -+ */
468static int alpha_flag_show_after_trunc = 0; /* -H */
469
470/* If the -+ switch is given, then a hash is appended to any name that is
11f45fb5 471 longer than 64 characters, else longer symbol names are truncated. */
252b5132 472
43b4c25e
MM
473#endif
474\f
475#ifdef RELOC_OP_P
476/* A table to map the spelling of a relocation operand into an appropriate
477 bfd_reloc_code_real_type type. The table is assumed to be ordered such
478 that op-O_literal indexes into it. */
479
480#define ALPHA_RELOC_TABLE(op) \
19f78583 481(&alpha_reloc_op[ ((!USER_RELOC_P (op)) \
43b4c25e 482 ? (abort (), 0) \
19f78583 483 : (int) (op) - (int) O_literal) ])
43b4c25e 484
ec8fcf4a
RH
485#define DEF(NAME, RELOC, REQ, ALLOW) \
486 { #NAME, sizeof(#NAME)-1, O_##NAME, RELOC, REQ, ALLOW}
43b4c25e 487
11f45fb5
NC
488static const struct alpha_reloc_op_tag
489{
43b4c25e
MM
490 const char *name; /* string to lookup */
491 size_t length; /* size of the string */
43b4c25e 492 operatorT op; /* which operator to use */
19f78583 493 bfd_reloc_code_real_type reloc; /* relocation before frob */
ec8fcf4a
RH
494 unsigned int require_seq : 1; /* require a sequence number */
495 unsigned int allow_seq : 1; /* allow a sequence number */
11f45fb5
NC
496}
497alpha_reloc_op[] =
498{
ec8fcf4a
RH
499 DEF(literal, BFD_RELOC_ALPHA_ELF_LITERAL, 0, 1),
500 DEF(lituse_addr, DUMMY_RELOC_LITUSE_ADDR, 1, 1),
501 DEF(lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1),
502 DEF(lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1),
503 DEF(lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1),
3765b1be
RH
504 DEF(lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1),
505 DEF(lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 1, 1),
ec8fcf4a
RH
506 DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1),
507 DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0),
508 DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0),
543833df 509 DEF(gprel, BFD_RELOC_GPREL16, 0, 0),
3765b1be
RH
510 DEF(samegp, BFD_RELOC_ALPHA_BRSGP, 0, 0),
511 DEF(tlsgd, BFD_RELOC_ALPHA_TLSGD, 0, 1),
512 DEF(tlsldm, BFD_RELOC_ALPHA_TLSLDM, 0, 1),
513 DEF(gotdtprel, BFD_RELOC_ALPHA_GOTDTPREL16, 0, 0),
514 DEF(dtprelhi, BFD_RELOC_ALPHA_DTPREL_HI16, 0, 0),
515 DEF(dtprello, BFD_RELOC_ALPHA_DTPREL_LO16, 0, 0),
516 DEF(dtprel, BFD_RELOC_ALPHA_DTPREL16, 0, 0),
517 DEF(gottprel, BFD_RELOC_ALPHA_GOTTPREL16, 0, 0),
518 DEF(tprelhi, BFD_RELOC_ALPHA_TPREL_HI16, 0, 0),
519 DEF(tprello, BFD_RELOC_ALPHA_TPREL_LO16, 0, 0),
520 DEF(tprel, BFD_RELOC_ALPHA_TPREL16, 0, 0),
43b4c25e
MM
521};
522
19f78583
RH
523#undef DEF
524
43b4c25e 525static const int alpha_num_reloc_op
bc805888 526 = sizeof (alpha_reloc_op) / sizeof (*alpha_reloc_op);
19f78583 527#endif /* RELOC_OP_P */
43b4c25e
MM
528
529/* Maximum # digits needed to hold the largest sequence # */
530#define ALPHA_RELOC_DIGITS 25
531
2d2255b5 532/* Structure to hold explicit sequence information. */
19f78583 533struct alpha_reloc_tag
43b4c25e 534{
3765b1be
RH
535 fixS *master; /* the literal reloc */
536 fixS *slaves; /* head of linked list of lituses */
43b4c25e 537 segT segment; /* segment relocs are in or undefined_section*/
19f78583
RH
538 long sequence; /* sequence # */
539 unsigned n_master; /* # of literals */
540 unsigned n_slaves; /* # of lituses */
3765b1be
RH
541 unsigned saw_tlsgd : 1; /* true if ... */
542 unsigned saw_tlsldm : 1;
543 unsigned saw_lu_tlsgd : 1;
544 unsigned saw_lu_tlsldm : 1;
545 unsigned multi_section_p : 1; /* true if more than one section was used */
43b4c25e
MM
546 char string[1]; /* printable form of sequence to hash with */
547};
548
549/* Hash table to link up literals with the appropriate lituse */
550static struct hash_control *alpha_literal_hash;
19f78583
RH
551
552/* Sequence numbers for internal use by macros. */
553static long next_sequence_num = -1;
252b5132
RH
554\f
555/* A table of CPU names and opcode sets. */
556
11f45fb5
NC
557static const struct cpu_type
558{
252b5132
RH
559 const char *name;
560 unsigned flags;
11f45fb5
NC
561}
562cpu_types[] =
563{
252b5132 564 /* Ad hoc convention: cpu number gets palcode, process code doesn't.
1dab94dd 565 This supports usage under DU 4.0b that does ".arch ev4", and
252b5132
RH
566 usage in MILO that does -m21064. Probably something more
567 specific like -m21064-pal should be used, but oh well. */
568
569 { "21064", AXP_OPCODE_BASE|AXP_OPCODE_EV4 },
570 { "21064a", AXP_OPCODE_BASE|AXP_OPCODE_EV4 },
571 { "21066", AXP_OPCODE_BASE|AXP_OPCODE_EV4 },
572 { "21068", AXP_OPCODE_BASE|AXP_OPCODE_EV4 },
573 { "21164", AXP_OPCODE_BASE|AXP_OPCODE_EV5 },
574 { "21164a", AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX },
575 { "21164pc", (AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX
576 |AXP_OPCODE_MAX) },
577 { "21264", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX
578 |AXP_OPCODE_MAX|AXP_OPCODE_CIX) },
dbac4f5b
RH
579 { "21264a", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX
580 |AXP_OPCODE_MAX|AXP_OPCODE_CIX) },
581 { "21264b", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX
582 |AXP_OPCODE_MAX|AXP_OPCODE_CIX) },
252b5132
RH
583
584 { "ev4", AXP_OPCODE_BASE },
585 { "ev45", AXP_OPCODE_BASE },
586 { "lca45", AXP_OPCODE_BASE },
587 { "ev5", AXP_OPCODE_BASE },
588 { "ev56", AXP_OPCODE_BASE|AXP_OPCODE_BWX },
589 { "pca56", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX },
590 { "ev6", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX },
dbac4f5b
RH
591 { "ev67", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX },
592 { "ev68", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX },
252b5132
RH
593
594 { "all", AXP_OPCODE_BASE },
446a06c9 595 { 0, 0 }
252b5132
RH
596};
597
598/* The macro table */
599
11f45fb5
NC
600static const struct alpha_macro alpha_macros[] =
601{
252b5132
RH
602/* Load/Store macros */
603 { "lda", emit_lda, NULL,
19f78583 604 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132
RH
605 { "ldah", emit_ldah, NULL,
606 { MACRO_IR, MACRO_EXP, MACRO_EOA } },
607
608 { "ldl", emit_ir_load, "ldl",
19f78583 609 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 610 { "ldl_l", emit_ir_load, "ldl_l",
19f78583 611 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 612 { "ldq", emit_ir_load, "ldq",
19f78583 613 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 614 { "ldq_l", emit_ir_load, "ldq_l",
19f78583 615 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 616 { "ldq_u", emit_ir_load, "ldq_u",
19f78583 617 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 618 { "ldf", emit_loadstore, "ldf",
19f78583 619 { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 620 { "ldg", emit_loadstore, "ldg",
19f78583 621 { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 622 { "lds", emit_loadstore, "lds",
19f78583 623 { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 624 { "ldt", emit_loadstore, "ldt",
19f78583 625 { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 626
32ff5c2e 627 { "ldb", emit_ldX, (PTR) 0,
19f78583 628 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 629 { "ldbu", emit_ldXu, (PTR) 0,
19f78583 630 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 631 { "ldw", emit_ldX, (PTR) 1,
19f78583 632 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 633 { "ldwu", emit_ldXu, (PTR) 1,
19f78583 634 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 635
32ff5c2e 636 { "uldw", emit_uldX, (PTR) 1,
19f78583 637 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 638 { "uldwu", emit_uldXu, (PTR) 1,
19f78583 639 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 640 { "uldl", emit_uldX, (PTR) 2,
19f78583 641 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 642 { "uldlu", emit_uldXu, (PTR) 2,
19f78583 643 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 644 { "uldq", emit_uldXu, (PTR) 3,
19f78583 645 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132
RH
646
647 { "ldgp", emit_ldgp, NULL,
648 { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } },
649
650 { "ldi", emit_lda, NULL,
651 { MACRO_IR, MACRO_EXP, MACRO_EOA } },
652 { "ldil", emit_ldil, NULL,
653 { MACRO_IR, MACRO_EXP, MACRO_EOA } },
654 { "ldiq", emit_lda, NULL,
655 { MACRO_IR, MACRO_EXP, MACRO_EOA } },
252b5132
RH
656
657 { "stl", emit_loadstore, "stl",
19f78583 658 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 659 { "stl_c", emit_loadstore, "stl_c",
19f78583 660 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 661 { "stq", emit_loadstore, "stq",
19f78583 662 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 663 { "stq_c", emit_loadstore, "stq_c",
19f78583 664 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 665 { "stq_u", emit_loadstore, "stq_u",
19f78583 666 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 667 { "stf", emit_loadstore, "stf",
19f78583 668 { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 669 { "stg", emit_loadstore, "stg",
19f78583 670 { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 671 { "sts", emit_loadstore, "sts",
19f78583 672 { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 673 { "stt", emit_loadstore, "stt",
19f78583 674 { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132 675
32ff5c2e 676 { "stb", emit_stX, (PTR) 0,
19f78583 677 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 678 { "stw", emit_stX, (PTR) 1,
19f78583 679 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 680 { "ustw", emit_ustX, (PTR) 1,
19f78583 681 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 682 { "ustl", emit_ustX, (PTR) 2,
19f78583 683 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
32ff5c2e 684 { "ustq", emit_ustX, (PTR) 3,
19f78583 685 { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_EOA } },
252b5132
RH
686
687/* Arithmetic macros */
252b5132 688
32ff5c2e 689 { "sextb", emit_sextX, (PTR) 0,
252b5132
RH
690 { MACRO_IR, MACRO_IR, MACRO_EOA,
691 MACRO_IR, MACRO_EOA,
692 /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } },
32ff5c2e 693 { "sextw", emit_sextX, (PTR) 1,
252b5132
RH
694 { MACRO_IR, MACRO_IR, MACRO_EOA,
695 MACRO_IR, MACRO_EOA,
696 /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } },
697
698 { "divl", emit_division, "__divl",
699 { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
700 MACRO_IR, MACRO_IR, MACRO_EOA,
701 /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
702 MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
703 { "divlu", emit_division, "__divlu",
704 { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
705 MACRO_IR, MACRO_IR, MACRO_EOA,
706 /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
707 MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
708 { "divq", emit_division, "__divq",
709 { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
710 MACRO_IR, MACRO_IR, MACRO_EOA,
711 /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
712 MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
713 { "divqu", emit_division, "__divqu",
714 { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
715 MACRO_IR, MACRO_IR, MACRO_EOA,
716 /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
717 MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
718 { "reml", emit_division, "__reml",
719 { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
720 MACRO_IR, MACRO_IR, MACRO_EOA,
721 /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
722 MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
723 { "remlu", emit_division, "__remlu",
724 { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
725 MACRO_IR, MACRO_IR, MACRO_EOA,
726 /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
727 MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
728 { "remq", emit_division, "__remq",
729 { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
730 MACRO_IR, MACRO_IR, MACRO_EOA,
731 /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
732 MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
733 { "remqu", emit_division, "__remqu",
734 { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA,
735 MACRO_IR, MACRO_IR, MACRO_EOA,
736 /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA,
737 MACRO_IR, MACRO_EXP, MACRO_EOA */ } },
738
739 { "jsr", emit_jsrjmp, "jsr",
19f78583
RH
740 { MACRO_PIR, MACRO_EXP, MACRO_EOA,
741 MACRO_PIR, MACRO_EOA,
742 MACRO_IR, MACRO_EXP, MACRO_EOA,
743 MACRO_EXP, MACRO_EOA } },
252b5132 744 { "jmp", emit_jsrjmp, "jmp",
19f78583
RH
745 { MACRO_PIR, MACRO_EXP, MACRO_EOA,
746 MACRO_PIR, MACRO_EOA,
747 MACRO_IR, MACRO_EXP, MACRO_EOA,
748 MACRO_EXP, MACRO_EOA } },
252b5132
RH
749 { "ret", emit_retjcr, "ret",
750 { MACRO_IR, MACRO_EXP, MACRO_EOA,
751 MACRO_IR, MACRO_EOA,
752 MACRO_PIR, MACRO_EXP, MACRO_EOA,
753 MACRO_PIR, MACRO_EOA,
754 MACRO_EXP, MACRO_EOA,
755 MACRO_EOA } },
756 { "jcr", emit_retjcr, "jcr",
757 { MACRO_IR, MACRO_EXP, MACRO_EOA,
758 MACRO_IR, MACRO_EOA,
759 MACRO_PIR, MACRO_EXP, MACRO_EOA,
760 MACRO_PIR, MACRO_EOA,
761 MACRO_EXP, MACRO_EOA,
762 MACRO_EOA } },
763 { "jsr_coroutine", emit_retjcr, "jcr",
764 { MACRO_IR, MACRO_EXP, MACRO_EOA,
765 MACRO_IR, MACRO_EOA,
766 MACRO_PIR, MACRO_EXP, MACRO_EOA,
767 MACRO_PIR, MACRO_EOA,
768 MACRO_EXP, MACRO_EOA,
769 MACRO_EOA } },
770};
771
446a06c9 772static const unsigned int alpha_num_macros
bc805888 773 = sizeof (alpha_macros) / sizeof (*alpha_macros);
252b5132
RH
774\f
775/* Public interface functions */
776
777/* This function is called once, at assembler startup time. It sets
778 up all the tables, etc. that the MD part of the assembler will
779 need, that can be determined before arguments are parsed. */
780
781void
782md_begin ()
783{
784 unsigned int i;
785
bf29b231
RH
786 /* Verify that X_op field is wide enough. */
787 {
788 expressionS e;
446a06c9
MM
789 e.X_op = O_max;
790 assert (e.X_op == O_max);
bf29b231
RH
791 }
792
11f45fb5 793 /* Create the opcode hash table. */
252b5132 794 alpha_opcode_hash = hash_new ();
66498417 795 for (i = 0; i < alpha_num_opcodes;)
252b5132
RH
796 {
797 const char *name, *retval, *slash;
798
799 name = alpha_opcodes[i].name;
66498417 800 retval = hash_insert (alpha_opcode_hash, name, (PTR) &alpha_opcodes[i]);
252b5132 801 if (retval)
19f78583
RH
802 as_fatal (_("internal error: can't hash opcode `%s': %s"),
803 name, retval);
252b5132
RH
804
805 /* Some opcodes include modifiers of various sorts with a "/mod"
806 syntax, like the architecture manual suggests. However, for
807 use with gcc at least, we also need access to those same opcodes
808 without the "/". */
809
810 if ((slash = strchr (name, '/')) != NULL)
811 {
812 char *p = xmalloc (strlen (name));
813 memcpy (p, name, slash - name);
814 strcpy (p + (slash - name), slash + 1);
815
66498417 816 (void) hash_insert (alpha_opcode_hash, p, (PTR) &alpha_opcodes[i]);
252b5132
RH
817 /* Ignore failures -- the opcode table does duplicate some
818 variants in different forms, like "hw_stq" and "hw_st/q". */
819 }
820
821 while (++i < alpha_num_opcodes
822 && (alpha_opcodes[i].name == name
823 || !strcmp (alpha_opcodes[i].name, name)))
824 continue;
825 }
826
11f45fb5 827 /* Create the macro hash table. */
252b5132 828 alpha_macro_hash = hash_new ();
66498417 829 for (i = 0; i < alpha_num_macros;)
252b5132
RH
830 {
831 const char *name, *retval;
832
833 name = alpha_macros[i].name;
66498417 834 retval = hash_insert (alpha_macro_hash, name, (PTR) &alpha_macros[i]);
252b5132 835 if (retval)
66498417
KH
836 as_fatal (_("internal error: can't hash macro `%s': %s"),
837 name, retval);
252b5132
RH
838
839 while (++i < alpha_num_macros
840 && (alpha_macros[i].name == name
841 || !strcmp (alpha_macros[i].name, name)))
842 continue;
843 }
844
11f45fb5 845 /* Construct symbols for each of the registers. */
252b5132
RH
846 for (i = 0; i < 32; ++i)
847 {
848 char name[4];
11f45fb5 849
bc805888 850 sprintf (name, "$%d", i);
32ff5c2e
KH
851 alpha_register_table[i] = symbol_create (name, reg_section, i,
852 &zero_address_frag);
252b5132
RH
853 }
854 for (; i < 64; ++i)
855 {
856 char name[5];
11f45fb5 857
66498417 858 sprintf (name, "$f%d", i - 32);
32ff5c2e
KH
859 alpha_register_table[i] = symbol_create (name, reg_section, i,
860 &zero_address_frag);
252b5132
RH
861 }
862
11f45fb5 863 /* Create the special symbols and sections we'll be using. */
252b5132
RH
864
865 /* So .sbss will get used for tiny objects. */
866 bfd_set_gp_size (stdoutput, g_switch_value);
867
868#ifdef OBJ_ECOFF
869 create_literal_section (".lita", &alpha_lita_section, &alpha_lita_symbol);
870
871 /* For handling the GP, create a symbol that won't be output in the
872 symbol table. We'll edit it out of relocs later. */
873 alpha_gp_symbol = symbol_create ("<GP value>", alpha_lita_section, 0x8000,
874 &zero_address_frag);
875#endif
876
877#ifdef OBJ_EVAX
878 create_literal_section (".link", &alpha_link_section, &alpha_link_symbol);
879#endif
880
881#ifdef OBJ_ELF
882 if (ECOFF_DEBUGGING)
883 {
32ff5c2e 884 segT sec = subseg_new (".mdebug", (subsegT) 0);
66498417 885 bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY);
32ff5c2e 886 bfd_set_section_alignment (stdoutput, sec, 3);
252b5132
RH
887 }
888#endif /* OBJ_ELF */
889
43b4c25e 890 /* Create literal lookup hash table. */
32ff5c2e 891 alpha_literal_hash = hash_new ();
19f78583
RH
892
893 subseg_set (text_section, 0);
252b5132
RH
894}
895
896/* The public interface to the instruction assembler. */
897
898void
899md_assemble (str)
900 char *str;
901{
11f45fb5 902 char opname[32]; /* Current maximum is 13. */
252b5132 903 expressionS tok[MAX_INSN_ARGS];
446a06c9
MM
904 int ntok, trunclen;
905 size_t opnamelen;
252b5132 906
11f45fb5 907 /* Split off the opcode. */
21b10511 908 opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/46819");
252b5132
RH
909 trunclen = (opnamelen < sizeof (opname) - 1
910 ? opnamelen
911 : sizeof (opname) - 1);
912 memcpy (opname, str, trunclen);
913 opname[trunclen] = '\0';
914
11f45fb5 915 /* Tokenize the rest of the line. */
252b5132
RH
916 if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0)
917 {
43b4c25e
MM
918 if (ntok != TOKENIZE_ERROR_REPORT)
919 as_bad (_("syntax error"));
920
252b5132
RH
921 return;
922 }
923
11f45fb5 924 /* Finish it off. */
252b5132
RH
925 assemble_tokens (opname, tok, ntok, alpha_macros_on);
926}
927
928/* Round up a section's size to the appropriate boundary. */
929
930valueT
931md_section_align (seg, size)
932 segT seg;
933 valueT size;
934{
32ff5c2e
KH
935 int align = bfd_get_section_alignment (stdoutput, seg);
936 valueT mask = ((valueT) 1 << align) - 1;
252b5132
RH
937
938 return (size + mask) & ~mask;
939}
940
941/* Turn a string in input_line_pointer into a floating point constant
bc0d738a
NC
942 of type TYPE, and store the appropriate bytes in *LITP. The number
943 of LITTLENUMS emitted is stored in *SIZEP. An error message is
252b5132
RH
944 returned, or NULL on OK. */
945
11f45fb5 946/* Equal to MAX_PRECISION in atof-ieee.c. */
252b5132
RH
947#define MAX_LITTLENUMS 6
948
949extern char *vax_md_atof PARAMS ((int, char *, int *));
950
951char *
952md_atof (type, litP, sizeP)
953 char type;
954 char *litP;
955 int *sizeP;
956{
957 int prec;
958 LITTLENUM_TYPE words[MAX_LITTLENUMS];
959 LITTLENUM_TYPE *wordP;
960 char *t;
961
962 switch (type)
963 {
964 /* VAX floats */
965 case 'G':
966 /* VAX md_atof doesn't like "G" for some reason. */
967 type = 'g';
968 case 'F':
969 case 'D':
970 return vax_md_atof (type, litP, sizeP);
971
972 /* IEEE floats */
973 case 'f':
974 prec = 2;
975 break;
976
977 case 'd':
978 prec = 4;
979 break;
980
981 case 'x':
982 case 'X':
983 prec = 6;
984 break;
985
986 case 'p':
987 case 'P':
988 prec = 6;
989 break;
990
991 default:
992 *sizeP = 0;
993 return _("Bad call to MD_ATOF()");
994 }
995 t = atof_ieee (input_line_pointer, type, words);
996 if (t)
997 input_line_pointer = t;
998 *sizeP = prec * sizeof (LITTLENUM_TYPE);
999
1000 for (wordP = words + prec - 1; prec--;)
1001 {
1002 md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE));
1003 litP += sizeof (LITTLENUM_TYPE);
1004 }
1005
1006 return 0;
1007}
1008
1009/* Take care of the target-specific command-line options. */
1010
1011int
1012md_parse_option (c, arg)
1013 int c;
1014 char *arg;
1015{
1016 switch (c)
1017 {
1018 case 'F':
1019 alpha_nofloats_on = 1;
1020 break;
1021
1022 case OPTION_32ADDR:
1023 alpha_addr32_on = 1;
1024 break;
1025
1026 case 'g':
1027 alpha_debug = 1;
1028 break;
1029
1030 case 'G':
32ff5c2e 1031 g_switch_value = atoi (arg);
252b5132
RH
1032 break;
1033
1034 case 'm':
1035 {
1036 const struct cpu_type *p;
1037 for (p = cpu_types; p->name; ++p)
32ff5c2e 1038 if (strcmp (arg, p->name) == 0)
252b5132
RH
1039 {
1040 alpha_target_name = p->name, alpha_target = p->flags;
1041 goto found;
1042 }
32ff5c2e 1043 as_warn (_("Unknown CPU identifier `%s'"), arg);
252b5132
RH
1044 found:;
1045 }
1046 break;
1047
1048#ifdef OBJ_EVAX
1dab94dd 1049 case '+': /* For g++. Hash any name > 63 chars long. */
252b5132
RH
1050 alpha_flag_hash_long_names = 1;
1051 break;
1052
1053 case 'H': /* Show new symbol after hash truncation */
1054 alpha_flag_show_after_trunc = 1;
1055 break;
1056
1057 case 'h': /* for gnu-c/vax compatibility. */
1058 break;
1059#endif
1060
1061 case OPTION_RELAX:
1062 alpha_flag_relax = 1;
1063 break;
1064
1065#ifdef OBJ_ELF
1066 case OPTION_MDEBUG:
1067 alpha_flag_mdebug = 1;
1068 break;
1069 case OPTION_NO_MDEBUG:
1070 alpha_flag_mdebug = 0;
1071 break;
1072#endif
1073
1074 default:
1075 return 0;
1076 }
1077
1078 return 1;
1079}
1080
1081/* Print a description of the command-line options that we accept. */
1082
1083void
1084md_show_usage (stream)
1085 FILE *stream;
1086{
32ff5c2e 1087 fputs (_("\
252b5132
RH
1088Alpha options:\n\
1089-32addr treat addresses as 32-bit values\n\
1090-F lack floating point instructions support\n\
dbac4f5b 1091-mev4 | -mev45 | -mev5 | -mev56 | -mpca56 | -mev6 | -mev67 | -mev68 | -mall\n\
252b5132 1092 specify variant of Alpha architecture\n\
dbac4f5b 1093-m21064 | -m21066 | -m21164 | -m21164a | -m21164pc | -m21264 | -m21264a | -m21264b\n\
252b5132
RH
1094 these variants include PALcode opcodes\n"),
1095 stream);
1096#ifdef OBJ_EVAX
1097 fputs (_("\
1098VMS options:\n\
1099-+ hash encode (don't truncate) names longer than 64 characters\n\
1100-H show new symbol after hash truncation\n"),
1101 stream);
1102#endif
1103}
1104
1105/* Decide from what point a pc-relative relocation is relative to,
1106 relative to the pc-relative fixup. Er, relatively speaking. */
1107
1108long
1109md_pcrel_from (fixP)
1110 fixS *fixP;
1111{
1112 valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
1113 switch (fixP->fx_r_type)
1114 {
021c2b5e
RH
1115 case BFD_RELOC_23_PCREL_S2:
1116 case BFD_RELOC_ALPHA_HINT:
1117 case BFD_RELOC_ALPHA_BRSGP:
1118 return addr + 4;
252b5132 1119 default:
021c2b5e 1120 return addr;
252b5132
RH
1121 }
1122}
1123
1124/* Attempt to simplify or even eliminate a fixup. The return value is
1125 ignored; perhaps it was once meaningful, but now it is historical.
1126 To indicate that a fixup has been eliminated, set fixP->fx_done.
1127
1128 For ELF, here it is that we transform the GPDISP_HI16 reloc we used
1129 internally into the GPDISP reloc used externally. We had to do
1130 this so that we'd have the GPDISP_LO16 reloc as a tag to compute
1131 the distance to the "lda" instruction for setting the addend to
1132 GPDISP. */
1133
94f592af 1134void
5ce56ab9 1135md_apply_fix3 (fixP, valP, seg)
252b5132 1136 fixS *fixP;
94f592af 1137 valueT * valP;
ca3f7695 1138 segT seg;
252b5132
RH
1139{
1140 char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
94f592af 1141 valueT value = * valP;
252b5132
RH
1142 unsigned image, size;
1143
1144 switch (fixP->fx_r_type)
1145 {
1146 /* The GPDISP relocations are processed internally with a symbol
a161fe53
AM
1147 referring to the current function's section; we need to drop
1148 in a value which, when added to the address of the start of
1149 the function, gives the desired GP. */
252b5132
RH
1150 case BFD_RELOC_ALPHA_GPDISP_HI16:
1151 {
1152 fixS *next = fixP->fx_next;
252b5132 1153
19f78583
RH
1154 /* With user-specified !gpdisp relocations, we can be missing
1155 the matching LO16 reloc. We will have already issued an
1156 error message. */
1157 if (next)
1158 fixP->fx_offset = (next->fx_frag->fr_address + next->fx_where
1159 - fixP->fx_frag->fr_address - fixP->fx_where);
252b5132
RH
1160
1161 value = (value - sign_extend_16 (value)) >> 16;
1162 }
1163#ifdef OBJ_ELF
1164 fixP->fx_r_type = BFD_RELOC_ALPHA_GPDISP;
1165#endif
1166 goto do_reloc_gp;
1167
1168 case BFD_RELOC_ALPHA_GPDISP_LO16:
1169 value = sign_extend_16 (value);
1170 fixP->fx_offset = 0;
1171#ifdef OBJ_ELF
1172 fixP->fx_done = 1;
1173#endif
1174
1175 do_reloc_gp:
ca3f7695 1176 fixP->fx_addsy = section_symbol (seg);
252b5132
RH
1177 md_number_to_chars (fixpos, value, 2);
1178 break;
1179
1180 case BFD_RELOC_16:
1181 if (fixP->fx_pcrel)
1182 fixP->fx_r_type = BFD_RELOC_16_PCREL;
1183 size = 2;
1184 goto do_reloc_xx;
1185 case BFD_RELOC_32:
1186 if (fixP->fx_pcrel)
1187 fixP->fx_r_type = BFD_RELOC_32_PCREL;
1188 size = 4;
1189 goto do_reloc_xx;
1190 case BFD_RELOC_64:
1191 if (fixP->fx_pcrel)
1192 fixP->fx_r_type = BFD_RELOC_64_PCREL;
1193 size = 8;
1194 do_reloc_xx:
1195 if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
1196 {
1197 md_number_to_chars (fixpos, value, size);
1198 goto done;
1199 }
94f592af 1200 return;
252b5132
RH
1201
1202#ifdef OBJ_ECOFF
1203 case BFD_RELOC_GPREL32:
1204 assert (fixP->fx_subsy == alpha_gp_symbol);
1205 fixP->fx_subsy = 0;
1206 /* FIXME: inherited this obliviousness of `value' -- why? */
1207 md_number_to_chars (fixpos, -alpha_gp_value, 4);
1208 break;
19f78583 1209#else
252b5132 1210 case BFD_RELOC_GPREL32:
252b5132 1211#endif
19f78583
RH
1212 case BFD_RELOC_GPREL16:
1213 case BFD_RELOC_ALPHA_GPREL_HI16:
1214 case BFD_RELOC_ALPHA_GPREL_LO16:
94f592af 1215 return;
252b5132
RH
1216
1217 case BFD_RELOC_23_PCREL_S2:
1218 if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
1219 {
32ff5c2e 1220 image = bfd_getl32 (fixpos);
252b5132
RH
1221 image = (image & ~0x1FFFFF) | ((value >> 2) & 0x1FFFFF);
1222 goto write_done;
1223 }
94f592af 1224 return;
252b5132
RH
1225
1226 case BFD_RELOC_ALPHA_HINT:
1227 if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
1228 {
32ff5c2e 1229 image = bfd_getl32 (fixpos);
252b5132
RH
1230 image = (image & ~0x3FFF) | ((value >> 2) & 0x3FFF);
1231 goto write_done;
1232 }
94f592af 1233 return;
252b5132 1234
543833df
RH
1235#ifdef OBJ_ELF
1236 case BFD_RELOC_ALPHA_BRSGP:
00f7efb6
JJ
1237 return;
1238
3765b1be
RH
1239 case BFD_RELOC_ALPHA_TLSGD:
1240 case BFD_RELOC_ALPHA_TLSLDM:
1241 case BFD_RELOC_ALPHA_GOTDTPREL16:
1242 case BFD_RELOC_ALPHA_DTPREL_HI16:
1243 case BFD_RELOC_ALPHA_DTPREL_LO16:
1244 case BFD_RELOC_ALPHA_DTPREL16:
1245 case BFD_RELOC_ALPHA_GOTTPREL16:
1246 case BFD_RELOC_ALPHA_TPREL_HI16:
1247 case BFD_RELOC_ALPHA_TPREL_LO16:
1248 case BFD_RELOC_ALPHA_TPREL16:
00f7efb6
JJ
1249 if (fixP->fx_addsy)
1250 S_SET_THREAD_LOCAL (fixP->fx_addsy);
543833df
RH
1251 return;
1252#endif
1253
252b5132
RH
1254#ifdef OBJ_ECOFF
1255 case BFD_RELOC_ALPHA_LITERAL:
1256 md_number_to_chars (fixpos, value, 2);
94f592af 1257 return;
252b5132 1258#endif
252b5132
RH
1259 case BFD_RELOC_ALPHA_ELF_LITERAL:
1260 case BFD_RELOC_ALPHA_LITUSE:
252b5132
RH
1261 case BFD_RELOC_ALPHA_LINKAGE:
1262 case BFD_RELOC_ALPHA_CODEADDR:
94f592af 1263 return;
43b4c25e 1264
b96ed59a
PB
1265 case BFD_RELOC_VTABLE_INHERIT:
1266 case BFD_RELOC_VTABLE_ENTRY:
94f592af 1267 return;
b96ed59a 1268
252b5132
RH
1269 default:
1270 {
1271 const struct alpha_operand *operand;
1272
32ff5c2e 1273 if ((int) fixP->fx_r_type >= 0)
252b5132
RH
1274 as_fatal (_("unhandled relocation type %s"),
1275 bfd_get_reloc_code_name (fixP->fx_r_type));
1276
32ff5c2e
KH
1277 assert (-(int) fixP->fx_r_type < (int) alpha_num_operands);
1278 operand = &alpha_operands[-(int) fixP->fx_r_type];
252b5132
RH
1279
1280 /* The rest of these fixups only exist internally during symbol
1281 resolution and have no representation in the object file.
1282 Therefore they must be completely resolved as constants. */
1283
1284 if (fixP->fx_addsy != 0
49309057 1285 && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
252b5132
RH
1286 as_bad_where (fixP->fx_file, fixP->fx_line,
1287 _("non-absolute expression in constant field"));
1288
32ff5c2e
KH
1289 image = bfd_getl32 (fixpos);
1290 image = insert_operand (image, operand, (offsetT) value,
1291 fixP->fx_file, fixP->fx_line);
252b5132
RH
1292 }
1293 goto write_done;
1294 }
1295
1296 if (fixP->fx_addsy != 0 || fixP->fx_pcrel != 0)
94f592af 1297 return;
252b5132
RH
1298 else
1299 {
32ff5c2e 1300 as_warn_where (fixP->fx_file, fixP->fx_line,
66498417 1301 _("type %d reloc done?\n"), (int) fixP->fx_r_type);
252b5132
RH
1302 goto done;
1303 }
1304
1305write_done:
32ff5c2e 1306 md_number_to_chars (fixpos, image, 4);
252b5132
RH
1307
1308done:
1309 fixP->fx_done = 1;
252b5132
RH
1310}
1311
94f592af 1312/* Look for a register name in the given symbol. */
252b5132
RH
1313
1314symbolS *
32ff5c2e 1315md_undefined_symbol (name)
252b5132
RH
1316 char *name;
1317{
1318 if (*name == '$')
1319 {
1320 int is_float = 0, num;
1321
1322 switch (*++name)
1323 {
1324 case 'f':
1325 if (name[1] == 'p' && name[2] == '\0')
1326 return alpha_register_table[AXP_REG_FP];
1327 is_float = 32;
1328 /* FALLTHRU */
1329
1330 case 'r':
3882b010 1331 if (!ISDIGIT (*++name))
252b5132
RH
1332 break;
1333 /* FALLTHRU */
1334
1335 case '0': case '1': case '2': case '3': case '4':
1336 case '5': case '6': case '7': case '8': case '9':
1337 if (name[1] == '\0')
1338 num = name[0] - '0';
3882b010 1339 else if (name[0] != '0' && ISDIGIT (name[1]) && name[2] == '\0')
252b5132
RH
1340 {
1341 num = (name[0] - '0') * 10 + name[1] - '0';
1342 if (num >= 32)
1343 break;
1344 }
1345 else
1346 break;
1347
6480b79a 1348 if (!alpha_noat_on && (num + is_float) == AXP_REG_AT)
32ff5c2e 1349 as_warn (_("Used $at without \".set noat\""));
252b5132
RH
1350 return alpha_register_table[num + is_float];
1351
1352 case 'a':
1353 if (name[1] == 't' && name[2] == '\0')
1354 {
1355 if (!alpha_noat_on)
32ff5c2e 1356 as_warn (_("Used $at without \".set noat\""));
252b5132
RH
1357 return alpha_register_table[AXP_REG_AT];
1358 }
1359 break;
1360
1361 case 'g':
1362 if (name[1] == 'p' && name[2] == '\0')
1363 return alpha_register_table[alpha_gp_register];
1364 break;
1365
1366 case 's':
1367 if (name[1] == 'p' && name[2] == '\0')
1368 return alpha_register_table[AXP_REG_SP];
1369 break;
1370 }
1371 }
1372 return NULL;
1373}
1374
1375#ifdef OBJ_ECOFF
1376/* @@@ Magic ECOFF bits. */
1377
1378void
1379alpha_frob_ecoff_data ()
1380{
1381 select_gp_value ();
1382 /* $zero and $f31 are read-only */
1383 alpha_gprmask &= ~1;
1384 alpha_fprmask &= ~1;
1385}
1386#endif
1387
1388/* Hook to remember a recently defined label so that the auto-align
1389 code can adjust the symbol after we know what alignment will be
1390 required. */
1391
1392void
1393alpha_define_label (sym)
1394 symbolS *sym;
1395{
1396 alpha_insn_label = sym;
1397}
1398
1399/* Return true if we must always emit a reloc for a type and false if
b6ff326e 1400 there is some hope of resolving it at assembly time. */
252b5132
RH
1401
1402int
1403alpha_force_relocation (f)
1404 fixS *f;
1405{
1406 if (alpha_flag_relax)
1407 return 1;
1408
1409 switch (f->fx_r_type)
1410 {
1411 case BFD_RELOC_ALPHA_GPDISP_HI16:
1412 case BFD_RELOC_ALPHA_GPDISP_LO16:
1413 case BFD_RELOC_ALPHA_GPDISP:
252b5132 1414 case BFD_RELOC_ALPHA_LITERAL:
252b5132 1415 case BFD_RELOC_ALPHA_ELF_LITERAL:
252b5132 1416 case BFD_RELOC_ALPHA_LITUSE:
19f78583 1417 case BFD_RELOC_GPREL16:
252b5132 1418 case BFD_RELOC_GPREL32:
19f78583
RH
1419 case BFD_RELOC_ALPHA_GPREL_HI16:
1420 case BFD_RELOC_ALPHA_GPREL_LO16:
252b5132
RH
1421 case BFD_RELOC_ALPHA_LINKAGE:
1422 case BFD_RELOC_ALPHA_CODEADDR:
543833df 1423 case BFD_RELOC_ALPHA_BRSGP:
3765b1be
RH
1424 case BFD_RELOC_ALPHA_TLSGD:
1425 case BFD_RELOC_ALPHA_TLSLDM:
1426 case BFD_RELOC_ALPHA_GOTDTPREL16:
1427 case BFD_RELOC_ALPHA_DTPREL_HI16:
1428 case BFD_RELOC_ALPHA_DTPREL_LO16:
1429 case BFD_RELOC_ALPHA_DTPREL16:
1430 case BFD_RELOC_ALPHA_GOTTPREL16:
1431 case BFD_RELOC_ALPHA_TPREL_HI16:
1432 case BFD_RELOC_ALPHA_TPREL_LO16:
1433 case BFD_RELOC_ALPHA_TPREL16:
252b5132
RH
1434 return 1;
1435
252b5132 1436 default:
a161fe53 1437 break;
252b5132 1438 }
a161fe53 1439
ae6063d4 1440 return generic_force_reloc (f);
252b5132
RH
1441}
1442
1443/* Return true if we can partially resolve a relocation now. */
1444
1445int
1446alpha_fix_adjustable (f)
1447 fixS *f;
1448{
252b5132
RH
1449 /* Are there any relocation types for which we must generate a reloc
1450 but we can adjust the values contained within it? */
1451 switch (f->fx_r_type)
1452 {
1453 case BFD_RELOC_ALPHA_GPDISP_HI16:
1454 case BFD_RELOC_ALPHA_GPDISP_LO16:
1455 case BFD_RELOC_ALPHA_GPDISP:
1456 return 0;
1457
252b5132 1458 case BFD_RELOC_ALPHA_LITERAL:
252b5132 1459 case BFD_RELOC_ALPHA_ELF_LITERAL:
19f78583 1460 case BFD_RELOC_ALPHA_LITUSE:
252b5132
RH
1461 case BFD_RELOC_ALPHA_LINKAGE:
1462 case BFD_RELOC_ALPHA_CODEADDR:
252b5132
RH
1463 return 1;
1464
b96ed59a
PB
1465 case BFD_RELOC_VTABLE_ENTRY:
1466 case BFD_RELOC_VTABLE_INHERIT:
252b5132
RH
1467 return 0;
1468
19f78583 1469 case BFD_RELOC_GPREL16:
252b5132 1470 case BFD_RELOC_GPREL32:
19f78583
RH
1471 case BFD_RELOC_ALPHA_GPREL_HI16:
1472 case BFD_RELOC_ALPHA_GPREL_LO16:
252b5132
RH
1473 case BFD_RELOC_23_PCREL_S2:
1474 case BFD_RELOC_32:
1475 case BFD_RELOC_64:
1476 case BFD_RELOC_ALPHA_HINT:
1477 return 1;
1478
3765b1be
RH
1479 case BFD_RELOC_ALPHA_TLSGD:
1480 case BFD_RELOC_ALPHA_TLSLDM:
1481 case BFD_RELOC_ALPHA_GOTDTPREL16:
1482 case BFD_RELOC_ALPHA_DTPREL_HI16:
1483 case BFD_RELOC_ALPHA_DTPREL_LO16:
1484 case BFD_RELOC_ALPHA_DTPREL16:
1485 case BFD_RELOC_ALPHA_GOTTPREL16:
1486 case BFD_RELOC_ALPHA_TPREL_HI16:
1487 case BFD_RELOC_ALPHA_TPREL_LO16:
1488 case BFD_RELOC_ALPHA_TPREL16:
1489 /* ??? No idea why we can't return a reference to .tbss+10, but
1490 we're preventing this in the other assemblers. Follow for now. */
1491 return 0;
1492
2469cfa2 1493#ifdef OBJ_ELF
66ba4c77
RH
1494 case BFD_RELOC_ALPHA_BRSGP:
1495 /* If we have a BRSGP reloc to a local symbol, adjust it to BRADDR and
1496 let it get resolved at assembly time. */
1497 {
1498 symbolS *sym = f->fx_addsy;
1499 const char *name;
1500 int offset = 0;
1501
ae6063d4 1502 if (generic_force_reloc (f))
66ba4c77
RH
1503 return 0;
1504
1505 switch (S_GET_OTHER (sym) & STO_ALPHA_STD_GPLOAD)
1506 {
1507 case STO_ALPHA_NOPV:
1508 break;
1509 case STO_ALPHA_STD_GPLOAD:
1510 offset = 8;
1511 break;
1512 default:
1513 if (S_IS_LOCAL (sym))
1514 name = "<local>";
1515 else
1516 name = S_GET_NAME (sym);
1517 as_bad_where (f->fx_file, f->fx_line,
1518 _("!samegp reloc against symbol without .prologue: %s"),
1519 name);
1520 break;
1521 }
1522 f->fx_r_type = BFD_RELOC_23_PCREL_S2;
1523 f->fx_offset += offset;
1524 return 1;
1525 }
2469cfa2 1526#endif
66ba4c77 1527
252b5132 1528 default:
252b5132
RH
1529 return 1;
1530 }
1531 /*NOTREACHED*/
1532}
1533
1534/* Generate the BFD reloc to be stuck in the object file from the
1535 fixup used internally in the assembler. */
1536
1537arelent *
1538tc_gen_reloc (sec, fixp)
446a06c9 1539 asection *sec ATTRIBUTE_UNUSED;
252b5132
RH
1540 fixS *fixp;
1541{
1542 arelent *reloc;
1543
1544 reloc = (arelent *) xmalloc (sizeof (arelent));
49309057
ILT
1545 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1546 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
252b5132
RH
1547 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1548
1549 /* Make sure none of our internal relocations make it this far.
1550 They'd better have been fully resolved by this point. */
32ff5c2e 1551 assert ((int) fixp->fx_r_type > 0);
252b5132
RH
1552
1553 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1554 if (reloc->howto == NULL)
1555 {
1556 as_bad_where (fixp->fx_file, fixp->fx_line,
1557 _("cannot represent `%s' relocation in object file"),
1558 bfd_get_reloc_code_name (fixp->fx_r_type));
1559 return NULL;
1560 }
1561
1562 if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
1563 {
1564 as_fatal (_("internal error? cannot generate `%s' relocation"),
1565 bfd_get_reloc_code_name (fixp->fx_r_type));
1566 }
1567 assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
1568
1569#ifdef OBJ_ECOFF
1570 if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL)
1571 {
11f45fb5 1572 /* Fake out bfd_perform_relocation. sigh. */
252b5132
RH
1573 reloc->addend = -alpha_gp_value;
1574 }
1575 else
1576#endif
1577 {
1578 reloc->addend = fixp->fx_offset;
1579#ifdef OBJ_ELF
11f45fb5
NC
1580 /* Ohhh, this is ugly. The problem is that if this is a local global
1581 symbol, the relocation will entirely be performed at link time, not
1582 at assembly time. bfd_perform_reloc doesn't know about this sort
1583 of thing, and as a result we need to fake it out here. */
f7460f5f 1584 if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)
13ae64f3
JJ
1585 || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE)
1586 || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_THREAD_LOCAL))
32ff5c2e 1587 && !S_IS_COMMON (fixp->fx_addsy))
49309057 1588 reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
252b5132
RH
1589#endif
1590 }
1591
1592 return reloc;
1593}
1594
1595/* Parse a register name off of the input_line and return a register
1596 number. Gets md_undefined_symbol above to do the register name
1597 matching for us.
1598
1599 Only called as a part of processing the ECOFF .frame directive. */
1600
1601int
1602tc_get_register (frame)
446a06c9 1603 int frame ATTRIBUTE_UNUSED;
252b5132
RH
1604{
1605 int framereg = AXP_REG_SP;
1606
1607 SKIP_WHITESPACE ();
1608 if (*input_line_pointer == '$')
1609 {
1610 char *s = input_line_pointer;
1611 char c = get_symbol_end ();
1612 symbolS *sym = md_undefined_symbol (s);
1613
32ff5c2e 1614 *strchr (s, '\0') = c;
252b5132
RH
1615 if (sym && (framereg = S_GET_VALUE (sym)) <= 31)
1616 goto found;
1617 }
1618 as_warn (_("frame reg expected, using $%d."), framereg);
1619
1620found:
1621 note_gpreg (framereg);
1622 return framereg;
1623}
1624
1625/* This is called before the symbol table is processed. In order to
1626 work with gcc when using mips-tfile, we must keep all local labels.
1627 However, in other cases, we want to discard them. If we were
1628 called with -g, but we didn't see any debugging information, it may
1629 mean that gcc is smuggling debugging information through to
1630 mips-tfile, in which case we must generate all local labels. */
1631
1632#ifdef OBJ_ECOFF
1633
1634void
1635alpha_frob_file_before_adjust ()
1636{
1637 if (alpha_debug != 0
1638 && ! ecoff_debugging_seen)
1639 flag_keep_locals = 1;
1640}
1641
1642#endif /* OBJ_ECOFF */
1643\f
19f78583
RH
1644static struct alpha_reloc_tag *
1645get_alpha_reloc_tag (sequence)
1646 long sequence;
1647{
1648 char buffer[ALPHA_RELOC_DIGITS];
1649 struct alpha_reloc_tag *info;
1650
1651 sprintf (buffer, "!%ld", sequence);
1652
1653 info = (struct alpha_reloc_tag *) hash_find (alpha_literal_hash, buffer);
1654 if (! info)
1655 {
1656 size_t len = strlen (buffer);
1657 const char *errmsg;
1658
1659 info = (struct alpha_reloc_tag *)
1660 xcalloc (sizeof (struct alpha_reloc_tag) + len, 1);
1661
1662 info->segment = now_seg;
1663 info->sequence = sequence;
1664 strcpy (info->string, buffer);
1665 errmsg = hash_insert (alpha_literal_hash, info->string, (PTR) info);
1666 if (errmsg)
1667 as_fatal (errmsg);
1668 }
1669
1670 return info;
1671}
43b4c25e 1672
66498417
KH
1673/* Before the relocations are written, reorder them, so that user
1674 supplied !lituse relocations follow the appropriate !literal
19f78583 1675 relocations, and similarly for !gpdisp relocations. */
43b4c25e
MM
1676
1677void
a161fe53 1678alpha_before_fix ()
43b4c25e
MM
1679{
1680 if (alpha_literal_hash)
a161fe53 1681 bfd_map_over_sections (stdoutput, alpha_adjust_relocs, NULL);
43b4c25e 1682}
43b4c25e
MM
1683
1684static void
a161fe53 1685alpha_adjust_relocs (abfd, sec, ptr)
4dc7ead9 1686 bfd *abfd ATTRIBUTE_UNUSED;
43b4c25e 1687 asection *sec;
4dc7ead9 1688 PTR ptr ATTRIBUTE_UNUSED;
43b4c25e
MM
1689{
1690 segment_info_type *seginfo = seg_info (sec);
1691 fixS **prevP;
1692 fixS *fixp;
1693 fixS *next;
19f78583 1694 fixS *slave;
43b4c25e 1695
66498417
KH
1696 /* If seginfo is NULL, we did not create this section; don't do
1697 anything with it. By using a pointer to a pointer, we can update
1698 the links in place. */
43b4c25e
MM
1699 if (seginfo == NULL)
1700 return;
1701
1702 /* If there are no relocations, skip the section. */
1703 if (! seginfo->fix_root)
1704 return;
1705
2d2255b5 1706 /* First rebuild the fixup chain without the explicit lituse and
19f78583
RH
1707 gpdisp_lo16 relocs. */
1708 prevP = &seginfo->fix_root;
43b4c25e
MM
1709 for (fixp = seginfo->fix_root; fixp; fixp = next)
1710 {
1711 next = fixp->fx_next;
32ff5c2e 1712 fixp->fx_next = (fixS *) 0;
43b4c25e
MM
1713
1714 switch (fixp->fx_r_type)
1715 {
19f78583 1716 case BFD_RELOC_ALPHA_LITUSE:
19f78583
RH
1717 if (fixp->tc_fix_data.info->n_master == 0)
1718 as_bad_where (fixp->fx_file, fixp->fx_line,
1719 _("No !literal!%ld was found"),
1720 fixp->tc_fix_data.info->sequence);
11f45fb5 1721#ifdef RELOC_OP_P
9e756d64 1722 if (fixp->fx_offset == LITUSE_ALPHA_TLSGD)
3765b1be
RH
1723 {
1724 if (! fixp->tc_fix_data.info->saw_tlsgd)
1725 as_bad_where (fixp->fx_file, fixp->fx_line,
1726 _("No !tlsgd!%ld was found"),
1727 fixp->tc_fix_data.info->sequence);
1728 }
9e756d64 1729 else if (fixp->fx_offset == LITUSE_ALPHA_TLSLDM)
3765b1be
RH
1730 {
1731 if (! fixp->tc_fix_data.info->saw_tlsldm)
1732 as_bad_where (fixp->fx_file, fixp->fx_line,
1733 _("No !tlsldm!%ld was found"),
1734 fixp->tc_fix_data.info->sequence);
1735 }
11f45fb5 1736#endif
43b4c25e
MM
1737 break;
1738
19f78583 1739 case BFD_RELOC_ALPHA_GPDISP_LO16:
19f78583 1740 if (fixp->tc_fix_data.info->n_master == 0)
43b4c25e 1741 as_bad_where (fixp->fx_file, fixp->fx_line,
19f78583 1742 _("No ldah !gpdisp!%ld was found"),
43b4c25e 1743 fixp->tc_fix_data.info->sequence);
19f78583
RH
1744 break;
1745
3765b1be 1746 case BFD_RELOC_ALPHA_ELF_LITERAL:
20e130e9
RH
1747 if (fixp->tc_fix_data.info
1748 && (fixp->tc_fix_data.info->saw_tlsgd
1749 || fixp->tc_fix_data.info->saw_tlsldm))
3765b1be
RH
1750 break;
1751 /* FALLTHRU */
1752
19f78583
RH
1753 default:
1754 *prevP = fixp;
1755 prevP = &fixp->fx_next;
43b4c25e
MM
1756 break;
1757 }
1758 }
1759
3765b1be
RH
1760 /* Go back and re-chain dependent relocations. They are currently
1761 linked through the next_reloc field in reverse order, so as we
1762 go through the next_reloc chain, we effectively reverse the chain
1763 once again.
19f78583
RH
1764
1765 Except if there is more than one !literal for a given sequence
1766 number. In that case, the programmer and/or compiler is not sure
1767 how control flows from literal to lituse, and we can't be sure to
1768 get the relaxation correct.
1769
1770 ??? Well, actually we could, if there are enough lituses such that
1771 we can make each literal have at least one of each lituse type
1772 present. Not implemented.
1773
1774 Also suppress the optimization if the !literals/!lituses are spread
1775 in different segments. This can happen with "intersting" uses of
1776 inline assembly; examples are present in the Linux kernel semaphores. */
1777
1778 for (fixp = seginfo->fix_root; fixp; fixp = next)
43b4c25e 1779 {
19f78583
RH
1780 next = fixp->fx_next;
1781 switch (fixp->fx_r_type)
43b4c25e 1782 {
3765b1be
RH
1783 case BFD_RELOC_ALPHA_TLSGD:
1784 case BFD_RELOC_ALPHA_TLSLDM:
1785 if (!fixp->tc_fix_data.info)
1786 break;
1787 if (fixp->tc_fix_data.info->n_master == 0)
1788 break;
1789 else if (fixp->tc_fix_data.info->n_master > 1)
1790 {
1791 as_bad_where (fixp->fx_file, fixp->fx_line,
1792 _("too many !literal!%ld for %s"),
1793 fixp->tc_fix_data.info->sequence,
1794 (fixp->fx_r_type == BFD_RELOC_ALPHA_TLSGD
1795 ? "!tlsgd" : "!tlsldm"));
1796 break;
1797 }
1798
1799 fixp->tc_fix_data.info->master->fx_next = fixp->fx_next;
1800 fixp->fx_next = fixp->tc_fix_data.info->master;
1801 fixp = fixp->fx_next;
1802 /* FALLTHRU */
1803
19f78583 1804 case BFD_RELOC_ALPHA_ELF_LITERAL:
20e130e9
RH
1805 if (fixp->tc_fix_data.info
1806 && fixp->tc_fix_data.info->n_master == 1
19f78583 1807 && ! fixp->tc_fix_data.info->multi_section_p)
43b4c25e 1808 {
19f78583
RH
1809 for (slave = fixp->tc_fix_data.info->slaves;
1810 slave != (fixS *) 0;
1811 slave = slave->tc_fix_data.next_reloc)
43b4c25e 1812 {
19f78583
RH
1813 slave->fx_next = fixp->fx_next;
1814 fixp->fx_next = slave;
43b4c25e 1815 }
19f78583
RH
1816 }
1817 break;
43b4c25e 1818
19f78583
RH
1819 case BFD_RELOC_ALPHA_GPDISP_HI16:
1820 if (fixp->tc_fix_data.info->n_slaves == 0)
1821 as_bad_where (fixp->fx_file, fixp->fx_line,
1822 _("No lda !gpdisp!%ld was found"),
1823 fixp->tc_fix_data.info->sequence);
1824 else
1825 {
1826 slave = fixp->tc_fix_data.info->slaves;
1827 slave->fx_next = next;
1828 fixp->fx_next = slave;
43b4c25e 1829 }
19f78583
RH
1830 break;
1831
1832 default:
1833 break;
43b4c25e
MM
1834 }
1835 }
43b4c25e 1836}
43b4c25e
MM
1837\f
1838#ifdef DEBUG_ALPHA
1839static void
1840debug_exp (tok, ntok)
1841 expressionS tok[];
1842 int ntok;
1843{
1844 int i;
1845
1846 fprintf (stderr, "debug_exp: %d tokens", ntok);
1847 for (i = 0; i < ntok; i++)
1848 {
1849 expressionS *t = &tok[i];
1850 const char *name;
11f45fb5 1851
43b4c25e
MM
1852 switch (t->X_op)
1853 {
1854 default: name = "unknown"; break;
1855 case O_illegal: name = "O_illegal"; break;
1856 case O_absent: name = "O_absent"; break;
1857 case O_constant: name = "O_constant"; break;
1858 case O_symbol: name = "O_symbol"; break;
1859 case O_symbol_rva: name = "O_symbol_rva"; break;
1860 case O_register: name = "O_register"; break;
1861 case O_big: name = "O_big"; break;
1862 case O_uminus: name = "O_uminus"; break;
1863 case O_bit_not: name = "O_bit_not"; break;
1864 case O_logical_not: name = "O_logical_not"; break;
1865 case O_multiply: name = "O_multiply"; break;
1866 case O_divide: name = "O_divide"; break;
1867 case O_modulus: name = "O_modulus"; break;
1868 case O_left_shift: name = "O_left_shift"; break;
1869 case O_right_shift: name = "O_right_shift"; break;
1870 case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break;
1871 case O_bit_or_not: name = "O_bit_or_not"; break;
1872 case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break;
1873 case O_bit_and: name = "O_bit_and"; break;
1874 case O_add: name = "O_add"; break;
1875 case O_subtract: name = "O_subtract"; break;
1876 case O_eq: name = "O_eq"; break;
1877 case O_ne: name = "O_ne"; break;
1878 case O_lt: name = "O_lt"; break;
1879 case O_le: name = "O_le"; break;
1880 case O_ge: name = "O_ge"; break;
1881 case O_gt: name = "O_gt"; break;
1882 case O_logical_and: name = "O_logical_and"; break;
1883 case O_logical_or: name = "O_logical_or"; break;
1884 case O_index: name = "O_index"; break;
1885 case O_pregister: name = "O_pregister"; break;
1886 case O_cpregister: name = "O_cpregister"; break;
1887 case O_literal: name = "O_literal"; break;
543833df 1888 case O_lituse_addr: name = "O_lituse_addr"; break;
43b4c25e
MM
1889 case O_lituse_base: name = "O_lituse_base"; break;
1890 case O_lituse_bytoff: name = "O_lituse_bytoff"; break;
1891 case O_lituse_jsr: name = "O_lituse_jsr"; break;
3765b1be
RH
1892 case O_lituse_tlsgd: name = "O_lituse_tlsgd"; break;
1893 case O_lituse_tlsldm: name = "O_lituse_tlsldm"; break;
43b4c25e
MM
1894 case O_gpdisp: name = "O_gpdisp"; break;
1895 case O_gprelhigh: name = "O_gprelhigh"; break;
1896 case O_gprellow: name = "O_gprellow"; break;
19f78583 1897 case O_gprel: name = "O_gprel"; break;
543833df 1898 case O_samegp: name = "O_samegp"; break;
3765b1be
RH
1899 case O_tlsgd: name = "O_tlsgd"; break;
1900 case O_tlsldm: name = "O_tlsldm"; break;
1901 case O_gotdtprel: name = "O_gotdtprel"; break;
1902 case O_dtprelhi: name = "O_dtprelhi"; break;
1903 case O_dtprello: name = "O_dtprello"; break;
1904 case O_dtprel: name = "O_dtprel"; break;
1905 case O_gottprel: name = "O_gottprel"; break;
1906 case O_tprelhi: name = "O_tprelhi"; break;
1907 case O_tprello: name = "O_tprello"; break;
1908 case O_tprel: name = "O_tprel"; break;
43b4c25e
MM
1909 }
1910
1911 fprintf (stderr, ", %s(%s, %s, %d)", name,
1912 (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
1913 (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
32ff5c2e 1914 (int) t->X_add_number);
43b4c25e
MM
1915 }
1916 fprintf (stderr, "\n");
1917 fflush (stderr);
1918}
1919#endif
1920
252b5132
RH
1921/* Parse the arguments to an opcode. */
1922
1923static int
1924tokenize_arguments (str, tok, ntok)
1925 char *str;
1926 expressionS tok[];
1927 int ntok;
1928{
1929 expressionS *end_tok = tok + ntok;
1930 char *old_input_line_pointer;
1931 int saw_comma = 0, saw_arg = 0;
43b4c25e
MM
1932#ifdef DEBUG_ALPHA
1933 expressionS *orig_tok = tok;
1934#endif
11f45fb5 1935#ifdef RELOC_OP_P
43b4c25e
MM
1936 char *p;
1937 const struct alpha_reloc_op_tag *r;
1938 int c, i;
1939 size_t len;
1940 int reloc_found_p = 0;
11f45fb5 1941#endif
252b5132
RH
1942
1943 memset (tok, 0, sizeof (*tok) * ntok);
1944
11f45fb5 1945 /* Save and restore input_line_pointer around this function. */
252b5132
RH
1946 old_input_line_pointer = input_line_pointer;
1947 input_line_pointer = str;
1948
19f78583
RH
1949#ifdef RELOC_OP_P
1950 /* ??? Wrest control of ! away from the regular expression parser. */
1951 is_end_of_line[(unsigned char) '!'] = 1;
1952#endif
1953
252b5132
RH
1954 while (tok < end_tok && *input_line_pointer)
1955 {
1956 SKIP_WHITESPACE ();
1957 switch (*input_line_pointer)
1958 {
1959 case '\0':
1960 goto fini;
1961
43b4c25e
MM
1962#ifdef RELOC_OP_P
1963 case '!':
1964 /* A relocation operand can be placed after the normal operand on an
1965 assembly language statement, and has the following form:
1966 !relocation_type!sequence_number. */
1967 if (reloc_found_p)
11f45fb5
NC
1968 {
1969 /* Only support one relocation op per insn. */
43b4c25e
MM
1970 as_bad (_("More than one relocation op per insn"));
1971 goto err_report;
1972 }
1973
1974 if (!saw_arg)
1975 goto err;
1976
19f78583 1977 ++input_line_pointer;
cc8a6dd0 1978 SKIP_WHITESPACE ();
19f78583
RH
1979 p = input_line_pointer;
1980 c = get_symbol_end ();
43b4c25e 1981
11f45fb5 1982 /* Parse !relocation_type. */
19f78583 1983 len = input_line_pointer - p;
43b4c25e
MM
1984 if (len == 0)
1985 {
1986 as_bad (_("No relocation operand"));
1987 goto err_report;
1988 }
1989
43b4c25e 1990 r = &alpha_reloc_op[0];
66498417 1991 for (i = alpha_num_reloc_op - 1; i >= 0; i--, r++)
19f78583
RH
1992 if (len == r->length && memcmp (p, r->name, len) == 0)
1993 break;
43b4c25e
MM
1994 if (i < 0)
1995 {
19f78583 1996 as_bad (_("Unknown relocation operand: !%s"), p);
43b4c25e
MM
1997 goto err_report;
1998 }
1999
19f78583 2000 *input_line_pointer = c;
cc8a6dd0 2001 SKIP_WHITESPACE ();
19f78583
RH
2002 if (*input_line_pointer != '!')
2003 {
ec8fcf4a 2004 if (r->require_seq)
19f78583 2005 {
ec8fcf4a 2006 as_bad (_("no sequence number after !%s"), p);
19f78583
RH
2007 goto err_report;
2008 }
2009
19f78583 2010 tok->X_add_number = 0;
19f78583 2011 }
ec8fcf4a
RH
2012 else
2013 {
2014 if (! r->allow_seq)
2015 {
2016 as_bad (_("!%s does not use a sequence number"), p);
2017 goto err_report;
2018 }
19f78583 2019
ec8fcf4a 2020 input_line_pointer++;
43b4c25e 2021
11f45fb5 2022 /* Parse !sequence_number. */
ec8fcf4a
RH
2023 expression (tok);
2024 if (tok->X_op != O_constant || tok->X_add_number <= 0)
2025 {
2026 as_bad (_("Bad sequence number: !%s!%s"),
2027 r->name, input_line_pointer);
2028 goto err_report;
2029 }
43b4c25e
MM
2030 }
2031
2032 tok->X_op = r->op;
2033 reloc_found_p = 1;
2034 ++tok;
2035 break;
19f78583 2036#endif /* RELOC_OP_P */
43b4c25e 2037
252b5132
RH
2038 case ',':
2039 ++input_line_pointer;
2040 if (saw_comma || !saw_arg)
2041 goto err;
2042 saw_comma = 1;
2043 break;
2044
2045 case '(':
2046 {
2047 char *hold = input_line_pointer++;
2048
1dab94dd 2049 /* First try for parenthesized register ... */
252b5132
RH
2050 expression (tok);
2051 if (*input_line_pointer == ')' && tok->X_op == O_register)
2052 {
2053 tok->X_op = (saw_comma ? O_cpregister : O_pregister);
2054 saw_comma = 0;
2055 saw_arg = 1;
2056 ++input_line_pointer;
2057 ++tok;
2058 break;
2059 }
2060
11f45fb5 2061 /* ... then fall through to plain expression. */
252b5132
RH
2062 input_line_pointer = hold;
2063 }
2064
2065 default:
2066 if (saw_arg && !saw_comma)
2067 goto err;
43b4c25e 2068
252b5132
RH
2069 expression (tok);
2070 if (tok->X_op == O_illegal || tok->X_op == O_absent)
2071 goto err;
2072
2073 saw_comma = 0;
2074 saw_arg = 1;
2075 ++tok;
2076 break;
2077 }
2078 }
2079
2080fini:
2081 if (saw_comma)
2082 goto err;
2083 input_line_pointer = old_input_line_pointer;
43b4c25e
MM
2084
2085#ifdef DEBUG_ALPHA
2086 debug_exp (orig_tok, ntok - (end_tok - tok));
2087#endif
19f78583
RH
2088#ifdef RELOC_OP_P
2089 is_end_of_line[(unsigned char) '!'] = 0;
2090#endif
43b4c25e 2091
252b5132
RH
2092 return ntok - (end_tok - tok);
2093
2094err:
19f78583
RH
2095#ifdef RELOC_OP_P
2096 is_end_of_line[(unsigned char) '!'] = 0;
2097#endif
252b5132 2098 input_line_pointer = old_input_line_pointer;
43b4c25e
MM
2099 return TOKENIZE_ERROR;
2100
19f78583 2101#ifdef RELOC_OP_P
11f45fb5 2102err_report:
19f78583
RH
2103 is_end_of_line[(unsigned char) '!'] = 0;
2104#endif
43b4c25e
MM
2105 input_line_pointer = old_input_line_pointer;
2106 return TOKENIZE_ERROR_REPORT;
252b5132
RH
2107}
2108
2109/* Search forward through all variants of an opcode looking for a
2110 syntax match. */
2111
2112static const struct alpha_opcode *
32ff5c2e 2113find_opcode_match (first_opcode, tok, pntok, pcpumatch)
252b5132
RH
2114 const struct alpha_opcode *first_opcode;
2115 const expressionS *tok;
2116 int *pntok;
2117 int *pcpumatch;
2118{
2119 const struct alpha_opcode *opcode = first_opcode;
2120 int ntok = *pntok;
2121 int got_cpu_match = 0;
2122
2123 do
2124 {
2125 const unsigned char *opidx;
2126 int tokidx = 0;
2127
11f45fb5 2128 /* Don't match opcodes that don't exist on this architecture. */
252b5132
RH
2129 if (!(opcode->flags & alpha_target))
2130 goto match_failed;
2131
2132 got_cpu_match = 1;
2133
2134 for (opidx = opcode->operands; *opidx; ++opidx)
2135 {
2136 const struct alpha_operand *operand = &alpha_operands[*opidx];
2137
11f45fb5 2138 /* Only take input from real operands. */
252b5132
RH
2139 if (operand->flags & AXP_OPERAND_FAKE)
2140 continue;
2141
11f45fb5 2142 /* When we expect input, make sure we have it. */
252b5132
RH
2143 if (tokidx >= ntok)
2144 {
2145 if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0)
2146 goto match_failed;
2147 continue;
2148 }
2149
11f45fb5 2150 /* Match operand type with expression type. */
252b5132
RH
2151 switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK)
2152 {
2153 case AXP_OPERAND_IR:
2154 if (tok[tokidx].X_op != O_register
32ff5c2e 2155 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2156 goto match_failed;
2157 break;
2158 case AXP_OPERAND_FPR:
2159 if (tok[tokidx].X_op != O_register
32ff5c2e 2160 || !is_fpr_num (tok[tokidx].X_add_number))
252b5132
RH
2161 goto match_failed;
2162 break;
66498417 2163 case AXP_OPERAND_IR | AXP_OPERAND_PARENS:
252b5132 2164 if (tok[tokidx].X_op != O_pregister
32ff5c2e 2165 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2166 goto match_failed;
2167 break;
66498417 2168 case AXP_OPERAND_IR | AXP_OPERAND_PARENS | AXP_OPERAND_COMMA:
252b5132 2169 if (tok[tokidx].X_op != O_cpregister
32ff5c2e 2170 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2171 goto match_failed;
2172 break;
2173
2174 case AXP_OPERAND_RELATIVE:
2175 case AXP_OPERAND_SIGNED:
2176 case AXP_OPERAND_UNSIGNED:
2177 switch (tok[tokidx].X_op)
2178 {
2179 case O_illegal:
2180 case O_absent:
2181 case O_register:
2182 case O_pregister:
2183 case O_cpregister:
2184 goto match_failed;
2185
2186 default:
2187 break;
2188 }
2189 break;
2190
2191 default:
11f45fb5 2192 /* Everything else should have been fake. */
bc805888 2193 abort ();
252b5132
RH
2194 }
2195 ++tokidx;
2196 }
2197
11f45fb5 2198 /* Possible match -- did we use all of our input? */
252b5132
RH
2199 if (tokidx == ntok)
2200 {
2201 *pntok = ntok;
2202 return opcode;
2203 }
2204
2205 match_failed:;
2206 }
11f45fb5 2207 while (++opcode - alpha_opcodes < (int) alpha_num_opcodes
32ff5c2e 2208 && !strcmp (opcode->name, first_opcode->name));
252b5132
RH
2209
2210 if (*pcpumatch)
1aad8cf8 2211 *pcpumatch = got_cpu_match;
252b5132
RH
2212
2213 return NULL;
2214}
2215
2216/* Search forward through all variants of a macro looking for a syntax
2217 match. */
2218
2219static const struct alpha_macro *
32ff5c2e 2220find_macro_match (first_macro, tok, pntok)
252b5132
RH
2221 const struct alpha_macro *first_macro;
2222 const expressionS *tok;
2223 int *pntok;
2224{
2225 const struct alpha_macro *macro = first_macro;
2226 int ntok = *pntok;
2227
2228 do
2229 {
2230 const enum alpha_macro_arg *arg = macro->argsets;
2231 int tokidx = 0;
2232
2233 while (*arg)
2234 {
2235 switch (*arg)
2236 {
2237 case MACRO_EOA:
2238 if (tokidx == ntok)
2239 return macro;
2240 else
2241 tokidx = 0;
2242 break;
2243
11f45fb5 2244 /* Index register. */
252b5132
RH
2245 case MACRO_IR:
2246 if (tokidx >= ntok || tok[tokidx].X_op != O_register
32ff5c2e 2247 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2248 goto match_failed;
2249 ++tokidx;
2250 break;
43b4c25e 2251
11f45fb5 2252 /* Parenthesized index register. */
252b5132
RH
2253 case MACRO_PIR:
2254 if (tokidx >= ntok || tok[tokidx].X_op != O_pregister
32ff5c2e 2255 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2256 goto match_failed;
2257 ++tokidx;
2258 break;
43b4c25e 2259
11f45fb5 2260 /* Optional parenthesized index register. */
43b4c25e
MM
2261 case MACRO_OPIR:
2262 if (tokidx < ntok && tok[tokidx].X_op == O_pregister
32ff5c2e 2263 && is_ir_num (tok[tokidx].X_add_number))
43b4c25e
MM
2264 ++tokidx;
2265 break;
2266
11f45fb5 2267 /* Leading comma with a parenthesized index register. */
252b5132
RH
2268 case MACRO_CPIR:
2269 if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister
32ff5c2e 2270 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2271 goto match_failed;
2272 ++tokidx;
2273 break;
43b4c25e 2274
11f45fb5 2275 /* Floating point register. */
252b5132
RH
2276 case MACRO_FPR:
2277 if (tokidx >= ntok || tok[tokidx].X_op != O_register
32ff5c2e 2278 || !is_fpr_num (tok[tokidx].X_add_number))
252b5132
RH
2279 goto match_failed;
2280 ++tokidx;
2281 break;
2282
11f45fb5 2283 /* Normal expression. */
252b5132
RH
2284 case MACRO_EXP:
2285 if (tokidx >= ntok)
2286 goto match_failed;
2287 switch (tok[tokidx].X_op)
2288 {
2289 case O_illegal:
2290 case O_absent:
2291 case O_register:
2292 case O_pregister:
2293 case O_cpregister:
43b4c25e
MM
2294 case O_literal:
2295 case O_lituse_base:
2296 case O_lituse_bytoff:
2297 case O_lituse_jsr:
2298 case O_gpdisp:
2299 case O_gprelhigh:
2300 case O_gprellow:
19f78583 2301 case O_gprel:
543833df 2302 case O_samegp:
252b5132
RH
2303 goto match_failed;
2304
2305 default:
2306 break;
2307 }
2308 ++tokidx;
2309 break;
2310
2311 match_failed:
2312 while (*arg != MACRO_EOA)
2313 ++arg;
2314 tokidx = 0;
2315 break;
2316 }
2317 ++arg;
2318 }
2319 }
11f45fb5 2320 while (++macro - alpha_macros < (int) alpha_num_macros
32ff5c2e 2321 && !strcmp (macro->name, first_macro->name));
252b5132
RH
2322
2323 return NULL;
2324}
2325
2326/* Insert an operand value into an instruction. */
2327
2328static unsigned
32ff5c2e 2329insert_operand (insn, operand, val, file, line)
252b5132
RH
2330 unsigned insn;
2331 const struct alpha_operand *operand;
2332 offsetT val;
2333 char *file;
2334 unsigned line;
2335{
2336 if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW))
2337 {
2338 offsetT min, max;
2339
2340 if (operand->flags & AXP_OPERAND_SIGNED)
2341 {
2342 max = (1 << (operand->bits - 1)) - 1;
2343 min = -(1 << (operand->bits - 1));
2344 }
2345 else
2346 {
2347 max = (1 << operand->bits) - 1;
2348 min = 0;
2349 }
2350
2351 if (val < min || val > max)
e5976317 2352 as_warn_value_out_of_range (_("operand"), val, min, max, file, line);
252b5132
RH
2353 }
2354
2355 if (operand->insert)
2356 {
2357 const char *errmsg = NULL;
2358
2359 insn = (*operand->insert) (insn, val, &errmsg);
2360 if (errmsg)
2361 as_warn (errmsg);
2362 }
2363 else
2364 insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
2365
2366 return insn;
2367}
2368
11f45fb5
NC
2369/* Turn an opcode description and a set of arguments into
2370 an instruction and a fixup. */
252b5132
RH
2371
2372static void
19f78583 2373assemble_insn (opcode, tok, ntok, insn, reloc)
252b5132
RH
2374 const struct alpha_opcode *opcode;
2375 const expressionS *tok;
2376 int ntok;
2377 struct alpha_insn *insn;
19f78583 2378 bfd_reloc_code_real_type reloc;
252b5132 2379{
19f78583
RH
2380 const struct alpha_operand *reloc_operand = NULL;
2381 const expressionS *reloc_exp = NULL;
252b5132
RH
2382 const unsigned char *argidx;
2383 unsigned image;
2384 int tokidx = 0;
2385
2386 memset (insn, 0, sizeof (*insn));
2387 image = opcode->opcode;
2388
2389 for (argidx = opcode->operands; *argidx; ++argidx)
2390 {
2391 const struct alpha_operand *operand = &alpha_operands[*argidx];
32ff5c2e 2392 const expressionS *t = (const expressionS *) 0;
252b5132
RH
2393
2394 if (operand->flags & AXP_OPERAND_FAKE)
2395 {
2396 /* fake operands take no value and generate no fixup */
32ff5c2e 2397 image = insert_operand (image, operand, 0, NULL, 0);
252b5132
RH
2398 continue;
2399 }
2400
2401 if (tokidx >= ntok)
2402 {
2403 switch (operand->flags & AXP_OPERAND_OPTIONAL_MASK)
2404 {
2405 case AXP_OPERAND_DEFAULT_FIRST:
2406 t = &tok[0];
2407 break;
2408 case AXP_OPERAND_DEFAULT_SECOND:
2409 t = &tok[1];
2410 break;
2411 case AXP_OPERAND_DEFAULT_ZERO:
2412 {
446a06c9 2413 static expressionS zero_exp;
252b5132 2414 t = &zero_exp;
446a06c9
MM
2415 zero_exp.X_op = O_constant;
2416 zero_exp.X_unsigned = 1;
252b5132
RH
2417 }
2418 break;
2419 default:
bc805888 2420 abort ();
252b5132
RH
2421 }
2422 }
2423 else
2424 t = &tok[tokidx++];
2425
2426 switch (t->X_op)
2427 {
2428 case O_register:
2429 case O_pregister:
2430 case O_cpregister:
32ff5c2e
KH
2431 image = insert_operand (image, operand, regno (t->X_add_number),
2432 NULL, 0);
252b5132
RH
2433 break;
2434
2435 case O_constant:
32ff5c2e 2436 image = insert_operand (image, operand, t->X_add_number, NULL, 0);
19f78583
RH
2437 assert (reloc_operand == NULL);
2438 reloc_operand = operand;
2439 reloc_exp = t;
252b5132
RH
2440 break;
2441
2442 default:
19f78583
RH
2443 /* This is only 0 for fields that should contain registers,
2444 which means this pattern shouldn't have matched. */
2445 if (operand->default_reloc == 0)
2446 abort ();
252b5132 2447
19f78583 2448 /* There is one special case for which an insn receives two
cc8a6dd0 2449 relocations, and thus the user-supplied reloc does not
19f78583
RH
2450 override the operand reloc. */
2451 if (operand->default_reloc == BFD_RELOC_ALPHA_HINT)
2452 {
2453 struct alpha_fixup *fixup;
252b5132 2454
19f78583
RH
2455 if (insn->nfixups >= MAX_INSN_FIXUPS)
2456 as_fatal (_("too many fixups"));
252b5132 2457
19f78583
RH
2458 fixup = &insn->fixups[insn->nfixups++];
2459 fixup->exp = *t;
2460 fixup->reloc = BFD_RELOC_ALPHA_HINT;
2461 }
2462 else
2463 {
2464 if (reloc == BFD_RELOC_UNUSED)
2465 reloc = operand->default_reloc;
2466
2467 assert (reloc_operand == NULL);
2468 reloc_operand = operand;
2469 reloc_exp = t;
2470 }
252b5132
RH
2471 break;
2472 }
2473 }
2474
19f78583
RH
2475 if (reloc != BFD_RELOC_UNUSED)
2476 {
2477 struct alpha_fixup *fixup;
2478
2479 if (insn->nfixups >= MAX_INSN_FIXUPS)
2480 as_fatal (_("too many fixups"));
2481
2482 /* ??? My but this is hacky. But the OSF/1 assembler uses the same
2483 relocation tag for both ldah and lda with gpdisp. Choose the
2484 correct internal relocation based on the opcode. */
2485 if (reloc == BFD_RELOC_ALPHA_GPDISP)
2486 {
2487 if (strcmp (opcode->name, "ldah") == 0)
2488 reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
2489 else if (strcmp (opcode->name, "lda") == 0)
2490 reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
2491 else
2492 as_bad (_("invalid relocation for instruction"));
2493 }
2494
2495 /* If this is a real relocation (as opposed to a lituse hint), then
2496 the relocation width should match the operand width. */
2497 else if (reloc < BFD_RELOC_UNUSED)
2498 {
2499 reloc_howto_type *reloc_howto
2500 = bfd_reloc_type_lookup (stdoutput, reloc);
2501 if (reloc_howto->bitsize != reloc_operand->bits)
2502 {
2503 as_bad (_("invalid relocation for field"));
2504 return;
2505 }
2506 }
2507
2508 fixup = &insn->fixups[insn->nfixups++];
2509 if (reloc_exp)
2510 fixup->exp = *reloc_exp;
2511 else
2512 fixup->exp.X_op = O_absent;
2513 fixup->reloc = reloc;
2514 }
2515
252b5132
RH
2516 insn->insn = image;
2517}
2518
11f45fb5 2519/* Actually output an instruction with its fixup. */
252b5132
RH
2520
2521static void
2522emit_insn (insn)
66498417 2523 struct alpha_insn *insn;
252b5132
RH
2524{
2525 char *f;
2526 int i;
2527
66498417 2528 /* Take care of alignment duties. */
252b5132
RH
2529 if (alpha_auto_align_on && alpha_current_align < 2)
2530 alpha_align (2, (char *) NULL, alpha_insn_label, 0);
2531 if (alpha_current_align > 2)
2532 alpha_current_align = 2;
2533 alpha_insn_label = NULL;
2534
2535 /* Write out the instruction. */
2536 f = frag_more (4);
2537 md_number_to_chars (f, insn->insn, 4);
2538
4dc7ead9
RH
2539#ifdef OBJ_ELF
2540 dwarf2_emit_insn (4);
2541#endif
2542
11f45fb5 2543 /* Apply the fixups in order. */
252b5132
RH
2544 for (i = 0; i < insn->nfixups; ++i)
2545 {
32ff5c2e 2546 const struct alpha_operand *operand = (const struct alpha_operand *) 0;
252b5132 2547 struct alpha_fixup *fixup = &insn->fixups[i];
3765b1be 2548 struct alpha_reloc_tag *info = NULL;
252b5132
RH
2549 int size, pcrel;
2550 fixS *fixP;
2551
11f45fb5 2552 /* Some fixups are only used internally and so have no howto. */
32ff5c2e 2553 if ((int) fixup->reloc < 0)
252b5132 2554 {
32ff5c2e 2555 operand = &alpha_operands[-(int) fixup->reloc];
252b5132
RH
2556 size = 4;
2557 pcrel = ((operand->flags & AXP_OPERAND_RELATIVE) != 0);
2558 }
19f78583
RH
2559 else if (fixup->reloc > BFD_RELOC_UNUSED
2560 || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16
2561 || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_LO16)
2562 {
2563 size = 2;
2564 pcrel = 0;
2565 }
1aad8cf8 2566 else
19f78583
RH
2567 {
2568 reloc_howto_type *reloc_howto
2569 = bfd_reloc_type_lookup (stdoutput, fixup->reloc);
2570 assert (reloc_howto);
252b5132 2571
19f78583
RH
2572 size = bfd_get_reloc_size (reloc_howto);
2573 assert (size >= 1 && size <= 4);
43b4c25e 2574
19f78583
RH
2575 pcrel = reloc_howto->pc_relative;
2576 }
252b5132
RH
2577
2578 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size,
2579 &fixup->exp, pcrel, fixup->reloc);
2580
43b4c25e
MM
2581 /* Turn off complaints that the addend is too large for some fixups,
2582 and copy in the sequence number for the explicit relocations. */
252b5132
RH
2583 switch (fixup->reloc)
2584 {
19f78583 2585 case BFD_RELOC_ALPHA_HINT:
252b5132 2586 case BFD_RELOC_GPREL32:
19f78583
RH
2587 case BFD_RELOC_GPREL16:
2588 case BFD_RELOC_ALPHA_GPREL_HI16:
2589 case BFD_RELOC_ALPHA_GPREL_LO16:
3765b1be
RH
2590 case BFD_RELOC_ALPHA_GOTDTPREL16:
2591 case BFD_RELOC_ALPHA_DTPREL_HI16:
2592 case BFD_RELOC_ALPHA_DTPREL_LO16:
2593 case BFD_RELOC_ALPHA_DTPREL16:
2594 case BFD_RELOC_ALPHA_GOTTPREL16:
2595 case BFD_RELOC_ALPHA_TPREL_HI16:
2596 case BFD_RELOC_ALPHA_TPREL_LO16:
2597 case BFD_RELOC_ALPHA_TPREL16:
252b5132
RH
2598 fixP->fx_no_overflow = 1;
2599 break;
2600
19f78583 2601 case BFD_RELOC_ALPHA_GPDISP_HI16:
43b4c25e 2602 fixP->fx_no_overflow = 1;
19f78583
RH
2603 fixP->fx_addsy = section_symbol (now_seg);
2604 fixP->fx_offset = 0;
43b4c25e 2605
19f78583
RH
2606 info = get_alpha_reloc_tag (insn->sequence);
2607 if (++info->n_master > 1)
2608 as_bad (_("too many ldah insns for !gpdisp!%ld"), insn->sequence);
2609 if (info->segment != now_seg)
2610 as_bad (_("both insns for !gpdisp!%ld must be in the same section"),
2611 insn->sequence);
2612 fixP->tc_fix_data.info = info;
2613 break;
43b4c25e 2614
19f78583
RH
2615 case BFD_RELOC_ALPHA_GPDISP_LO16:
2616 fixP->fx_no_overflow = 1;
43b4c25e 2617
19f78583
RH
2618 info = get_alpha_reloc_tag (insn->sequence);
2619 if (++info->n_slaves > 1)
2620 as_bad (_("too many lda insns for !gpdisp!%ld"), insn->sequence);
43b4c25e 2621 if (info->segment != now_seg)
19f78583
RH
2622 as_bad (_("both insns for !gpdisp!%ld must be in the same section"),
2623 insn->sequence);
43b4c25e 2624 fixP->tc_fix_data.info = info;
19f78583 2625 info->slaves = fixP;
43b4c25e
MM
2626 break;
2627
19f78583
RH
2628 case BFD_RELOC_ALPHA_LITERAL:
2629 case BFD_RELOC_ALPHA_ELF_LITERAL:
2630 fixP->fx_no_overflow = 1;
43b4c25e 2631
3765b1be
RH
2632 if (insn->sequence == 0)
2633 break;
19f78583 2634 info = get_alpha_reloc_tag (insn->sequence);
3765b1be 2635 info->master = fixP;
19f78583 2636 info->n_master++;
43b4c25e
MM
2637 if (info->segment != now_seg)
2638 info->multi_section_p = 1;
19f78583
RH
2639 fixP->tc_fix_data.info = info;
2640 break;
43b4c25e 2641
11f45fb5 2642#ifdef RELOC_OP_P
19f78583 2643 case DUMMY_RELOC_LITUSE_ADDR:
9e756d64 2644 fixP->fx_offset = LITUSE_ALPHA_ADDR;
19f78583
RH
2645 goto do_lituse;
2646 case DUMMY_RELOC_LITUSE_BASE:
9e756d64 2647 fixP->fx_offset = LITUSE_ALPHA_BASE;
19f78583
RH
2648 goto do_lituse;
2649 case DUMMY_RELOC_LITUSE_BYTOFF:
9e756d64 2650 fixP->fx_offset = LITUSE_ALPHA_BYTOFF;
19f78583
RH
2651 goto do_lituse;
2652 case DUMMY_RELOC_LITUSE_JSR:
9e756d64 2653 fixP->fx_offset = LITUSE_ALPHA_JSR;
3765b1be
RH
2654 goto do_lituse;
2655 case DUMMY_RELOC_LITUSE_TLSGD:
9e756d64 2656 fixP->fx_offset = LITUSE_ALPHA_TLSGD;
3765b1be
RH
2657 goto do_lituse;
2658 case DUMMY_RELOC_LITUSE_TLSLDM:
9e756d64 2659 fixP->fx_offset = LITUSE_ALPHA_TLSLDM;
3765b1be 2660 goto do_lituse;
19f78583
RH
2661 do_lituse:
2662 fixP->fx_addsy = section_symbol (now_seg);
2663 fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE;
2664
2665 info = get_alpha_reloc_tag (insn->sequence);
3765b1be
RH
2666 if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSGD)
2667 info->saw_lu_tlsgd = 1;
2668 else if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSLDM)
2669 info->saw_lu_tlsldm = 1;
2670 if (++info->n_slaves > 1)
2671 {
2672 if (info->saw_lu_tlsgd)
2673 as_bad (_("too many lituse insns for !lituse_tlsgd!%ld"),
2674 insn->sequence);
2675 else if (info->saw_lu_tlsldm)
2676 as_bad (_("too many lituse insns for !lituse_tlsldm!%ld"),
2677 insn->sequence);
2678 }
19f78583
RH
2679 fixP->tc_fix_data.info = info;
2680 fixP->tc_fix_data.next_reloc = info->slaves;
2681 info->slaves = fixP;
2682 if (info->segment != now_seg)
2683 info->multi_section_p = 1;
43b4c25e 2684 break;
43b4c25e 2685
3765b1be
RH
2686 case BFD_RELOC_ALPHA_TLSGD:
2687 fixP->fx_no_overflow = 1;
2688
2689 if (insn->sequence == 0)
2690 break;
2691 info = get_alpha_reloc_tag (insn->sequence);
2692 if (info->saw_tlsgd)
2693 as_bad (_("duplicate !tlsgd!%ld"), insn->sequence);
2694 else if (info->saw_tlsldm)
2695 as_bad (_("sequence number in use for !tlsldm!%ld"),
2696 insn->sequence);
2697 else
2698 info->saw_tlsgd = 1;
2699 fixP->tc_fix_data.info = info;
2700 break;
2701
2702 case BFD_RELOC_ALPHA_TLSLDM:
2703 fixP->fx_no_overflow = 1;
2704
2705 if (insn->sequence == 0)
2706 break;
2707 info = get_alpha_reloc_tag (insn->sequence);
2708 if (info->saw_tlsldm)
2709 as_bad (_("duplicate !tlsldm!%ld"), insn->sequence);
2710 else if (info->saw_tlsgd)
2711 as_bad (_("sequence number in use for !tlsgd!%ld"),
2712 insn->sequence);
2713 else
2714 info->saw_tlsldm = 1;
2715 fixP->tc_fix_data.info = info;
2716 break;
11f45fb5 2717#endif
252b5132 2718 default:
32ff5c2e 2719 if ((int) fixup->reloc < 0)
252b5132
RH
2720 {
2721 if (operand->flags & AXP_OPERAND_NOOVERFLOW)
2722 fixP->fx_no_overflow = 1;
2723 }
2724 break;
2725 }
2726 }
2727}
2728
2729/* Given an opcode name and a pre-tokenized set of arguments, assemble
2730 the insn, but do not emit it.
2731
2732 Note that this implies no macros allowed, since we can't store more
2733 than one insn in an insn structure. */
2734
2735static void
32ff5c2e 2736assemble_tokens_to_insn (opname, tok, ntok, insn)
252b5132
RH
2737 const char *opname;
2738 const expressionS *tok;
2739 int ntok;
2740 struct alpha_insn *insn;
2741{
2742 const struct alpha_opcode *opcode;
2743
2744 /* search opcodes */
2745 opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
2746 if (opcode)
2747 {
2748 int cpumatch;
2749 opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
2750 if (opcode)
2751 {
19f78583 2752 assemble_insn (opcode, tok, ntok, insn, BFD_RELOC_UNUSED);
252b5132
RH
2753 return;
2754 }
2755 else if (cpumatch)
2756 as_bad (_("inappropriate arguments for opcode `%s'"), opname);
2757 else
2758 as_bad (_("opcode `%s' not supported for target %s"), opname,
1aad8cf8 2759 alpha_target_name);
252b5132
RH
2760 }
2761 else
2762 as_bad (_("unknown opcode `%s'"), opname);
2763}
2764
2765/* Given an opcode name and a pre-tokenized set of arguments, take the
2766 opcode all the way through emission. */
2767
2768static void
2769assemble_tokens (opname, tok, ntok, local_macros_on)
2770 const char *opname;
2771 const expressionS *tok;
2772 int ntok;
2773 int local_macros_on;
2774{
2775 int found_something = 0;
2776 const struct alpha_opcode *opcode;
2777 const struct alpha_macro *macro;
2778 int cpumatch = 1;
19f78583 2779 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
252b5132 2780
69108c1f 2781#ifdef RELOC_OP_P
19f78583
RH
2782 /* If a user-specified relocation is present, this is not a macro. */
2783 if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
2784 {
2785 reloc = ALPHA_RELOC_TABLE (tok[ntok - 1].X_op)->reloc;
2786 ntok--;
2787 }
69108c1f
AM
2788 else
2789#endif
2790 if (local_macros_on)
252b5132
RH
2791 {
2792 macro = ((const struct alpha_macro *)
2793 hash_find (alpha_macro_hash, opname));
2794 if (macro)
2795 {
2796 found_something = 1;
2797 macro = find_macro_match (macro, tok, &ntok);
2798 if (macro)
2799 {
2800 (*macro->emit) (tok, ntok, macro->arg);
2801 return;
2802 }
2803 }
2804 }
2805
11f45fb5 2806 /* Search opcodes. */
252b5132
RH
2807 opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
2808 if (opcode)
2809 {
2810 found_something = 1;
2811 opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
2812 if (opcode)
2813 {
2814 struct alpha_insn insn;
19f78583
RH
2815 assemble_insn (opcode, tok, ntok, &insn, reloc);
2816
2817 /* Copy the sequence number for the reloc from the reloc token. */
2818 if (reloc != BFD_RELOC_UNUSED)
2819 insn.sequence = tok[ntok].X_add_number;
2820
252b5132
RH
2821 emit_insn (&insn);
2822 return;
2823 }
2824 }
2825
2826 if (found_something)
19f78583
RH
2827 {
2828 if (cpumatch)
2829 as_bad (_("inappropriate arguments for opcode `%s'"), opname);
2830 else
2831 as_bad (_("opcode `%s' not supported for target %s"), opname,
2832 alpha_target_name);
2833 }
252b5132
RH
2834 else
2835 as_bad (_("unknown opcode `%s'"), opname);
2836}
252b5132 2837\f
11f45fb5 2838/* Some instruction sets indexed by lg(size). */
252b5132
RH
2839static const char * const sextX_op[] = { "sextb", "sextw", "sextl", NULL };
2840static const char * const insXl_op[] = { "insbl", "inswl", "insll", "insql" };
2841static const char * const insXh_op[] = { NULL, "inswh", "inslh", "insqh" };
2842static const char * const extXl_op[] = { "extbl", "extwl", "extll", "extql" };
2843static const char * const extXh_op[] = { NULL, "extwh", "extlh", "extqh" };
2844static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" };
2845static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" };
2846static const char * const stX_op[] = { "stb", "stw", "stl", "stq" };
252b5132
RH
2847static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL };
2848
2849/* Implement the ldgp macro. */
2850
2851static void
2852emit_ldgp (tok, ntok, unused)
2853 const expressionS *tok;
446a06c9
MM
2854 int ntok ATTRIBUTE_UNUSED;
2855 const PTR unused ATTRIBUTE_UNUSED;
252b5132
RH
2856{
2857#ifdef OBJ_AOUT
2858FIXME
2859#endif
2860#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
2861 /* from "ldgp r1,n(r2)", generate "ldah r1,X(R2); lda r1,Y(r1)"
2862 with appropriate constants and relocations. */
2863 struct alpha_insn insn;
2864 expressionS newtok[3];
2865 expressionS addend;
2866
252b5132
RH
2867#ifdef OBJ_ECOFF
2868 if (regno (tok[2].X_add_number) == AXP_REG_PV)
2869 ecoff_set_gp_prolog_size (0);
2870#endif
2871
2872 newtok[0] = tok[0];
2873 set_tok_const (newtok[1], 0);
2874 newtok[2] = tok[2];
2875
2876 assemble_tokens_to_insn ("ldah", newtok, 3, &insn);
2877
2878 addend = tok[1];
2879
2880#ifdef OBJ_ECOFF
2881 if (addend.X_op != O_constant)
2882 as_bad (_("can not resolve expression"));
2883 addend.X_op = O_symbol;
2884 addend.X_add_symbol = alpha_gp_symbol;
2885#endif
2886
2887 insn.nfixups = 1;
2888 insn.fixups[0].exp = addend;
2889 insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
19f78583 2890 insn.sequence = next_sequence_num;
252b5132
RH
2891
2892 emit_insn (&insn);
2893
2894 set_tok_preg (newtok[2], tok[0].X_add_number);
2895
2896 assemble_tokens_to_insn ("lda", newtok, 3, &insn);
2897
2898#ifdef OBJ_ECOFF
2899 addend.X_add_number += 4;
2900#endif
2901
2902 insn.nfixups = 1;
2903 insn.fixups[0].exp = addend;
2904 insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
19f78583 2905 insn.sequence = next_sequence_num--;
252b5132
RH
2906
2907 emit_insn (&insn);
2908#endif /* OBJ_ECOFF || OBJ_ELF */
2909}
2910
2911#ifdef OBJ_EVAX
2912
2913/* Add symbol+addend to link pool.
2914 Return offset from basesym to entry in link pool.
2915
2916 Add new fixup only if offset isn't 16bit. */
2917
2918valueT
2919add_to_link_pool (basesym, sym, addend)
2920 symbolS *basesym;
2921 symbolS *sym;
2922 offsetT addend;
2923{
2924 segT current_section = now_seg;
2925 int current_subsec = now_subseg;
2926 valueT offset;
2927 bfd_reloc_code_real_type reloc_type;
2928 char *p;
2929 segment_info_type *seginfo = seg_info (alpha_link_section);
2930 fixS *fixp;
2931
7dcc9865 2932 offset = - *symbol_get_obj (basesym);
252b5132
RH
2933
2934 /* @@ This assumes all entries in a given section will be of the same
2935 size... Probably correct, but unwise to rely on. */
2936 /* This must always be called with the same subsegment. */
2937
2938 if (seginfo->frchainP)
2939 for (fixp = seginfo->frchainP->fix_root;
2940 fixp != (fixS *) NULL;
2941 fixp = fixp->fx_next, offset += 8)
2942 {
2943 if (fixp->fx_addsy == sym && fixp->fx_offset == addend)
2944 {
2945 if (range_signed_16 (offset))
2946 {
1aad8cf8 2947 return offset;
252b5132
RH
2948 }
2949 }
2950 }
2951
2952 /* Not found in 16bit signed range. */
2953
2954 subseg_set (alpha_link_section, 0);
2955 p = frag_more (8);
2956 memset (p, 0, 8);
2957
2958 fix_new (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0,
2959 BFD_RELOC_64);
2960
2961 subseg_set (current_section, current_subsec);
2962 seginfo->literal_pool_size += 8;
2963 return offset;
2964}
2965
2966#endif /* OBJ_EVAX */
2967
2968/* Load a (partial) expression into a target register.
2969
2970 If poffset is not null, after the call it will either contain
2971 O_constant 0, or a 16-bit offset appropriate for any MEM format
2972 instruction. In addition, pbasereg will be modified to point to
2973 the base register to use in that MEM format instruction.
2974
2975 In any case, *pbasereg should contain a base register to add to the
2976 expression. This will normally be either AXP_REG_ZERO or
2977 alpha_gp_register. Symbol addresses will always be loaded via $gp,
2978 so "foo($0)" is interpreted as adding the address of foo to $0;
2979 i.e. "ldq $targ, LIT($gp); addq $targ, $0, $targ". Odd, perhaps,
2980 but this is what OSF/1 does.
2981
43b4c25e 2982 If explicit relocations of the form !literal!<number> are allowed,
2d2255b5 2983 and used, then explicit_reloc with be an expression pointer.
43b4c25e 2984
19f78583
RH
2985 Finally, the return value is nonzero if the calling macro may emit
2986 a LITUSE reloc if otherwise appropriate; the return value is the
2987 sequence number to use. */
252b5132 2988
19f78583
RH
2989static long
2990load_expression (targreg, exp, pbasereg, poffset)
252b5132
RH
2991 int targreg;
2992 const expressionS *exp;
2993 int *pbasereg;
2994 expressionS *poffset;
2995{
19f78583 2996 long emit_lituse = 0;
252b5132
RH
2997 offsetT addend = exp->X_add_number;
2998 int basereg = *pbasereg;
2999 struct alpha_insn insn;
3000 expressionS newtok[3];
3001
3002 switch (exp->X_op)
3003 {
3004 case O_symbol:
3005 {
3006#ifdef OBJ_ECOFF
3007 offsetT lit;
3008
11f45fb5 3009 /* Attempt to reduce .lit load by splitting the offset from
252b5132
RH
3010 its symbol when possible, but don't create a situation in
3011 which we'd fail. */
3012 if (!range_signed_32 (addend) &&
3013 (alpha_noat_on || targreg == AXP_REG_AT))
3014 {
3015 lit = add_to_literal_pool (exp->X_add_symbol, addend,
3016 alpha_lita_section, 8);
3017 addend = 0;
3018 }
3019 else
3020 {
3021 lit = add_to_literal_pool (exp->X_add_symbol, 0,
3022 alpha_lita_section, 8);
3023 }
3024
3025 if (lit >= 0x8000)
3026 as_fatal (_("overflow in literal (.lita) table"));
3027
3028 /* emit "ldq r, lit(gp)" */
3029
3030 if (basereg != alpha_gp_register && targreg == basereg)
3031 {
3032 if (alpha_noat_on)
3033 as_bad (_("macro requires $at register while noat in effect"));
3034 if (targreg == AXP_REG_AT)
3035 as_bad (_("macro requires $at while $at in use"));
3036
3037 set_tok_reg (newtok[0], AXP_REG_AT);
3038 }
3039 else
3040 set_tok_reg (newtok[0], targreg);
3041 set_tok_sym (newtok[1], alpha_lita_symbol, lit);
3042 set_tok_preg (newtok[2], alpha_gp_register);
3043
3044 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
3045
3046 assert (insn.nfixups == 1);
3047 insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
19f78583 3048 insn.sequence = emit_lituse = next_sequence_num--;
252b5132
RH
3049#endif /* OBJ_ECOFF */
3050#ifdef OBJ_ELF
3051 /* emit "ldq r, gotoff(gp)" */
3052
3053 if (basereg != alpha_gp_register && targreg == basereg)
3054 {
3055 if (alpha_noat_on)
3056 as_bad (_("macro requires $at register while noat in effect"));
3057 if (targreg == AXP_REG_AT)
3058 as_bad (_("macro requires $at while $at in use"));
3059
3060 set_tok_reg (newtok[0], AXP_REG_AT);
3061 }
3062 else
3063 set_tok_reg (newtok[0], targreg);
3064
3065 /* XXX: Disable this .got minimizing optimization so that we can get
3066 better instruction offset knowledge in the compiler. This happens
3067 very infrequently anyway. */
66498417
KH
3068 if (1
3069 || (!range_signed_32 (addend)
3070 && (alpha_noat_on || targreg == AXP_REG_AT)))
252b5132
RH
3071 {
3072 newtok[1] = *exp;
3073 addend = 0;
3074 }
3075 else
3076 {
3077 set_tok_sym (newtok[1], exp->X_add_symbol, 0);
3078 }
3079
3080 set_tok_preg (newtok[2], alpha_gp_register);
3081
3082 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
3083
3084 assert (insn.nfixups == 1);
19f78583
RH
3085 insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
3086 insn.sequence = emit_lituse = next_sequence_num--;
252b5132
RH
3087#endif /* OBJ_ELF */
3088#ifdef OBJ_EVAX
3089 offsetT link;
3090
3091 /* Find symbol or symbol pointer in link section. */
3092
3093 if (exp->X_add_symbol == alpha_evax_proc.symbol)
3094 {
3095 if (range_signed_16 (addend))
3096 {
3097 set_tok_reg (newtok[0], targreg);
3098 set_tok_const (newtok[1], addend);
3099 set_tok_preg (newtok[2], basereg);
3100 assemble_tokens_to_insn ("lda", newtok, 3, &insn);
3101 addend = 0;
3102 }
3103 else
3104 {
3105 set_tok_reg (newtok[0], targreg);
3106 set_tok_const (newtok[1], 0);
3107 set_tok_preg (newtok[2], basereg);
3108 assemble_tokens_to_insn ("lda", newtok, 3, &insn);
3109 }
3110 }
3111 else
3112 {
3113 if (!range_signed_32 (addend))
3114 {
3115 link = add_to_link_pool (alpha_evax_proc.symbol,
3116 exp->X_add_symbol, addend);
3117 addend = 0;
3118 }
3119 else
3120 {
3121 link = add_to_link_pool (alpha_evax_proc.symbol,
3122 exp->X_add_symbol, 0);
3123 }
3124 set_tok_reg (newtok[0], targreg);
3125 set_tok_const (newtok[1], link);
3126 set_tok_preg (newtok[2], basereg);
3127 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
3128 }
3129#endif /* OBJ_EVAX */
3130
32ff5c2e 3131 emit_insn (&insn);
252b5132
RH
3132
3133#ifndef OBJ_EVAX
252b5132
RH
3134 if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO)
3135 {
3136 /* emit "addq r, base, r" */
3137
3138 set_tok_reg (newtok[1], basereg);
3139 set_tok_reg (newtok[2], targreg);
3140 assemble_tokens ("addq", newtok, 3, 0);
3141 }
3142#endif
3143
3144 basereg = targreg;
3145 }
3146 break;
3147
3148 case O_constant:
3149 break;
3150
3151 case O_subtract:
3152 /* Assume that this difference expression will be resolved to an
1dab94dd 3153 absolute value and that that value will fit in 16 bits. */
252b5132
RH
3154
3155 set_tok_reg (newtok[0], targreg);
3156 newtok[1] = *exp;
3157 set_tok_preg (newtok[2], basereg);
3158 assemble_tokens ("lda", newtok, 3, 0);
3159
3160 if (poffset)
3161 set_tok_const (*poffset, 0);
3162 return 0;
3163
3164 case O_big:
3165 if (exp->X_add_number > 0)
3166 as_bad (_("bignum invalid; zero assumed"));
3167 else
3168 as_bad (_("floating point number invalid; zero assumed"));
3169 addend = 0;
3170 break;
3171
3172 default:
3173 as_bad (_("can't handle expression"));
3174 addend = 0;
3175 break;
3176 }
3177
3178 if (!range_signed_32 (addend))
3179 {
3180 offsetT lit;
19f78583 3181 long seq_num = next_sequence_num--;
252b5132 3182
19f78583 3183 /* For 64-bit addends, just put it in the literal pool. */
252b5132
RH
3184
3185#ifdef OBJ_EVAX
3186 /* emit "ldq targreg, lit(basereg)" */
3187 lit = add_to_link_pool (alpha_evax_proc.symbol,
3188 section_symbol (absolute_section), addend);
3189 set_tok_reg (newtok[0], targreg);
3190 set_tok_const (newtok[1], lit);
3191 set_tok_preg (newtok[2], alpha_gp_register);
3192 assemble_tokens ("ldq", newtok, 3, 0);
3193#else
3194
3195 if (alpha_lit8_section == NULL)
3196 {
3197 create_literal_section (".lit8",
3198 &alpha_lit8_section,
3199 &alpha_lit8_symbol);
3200
3201#ifdef OBJ_ECOFF
3202 alpha_lit8_literal = add_to_literal_pool (alpha_lit8_symbol, 0x8000,
3203 alpha_lita_section, 8);
3204 if (alpha_lit8_literal >= 0x8000)
3205 as_fatal (_("overflow in literal (.lita) table"));
3206#endif
3207 }
3208
3209 lit = add_to_literal_pool (NULL, addend, alpha_lit8_section, 8) - 0x8000;
3210 if (lit >= 0x8000)
3211 as_fatal (_("overflow in literal (.lit8) table"));
3212
3213 /* emit "lda litreg, .lit8+0x8000" */
3214
3215 if (targreg == basereg)
3216 {
3217 if (alpha_noat_on)
3218 as_bad (_("macro requires $at register while noat in effect"));
3219 if (targreg == AXP_REG_AT)
3220 as_bad (_("macro requires $at while $at in use"));
3221
3222 set_tok_reg (newtok[0], AXP_REG_AT);
3223 }
3224 else
3225 set_tok_reg (newtok[0], targreg);
3226#ifdef OBJ_ECOFF
3227 set_tok_sym (newtok[1], alpha_lita_symbol, alpha_lit8_literal);
3228#endif
3229#ifdef OBJ_ELF
3230 set_tok_sym (newtok[1], alpha_lit8_symbol, 0x8000);
3231#endif
3232 set_tok_preg (newtok[2], alpha_gp_register);
3233
3234 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
3235
3236 assert (insn.nfixups == 1);
3237#ifdef OBJ_ECOFF
3238 insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
3239#endif
3240#ifdef OBJ_ELF
3241 insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
3242#endif
19f78583 3243 insn.sequence = seq_num;
252b5132
RH
3244
3245 emit_insn (&insn);
3246
3247 /* emit "ldq litreg, lit(litreg)" */
3248
3249 set_tok_const (newtok[1], lit);
3250 set_tok_preg (newtok[2], newtok[0].X_add_number);
3251
3252 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
3253
3254 assert (insn.nfixups < MAX_INSN_FIXUPS);
19f78583
RH
3255 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3256 insn.fixups[insn.nfixups].exp.X_op = O_absent;
252b5132 3257 insn.nfixups++;
19f78583 3258 insn.sequence = seq_num;
252b5132
RH
3259 emit_lituse = 0;
3260
3261 emit_insn (&insn);
3262
3263 /* emit "addq litreg, base, target" */
3264
3265 if (basereg != AXP_REG_ZERO)
3266 {
3267 set_tok_reg (newtok[1], basereg);
3268 set_tok_reg (newtok[2], targreg);
3269 assemble_tokens ("addq", newtok, 3, 0);
3270 }
3271#endif /* !OBJ_EVAX */
3272
3273 if (poffset)
3274 set_tok_const (*poffset, 0);
3275 *pbasereg = targreg;
3276 }
3277 else
3278 {
3279 offsetT low, high, extra, tmp;
3280
3281 /* for 32-bit operands, break up the addend */
3282
3283 low = sign_extend_16 (addend);
3284 tmp = addend - low;
3285 high = sign_extend_16 (tmp >> 16);
3286
3287 if (tmp - (high << 16))
3288 {
3289 extra = 0x4000;
3290 tmp -= 0x40000000;
3291 high = sign_extend_16 (tmp >> 16);
3292 }
3293 else
3294 extra = 0;
3295
3296 set_tok_reg (newtok[0], targreg);
3297 set_tok_preg (newtok[2], basereg);
3298
3299 if (extra)
3300 {
3301 /* emit "ldah r, extra(r) */
3302 set_tok_const (newtok[1], extra);
3303 assemble_tokens ("ldah", newtok, 3, 0);
3304 set_tok_preg (newtok[2], basereg = targreg);
3305 }
3306
3307 if (high)
3308 {
3309 /* emit "ldah r, high(r) */
3310 set_tok_const (newtok[1], high);
3311 assemble_tokens ("ldah", newtok, 3, 0);
3312 basereg = targreg;
3313 set_tok_preg (newtok[2], basereg);
3314 }
3315
3316 if ((low && !poffset) || (!poffset && basereg != targreg))
3317 {
3318 /* emit "lda r, low(base)" */
3319 set_tok_const (newtok[1], low);
3320 assemble_tokens ("lda", newtok, 3, 0);
3321 basereg = targreg;
3322 low = 0;
3323 }
3324
3325 if (poffset)
3326 set_tok_const (*poffset, low);
3327 *pbasereg = basereg;
3328 }
3329
3330 return emit_lituse;
3331}
3332
3333/* The lda macro differs from the lda instruction in that it handles
2d2255b5 3334 most simple expressions, particularly symbol address loads and
252b5132
RH
3335 large constants. */
3336
3337static void
19f78583 3338emit_lda (tok, ntok, unused)
252b5132
RH
3339 const expressionS *tok;
3340 int ntok;
19f78583 3341 const PTR unused ATTRIBUTE_UNUSED;
252b5132
RH
3342{
3343 int basereg;
3344
3345 if (ntok == 2)
3346 basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
3347 else
3348 basereg = tok[2].X_add_number;
3349
19f78583 3350 (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL);
252b5132
RH
3351}
3352
3353/* The ldah macro differs from the ldah instruction in that it has $31
3354 as an implied base register. */
3355
3356static void
3357emit_ldah (tok, ntok, unused)
3358 const expressionS *tok;
446a06c9
MM
3359 int ntok ATTRIBUTE_UNUSED;
3360 const PTR unused ATTRIBUTE_UNUSED;
252b5132
RH
3361{
3362 expressionS newtok[3];
3363
3364 newtok[0] = tok[0];
3365 newtok[1] = tok[1];
3366 set_tok_preg (newtok[2], AXP_REG_ZERO);
3367
3368 assemble_tokens ("ldah", newtok, 3, 0);
3369}
3370
3371/* Handle all "simple" integer register loads -- ldq, ldq_l, ldq_u,
3372 etc. They differ from the real instructions in that they do simple
3373 expressions like the lda macro. */
3374
3375static void
3376emit_ir_load (tok, ntok, opname)
3377 const expressionS *tok;
3378 int ntok;
3379 const PTR opname;
3380{
19f78583
RH
3381 int basereg;
3382 long lituse;
252b5132
RH
3383 expressionS newtok[3];
3384 struct alpha_insn insn;
3385
3386 if (ntok == 2)
3387 basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
3388 else
3389 basereg = tok[2].X_add_number;
3390
3391 lituse = load_expression (tok[0].X_add_number, &tok[1], &basereg,
19f78583 3392 &newtok[1]);
252b5132
RH
3393
3394 newtok[0] = tok[0];
3395 set_tok_preg (newtok[2], basereg);
3396
32ff5c2e 3397 assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn);
252b5132
RH
3398
3399 if (lituse)
3400 {
3401 assert (insn.nfixups < MAX_INSN_FIXUPS);
19f78583
RH
3402 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3403 insn.fixups[insn.nfixups].exp.X_op = O_absent;
252b5132 3404 insn.nfixups++;
19f78583 3405 insn.sequence = lituse;
252b5132
RH
3406 }
3407
3408 emit_insn (&insn);
3409}
3410
3411/* Handle fp register loads, and both integer and fp register stores.
3412 Again, we handle simple expressions. */
3413
3414static void
3415emit_loadstore (tok, ntok, opname)
3416 const expressionS *tok;
3417 int ntok;
3418 const PTR opname;
3419{
19f78583
RH
3420 int basereg;
3421 long lituse;
252b5132
RH
3422 expressionS newtok[3];
3423 struct alpha_insn insn;
3424
3425 if (ntok == 2)
3426 basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
3427 else
3428 basereg = tok[2].X_add_number;
3429
32ff5c2e 3430 if (tok[1].X_op != O_constant || !range_signed_16 (tok[1].X_add_number))
252b5132
RH
3431 {
3432 if (alpha_noat_on)
3433 as_bad (_("macro requires $at register while noat in effect"));
3434
19f78583 3435 lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]);
252b5132
RH
3436 }
3437 else
3438 {
3439 newtok[1] = tok[1];
3440 lituse = 0;
3441 }
3442
3443 newtok[0] = tok[0];
3444 set_tok_preg (newtok[2], basereg);
3445
32ff5c2e 3446 assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn);
252b5132
RH
3447
3448 if (lituse)
3449 {
3450 assert (insn.nfixups < MAX_INSN_FIXUPS);
19f78583
RH
3451 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3452 insn.fixups[insn.nfixups].exp.X_op = O_absent;
252b5132 3453 insn.nfixups++;
19f78583 3454 insn.sequence = lituse;
252b5132
RH
3455 }
3456
3457 emit_insn (&insn);
3458}
3459
3460/* Load a half-word or byte as an unsigned value. */
3461
3462static void
3463emit_ldXu (tok, ntok, vlgsize)
3464 const expressionS *tok;
3465 int ntok;
3466 const PTR vlgsize;
3467{
3468 if (alpha_target & AXP_OPCODE_BWX)
32ff5c2e 3469 emit_ir_load (tok, ntok, ldXu_op[(long) vlgsize]);
252b5132
RH
3470 else
3471 {
3472 expressionS newtok[3];
19f78583
RH
3473 struct alpha_insn insn;
3474 int basereg;
3475 long lituse;
43b4c25e 3476
252b5132
RH
3477 if (alpha_noat_on)
3478 as_bad (_("macro requires $at register while noat in effect"));
3479
19f78583
RH
3480 if (ntok == 2)
3481 basereg = (tok[1].X_op == O_constant
3482 ? AXP_REG_ZERO : alpha_gp_register);
3483 else
3484 basereg = tok[2].X_add_number;
3485
252b5132
RH
3486 /* emit "lda $at, exp" */
3487
19f78583 3488 lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL);
252b5132
RH
3489
3490 /* emit "ldq_u targ, 0($at)" */
3491
3492 newtok[0] = tok[0];
3493 set_tok_const (newtok[1], 0);
19f78583
RH
3494 set_tok_preg (newtok[2], basereg);
3495 assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn);
3496
3497 if (lituse)
3498 {
3499 assert (insn.nfixups < MAX_INSN_FIXUPS);
3500 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3501 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3502 insn.nfixups++;
3503 insn.sequence = lituse;
3504 }
3505
3506 emit_insn (&insn);
252b5132
RH
3507
3508 /* emit "extXl targ, $at, targ" */
3509
19f78583 3510 set_tok_reg (newtok[1], basereg);
252b5132 3511 newtok[2] = newtok[0];
19f78583
RH
3512 assemble_tokens_to_insn (extXl_op[(long) vlgsize], newtok, 3, &insn);
3513
3514 if (lituse)
3515 {
3516 assert (insn.nfixups < MAX_INSN_FIXUPS);
3517 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
3518 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3519 insn.nfixups++;
3520 insn.sequence = lituse;
3521 }
3522
3523 emit_insn (&insn);
252b5132
RH
3524 }
3525}
3526
3527/* Load a half-word or byte as a signed value. */
3528
3529static void
3530emit_ldX (tok, ntok, vlgsize)
3531 const expressionS *tok;
3532 int ntok;
3533 const PTR vlgsize;
3534{
3535 emit_ldXu (tok, ntok, vlgsize);
32ff5c2e 3536 assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1);
252b5132
RH
3537}
3538
3539/* Load an integral value from an unaligned address as an unsigned
3540 value. */
3541
3542static void
3543emit_uldXu (tok, ntok, vlgsize)
3544 const expressionS *tok;
3545 int ntok;
3546 const PTR vlgsize;
3547{
32ff5c2e 3548 long lgsize = (long) vlgsize;
252b5132
RH
3549 expressionS newtok[3];
3550
3551 if (alpha_noat_on)
3552 as_bad (_("macro requires $at register while noat in effect"));
3553
3554 /* emit "lda $at, exp" */
3555
3556 memcpy (newtok, tok, sizeof (expressionS) * ntok);
3557 newtok[0].X_add_number = AXP_REG_AT;
3558 assemble_tokens ("lda", newtok, ntok, 1);
3559
3560 /* emit "ldq_u $t9, 0($at)" */
3561
3562 set_tok_reg (newtok[0], AXP_REG_T9);
3563 set_tok_const (newtok[1], 0);
3564 set_tok_preg (newtok[2], AXP_REG_AT);
3565 assemble_tokens ("ldq_u", newtok, 3, 1);
3566
3567 /* emit "ldq_u $t10, size-1($at)" */
3568
3569 set_tok_reg (newtok[0], AXP_REG_T10);
66498417 3570 set_tok_const (newtok[1], (1 << lgsize) - 1);
252b5132
RH
3571 assemble_tokens ("ldq_u", newtok, 3, 1);
3572
3573 /* emit "extXl $t9, $at, $t9" */
3574
3575 set_tok_reg (newtok[0], AXP_REG_T9);
3576 set_tok_reg (newtok[1], AXP_REG_AT);
3577 set_tok_reg (newtok[2], AXP_REG_T9);
3578 assemble_tokens (extXl_op[lgsize], newtok, 3, 1);
3579
3580 /* emit "extXh $t10, $at, $t10" */
3581
3582 set_tok_reg (newtok[0], AXP_REG_T10);
3583 set_tok_reg (newtok[2], AXP_REG_T10);
3584 assemble_tokens (extXh_op[lgsize], newtok, 3, 1);
3585
3586 /* emit "or $t9, $t10, targ" */
3587
3588 set_tok_reg (newtok[0], AXP_REG_T9);
3589 set_tok_reg (newtok[1], AXP_REG_T10);
3590 newtok[2] = tok[0];
3591 assemble_tokens ("or", newtok, 3, 1);
3592}
3593
3594/* Load an integral value from an unaligned address as a signed value.
3595 Note that quads should get funneled to the unsigned load since we
3596 don't have to do the sign extension. */
3597
3598static void
3599emit_uldX (tok, ntok, vlgsize)
3600 const expressionS *tok;
3601 int ntok;
3602 const PTR vlgsize;
3603{
3604 emit_uldXu (tok, ntok, vlgsize);
32ff5c2e 3605 assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1);
252b5132
RH
3606}
3607
3608/* Implement the ldil macro. */
3609
3610static void
3611emit_ldil (tok, ntok, unused)
3612 const expressionS *tok;
3613 int ntok;
446a06c9 3614 const PTR unused ATTRIBUTE_UNUSED;
252b5132
RH
3615{
3616 expressionS newtok[2];
3617
bc805888 3618 memcpy (newtok, tok, sizeof (newtok));
252b5132
RH
3619 newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number);
3620
3621 assemble_tokens ("lda", newtok, ntok, 1);
3622}
3623
3624/* Store a half-word or byte. */
3625
3626static void
3627emit_stX (tok, ntok, vlgsize)
3628 const expressionS *tok;
3629 int ntok;
3630 const PTR vlgsize;
3631{
32ff5c2e 3632 int lgsize = (int) (long) vlgsize;
252b5132
RH
3633
3634 if (alpha_target & AXP_OPCODE_BWX)
3635 emit_loadstore (tok, ntok, stX_op[lgsize]);
3636 else
3637 {
3638 expressionS newtok[3];
19f78583
RH
3639 struct alpha_insn insn;
3640 int basereg;
3641 long lituse;
252b5132
RH
3642
3643 if (alpha_noat_on)
32ff5c2e 3644 as_bad (_("macro requires $at register while noat in effect"));
252b5132 3645
19f78583
RH
3646 if (ntok == 2)
3647 basereg = (tok[1].X_op == O_constant
3648 ? AXP_REG_ZERO : alpha_gp_register);
3649 else
3650 basereg = tok[2].X_add_number;
3651
252b5132
RH
3652 /* emit "lda $at, exp" */
3653
19f78583 3654 lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL);
252b5132
RH
3655
3656 /* emit "ldq_u $t9, 0($at)" */
3657
3658 set_tok_reg (newtok[0], AXP_REG_T9);
3659 set_tok_const (newtok[1], 0);
19f78583
RH
3660 set_tok_preg (newtok[2], basereg);
3661 assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn);
3662
3663 if (lituse)
3664 {
3665 assert (insn.nfixups < MAX_INSN_FIXUPS);
3666 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3667 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3668 insn.nfixups++;
3669 insn.sequence = lituse;
3670 }
3671
3672 emit_insn (&insn);
252b5132
RH
3673
3674 /* emit "insXl src, $at, $t10" */
3675
3676 newtok[0] = tok[0];
19f78583 3677 set_tok_reg (newtok[1], basereg);
252b5132 3678 set_tok_reg (newtok[2], AXP_REG_T10);
19f78583
RH
3679 assemble_tokens_to_insn (insXl_op[lgsize], newtok, 3, &insn);
3680
3681 if (lituse)
3682 {
3683 assert (insn.nfixups < MAX_INSN_FIXUPS);
3684 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
3685 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3686 insn.nfixups++;
3687 insn.sequence = lituse;
3688 }
3689
3690 emit_insn (&insn);
252b5132
RH
3691
3692 /* emit "mskXl $t9, $at, $t9" */
3693
3694 set_tok_reg (newtok[0], AXP_REG_T9);
3695 newtok[2] = newtok[0];
19f78583
RH
3696 assemble_tokens_to_insn (mskXl_op[lgsize], newtok, 3, &insn);
3697
3698 if (lituse)
3699 {
3700 assert (insn.nfixups < MAX_INSN_FIXUPS);
3701 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
3702 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3703 insn.nfixups++;
3704 insn.sequence = lituse;
3705 }
3706
3707 emit_insn (&insn);
252b5132
RH
3708
3709 /* emit "or $t9, $t10, $t9" */
3710
3711 set_tok_reg (newtok[1], AXP_REG_T10);
3712 assemble_tokens ("or", newtok, 3, 1);
3713
3714 /* emit "stq_u $t9, 0($at) */
3715
19f78583 3716 set_tok_const(newtok[1], 0);
252b5132 3717 set_tok_preg (newtok[2], AXP_REG_AT);
19f78583
RH
3718 assemble_tokens_to_insn ("stq_u", newtok, 3, &insn);
3719
3720 if (lituse)
3721 {
3722 assert (insn.nfixups < MAX_INSN_FIXUPS);
3723 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3724 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3725 insn.nfixups++;
3726 insn.sequence = lituse;
3727 }
3728
3729 emit_insn (&insn);
252b5132
RH
3730 }
3731}
3732
3733/* Store an integer to an unaligned address. */
3734
3735static void
3736emit_ustX (tok, ntok, vlgsize)
3737 const expressionS *tok;
3738 int ntok;
3739 const PTR vlgsize;
3740{
32ff5c2e 3741 int lgsize = (int) (long) vlgsize;
252b5132
RH
3742 expressionS newtok[3];
3743
3744 /* emit "lda $at, exp" */
3745
3746 memcpy (newtok, tok, sizeof (expressionS) * ntok);
3747 newtok[0].X_add_number = AXP_REG_AT;
3748 assemble_tokens ("lda", newtok, ntok, 1);
3749
3750 /* emit "ldq_u $9, 0($at)" */
3751
3752 set_tok_reg (newtok[0], AXP_REG_T9);
3753 set_tok_const (newtok[1], 0);
3754 set_tok_preg (newtok[2], AXP_REG_AT);
3755 assemble_tokens ("ldq_u", newtok, 3, 1);
3756
3757 /* emit "ldq_u $10, size-1($at)" */
3758
3759 set_tok_reg (newtok[0], AXP_REG_T10);
66498417 3760 set_tok_const (newtok[1], (1 << lgsize) - 1);
252b5132
RH
3761 assemble_tokens ("ldq_u", newtok, 3, 1);
3762
3763 /* emit "insXl src, $at, $t11" */
3764
3765 newtok[0] = tok[0];
3766 set_tok_reg (newtok[1], AXP_REG_AT);
3767 set_tok_reg (newtok[2], AXP_REG_T11);
3768 assemble_tokens (insXl_op[lgsize], newtok, 3, 1);
3769
3770 /* emit "insXh src, $at, $t12" */
3771
3772 set_tok_reg (newtok[2], AXP_REG_T12);
3773 assemble_tokens (insXh_op[lgsize], newtok, 3, 1);
3774
3775 /* emit "mskXl $t9, $at, $t9" */
3776
3777 set_tok_reg (newtok[0], AXP_REG_T9);
3778 newtok[2] = newtok[0];
3779 assemble_tokens (mskXl_op[lgsize], newtok, 3, 1);
3780
3781 /* emit "mskXh $t10, $at, $t10" */
3782
3783 set_tok_reg (newtok[0], AXP_REG_T10);
3784 newtok[2] = newtok[0];
3785 assemble_tokens (mskXh_op[lgsize], newtok, 3, 1);
3786
3787 /* emit "or $t9, $t11, $t9" */
3788
3789 set_tok_reg (newtok[0], AXP_REG_T9);
3790 set_tok_reg (newtok[1], AXP_REG_T11);
3791 newtok[2] = newtok[0];
3792 assemble_tokens ("or", newtok, 3, 1);
3793
3794 /* emit "or $t10, $t12, $t10" */
3795
3796 set_tok_reg (newtok[0], AXP_REG_T10);
3797 set_tok_reg (newtok[1], AXP_REG_T12);
3798 newtok[2] = newtok[0];
3799 assemble_tokens ("or", newtok, 3, 1);
3800
3801 /* emit "stq_u $t9, 0($at)" */
3802
3803 set_tok_reg (newtok[0], AXP_REG_T9);
3804 set_tok_const (newtok[1], 0);
3805 set_tok_preg (newtok[2], AXP_REG_AT);
3806 assemble_tokens ("stq_u", newtok, 3, 1);
3807
3808 /* emit "stq_u $t10, size-1($at)" */
3809
3810 set_tok_reg (newtok[0], AXP_REG_T10);
66498417 3811 set_tok_const (newtok[1], (1 << lgsize) - 1);
252b5132
RH
3812 assemble_tokens ("stq_u", newtok, 3, 1);
3813}
3814
3815/* Sign extend a half-word or byte. The 32-bit sign extend is
3816 implemented as "addl $31, $r, $t" in the opcode table. */
3817
3818static void
3819emit_sextX (tok, ntok, vlgsize)
3820 const expressionS *tok;
3821 int ntok;
3822 const PTR vlgsize;
3823{
32ff5c2e 3824 long lgsize = (long) vlgsize;
252b5132
RH
3825
3826 if (alpha_target & AXP_OPCODE_BWX)
3827 assemble_tokens (sextX_op[lgsize], tok, ntok, 0);
3828 else
3829 {
3830 int bitshift = 64 - 8 * (1 << lgsize);
3831 expressionS newtok[3];
3832
3833 /* emit "sll src,bits,dst" */
3834
3835 newtok[0] = tok[0];
3836 set_tok_const (newtok[1], bitshift);
3837 newtok[2] = tok[ntok - 1];
3838 assemble_tokens ("sll", newtok, 3, 1);
3839
3840 /* emit "sra dst,bits,dst" */
3841
3842 newtok[0] = newtok[2];
3843 assemble_tokens ("sra", newtok, 3, 1);
3844 }
3845}
3846
3847/* Implement the division and modulus macros. */
3848
3849#ifdef OBJ_EVAX
3850
3851/* Make register usage like in normal procedure call.
3852 Don't clobber PV and RA. */
3853
3854static void
3855emit_division (tok, ntok, symname)
3856 const expressionS *tok;
3857 int ntok;
3858 const PTR symname;
3859{
3860 /* DIVISION and MODULUS. Yech.
11f45fb5
NC
3861
3862 Convert
3863 OP x,y,result
3864 to
3865 mov x,R16 # if x != R16
3866 mov y,R17 # if y != R17
3867 lda AT,__OP
3868 jsr AT,(AT),0
3869 mov R0,result
3870
3871 with appropriate optimizations if R0,R16,R17 are the registers
3872 specified by the compiler. */
252b5132
RH
3873
3874 int xr, yr, rr;
3875 symbolS *sym;
3876 expressionS newtok[3];
3877
3878 xr = regno (tok[0].X_add_number);
3879 yr = regno (tok[1].X_add_number);
3880
3881 if (ntok < 3)
3882 rr = xr;
3883 else
3884 rr = regno (tok[2].X_add_number);
3885
11f45fb5 3886 /* Move the operands into the right place. */
252b5132
RH
3887 if (yr == AXP_REG_R16 && xr == AXP_REG_R17)
3888 {
11f45fb5 3889 /* They are in exactly the wrong order -- swap through AT. */
252b5132
RH
3890
3891 if (alpha_noat_on)
3892 as_bad (_("macro requires $at register while noat in effect"));
3893
3894 set_tok_reg (newtok[0], AXP_REG_R16);
3895 set_tok_reg (newtok[1], AXP_REG_AT);
3896 assemble_tokens ("mov", newtok, 2, 1);
3897
3898 set_tok_reg (newtok[0], AXP_REG_R17);
3899 set_tok_reg (newtok[1], AXP_REG_R16);
3900 assemble_tokens ("mov", newtok, 2, 1);
3901
3902 set_tok_reg (newtok[0], AXP_REG_AT);
3903 set_tok_reg (newtok[1], AXP_REG_R17);
3904 assemble_tokens ("mov", newtok, 2, 1);
3905 }
3906 else
3907 {
3908 if (yr == AXP_REG_R16)
3909 {
3910 set_tok_reg (newtok[0], AXP_REG_R16);
3911 set_tok_reg (newtok[1], AXP_REG_R17);
3912 assemble_tokens ("mov", newtok, 2, 1);
3913 }
3914
3915 if (xr != AXP_REG_R16)
3916 {
3917 set_tok_reg (newtok[0], xr);
3918 set_tok_reg (newtok[1], AXP_REG_R16);
1aad8cf8 3919 assemble_tokens ("mov", newtok, 2, 1);
252b5132
RH
3920 }
3921
3922 if (yr != AXP_REG_R16 && yr != AXP_REG_R17)
3923 {
3924 set_tok_reg (newtok[0], yr);
3925 set_tok_reg (newtok[1], AXP_REG_R17);
3926 assemble_tokens ("mov", newtok, 2, 1);
3927 }
3928 }
3929
32ff5c2e 3930 sym = symbol_find_or_make ((const char *) symname);
252b5132
RH
3931
3932 set_tok_reg (newtok[0], AXP_REG_AT);
3933 set_tok_sym (newtok[1], sym, 0);
3934 assemble_tokens ("lda", newtok, 2, 1);
3935
11f45fb5 3936 /* Call the division routine. */
252b5132
RH
3937 set_tok_reg (newtok[0], AXP_REG_AT);
3938 set_tok_cpreg (newtok[1], AXP_REG_AT);
3939 set_tok_const (newtok[2], 0);
3940 assemble_tokens ("jsr", newtok, 3, 1);
3941
11f45fb5 3942 /* Move the result to the right place. */
252b5132
RH
3943 if (rr != AXP_REG_R0)
3944 {
3945 set_tok_reg (newtok[0], AXP_REG_R0);
3946 set_tok_reg (newtok[1], rr);
3947 assemble_tokens ("mov", newtok, 2, 1);
3948 }
3949}
3950
3951#else /* !OBJ_EVAX */
3952
3953static void
3954emit_division (tok, ntok, symname)
3955 const expressionS *tok;
3956 int ntok;
3957 const PTR symname;
3958{
3959 /* DIVISION and MODULUS. Yech.
11f45fb5
NC
3960 Convert
3961 OP x,y,result
3962 to
3963 lda pv,__OP
3964 mov x,t10
3965 mov y,t11
3966 jsr t9,(pv),__OP
3967 mov t12,result
3968
3969 with appropriate optimizations if t10,t11,t12 are the registers
3970 specified by the compiler. */
252b5132
RH
3971
3972 int xr, yr, rr;
3973 symbolS *sym;
3974 expressionS newtok[3];
3975
3976 xr = regno (tok[0].X_add_number);
3977 yr = regno (tok[1].X_add_number);
3978
3979 if (ntok < 3)
3980 rr = xr;
3981 else
3982 rr = regno (tok[2].X_add_number);
3983
32ff5c2e 3984 sym = symbol_find_or_make ((const char *) symname);
252b5132 3985
11f45fb5 3986 /* Move the operands into the right place. */
252b5132
RH
3987 if (yr == AXP_REG_T10 && xr == AXP_REG_T11)
3988 {
11f45fb5 3989 /* They are in exactly the wrong order -- swap through AT. */
252b5132
RH
3990 if (alpha_noat_on)
3991 as_bad (_("macro requires $at register while noat in effect"));
3992
3993 set_tok_reg (newtok[0], AXP_REG_T10);
3994 set_tok_reg (newtok[1], AXP_REG_AT);
3995 assemble_tokens ("mov", newtok, 2, 1);
3996
3997 set_tok_reg (newtok[0], AXP_REG_T11);
3998 set_tok_reg (newtok[1], AXP_REG_T10);
3999 assemble_tokens ("mov", newtok, 2, 1);
4000
4001 set_tok_reg (newtok[0], AXP_REG_AT);
4002 set_tok_reg (newtok[1], AXP_REG_T11);
4003 assemble_tokens ("mov", newtok, 2, 1);
4004 }
4005 else
4006 {
4007 if (yr == AXP_REG_T10)
4008 {
4009 set_tok_reg (newtok[0], AXP_REG_T10);
4010 set_tok_reg (newtok[1], AXP_REG_T11);
4011 assemble_tokens ("mov", newtok, 2, 1);
4012 }
4013
4014 if (xr != AXP_REG_T10)
4015 {
4016 set_tok_reg (newtok[0], xr);
4017 set_tok_reg (newtok[1], AXP_REG_T10);
1aad8cf8 4018 assemble_tokens ("mov", newtok, 2, 1);
252b5132
RH
4019 }
4020
4021 if (yr != AXP_REG_T10 && yr != AXP_REG_T11)
4022 {
4023 set_tok_reg (newtok[0], yr);
4024 set_tok_reg (newtok[1], AXP_REG_T11);
4025 assemble_tokens ("mov", newtok, 2, 1);
4026 }
4027 }
4028
11f45fb5 4029 /* Call the division routine. */
252b5132
RH
4030 set_tok_reg (newtok[0], AXP_REG_T9);
4031 set_tok_sym (newtok[1], sym, 0);
4032 assemble_tokens ("jsr", newtok, 2, 1);
4033
11f45fb5 4034 /* Reload the GP register. */
252b5132
RH
4035#ifdef OBJ_AOUT
4036FIXME
4037#endif
4038#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
4039 set_tok_reg (newtok[0], alpha_gp_register);
4040 set_tok_const (newtok[1], 0);
4041 set_tok_preg (newtok[2], AXP_REG_T9);
4042 assemble_tokens ("ldgp", newtok, 3, 1);
4043#endif
4044
11f45fb5 4045 /* Move the result to the right place. */
252b5132
RH
4046 if (rr != AXP_REG_T12)
4047 {
4048 set_tok_reg (newtok[0], AXP_REG_T12);
4049 set_tok_reg (newtok[1], rr);
4050 assemble_tokens ("mov", newtok, 2, 1);
4051 }
4052}
4053
4054#endif /* !OBJ_EVAX */
4055
4056/* The jsr and jmp macros differ from their instruction counterparts
4057 in that they can load the target address and default most
4058 everything. */
4059
4060static void
4061emit_jsrjmp (tok, ntok, vopname)
4062 const expressionS *tok;
4063 int ntok;
4064 const PTR vopname;
4065{
4066 const char *opname = (const char *) vopname;
4067 struct alpha_insn insn;
4068 expressionS newtok[3];
19f78583
RH
4069 int r, tokidx = 0;
4070 long lituse = 0;
43b4c25e 4071
252b5132
RH
4072 if (tokidx < ntok && tok[tokidx].X_op == O_register)
4073 r = regno (tok[tokidx++].X_add_number);
4074 else
4075 r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA;
4076
4077 set_tok_reg (newtok[0], r);
4078
4079 if (tokidx < ntok &&
4080 (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
4081 r = regno (tok[tokidx++].X_add_number);
4082#ifdef OBJ_EVAX
4083 /* keep register if jsr $n.<sym> */
4084#else
4085 else
4086 {
4087 int basereg = alpha_gp_register;
19f78583 4088 lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL);
252b5132
RH
4089 }
4090#endif
4091
4092 set_tok_cpreg (newtok[1], r);
4093
4094#ifdef OBJ_EVAX
4095 /* FIXME: Add hint relocs to BFD for evax. */
4096#else
4097 if (tokidx < ntok)
4098 newtok[2] = tok[tokidx];
4099 else
4100#endif
4101 set_tok_const (newtok[2], 0);
4102
4103 assemble_tokens_to_insn (opname, newtok, 3, &insn);
4104
252b5132
RH
4105 if (lituse)
4106 {
4107 assert (insn.nfixups < MAX_INSN_FIXUPS);
19f78583
RH
4108 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_JSR;
4109 insn.fixups[insn.nfixups].exp.X_op = O_absent;
252b5132 4110 insn.nfixups++;
19f78583 4111 insn.sequence = lituse;
252b5132
RH
4112 }
4113
4114 emit_insn (&insn);
4115}
4116
4117/* The ret and jcr instructions differ from their instruction
4118 counterparts in that everything can be defaulted. */
4119
4120static void
4121emit_retjcr (tok, ntok, vopname)
4122 const expressionS *tok;
4123 int ntok;
4124 const PTR vopname;
4125{
32ff5c2e 4126 const char *opname = (const char *) vopname;
252b5132
RH
4127 expressionS newtok[3];
4128 int r, tokidx = 0;
4129
4130 if (tokidx < ntok && tok[tokidx].X_op == O_register)
4131 r = regno (tok[tokidx++].X_add_number);
4132 else
4133 r = AXP_REG_ZERO;
4134
4135 set_tok_reg (newtok[0], r);
4136
4137 if (tokidx < ntok &&
4138 (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
4139 r = regno (tok[tokidx++].X_add_number);
4140 else
4141 r = AXP_REG_RA;
4142
4143 set_tok_cpreg (newtok[1], r);
4144
4145 if (tokidx < ntok)
4146 newtok[2] = tok[tokidx];
4147 else
32ff5c2e 4148 set_tok_const (newtok[2], strcmp (opname, "ret") == 0);
252b5132
RH
4149
4150 assemble_tokens (opname, newtok, 3, 0);
4151}
4152\f
11f45fb5 4153/* Assembler directives. */
252b5132
RH
4154
4155/* Handle the .text pseudo-op. This is like the usual one, but it
4156 clears alpha_insn_label and restores auto alignment. */
4157
4158static void
4159s_alpha_text (i)
4160 int i;
4161
4162{
559e22f3
JJ
4163#ifdef OBJ_ELF
4164 obj_elf_text (i);
4165#else
252b5132 4166 s_text (i);
559e22f3 4167#endif
252b5132
RH
4168 alpha_insn_label = NULL;
4169 alpha_auto_align_on = 1;
4170 alpha_current_align = 0;
4171}
4172
4173/* Handle the .data pseudo-op. This is like the usual one, but it
4174 clears alpha_insn_label and restores auto alignment. */
4175
4176static void
4177s_alpha_data (i)
4178 int i;
4179{
559e22f3
JJ
4180#ifdef OBJ_ELF
4181 obj_elf_data (i);
4182#else
252b5132 4183 s_data (i);
559e22f3 4184#endif
252b5132
RH
4185 alpha_insn_label = NULL;
4186 alpha_auto_align_on = 1;
4187 alpha_current_align = 0;
4188}
4189
4190#if defined (OBJ_ECOFF) || defined (OBJ_EVAX)
4191
4192/* Handle the OSF/1 and openVMS .comm pseudo quirks.
4193 openVMS constructs a section for every common symbol. */
4194
4195static void
4196s_alpha_comm (ignore)
11f45fb5 4197 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4198{
4199 register char *name;
4200 register char c;
4201 register char *p;
4202 offsetT temp;
4203 register symbolS *symbolP;
4204
4205#ifdef OBJ_EVAX
4206 segT current_section = now_seg;
4207 int current_subsec = now_subseg;
4208 segT new_seg;
4209#endif
4210
4211 name = input_line_pointer;
4212 c = get_symbol_end ();
4213
4214 /* just after name is now '\0' */
4215 p = input_line_pointer;
4216 *p = c;
4217
4218 SKIP_WHITESPACE ();
4219
4220 /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */
4221 if (*input_line_pointer == ',')
4222 {
4223 input_line_pointer++;
4224 SKIP_WHITESPACE ();
4225 }
4226 if ((temp = get_absolute_expression ()) < 0)
4227 {
4228 as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
4229 ignore_rest_of_line ();
4230 return;
4231 }
4232
4233 *p = 0;
4234 symbolP = symbol_find_or_make (name);
4235
4236#ifdef OBJ_EVAX
4237 /* Make a section for the common symbol. */
4238 new_seg = subseg_new (xstrdup (name), 0);
4239#endif
4240
4241 *p = c;
4242
4243#ifdef OBJ_EVAX
4244 /* alignment might follow */
4245 if (*input_line_pointer == ',')
4246 {
4247 offsetT align;
4248
1dab94dd 4249 input_line_pointer++;
252b5132
RH
4250 align = get_absolute_expression ();
4251 bfd_set_section_alignment (stdoutput, new_seg, align);
4252 }
4253#endif
4254
4255 if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
4256 {
4257 as_bad (_("Ignoring attempt to re-define symbol"));
4258 ignore_rest_of_line ();
4259 return;
4260 }
4261
4262#ifdef OBJ_EVAX
4263 if (bfd_section_size (stdoutput, new_seg) > 0)
1dab94dd 4264 {
252b5132
RH
4265 if (bfd_section_size (stdoutput, new_seg) != temp)
4266 as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
4267 S_GET_NAME (symbolP),
4268 (long) bfd_section_size (stdoutput, new_seg),
4269 (long) temp);
4270 }
4271#else
4272 if (S_GET_VALUE (symbolP))
4273 {
4274 if (S_GET_VALUE (symbolP) != (valueT) temp)
4275 as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
4276 S_GET_NAME (symbolP),
4277 (long) S_GET_VALUE (symbolP),
4278 (long) temp);
4279 }
4280#endif
4281 else
4282 {
1dab94dd 4283#ifdef OBJ_EVAX
252b5132
RH
4284 subseg_set (new_seg, 0);
4285 p = frag_more (temp);
4286 new_seg->flags |= SEC_IS_COMMON;
4287 if (! S_IS_DEFINED (symbolP))
9de8d8f1 4288 S_SET_SEGMENT (symbolP, new_seg);
252b5132
RH
4289#else
4290 S_SET_VALUE (symbolP, (valueT) temp);
4291#endif
4292 S_SET_EXTERNAL (symbolP);
4293 }
4294
4295#ifdef OBJ_EVAX
4296 subseg_set (current_section, current_subsec);
4297#endif
4298
7dcc9865 4299 know (symbol_get_frag (symbolP) == &zero_address_frag);
252b5132
RH
4300
4301 demand_empty_rest_of_line ();
4302}
4303
4304#endif /* ! OBJ_ELF */
4305
4306#ifdef OBJ_ECOFF
4307
4308/* Handle the .rdata pseudo-op. This is like the usual one, but it
4309 clears alpha_insn_label and restores auto alignment. */
4310
4311static void
4312s_alpha_rdata (ignore)
11f45fb5 4313 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4314{
4315 int temp;
4316
4317 temp = get_absolute_expression ();
4318 subseg_new (".rdata", 0);
4319 demand_empty_rest_of_line ();
4320 alpha_insn_label = NULL;
4321 alpha_auto_align_on = 1;
4322 alpha_current_align = 0;
4323}
4324
4325#endif
4326
4327#ifdef OBJ_ECOFF
4328
4329/* Handle the .sdata pseudo-op. This is like the usual one, but it
4330 clears alpha_insn_label and restores auto alignment. */
4331
4332static void
4333s_alpha_sdata (ignore)
11f45fb5 4334 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4335{
4336 int temp;
4337
4338 temp = get_absolute_expression ();
4339 subseg_new (".sdata", 0);
4340 demand_empty_rest_of_line ();
4341 alpha_insn_label = NULL;
4342 alpha_auto_align_on = 1;
4343 alpha_current_align = 0;
4344}
4345#endif
4346
4347#ifdef OBJ_ELF
f37f01cf
RH
4348struct alpha_elf_frame_data
4349{
4350 symbolS *func_sym;
4351 symbolS *func_end_sym;
4352 symbolS *prologue_sym;
4353 unsigned int mask;
4354 unsigned int fmask;
4355 int fp_regno;
4356 int ra_regno;
4357 offsetT frame_size;
4358 offsetT mask_offset;
4359 offsetT fmask_offset;
4360
4361 struct alpha_elf_frame_data *next;
4362};
4363
4364static struct alpha_elf_frame_data *all_frame_data;
4365static struct alpha_elf_frame_data **plast_frame_data = &all_frame_data;
4366static struct alpha_elf_frame_data *cur_frame_data;
252b5132
RH
4367
4368/* Handle the .section pseudo-op. This is like the usual one, but it
4369 clears alpha_insn_label and restores auto alignment. */
4370
4371static void
4372s_alpha_section (ignore)
11f45fb5 4373 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4374{
4375 obj_elf_section (ignore);
4376
4377 alpha_insn_label = NULL;
4378 alpha_auto_align_on = 1;
4379 alpha_current_align = 0;
4380}
4381
4382static void
4383s_alpha_ent (dummy)
446a06c9 4384 int dummy ATTRIBUTE_UNUSED;
252b5132
RH
4385{
4386 if (ECOFF_DEBUGGING)
4387 ecoff_directive_ent (0);
4388 else
4389 {
4390 char *name, name_end;
4391 name = input_line_pointer;
4392 name_end = get_symbol_end ();
4393
4394 if (! is_name_beginner (*name))
4395 {
4396 as_warn (_(".ent directive has no name"));
4397 *input_line_pointer = name_end;
4398 }
4399 else
4400 {
4401 symbolS *sym;
4402
f37f01cf 4403 if (cur_frame_data)
252b5132
RH
4404 as_warn (_("nested .ent directives"));
4405
4406 sym = symbol_find_or_make (name);
49309057 4407 symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
f37f01cf
RH
4408
4409 cur_frame_data = calloc (1, sizeof (*cur_frame_data));
4410 cur_frame_data->func_sym = sym;
4411
4412 /* Provide sensible defaults. */
4413 cur_frame_data->fp_regno = 30; /* sp */
4414 cur_frame_data->ra_regno = 26; /* ra */
4415
4416 *plast_frame_data = cur_frame_data;
4417 plast_frame_data = &cur_frame_data->next;
252b5132
RH
4418
4419 /* The .ent directive is sometimes followed by a number. Not sure
4420 what it really means, but ignore it. */
4421 *input_line_pointer = name_end;
4422 SKIP_WHITESPACE ();
4423 if (*input_line_pointer == ',')
4424 {
4425 input_line_pointer++;
4426 SKIP_WHITESPACE ();
4427 }
3882b010 4428 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
252b5132
RH
4429 (void) get_absolute_expression ();
4430 }
4431 demand_empty_rest_of_line ();
4432 }
4433}
4434
4435static void
4436s_alpha_end (dummy)
446a06c9 4437 int dummy ATTRIBUTE_UNUSED;
252b5132
RH
4438{
4439 if (ECOFF_DEBUGGING)
4440 ecoff_directive_end (0);
4441 else
4442 {
4443 char *name, name_end;
4444 name = input_line_pointer;
4445 name_end = get_symbol_end ();
4446
4447 if (! is_name_beginner (*name))
4448 {
4449 as_warn (_(".end directive has no name"));
4450 *input_line_pointer = name_end;
4451 }
4452 else
4453 {
4454 symbolS *sym;
4455
4456 sym = symbol_find (name);
f37f01cf
RH
4457 if (!cur_frame_data)
4458 as_warn (_(".end directive without matching .ent"));
4459 else if (sym != cur_frame_data->func_sym)
252b5132
RH
4460 as_warn (_(".end directive names different symbol than .ent"));
4461
4462 /* Create an expression to calculate the size of the function. */
b80901c7 4463 if (sym && cur_frame_data)
252b5132 4464 {
f37f01cf
RH
4465 OBJ_SYMFIELD_TYPE *obj = symbol_get_obj (sym);
4466 expressionS *exp = xmalloc (sizeof (expressionS));
4467
4468 obj->size = exp;
4469 exp->X_op = O_subtract;
4470 exp->X_add_symbol = symbol_temp_new_now ();
4471 exp->X_op_symbol = sym;
4472 exp->X_add_number = 0;
4473
4474 cur_frame_data->func_end_sym = exp->X_add_symbol;
252b5132
RH
4475 }
4476
f37f01cf 4477 cur_frame_data = NULL;
252b5132
RH
4478
4479 *input_line_pointer = name_end;
4480 }
4481 demand_empty_rest_of_line ();
4482 }
4483}
4484
4485static void
4486s_alpha_mask (fp)
4487 int fp;
4488{
4489 if (ECOFF_DEBUGGING)
4490 {
4491 if (fp)
1aad8cf8 4492 ecoff_directive_fmask (0);
252b5132 4493 else
1aad8cf8 4494 ecoff_directive_mask (0);
252b5132
RH
4495 }
4496 else
f37f01cf
RH
4497 {
4498 long val;
4499 offsetT offset;
4500
4501 if (!cur_frame_data)
4502 {
4503 if (fp)
4504 as_warn (_(".fmask outside of .ent"));
4505 else
4506 as_warn (_(".mask outside of .ent"));
4507 discard_rest_of_line ();
4508 return;
4509 }
4510
4511 if (get_absolute_expression_and_terminator (&val) != ',')
4512 {
4513 if (fp)
4514 as_warn (_("bad .fmask directive"));
4515 else
4516 as_warn (_("bad .mask directive"));
4517 --input_line_pointer;
4518 discard_rest_of_line ();
4519 return;
4520 }
4521
4522 offset = get_absolute_expression ();
4523 demand_empty_rest_of_line ();
4524
4525 if (fp)
4526 {
4527 cur_frame_data->fmask = val;
4528 cur_frame_data->fmask_offset = offset;
4529 }
4530 else
4531 {
4532 cur_frame_data->mask = val;
4533 cur_frame_data->mask_offset = offset;
4534 }
4535 }
252b5132
RH
4536}
4537
4538static void
4539s_alpha_frame (dummy)
446a06c9 4540 int dummy ATTRIBUTE_UNUSED;
252b5132
RH
4541{
4542 if (ECOFF_DEBUGGING)
4543 ecoff_directive_frame (0);
4544 else
f37f01cf
RH
4545 {
4546 long val;
4547
4548 if (!cur_frame_data)
4549 {
4550 as_warn (_(".frame outside of .ent"));
4551 discard_rest_of_line ();
4552 return;
4553 }
4554
4555 cur_frame_data->fp_regno = tc_get_register (1);
4556
4557 SKIP_WHITESPACE ();
4558 if (*input_line_pointer++ != ','
4559 || get_absolute_expression_and_terminator (&val) != ',')
4560 {
4561 as_warn (_("bad .frame directive"));
4562 --input_line_pointer;
4563 discard_rest_of_line ();
4564 return;
4565 }
4566 cur_frame_data->frame_size = val;
4567
4568 cur_frame_data->ra_regno = tc_get_register (0);
4569
4570 /* Next comes the "offset of saved $a0 from $sp". In gcc terms
4571 this is current_function_pretend_args_size. There's no place
4572 to put this value, so ignore it. */
4573 s_ignore (42);
4574 }
252b5132
RH
4575}
4576
4577static void
4578s_alpha_prologue (ignore)
446a06c9 4579 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4580{
4581 symbolS *sym;
4582 int arg;
4583
4584 arg = get_absolute_expression ();
4585 demand_empty_rest_of_line ();
4586
4587 if (ECOFF_DEBUGGING)
4588 sym = ecoff_get_cur_proc_sym ();
4589 else
f37f01cf 4590 sym = cur_frame_data ? cur_frame_data->func_sym : NULL;
81283cde
AM
4591
4592 if (sym == NULL)
4593 {
4594 as_bad (_(".prologue directive without a preceding .ent directive"));
4595 return;
4596 }
252b5132
RH
4597
4598 switch (arg)
4599 {
1aad8cf8
KH
4600 case 0: /* No PV required. */
4601 S_SET_OTHER (sym, STO_ALPHA_NOPV
4602 | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD));
4603 break;
4604 case 1: /* Std GP load. */
4605 S_SET_OTHER (sym, STO_ALPHA_STD_GPLOAD
4606 | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD));
4607 break;
4608 case 2: /* Non-std use of PV. */
4609 break;
4610
4611 default:
4612 as_bad (_("Invalid argument %d to .prologue."), arg);
4613 break;
1dab94dd 4614 }
f37f01cf
RH
4615
4616 if (cur_frame_data)
4617 cur_frame_data->prologue_sym = symbol_temp_new_now ();
252b5132
RH
4618}
4619
66498417 4620static char *first_file_directive;
a8316fe2 4621
4dc7ead9
RH
4622static void
4623s_alpha_file (ignore)
4624 int ignore ATTRIBUTE_UNUSED;
4625{
a8316fe2
RH
4626 /* Save the first .file directive we see, so that we can change our
4627 minds about whether ecoff debugging should or shouldn't be enabled. */
4628 if (alpha_flag_mdebug < 0 && ! first_file_directive)
4629 {
4630 char *start = input_line_pointer;
4631 size_t len;
4632
4633 discard_rest_of_line ();
4634
4635 len = input_line_pointer - start;
4636 first_file_directive = xmalloc (len + 1);
4637 memcpy (first_file_directive, start, len);
4638 first_file_directive[len] = '\0';
4639
4640 input_line_pointer = start;
4641 }
4642
4dc7ead9
RH
4643 if (ECOFF_DEBUGGING)
4644 ecoff_directive_file (0);
4645 else
4646 dwarf2_directive_file (0);
4647}
4648
4649static void
4650s_alpha_loc (ignore)
4651 int ignore ATTRIBUTE_UNUSED;
4652{
4653 if (ECOFF_DEBUGGING)
4654 ecoff_directive_loc (0);
4655 else
4656 dwarf2_directive_loc (0);
4657}
4658
a8316fe2
RH
4659static void
4660s_alpha_stab (n)
4661 int n;
4662{
4663 /* If we've been undecided about mdebug, make up our minds in favour. */
4664 if (alpha_flag_mdebug < 0)
4665 {
32ff5c2e 4666 segT sec = subseg_new (".mdebug", 0);
66498417 4667 bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY);
32ff5c2e 4668 bfd_set_section_alignment (stdoutput, sec, 3);
a8316fe2
RH
4669
4670 ecoff_read_begin_hook ();
4671
4672 if (first_file_directive)
4673 {
4674 char *save_ilp = input_line_pointer;
66498417 4675 input_line_pointer = first_file_directive;
a8316fe2
RH
4676 ecoff_directive_file (0);
4677 input_line_pointer = save_ilp;
4678 free (first_file_directive);
4679 }
4680
4681 alpha_flag_mdebug = 1;
4682 }
4683 s_stab (n);
4684}
4685
252b5132
RH
4686static void
4687s_alpha_coff_wrapper (which)
4688 int which;
4689{
4690 static void (* const fns[]) PARAMS ((int)) = {
4691 ecoff_directive_begin,
4692 ecoff_directive_bend,
4693 ecoff_directive_def,
4694 ecoff_directive_dim,
4695 ecoff_directive_endef,
252b5132
RH
4696 ecoff_directive_scl,
4697 ecoff_directive_tag,
4698 ecoff_directive_val,
252b5132
RH
4699 };
4700
bc805888 4701 assert (which >= 0 && which < (int) (sizeof (fns)/sizeof (*fns)));
252b5132
RH
4702
4703 if (ECOFF_DEBUGGING)
bc805888 4704 (*fns[which]) (0);
252b5132
RH
4705 else
4706 {
4707 as_bad (_("ECOFF debugging is disabled."));
4708 ignore_rest_of_line ();
4709 }
4710}
f37f01cf
RH
4711
4712/* Called at the end of assembly. Here we emit unwind info for frames
4713 unless the compiler has done it for us. */
4714
4715void
4716alpha_elf_md_end (void)
4717{
4718 struct alpha_elf_frame_data *p;
4719
4720 if (cur_frame_data)
4721 as_warn (_(".ent directive without matching .end"));
4722
4723 /* If someone has generated the unwind info themselves, great. */
4724 if (bfd_get_section_by_name (stdoutput, ".eh_frame") != NULL)
4725 return;
4726
4727 /* Generate .eh_frame data for the unwind directives specified. */
4728 for (p = all_frame_data; p ; p = p->next)
4729 if (p->prologue_sym)
4730 {
4731 /* Create a temporary symbol at the same location as our
4732 function symbol. This prevents problems with globals. */
4733 cfi_new_fde (symbol_temp_new (S_GET_SEGMENT (p->func_sym),
4734 S_GET_VALUE (p->func_sym),
4735 symbol_get_frag (p->func_sym)));
4736
4737 cfi_set_return_column (p->ra_regno);
4738 cfi_add_CFA_def_cfa_register (30);
4739 if (p->fp_regno != 30 || p->mask || p->fmask || p->frame_size)
4740 {
4741 unsigned int mask;
4742 offsetT offset;
4743
4744 cfi_add_advance_loc (p->prologue_sym);
4745
4746 if (p->fp_regno != 30)
4747 if (p->frame_size != 0)
4748 cfi_add_CFA_def_cfa (p->fp_regno, p->frame_size);
4749 else
4750 cfi_add_CFA_def_cfa_register (p->fp_regno);
4751 else if (p->frame_size != 0)
4752 cfi_add_CFA_def_cfa_offset (p->frame_size);
4753
4754 mask = p->mask;
4755 offset = p->mask_offset;
4756
4757 /* Recall that $26 is special-cased and stored first. */
4758 if ((mask >> 26) & 1)
4759 {
4760 cfi_add_CFA_offset (26, offset);
4761 offset += 8;
4762 mask &= ~(1 << 26);
4763 }
4764 while (mask)
4765 {
4766 unsigned int i;
4767 i = mask & -mask;
4768 mask ^= i;
4769 i = ffs (i) - 1;
4770
4771 cfi_add_CFA_offset (i, offset);
4772 offset += 8;
4773 }
4774
4775 mask = p->fmask;
4776 offset = p->fmask_offset;
4777 while (mask)
4778 {
4779 unsigned int i;
4780 i = mask & -mask;
4781 mask ^= i;
4782 i = ffs (i) - 1;
4783
4784 cfi_add_CFA_offset (i + 32, offset);
4785 offset += 8;
4786 }
4787 }
4788
4789 cfi_end_fde (p->func_end_sym);
4790 }
4791}
f4b97536
RH
4792
4793static void
4794s_alpha_usepv (int unused ATTRIBUTE_UNUSED)
4795{
4796 char *name, name_end;
4797 char *which, which_end;
4798 symbolS *sym;
4799 int other;
4800
4801 name = input_line_pointer;
4802 name_end = get_symbol_end ();
4803
4804 if (! is_name_beginner (*name))
4805 {
4806 as_bad (_(".usepv directive has no name"));
4807 *input_line_pointer = name_end;
4808 ignore_rest_of_line ();
4809 return;
4810 }
4811
4812 sym = symbol_find_or_make (name);
4813 *input_line_pointer++ = name_end;
4814
4815 if (name_end != ',')
4816 {
4817 as_bad (_(".usepv directive has no type"));
4818 ignore_rest_of_line ();
4819 return;
4820 }
4821
4822 SKIP_WHITESPACE ();
4823 which = input_line_pointer;
4824 which_end = get_symbol_end ();
4825
4826 if (strcmp (which, "no") == 0)
4827 other = STO_ALPHA_NOPV;
4828 else if (strcmp (which, "std") == 0)
4829 other = STO_ALPHA_STD_GPLOAD;
4830 else
4831 {
4832 as_bad (_("unknown argument for .usepv"));
4833 other = 0;
4834 }
4835
4836 *input_line_pointer = which_end;
4837 demand_empty_rest_of_line ();
4838
4839 S_SET_OTHER (sym, other | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD));
4840}
252b5132
RH
4841#endif /* OBJ_ELF */
4842
f4b97536
RH
4843/* Standard calling conventions leaves the CFA at $30 on entry. */
4844
4845void
4846alpha_cfi_frame_initial_instructions ()
4847{
4848 cfi_add_CFA_def_cfa_register (30);
4849}
4850
252b5132 4851#ifdef OBJ_EVAX
1dab94dd 4852
252b5132 4853/* Handle the section specific pseudo-op. */
1dab94dd 4854
252b5132
RH
4855static void
4856s_alpha_section (secid)
4857 int secid;
4858{
4859 int temp;
4860#define EVAX_SECTION_COUNT 5
66498417 4861 static char *section_name[EVAX_SECTION_COUNT + 1] =
252b5132
RH
4862 { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors" };
4863
4864 if ((secid <= 0) || (secid > EVAX_SECTION_COUNT))
4865 {
4866 as_fatal (_("Unknown section directive"));
4867 demand_empty_rest_of_line ();
4868 return;
4869 }
4870 temp = get_absolute_expression ();
4871 subseg_new (section_name[secid], 0);
4872 demand_empty_rest_of_line ();
4873 alpha_insn_label = NULL;
4874 alpha_auto_align_on = 1;
4875 alpha_current_align = 0;
4876}
4877
252b5132
RH
4878/* Parse .ent directives. */
4879
4880static void
4881s_alpha_ent (ignore)
11f45fb5 4882 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4883{
4884 symbolS *symbol;
4885 expressionS symexpr;
4886
4887 alpha_evax_proc.pdsckind = 0;
4888 alpha_evax_proc.framereg = -1;
4889 alpha_evax_proc.framesize = 0;
4890 alpha_evax_proc.rsa_offset = 0;
4891 alpha_evax_proc.ra_save = AXP_REG_RA;
4892 alpha_evax_proc.fp_save = -1;
4893 alpha_evax_proc.imask = 0;
4894 alpha_evax_proc.fmask = 0;
4895 alpha_evax_proc.prologue = 0;
4896 alpha_evax_proc.type = 0;
4897
4898 expression (&symexpr);
4899
4900 if (symexpr.X_op != O_symbol)
4901 {
4902 as_fatal (_(".ent directive has no symbol"));
4903 demand_empty_rest_of_line ();
4904 return;
4905 }
4906
4907 symbol = make_expr_symbol (&symexpr);
9de8d8f1 4908 symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION;
252b5132
RH
4909 alpha_evax_proc.symbol = symbol;
4910
4911 demand_empty_rest_of_line ();
252b5132
RH
4912}
4913
252b5132
RH
4914/* Parse .frame <framreg>,<framesize>,RA,<rsa_offset> directives. */
4915
4916static void
4917s_alpha_frame (ignore)
11f45fb5 4918 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4919{
4920 long val;
4921
4922 alpha_evax_proc.framereg = tc_get_register (1);
4923
4924 SKIP_WHITESPACE ();
4925 if (*input_line_pointer++ != ','
4926 || get_absolute_expression_and_terminator (&val) != ',')
4927 {
4928 as_warn (_("Bad .frame directive 1./2. param"));
4929 --input_line_pointer;
4930 demand_empty_rest_of_line ();
4931 return;
4932 }
4933
4934 alpha_evax_proc.framesize = val;
4935
4936 (void) tc_get_register (1);
4937 SKIP_WHITESPACE ();
4938 if (*input_line_pointer++ != ',')
4939 {
4940 as_warn (_("Bad .frame directive 3./4. param"));
4941 --input_line_pointer;
4942 demand_empty_rest_of_line ();
4943 return;
4944 }
4945 alpha_evax_proc.rsa_offset = get_absolute_expression ();
252b5132
RH
4946}
4947
4948static void
4949s_alpha_pdesc (ignore)
11f45fb5 4950 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4951{
4952 char *name;
4953 char name_end;
4954 long val;
4955 register char *p;
4956 expressionS exp;
4957 symbolS *entry_sym;
4958 fixS *fixp;
4959 segment_info_type *seginfo = seg_info (alpha_link_section);
4960
4961 if (now_seg != alpha_link_section)
4962 {
4963 as_bad (_(".pdesc directive not in link (.link) section"));
4964 demand_empty_rest_of_line ();
4965 return;
4966 }
4967
4968 if ((alpha_evax_proc.symbol == 0)
4969 || (!S_IS_DEFINED (alpha_evax_proc.symbol)))
4970 {
4971 as_fatal (_(".pdesc has no matching .ent"));
4972 demand_empty_rest_of_line ();
4973 return;
4974 }
4975
7dcc9865
ILT
4976 *symbol_get_obj (alpha_evax_proc.symbol) =
4977 (valueT) seginfo->literal_pool_size;
252b5132
RH
4978
4979 expression (&exp);
4980 if (exp.X_op != O_symbol)
4981 {
4982 as_warn (_(".pdesc directive has no entry symbol"));
4983 demand_empty_rest_of_line ();
4984 return;
4985 }
4986
4987 entry_sym = make_expr_symbol (&exp);
4988 /* Save bfd symbol of proc desc in function symbol. */
9de8d8f1
RH
4989 symbol_get_bfdsym (alpha_evax_proc.symbol)->udata.p
4990 = symbol_get_bfdsym (entry_sym);
252b5132
RH
4991
4992 SKIP_WHITESPACE ();
4993 if (*input_line_pointer++ != ',')
4994 {
4995 as_warn (_("No comma after .pdesc <entryname>"));
4996 demand_empty_rest_of_line ();
4997 return;
4998 }
4999
5000 SKIP_WHITESPACE ();
5001 name = input_line_pointer;
5002 name_end = get_symbol_end ();
5003
32ff5c2e 5004 if (strncmp (name, "stack", 5) == 0)
252b5132
RH
5005 {
5006 alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_STACK;
5007 }
32ff5c2e 5008 else if (strncmp (name, "reg", 3) == 0)
252b5132
RH
5009 {
5010 alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_REGISTER;
5011 }
32ff5c2e 5012 else if (strncmp (name, "null", 4) == 0)
252b5132
RH
5013 {
5014 alpha_evax_proc.pdsckind = PDSC_S_K_KIND_NULL;
5015 }
5016 else
5017 {
5018 as_fatal (_("unknown procedure kind"));
5019 demand_empty_rest_of_line ();
5020 return;
5021 }
5022
5023 *input_line_pointer = name_end;
5024 demand_empty_rest_of_line ();
5025
5026#ifdef md_flush_pending_output
5027 md_flush_pending_output ();
5028#endif
5029
5030 frag_align (3, 0, 0);
5031 p = frag_more (16);
5032 fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
5033 fixp->fx_done = 1;
5034 seginfo->literal_pool_size += 16;
5035
5036 *p = alpha_evax_proc.pdsckind
1aad8cf8 5037 | ((alpha_evax_proc.framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0);
66498417 5038 *(p + 1) = PDSC_S_M_NATIVE | PDSC_S_M_NO_JACKET;
252b5132
RH
5039
5040 switch (alpha_evax_proc.pdsckind)
5041 {
1aad8cf8 5042 case PDSC_S_K_KIND_NULL:
66498417
KH
5043 *(p + 2) = 0;
5044 *(p + 3) = 0;
1aad8cf8
KH
5045 break;
5046 case PDSC_S_K_KIND_FP_REGISTER:
66498417
KH
5047 *(p + 2) = alpha_evax_proc.fp_save;
5048 *(p + 3) = alpha_evax_proc.ra_save;
1aad8cf8
KH
5049 break;
5050 case PDSC_S_K_KIND_FP_STACK:
66498417 5051 md_number_to_chars (p + 2, (valueT) alpha_evax_proc.rsa_offset, 2);
1aad8cf8
KH
5052 break;
5053 default: /* impossible */
5054 break;
252b5132
RH
5055 }
5056
66498417
KH
5057 *(p + 4) = 0;
5058 *(p + 5) = alpha_evax_proc.type & 0x0f;
252b5132
RH
5059
5060 /* Signature offset. */
66498417 5061 md_number_to_chars (p + 6, (valueT) 0, 2);
252b5132 5062
66498417 5063 fix_new_exp (frag_now, p - frag_now->fr_literal+8, 8, &exp, 0, BFD_RELOC_64);
252b5132
RH
5064
5065 if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_NULL)
5066 return;
5067
5068 /* Add dummy fix to make add_to_link_pool work. */
5069 p = frag_more (8);
5070 fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
5071 fixp->fx_done = 1;
5072 seginfo->literal_pool_size += 8;
5073
5074 /* pdesc+16: Size. */
32ff5c2e 5075 md_number_to_chars (p, (valueT) alpha_evax_proc.framesize, 4);
252b5132 5076
66498417 5077 md_number_to_chars (p + 4, (valueT) 0, 2);
252b5132
RH
5078
5079 /* Entry length. */
66498417 5080 md_number_to_chars (p + 6, alpha_evax_proc.prologue, 2);
252b5132
RH
5081
5082 if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_FP_REGISTER)
5083 return;
5084
5085 /* Add dummy fix to make add_to_link_pool work. */
5086 p = frag_more (8);
5087 fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
5088 fixp->fx_done = 1;
5089 seginfo->literal_pool_size += 8;
5090
5091 /* pdesc+24: register masks. */
5092
5093 md_number_to_chars (p, alpha_evax_proc.imask, 4);
66498417 5094 md_number_to_chars (p + 4, alpha_evax_proc.fmask, 4);
252b5132
RH
5095}
5096
252b5132
RH
5097/* Support for crash debug on vms. */
5098
5099static void
5100s_alpha_name (ignore)
11f45fb5 5101 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5102{
5103 register char *p;
5104 expressionS exp;
5105 segment_info_type *seginfo = seg_info (alpha_link_section);
5106
5107 if (now_seg != alpha_link_section)
5108 {
5109 as_bad (_(".name directive not in link (.link) section"));
5110 demand_empty_rest_of_line ();
5111 return;
5112 }
5113
5114 expression (&exp);
5115 if (exp.X_op != O_symbol)
5116 {
5117 as_warn (_(".name directive has no symbol"));
5118 demand_empty_rest_of_line ();
5119 return;
5120 }
5121
5122 demand_empty_rest_of_line ();
5123
5124#ifdef md_flush_pending_output
5125 md_flush_pending_output ();
5126#endif
5127
5128 frag_align (3, 0, 0);
5129 p = frag_more (8);
5130 seginfo->literal_pool_size += 8;
5131
66498417 5132 fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0, BFD_RELOC_64);
252b5132
RH
5133}
5134
252b5132
RH
5135static void
5136s_alpha_linkage (ignore)
11f45fb5 5137 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5138{
5139 expressionS exp;
5140 char *p;
5141
5142#ifdef md_flush_pending_output
5143 md_flush_pending_output ();
5144#endif
5145
5146 expression (&exp);
5147 if (exp.X_op != O_symbol)
5148 {
5149 as_fatal (_("No symbol after .linkage"));
5150 }
5151 else
5152 {
5153 p = frag_more (LKP_S_K_SIZE);
5154 memset (p, 0, LKP_S_K_SIZE);
5155 fix_new_exp (frag_now, p - frag_now->fr_literal, LKP_S_K_SIZE, &exp, 0,\
5156 BFD_RELOC_ALPHA_LINKAGE);
5157 }
5158 demand_empty_rest_of_line ();
252b5132
RH
5159}
5160
252b5132
RH
5161static void
5162s_alpha_code_address (ignore)
11f45fb5 5163 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5164{
5165 expressionS exp;
5166 char *p;
5167
5168#ifdef md_flush_pending_output
5169 md_flush_pending_output ();
5170#endif
5171
5172 expression (&exp);
5173 if (exp.X_op != O_symbol)
5174 {
5175 as_fatal (_("No symbol after .code_address"));
5176 }
5177 else
5178 {
5179 p = frag_more (8);
5180 memset (p, 0, 8);
5181 fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0,\
5182 BFD_RELOC_ALPHA_CODEADDR);
5183 }
5184 demand_empty_rest_of_line ();
252b5132
RH
5185}
5186
252b5132
RH
5187static void
5188s_alpha_fp_save (ignore)
11f45fb5 5189 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5190{
5191
5192 alpha_evax_proc.fp_save = tc_get_register (1);
5193
5194 demand_empty_rest_of_line ();
252b5132
RH
5195}
5196
252b5132
RH
5197static void
5198s_alpha_mask (ignore)
11f45fb5 5199 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5200{
5201 long val;
5202
5203 if (get_absolute_expression_and_terminator (&val) != ',')
5204 {
5205 as_warn (_("Bad .mask directive"));
5206 --input_line_pointer;
5207 }
5208 else
5209 {
5210 alpha_evax_proc.imask = val;
32ff5c2e 5211 (void) get_absolute_expression ();
252b5132
RH
5212 }
5213 demand_empty_rest_of_line ();
252b5132
RH
5214}
5215
252b5132
RH
5216static void
5217s_alpha_fmask (ignore)
11f45fb5 5218 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5219{
5220 long val;
5221
5222 if (get_absolute_expression_and_terminator (&val) != ',')
5223 {
5224 as_warn (_("Bad .fmask directive"));
5225 --input_line_pointer;
5226 }
5227 else
5228 {
5229 alpha_evax_proc.fmask = val;
5230 (void) get_absolute_expression ();
5231 }
5232 demand_empty_rest_of_line ();
252b5132
RH
5233}
5234
5235static void
5236s_alpha_end (ignore)
11f45fb5 5237 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5238{
5239 char c;
5240
5241 c = get_symbol_end ();
5242 *input_line_pointer = c;
5243 demand_empty_rest_of_line ();
5244 alpha_evax_proc.symbol = 0;
252b5132
RH
5245}
5246
252b5132
RH
5247static void
5248s_alpha_file (ignore)
11f45fb5 5249 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5250{
5251 symbolS *s;
5252 int length;
5253 static char case_hack[32];
5254
252b5132 5255 sprintf (case_hack, "<CASE:%01d%01d>",
9de8d8f1 5256 alpha_flag_hash_long_names, alpha_flag_show_after_trunc);
252b5132
RH
5257
5258 s = symbol_find_or_make (case_hack);
9de8d8f1 5259 symbol_get_bfdsym (s)->flags |= BSF_FILE;
252b5132
RH
5260
5261 get_absolute_expression ();
5262 s = symbol_find_or_make (demand_copy_string (&length));
9de8d8f1 5263 symbol_get_bfdsym (s)->flags |= BSF_FILE;
252b5132 5264 demand_empty_rest_of_line ();
252b5132
RH
5265}
5266#endif /* OBJ_EVAX */
5267
5268/* Handle the .gprel32 pseudo op. */
5269
5270static void
5271s_alpha_gprel32 (ignore)
446a06c9 5272 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5273{
5274 expressionS e;
5275 char *p;
5276
5277 SKIP_WHITESPACE ();
5278 expression (&e);
5279
5280#ifdef OBJ_ELF
5281 switch (e.X_op)
5282 {
5283 case O_constant:
32ff5c2e 5284 e.X_add_symbol = section_symbol (absolute_section);
252b5132
RH
5285 e.X_op = O_symbol;
5286 /* FALLTHRU */
5287 case O_symbol:
5288 break;
5289 default:
bc805888 5290 abort ();
252b5132
RH
5291 }
5292#else
5293#ifdef OBJ_ECOFF
5294 switch (e.X_op)
5295 {
5296 case O_constant:
5297 e.X_add_symbol = section_symbol (absolute_section);
5298 /* fall through */
5299 case O_symbol:
5300 e.X_op = O_subtract;
5301 e.X_op_symbol = alpha_gp_symbol;
5302 break;
5303 default:
5304 abort ();
5305 }
5306#endif
5307#endif
5308
5309 if (alpha_auto_align_on && alpha_current_align < 2)
5310 alpha_align (2, (char *) NULL, alpha_insn_label, 0);
5311 if (alpha_current_align > 2)
5312 alpha_current_align = 2;
5313 alpha_insn_label = NULL;
5314
5315 p = frag_more (4);
5316 memset (p, 0, 4);
66498417 5317 fix_new_exp (frag_now, p - frag_now->fr_literal, 4,
252b5132
RH
5318 &e, 0, BFD_RELOC_GPREL32);
5319}
5320
5321/* Handle floating point allocation pseudo-ops. This is like the
5322 generic vresion, but it makes sure the current label, if any, is
5323 correctly aligned. */
5324
5325static void
5326s_alpha_float_cons (type)
5327 int type;
5328{
5329 int log_size;
5330
5331 switch (type)
5332 {
5333 default:
5334 case 'f':
5335 case 'F':
5336 log_size = 2;
5337 break;
5338
5339 case 'd':
5340 case 'D':
5341 case 'G':
5342 log_size = 3;
5343 break;
5344
5345 case 'x':
5346 case 'X':
5347 case 'p':
5348 case 'P':
5349 log_size = 4;
5350 break;
5351 }
5352
5353 if (alpha_auto_align_on && alpha_current_align < log_size)
5354 alpha_align (log_size, (char *) NULL, alpha_insn_label, 0);
5355 if (alpha_current_align > log_size)
5356 alpha_current_align = log_size;
5357 alpha_insn_label = NULL;
5358
5359 float_cons (type);
5360}
5361
5362/* Handle the .proc pseudo op. We don't really do much with it except
5363 parse it. */
5364
5365static void
5366s_alpha_proc (is_static)
446a06c9 5367 int is_static ATTRIBUTE_UNUSED;
252b5132
RH
5368{
5369 char *name;
5370 char c;
5371 char *p;
5372 symbolS *symbolP;
5373 int temp;
5374
5375 /* Takes ".proc name,nargs" */
5376 SKIP_WHITESPACE ();
5377 name = input_line_pointer;
5378 c = get_symbol_end ();
5379 p = input_line_pointer;
5380 symbolP = symbol_find_or_make (name);
5381 *p = c;
5382 SKIP_WHITESPACE ();
5383 if (*input_line_pointer != ',')
5384 {
5385 *p = 0;
5386 as_warn (_("Expected comma after name \"%s\""), name);
5387 *p = c;
5388 temp = 0;
5389 ignore_rest_of_line ();
5390 }
5391 else
5392 {
5393 input_line_pointer++;
5394 temp = get_absolute_expression ();
5395 }
7dcc9865 5396 /* *symbol_get_obj (symbolP) = (signed char) temp; */
252b5132
RH
5397 as_warn (_("unhandled: .proc %s,%d"), name, temp);
5398 demand_empty_rest_of_line ();
5399}
5400
5401/* Handle the .set pseudo op. This is used to turn on and off most of
5402 the assembler features. */
5403
5404static void
5405s_alpha_set (x)
446a06c9 5406 int x ATTRIBUTE_UNUSED;
252b5132
RH
5407{
5408 char *name, ch, *s;
5409 int yesno = 1;
5410
5411 SKIP_WHITESPACE ();
5412 name = input_line_pointer;
5413 ch = get_symbol_end ();
5414
5415 s = name;
5416 if (s[0] == 'n' && s[1] == 'o')
5417 {
5418 yesno = 0;
5419 s += 2;
5420 }
5421 if (!strcmp ("reorder", s))
5422 /* ignore */ ;
5423 else if (!strcmp ("at", s))
5424 alpha_noat_on = !yesno;
5425 else if (!strcmp ("macro", s))
5426 alpha_macros_on = yesno;
5427 else if (!strcmp ("move", s))
5428 /* ignore */ ;
5429 else if (!strcmp ("volatile", s))
5430 /* ignore */ ;
5431 else
5432 as_warn (_("Tried to .set unrecognized mode `%s'"), name);
5433
5434 *input_line_pointer = ch;
5435 demand_empty_rest_of_line ();
5436}
5437
5438/* Handle the .base pseudo op. This changes the assembler's notion of
5439 the $gp register. */
5440
5441static void
5442s_alpha_base (ignore)
446a06c9 5443 int ignore ATTRIBUTE_UNUSED;
252b5132 5444{
252b5132
RH
5445 SKIP_WHITESPACE ();
5446 if (*input_line_pointer == '$')
5447 { /* $rNN form */
5448 input_line_pointer++;
5449 if (*input_line_pointer == 'r')
5450 input_line_pointer++;
5451 }
5452
5453 alpha_gp_register = get_absolute_expression ();
5454 if (alpha_gp_register < 0 || alpha_gp_register > 31)
5455 {
5456 alpha_gp_register = AXP_REG_GP;
5457 as_warn (_("Bad base register, using $%d."), alpha_gp_register);
5458 }
5459
5460 demand_empty_rest_of_line ();
5461}
5462
5463/* Handle the .align pseudo-op. This aligns to a power of two. It
5464 also adjusts any current instruction label. We treat this the same
5465 way the MIPS port does: .align 0 turns off auto alignment. */
5466
5467static void
5468s_alpha_align (ignore)
446a06c9 5469 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5470{
5471 int align;
5472 char fill, *pfill;
5473 long max_alignment = 15;
5474
5475 align = get_absolute_expression ();
5476 if (align > max_alignment)
5477 {
5478 align = max_alignment;
5479 as_bad (_("Alignment too large: %d. assumed"), align);
5480 }
5481 else if (align < 0)
5482 {
5483 as_warn (_("Alignment negative: 0 assumed"));
5484 align = 0;
5485 }
5486
5487 if (*input_line_pointer == ',')
5488 {
5489 input_line_pointer++;
5490 fill = get_absolute_expression ();
5491 pfill = &fill;
5492 }
5493 else
5494 pfill = NULL;
5495
5496 if (align != 0)
5497 {
5498 alpha_auto_align_on = 1;
5499 alpha_align (align, pfill, alpha_insn_label, 1);
5500 }
5501 else
5502 {
5503 alpha_auto_align_on = 0;
5504 }
5505
5506 demand_empty_rest_of_line ();
5507}
5508
5509/* Hook the normal string processor to reset known alignment. */
5510
5511static void
5512s_alpha_stringer (terminate)
5513 int terminate;
5514{
5515 alpha_current_align = 0;
5516 alpha_insn_label = NULL;
5517 stringer (terminate);
5518}
5519
5520/* Hook the normal space processing to reset known alignment. */
5521
5522static void
5523s_alpha_space (ignore)
5524 int ignore;
5525{
5526 alpha_current_align = 0;
5527 alpha_insn_label = NULL;
5528 s_space (ignore);
5529}
5530
5531/* Hook into cons for auto-alignment. */
5532
5533void
5534alpha_cons_align (size)
5535 int size;
5536{
5537 int log_size;
5538
5539 log_size = 0;
5540 while ((size >>= 1) != 0)
5541 ++log_size;
5542
5543 if (alpha_auto_align_on && alpha_current_align < log_size)
5544 alpha_align (log_size, (char *) NULL, alpha_insn_label, 0);
5545 if (alpha_current_align > log_size)
5546 alpha_current_align = log_size;
5547 alpha_insn_label = NULL;
5548}
5549
5550/* Here come the .uword, .ulong, and .uquad explicitly unaligned
5551 pseudos. We just turn off auto-alignment and call down to cons. */
5552
5553static void
5554s_alpha_ucons (bytes)
5555 int bytes;
5556{
5557 int hold = alpha_auto_align_on;
5558 alpha_auto_align_on = 0;
5559 cons (bytes);
5560 alpha_auto_align_on = hold;
5561}
5562
5563/* Switch the working cpu type. */
5564
5565static void
5566s_alpha_arch (ignored)
446a06c9 5567 int ignored ATTRIBUTE_UNUSED;
252b5132
RH
5568{
5569 char *name, ch;
5570 const struct cpu_type *p;
5571
5572 SKIP_WHITESPACE ();
5573 name = input_line_pointer;
5574 ch = get_symbol_end ();
5575
5576 for (p = cpu_types; p->name; ++p)
32ff5c2e 5577 if (strcmp (name, p->name) == 0)
252b5132 5578 {
1aad8cf8 5579 alpha_target_name = p->name, alpha_target = p->flags;
252b5132
RH
5580 goto found;
5581 }
32ff5c2e 5582 as_warn ("Unknown CPU identifier `%s'", name);
252b5132
RH
5583
5584found:
5585 *input_line_pointer = ch;
5586 demand_empty_rest_of_line ();
5587}
252b5132 5588\f
252b5132
RH
5589#ifdef DEBUG1
5590/* print token expression with alpha specific extension. */
5591
5592static void
32ff5c2e 5593alpha_print_token (f, exp)
1aad8cf8
KH
5594 FILE *f;
5595 const expressionS *exp;
252b5132
RH
5596{
5597 switch (exp->X_op)
5598 {
1aad8cf8
KH
5599 case O_cpregister:
5600 putc (',', f);
5601 /* FALLTHRU */
5602 case O_pregister:
5603 putc ('(', f);
5604 {
5605 expressionS nexp = *exp;
5606 nexp.X_op = O_register;
5607 print_expr (f, &nexp);
5608 }
5609 putc (')', f);
5610 break;
5611 default:
5612 print_expr (f, exp);
5613 break;
252b5132 5614 }
252b5132
RH
5615}
5616#endif
5617\f
5618/* The target specific pseudo-ops which we support. */
5619
66498417 5620const pseudo_typeS md_pseudo_table[] = {
252b5132
RH
5621#ifdef OBJ_ECOFF
5622 {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */
5623 {"rdata", s_alpha_rdata, 0},
5624#endif
5625 {"text", s_alpha_text, 0},
5626 {"data", s_alpha_data, 0},
5627#ifdef OBJ_ECOFF
5628 {"sdata", s_alpha_sdata, 0},
5629#endif
5630#ifdef OBJ_ELF
5631 {"section", s_alpha_section, 0},
5632 {"section.s", s_alpha_section, 0},
5633 {"sect", s_alpha_section, 0},
5634 {"sect.s", s_alpha_section, 0},
5635#endif
5636#ifdef OBJ_EVAX
5637 { "pdesc", s_alpha_pdesc, 0},
5638 { "name", s_alpha_name, 0},
5639 { "linkage", s_alpha_linkage, 0},
5640 { "code_address", s_alpha_code_address, 0},
5641 { "ent", s_alpha_ent, 0},
5642 { "frame", s_alpha_frame, 0},
5643 { "fp_save", s_alpha_fp_save, 0},
5644 { "mask", s_alpha_mask, 0},
5645 { "fmask", s_alpha_fmask, 0},
5646 { "end", s_alpha_end, 0},
5647 { "file", s_alpha_file, 0},
5648 { "rdata", s_alpha_section, 1},
5649 { "comm", s_alpha_comm, 0},
5650 { "link", s_alpha_section, 3},
5651 { "ctors", s_alpha_section, 4},
5652 { "dtors", s_alpha_section, 5},
5653#endif
5654#ifdef OBJ_ELF
5655 /* Frame related pseudos. */
5656 {"ent", s_alpha_ent, 0},
5657 {"end", s_alpha_end, 0},
5658 {"mask", s_alpha_mask, 0},
5659 {"fmask", s_alpha_mask, 1},
5660 {"frame", s_alpha_frame, 0},
5661 {"prologue", s_alpha_prologue, 0},
4dc7ead9
RH
5662 {"file", s_alpha_file, 5},
5663 {"loc", s_alpha_loc, 9},
a8316fe2
RH
5664 {"stabs", s_alpha_stab, 's'},
5665 {"stabn", s_alpha_stab, 'n'},
f4b97536 5666 {"usepv", s_alpha_usepv, 0},
252b5132
RH
5667 /* COFF debugging related pseudos. */
5668 {"begin", s_alpha_coff_wrapper, 0},
5669 {"bend", s_alpha_coff_wrapper, 1},
5670 {"def", s_alpha_coff_wrapper, 2},
5671 {"dim", s_alpha_coff_wrapper, 3},
5672 {"endef", s_alpha_coff_wrapper, 4},
4dc7ead9
RH
5673 {"scl", s_alpha_coff_wrapper, 5},
5674 {"tag", s_alpha_coff_wrapper, 6},
5675 {"val", s_alpha_coff_wrapper, 7},
252b5132
RH
5676#else
5677 {"prologue", s_ignore, 0},
5678#endif
5679 {"gprel32", s_alpha_gprel32, 0},
5680 {"t_floating", s_alpha_float_cons, 'd'},
5681 {"s_floating", s_alpha_float_cons, 'f'},
5682 {"f_floating", s_alpha_float_cons, 'F'},
5683 {"g_floating", s_alpha_float_cons, 'G'},
5684 {"d_floating", s_alpha_float_cons, 'D'},
5685
5686 {"proc", s_alpha_proc, 0},
5687 {"aproc", s_alpha_proc, 1},
5688 {"set", s_alpha_set, 0},
5689 {"reguse", s_ignore, 0},
5690 {"livereg", s_ignore, 0},
5691 {"base", s_alpha_base, 0}, /*??*/
5692 {"option", s_ignore, 0},
5693 {"aent", s_ignore, 0},
5694 {"ugen", s_ignore, 0},
5695 {"eflag", s_ignore, 0},
5696
5697 {"align", s_alpha_align, 0},
5698 {"double", s_alpha_float_cons, 'd'},
5699 {"float", s_alpha_float_cons, 'f'},
5700 {"single", s_alpha_float_cons, 'f'},
5701 {"ascii", s_alpha_stringer, 0},
5702 {"asciz", s_alpha_stringer, 1},
5703 {"string", s_alpha_stringer, 1},
5704 {"space", s_alpha_space, 0},
5705 {"skip", s_alpha_space, 0},
5706 {"zero", s_alpha_space, 0},
5707
5708/* Unaligned data pseudos. */
5709 {"uword", s_alpha_ucons, 2},
5710 {"ulong", s_alpha_ucons, 4},
5711 {"uquad", s_alpha_ucons, 8},
5712
5713#ifdef OBJ_ELF
5714/* Dwarf wants these versions of unaligned. */
5715 {"2byte", s_alpha_ucons, 2},
5716 {"4byte", s_alpha_ucons, 4},
5717 {"8byte", s_alpha_ucons, 8},
5718#endif
5719
5720/* We don't do any optimizing, so we can safely ignore these. */
5721 {"noalias", s_ignore, 0},
5722 {"alias", s_ignore, 0},
5723
5724 {"arch", s_alpha_arch, 0},
5725
5726 {NULL, 0, 0},
5727};
252b5132
RH
5728\f
5729/* Build a BFD section with its flags set appropriately for the .lita,
5730 .lit8, or .lit4 sections. */
5731
5732static void
5733create_literal_section (name, secp, symp)
5734 const char *name;
5735 segT *secp;
5736 symbolS **symp;
5737{
5738 segT current_section = now_seg;
5739 int current_subsec = now_subseg;
5740 segT new_sec;
5741
5742 *secp = new_sec = subseg_new (name, 0);
5743 subseg_set (current_section, current_subsec);
5744 bfd_set_section_alignment (stdoutput, new_sec, 4);
5745 bfd_set_section_flags (stdoutput, new_sec,
5746 SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY
5747 | SEC_DATA);
5748
5749 S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec));
5750}
5751
5752#ifdef OBJ_ECOFF
5753
5754/* @@@ GP selection voodoo. All of this seems overly complicated and
5755 unnecessary; which is the primary reason it's for ECOFF only. */
11f45fb5 5756static inline void maybe_set_gp PARAMS ((asection *));
252b5132
RH
5757
5758static inline void
5759maybe_set_gp (sec)
5760 asection *sec;
5761{
5762 bfd_vma vma;
5763 if (!sec)
5764 return;
5765 vma = bfd_get_section_vma (foo, sec);
5766 if (vma && vma < alpha_gp_value)
5767 alpha_gp_value = vma;
5768}
5769
5770static void
5771select_gp_value ()
5772{
5773 assert (alpha_gp_value == 0);
5774
5775 /* Get minus-one in whatever width... */
66498417
KH
5776 alpha_gp_value = 0;
5777 alpha_gp_value--;
252b5132
RH
5778
5779 /* Select the smallest VMA of these existing sections. */
5780 maybe_set_gp (alpha_lita_section);
252b5132
RH
5781
5782/* @@ Will a simple 0x8000 work here? If not, why not? */
5783#define GP_ADJUSTMENT (0x8000 - 0x10)
5784
5785 alpha_gp_value += GP_ADJUSTMENT;
5786
5787 S_SET_VALUE (alpha_gp_symbol, alpha_gp_value);
5788
5789#ifdef DEBUG1
5790 printf (_("Chose GP value of %lx\n"), alpha_gp_value);
5791#endif
5792}
5793#endif /* OBJ_ECOFF */
5794
d61a78a7
RH
5795#ifdef OBJ_ELF
5796/* Map 's' to SHF_ALPHA_GPREL. */
5797
5798int
5799alpha_elf_section_letter (letter, ptr_msg)
5800 int letter;
5801 char **ptr_msg;
5802{
5803 if (letter == 's')
5804 return SHF_ALPHA_GPREL;
5805
13ae64f3 5806 *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string");
711ef82f 5807 return -1;
d61a78a7
RH
5808}
5809
5810/* Map SHF_ALPHA_GPREL to SEC_SMALL_DATA. */
5811
5812flagword
5813alpha_elf_section_flags (flags, attr, type)
5814 flagword flags;
5815 int attr, type ATTRIBUTE_UNUSED;
5816{
5817 if (attr & SHF_ALPHA_GPREL)
5818 flags |= SEC_SMALL_DATA;
5819 return flags;
5820}
5821#endif /* OBJ_ELF */
5822
252b5132
RH
5823/* Called internally to handle all alignment needs. This takes care
5824 of eliding calls to frag_align if'n the cached current alignment
5825 says we've already got it, as well as taking care of the auto-align
5826 feature wrt labels. */
5827
5828static void
5829alpha_align (n, pfill, label, force)
5830 int n;
5831 char *pfill;
5832 symbolS *label;
446a06c9 5833 int force ATTRIBUTE_UNUSED;
252b5132
RH
5834{
5835 if (alpha_current_align >= n)
5836 return;
5837
5838 if (pfill == NULL)
5839 {
0a9ef439
RH
5840 if (subseg_text_p (now_seg))
5841 frag_align_code (n, 0);
252b5132
RH
5842 else
5843 frag_align (n, 0, 0);
5844 }
5845 else
5846 frag_align (n, *pfill, 0);
5847
5848 alpha_current_align = n;
5849
98007ce7 5850 if (label != NULL && S_GET_SEGMENT (label) == now_seg)
252b5132 5851 {
49309057 5852 symbol_set_frag (label, frag_now);
252b5132
RH
5853 S_SET_VALUE (label, (valueT) frag_now_fix ());
5854 }
5855
98007ce7 5856 record_alignment (now_seg, n);
252b5132 5857
0a9ef439 5858 /* ??? If alpha_flag_relax && force && elf, record the requested alignment
252b5132
RH
5859 in a reloc for the linker to see. */
5860}
5861
0a9ef439
RH
5862/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
5863 of an rs_align_code fragment. */
5864
bfb32b52 5865void
0a9ef439
RH
5866alpha_handle_align (fragp)
5867 fragS *fragp;
5868{
84b229ef 5869 static char const unop[4] = { 0x00, 0x00, 0xfe, 0x2f };
0a9ef439 5870 static char const nopunop[8] = {
1aad8cf8 5871 0x1f, 0x04, 0xff, 0x47,
84b229ef 5872 0x00, 0x00, 0xfe, 0x2f
0a9ef439
RH
5873 };
5874
5875 int bytes, fix;
5876 char *p;
5877
5878 if (fragp->fr_type != rs_align_code)
5879 return;
5880
5881 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
5882 p = fragp->fr_literal + fragp->fr_fix;
5883 fix = 0;
5884
5885 if (bytes & 3)
5886 {
5887 fix = bytes & 3;
5888 memset (p, 0, fix);
5889 p += fix;
5890 bytes -= fix;
5891 }
5892
5893 if (bytes & 4)
5894 {
5895 memcpy (p, unop, 4);
5896 p += 4;
5897 bytes -= 4;
5898 fix += 4;
5899 }
5900
5901 memcpy (p, nopunop, 8);
5902
5903 fragp->fr_fix += fix;
5904 fragp->fr_var = 8;
5905}
5906
252b5132
RH
5907/* The Alpha has support for some VAX floating point types, as well as for
5908 IEEE floating point. We consider IEEE to be the primary floating point
5909 format, and sneak in the VAX floating point support here. */
5910#define md_atof vax_md_atof
5911#include "config/atof-vax.c"
This page took 0.715016 seconds and 4 git commands to generate.