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