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