daily update
[deliverable/binutils-gdb.git] / gas / config / tc-alpha.c
CommitLineData
252b5132 1/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU.
f7e42eb4
NC
2 Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
3 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
JJ
1558 if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)
1559 || (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
32ff5c2e 1560 && !S_IS_COMMON (fixp->fx_addsy))
49309057 1561 reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
252b5132
RH
1562#endif
1563 }
1564
1565 return reloc;
1566}
1567
1568/* Parse a register name off of the input_line and return a register
1569 number. Gets md_undefined_symbol above to do the register name
1570 matching for us.
1571
1572 Only called as a part of processing the ECOFF .frame directive. */
1573
1574int
1575tc_get_register (frame)
446a06c9 1576 int frame ATTRIBUTE_UNUSED;
252b5132
RH
1577{
1578 int framereg = AXP_REG_SP;
1579
1580 SKIP_WHITESPACE ();
1581 if (*input_line_pointer == '$')
1582 {
1583 char *s = input_line_pointer;
1584 char c = get_symbol_end ();
1585 symbolS *sym = md_undefined_symbol (s);
1586
32ff5c2e 1587 *strchr (s, '\0') = c;
252b5132
RH
1588 if (sym && (framereg = S_GET_VALUE (sym)) <= 31)
1589 goto found;
1590 }
1591 as_warn (_("frame reg expected, using $%d."), framereg);
1592
1593found:
1594 note_gpreg (framereg);
1595 return framereg;
1596}
1597
1598/* This is called before the symbol table is processed. In order to
1599 work with gcc when using mips-tfile, we must keep all local labels.
1600 However, in other cases, we want to discard them. If we were
1601 called with -g, but we didn't see any debugging information, it may
1602 mean that gcc is smuggling debugging information through to
1603 mips-tfile, in which case we must generate all local labels. */
1604
1605#ifdef OBJ_ECOFF
1606
1607void
1608alpha_frob_file_before_adjust ()
1609{
1610 if (alpha_debug != 0
1611 && ! ecoff_debugging_seen)
1612 flag_keep_locals = 1;
1613}
1614
1615#endif /* OBJ_ECOFF */
1616\f
19f78583
RH
1617static struct alpha_reloc_tag *
1618get_alpha_reloc_tag (sequence)
1619 long sequence;
1620{
1621 char buffer[ALPHA_RELOC_DIGITS];
1622 struct alpha_reloc_tag *info;
1623
1624 sprintf (buffer, "!%ld", sequence);
1625
1626 info = (struct alpha_reloc_tag *) hash_find (alpha_literal_hash, buffer);
1627 if (! info)
1628 {
1629 size_t len = strlen (buffer);
1630 const char *errmsg;
1631
1632 info = (struct alpha_reloc_tag *)
1633 xcalloc (sizeof (struct alpha_reloc_tag) + len, 1);
1634
1635 info->segment = now_seg;
1636 info->sequence = sequence;
1637 strcpy (info->string, buffer);
1638 errmsg = hash_insert (alpha_literal_hash, info->string, (PTR) info);
1639 if (errmsg)
1640 as_fatal (errmsg);
1641 }
1642
1643 return info;
1644}
43b4c25e 1645
66498417
KH
1646/* Before the relocations are written, reorder them, so that user
1647 supplied !lituse relocations follow the appropriate !literal
19f78583 1648 relocations, and similarly for !gpdisp relocations. */
43b4c25e
MM
1649
1650void
1651alpha_adjust_symtab ()
1652{
1653 if (alpha_literal_hash)
19f78583 1654 bfd_map_over_sections (stdoutput, alpha_adjust_symtab_relocs, NULL);
43b4c25e 1655}
43b4c25e
MM
1656
1657static void
1658alpha_adjust_symtab_relocs (abfd, sec, ptr)
4dc7ead9 1659 bfd *abfd ATTRIBUTE_UNUSED;
43b4c25e 1660 asection *sec;
4dc7ead9 1661 PTR ptr ATTRIBUTE_UNUSED;
43b4c25e
MM
1662{
1663 segment_info_type *seginfo = seg_info (sec);
1664 fixS **prevP;
1665 fixS *fixp;
1666 fixS *next;
19f78583
RH
1667 fixS *slave;
1668 unsigned long n_slaves = 0;
43b4c25e 1669
66498417
KH
1670 /* If seginfo is NULL, we did not create this section; don't do
1671 anything with it. By using a pointer to a pointer, we can update
1672 the links in place. */
43b4c25e
MM
1673 if (seginfo == NULL)
1674 return;
1675
1676 /* If there are no relocations, skip the section. */
1677 if (! seginfo->fix_root)
1678 return;
1679
19f78583
RH
1680 /* First rebuild the fixup chain without the expicit lituse and
1681 gpdisp_lo16 relocs. */
1682 prevP = &seginfo->fix_root;
43b4c25e
MM
1683 for (fixp = seginfo->fix_root; fixp; fixp = next)
1684 {
1685 next = fixp->fx_next;
32ff5c2e 1686 fixp->fx_next = (fixS *) 0;
43b4c25e
MM
1687
1688 switch (fixp->fx_r_type)
1689 {
19f78583
RH
1690 case BFD_RELOC_ALPHA_LITUSE:
1691 n_slaves++;
1692 if (fixp->tc_fix_data.info->n_master == 0)
1693 as_bad_where (fixp->fx_file, fixp->fx_line,
1694 _("No !literal!%ld was found"),
1695 fixp->tc_fix_data.info->sequence);
43b4c25e
MM
1696 break;
1697
19f78583
RH
1698 case BFD_RELOC_ALPHA_GPDISP_LO16:
1699 n_slaves++;
1700 if (fixp->tc_fix_data.info->n_master == 0)
43b4c25e 1701 as_bad_where (fixp->fx_file, fixp->fx_line,
19f78583 1702 _("No ldah !gpdisp!%ld was found"),
43b4c25e 1703 fixp->tc_fix_data.info->sequence);
19f78583
RH
1704 break;
1705
1706 default:
1707 *prevP = fixp;
1708 prevP = &fixp->fx_next;
43b4c25e
MM
1709 break;
1710 }
1711 }
1712
19f78583
RH
1713 /* If there were any dependent relocations, go and add them back to
1714 the chain. They are linked through the next_reloc field in
1715 reverse order, so as we go through the next_reloc chain, we
1716 effectively reverse the chain once again.
1717
1718 Except if there is more than one !literal for a given sequence
1719 number. In that case, the programmer and/or compiler is not sure
1720 how control flows from literal to lituse, and we can't be sure to
1721 get the relaxation correct.
1722
1723 ??? Well, actually we could, if there are enough lituses such that
1724 we can make each literal have at least one of each lituse type
1725 present. Not implemented.
1726
1727 Also suppress the optimization if the !literals/!lituses are spread
1728 in different segments. This can happen with "intersting" uses of
1729 inline assembly; examples are present in the Linux kernel semaphores. */
1730
1731 for (fixp = seginfo->fix_root; fixp; fixp = next)
43b4c25e 1732 {
19f78583
RH
1733 next = fixp->fx_next;
1734 switch (fixp->fx_r_type)
43b4c25e 1735 {
19f78583
RH
1736 case BFD_RELOC_ALPHA_ELF_LITERAL:
1737 if (fixp->tc_fix_data.info->n_master == 1
1738 && ! fixp->tc_fix_data.info->multi_section_p)
43b4c25e 1739 {
19f78583
RH
1740 for (slave = fixp->tc_fix_data.info->slaves;
1741 slave != (fixS *) 0;
1742 slave = slave->tc_fix_data.next_reloc)
43b4c25e 1743 {
19f78583
RH
1744 slave->fx_next = fixp->fx_next;
1745 fixp->fx_next = slave;
43b4c25e 1746 }
19f78583
RH
1747 }
1748 break;
43b4c25e 1749
19f78583
RH
1750 case BFD_RELOC_ALPHA_GPDISP_HI16:
1751 if (fixp->tc_fix_data.info->n_slaves == 0)
1752 as_bad_where (fixp->fx_file, fixp->fx_line,
1753 _("No lda !gpdisp!%ld was found"),
1754 fixp->tc_fix_data.info->sequence);
1755 else
1756 {
1757 slave = fixp->tc_fix_data.info->slaves;
1758 slave->fx_next = next;
1759 fixp->fx_next = slave;
43b4c25e 1760 }
19f78583
RH
1761 break;
1762
1763 default:
1764 break;
43b4c25e
MM
1765 }
1766 }
43b4c25e 1767}
43b4c25e
MM
1768\f
1769#ifdef DEBUG_ALPHA
1770static void
1771debug_exp (tok, ntok)
1772 expressionS tok[];
1773 int ntok;
1774{
1775 int i;
1776
1777 fprintf (stderr, "debug_exp: %d tokens", ntok);
1778 for (i = 0; i < ntok; i++)
1779 {
1780 expressionS *t = &tok[i];
1781 const char *name;
1782 switch (t->X_op)
1783 {
1784 default: name = "unknown"; break;
1785 case O_illegal: name = "O_illegal"; break;
1786 case O_absent: name = "O_absent"; break;
1787 case O_constant: name = "O_constant"; break;
1788 case O_symbol: name = "O_symbol"; break;
1789 case O_symbol_rva: name = "O_symbol_rva"; break;
1790 case O_register: name = "O_register"; break;
1791 case O_big: name = "O_big"; break;
1792 case O_uminus: name = "O_uminus"; break;
1793 case O_bit_not: name = "O_bit_not"; break;
1794 case O_logical_not: name = "O_logical_not"; break;
1795 case O_multiply: name = "O_multiply"; break;
1796 case O_divide: name = "O_divide"; break;
1797 case O_modulus: name = "O_modulus"; break;
1798 case O_left_shift: name = "O_left_shift"; break;
1799 case O_right_shift: name = "O_right_shift"; break;
1800 case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break;
1801 case O_bit_or_not: name = "O_bit_or_not"; break;
1802 case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break;
1803 case O_bit_and: name = "O_bit_and"; break;
1804 case O_add: name = "O_add"; break;
1805 case O_subtract: name = "O_subtract"; break;
1806 case O_eq: name = "O_eq"; break;
1807 case O_ne: name = "O_ne"; break;
1808 case O_lt: name = "O_lt"; break;
1809 case O_le: name = "O_le"; break;
1810 case O_ge: name = "O_ge"; break;
1811 case O_gt: name = "O_gt"; break;
1812 case O_logical_and: name = "O_logical_and"; break;
1813 case O_logical_or: name = "O_logical_or"; break;
1814 case O_index: name = "O_index"; break;
1815 case O_pregister: name = "O_pregister"; break;
1816 case O_cpregister: name = "O_cpregister"; break;
1817 case O_literal: name = "O_literal"; break;
543833df 1818 case O_lituse_addr: name = "O_lituse_addr"; break;
43b4c25e
MM
1819 case O_lituse_base: name = "O_lituse_base"; break;
1820 case O_lituse_bytoff: name = "O_lituse_bytoff"; break;
1821 case O_lituse_jsr: name = "O_lituse_jsr"; break;
1822 case O_gpdisp: name = "O_gpdisp"; break;
1823 case O_gprelhigh: name = "O_gprelhigh"; break;
1824 case O_gprellow: name = "O_gprellow"; break;
19f78583 1825 case O_gprel: name = "O_gprel"; break;
543833df 1826 case O_samegp: name = "O_samegp"; break;
43b4c25e
MM
1827 case O_md13: name = "O_md13"; break;
1828 case O_md14: name = "O_md14"; break;
1829 case O_md15: name = "O_md15"; break;
1830 case O_md16: name = "O_md16"; break;
1831 }
1832
1833 fprintf (stderr, ", %s(%s, %s, %d)", name,
1834 (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
1835 (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
32ff5c2e 1836 (int) t->X_add_number);
43b4c25e
MM
1837 }
1838 fprintf (stderr, "\n");
1839 fflush (stderr);
1840}
1841#endif
1842
252b5132
RH
1843/* Parse the arguments to an opcode. */
1844
1845static int
1846tokenize_arguments (str, tok, ntok)
1847 char *str;
1848 expressionS tok[];
1849 int ntok;
1850{
1851 expressionS *end_tok = tok + ntok;
1852 char *old_input_line_pointer;
1853 int saw_comma = 0, saw_arg = 0;
43b4c25e
MM
1854#ifdef DEBUG_ALPHA
1855 expressionS *orig_tok = tok;
1856#endif
43b4c25e
MM
1857 char *p;
1858 const struct alpha_reloc_op_tag *r;
1859 int c, i;
1860 size_t len;
1861 int reloc_found_p = 0;
252b5132
RH
1862
1863 memset (tok, 0, sizeof (*tok) * ntok);
1864
1865 /* Save and restore input_line_pointer around this function */
1866 old_input_line_pointer = input_line_pointer;
1867 input_line_pointer = str;
1868
19f78583
RH
1869#ifdef RELOC_OP_P
1870 /* ??? Wrest control of ! away from the regular expression parser. */
1871 is_end_of_line[(unsigned char) '!'] = 1;
1872#endif
1873
252b5132
RH
1874 while (tok < end_tok && *input_line_pointer)
1875 {
1876 SKIP_WHITESPACE ();
1877 switch (*input_line_pointer)
1878 {
1879 case '\0':
1880 goto fini;
1881
43b4c25e
MM
1882#ifdef RELOC_OP_P
1883 case '!':
1884 /* A relocation operand can be placed after the normal operand on an
1885 assembly language statement, and has the following form:
1886 !relocation_type!sequence_number. */
1887 if (reloc_found_p)
1888 { /* only support one relocation op per insn */
1889 as_bad (_("More than one relocation op per insn"));
1890 goto err_report;
1891 }
1892
1893 if (!saw_arg)
1894 goto err;
1895
19f78583
RH
1896 ++input_line_pointer;
1897 SKIP_WHITESPACE ();
1898 p = input_line_pointer;
1899 c = get_symbol_end ();
43b4c25e
MM
1900
1901 /* Parse !relocation_type */
19f78583 1902 len = input_line_pointer - p;
43b4c25e
MM
1903 if (len == 0)
1904 {
1905 as_bad (_("No relocation operand"));
1906 goto err_report;
1907 }
1908
43b4c25e 1909 r = &alpha_reloc_op[0];
66498417 1910 for (i = alpha_num_reloc_op - 1; i >= 0; i--, r++)
19f78583
RH
1911 if (len == r->length && memcmp (p, r->name, len) == 0)
1912 break;
43b4c25e
MM
1913 if (i < 0)
1914 {
19f78583 1915 as_bad (_("Unknown relocation operand: !%s"), p);
43b4c25e
MM
1916 goto err_report;
1917 }
1918
19f78583
RH
1919 *input_line_pointer = c;
1920 SKIP_WHITESPACE ();
1921 if (*input_line_pointer != '!')
1922 {
ec8fcf4a 1923 if (r->require_seq)
19f78583 1924 {
ec8fcf4a 1925 as_bad (_("no sequence number after !%s"), p);
19f78583
RH
1926 goto err_report;
1927 }
1928
19f78583 1929 tok->X_add_number = 0;
19f78583 1930 }
ec8fcf4a
RH
1931 else
1932 {
1933 if (! r->allow_seq)
1934 {
1935 as_bad (_("!%s does not use a sequence number"), p);
1936 goto err_report;
1937 }
19f78583 1938
ec8fcf4a 1939 input_line_pointer++;
43b4c25e 1940
ec8fcf4a
RH
1941 /* Parse !sequence_number */
1942 expression (tok);
1943 if (tok->X_op != O_constant || tok->X_add_number <= 0)
1944 {
1945 as_bad (_("Bad sequence number: !%s!%s"),
1946 r->name, input_line_pointer);
1947 goto err_report;
1948 }
43b4c25e
MM
1949 }
1950
1951 tok->X_op = r->op;
1952 reloc_found_p = 1;
1953 ++tok;
1954 break;
19f78583 1955#endif /* RELOC_OP_P */
43b4c25e 1956
252b5132
RH
1957 case ',':
1958 ++input_line_pointer;
1959 if (saw_comma || !saw_arg)
1960 goto err;
1961 saw_comma = 1;
1962 break;
1963
1964 case '(':
1965 {
1966 char *hold = input_line_pointer++;
1967
1dab94dd 1968 /* First try for parenthesized register ... */
252b5132
RH
1969 expression (tok);
1970 if (*input_line_pointer == ')' && tok->X_op == O_register)
1971 {
1972 tok->X_op = (saw_comma ? O_cpregister : O_pregister);
1973 saw_comma = 0;
1974 saw_arg = 1;
1975 ++input_line_pointer;
1976 ++tok;
1977 break;
1978 }
1979
1980 /* ... then fall through to plain expression */
1981 input_line_pointer = hold;
1982 }
1983
1984 default:
1985 if (saw_arg && !saw_comma)
1986 goto err;
43b4c25e 1987
252b5132
RH
1988 expression (tok);
1989 if (tok->X_op == O_illegal || tok->X_op == O_absent)
1990 goto err;
1991
1992 saw_comma = 0;
1993 saw_arg = 1;
1994 ++tok;
1995 break;
1996 }
1997 }
1998
1999fini:
2000 if (saw_comma)
2001 goto err;
2002 input_line_pointer = old_input_line_pointer;
43b4c25e
MM
2003
2004#ifdef DEBUG_ALPHA
2005 debug_exp (orig_tok, ntok - (end_tok - tok));
2006#endif
19f78583
RH
2007#ifdef RELOC_OP_P
2008 is_end_of_line[(unsigned char) '!'] = 0;
2009#endif
43b4c25e 2010
252b5132
RH
2011 return ntok - (end_tok - tok);
2012
2013err:
19f78583
RH
2014#ifdef RELOC_OP_P
2015 is_end_of_line[(unsigned char) '!'] = 0;
2016#endif
252b5132 2017 input_line_pointer = old_input_line_pointer;
43b4c25e
MM
2018 return TOKENIZE_ERROR;
2019
43b4c25e 2020err_report:
19f78583
RH
2021#ifdef RELOC_OP_P
2022 is_end_of_line[(unsigned char) '!'] = 0;
2023#endif
43b4c25e
MM
2024 input_line_pointer = old_input_line_pointer;
2025 return TOKENIZE_ERROR_REPORT;
252b5132
RH
2026}
2027
2028/* Search forward through all variants of an opcode looking for a
2029 syntax match. */
2030
2031static const struct alpha_opcode *
32ff5c2e 2032find_opcode_match (first_opcode, tok, pntok, pcpumatch)
252b5132
RH
2033 const struct alpha_opcode *first_opcode;
2034 const expressionS *tok;
2035 int *pntok;
2036 int *pcpumatch;
2037{
2038 const struct alpha_opcode *opcode = first_opcode;
2039 int ntok = *pntok;
2040 int got_cpu_match = 0;
2041
2042 do
2043 {
2044 const unsigned char *opidx;
2045 int tokidx = 0;
2046
2047 /* Don't match opcodes that don't exist on this architecture */
2048 if (!(opcode->flags & alpha_target))
2049 goto match_failed;
2050
2051 got_cpu_match = 1;
2052
2053 for (opidx = opcode->operands; *opidx; ++opidx)
2054 {
2055 const struct alpha_operand *operand = &alpha_operands[*opidx];
2056
2057 /* only take input from real operands */
2058 if (operand->flags & AXP_OPERAND_FAKE)
2059 continue;
2060
2061 /* when we expect input, make sure we have it */
2062 if (tokidx >= ntok)
2063 {
2064 if ((operand->flags & AXP_OPERAND_OPTIONAL_MASK) == 0)
2065 goto match_failed;
2066 continue;
2067 }
2068
2069 /* match operand type with expression type */
2070 switch (operand->flags & AXP_OPERAND_TYPECHECK_MASK)
2071 {
2072 case AXP_OPERAND_IR:
2073 if (tok[tokidx].X_op != O_register
32ff5c2e 2074 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2075 goto match_failed;
2076 break;
2077 case AXP_OPERAND_FPR:
2078 if (tok[tokidx].X_op != O_register
32ff5c2e 2079 || !is_fpr_num (tok[tokidx].X_add_number))
252b5132
RH
2080 goto match_failed;
2081 break;
66498417 2082 case AXP_OPERAND_IR | AXP_OPERAND_PARENS:
252b5132 2083 if (tok[tokidx].X_op != O_pregister
32ff5c2e 2084 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2085 goto match_failed;
2086 break;
66498417 2087 case AXP_OPERAND_IR | AXP_OPERAND_PARENS | AXP_OPERAND_COMMA:
252b5132 2088 if (tok[tokidx].X_op != O_cpregister
32ff5c2e 2089 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2090 goto match_failed;
2091 break;
2092
2093 case AXP_OPERAND_RELATIVE:
2094 case AXP_OPERAND_SIGNED:
2095 case AXP_OPERAND_UNSIGNED:
2096 switch (tok[tokidx].X_op)
2097 {
2098 case O_illegal:
2099 case O_absent:
2100 case O_register:
2101 case O_pregister:
2102 case O_cpregister:
2103 goto match_failed;
2104
2105 default:
2106 break;
2107 }
2108 break;
2109
2110 default:
2111 /* everything else should have been fake */
bc805888 2112 abort ();
252b5132
RH
2113 }
2114 ++tokidx;
2115 }
2116
2117 /* possible match -- did we use all of our input? */
2118 if (tokidx == ntok)
2119 {
2120 *pntok = ntok;
2121 return opcode;
2122 }
2123
2124 match_failed:;
2125 }
66498417 2126 while (++opcode - alpha_opcodes < alpha_num_opcodes
32ff5c2e 2127 && !strcmp (opcode->name, first_opcode->name));
252b5132
RH
2128
2129 if (*pcpumatch)
1aad8cf8 2130 *pcpumatch = got_cpu_match;
252b5132
RH
2131
2132 return NULL;
2133}
2134
2135/* Search forward through all variants of a macro looking for a syntax
2136 match. */
2137
2138static const struct alpha_macro *
32ff5c2e 2139find_macro_match (first_macro, tok, pntok)
252b5132
RH
2140 const struct alpha_macro *first_macro;
2141 const expressionS *tok;
2142 int *pntok;
2143{
2144 const struct alpha_macro *macro = first_macro;
2145 int ntok = *pntok;
2146
2147 do
2148 {
2149 const enum alpha_macro_arg *arg = macro->argsets;
2150 int tokidx = 0;
2151
2152 while (*arg)
2153 {
2154 switch (*arg)
2155 {
2156 case MACRO_EOA:
2157 if (tokidx == ntok)
2158 return macro;
2159 else
2160 tokidx = 0;
2161 break;
2162
43b4c25e 2163 /* index register */
252b5132
RH
2164 case MACRO_IR:
2165 if (tokidx >= ntok || tok[tokidx].X_op != O_register
32ff5c2e 2166 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2167 goto match_failed;
2168 ++tokidx;
2169 break;
43b4c25e
MM
2170
2171 /* parenthesized index register */
252b5132
RH
2172 case MACRO_PIR:
2173 if (tokidx >= ntok || tok[tokidx].X_op != O_pregister
32ff5c2e 2174 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2175 goto match_failed;
2176 ++tokidx;
2177 break;
43b4c25e
MM
2178
2179 /* optional parenthesized index register */
2180 case MACRO_OPIR:
2181 if (tokidx < ntok && tok[tokidx].X_op == O_pregister
32ff5c2e 2182 && is_ir_num (tok[tokidx].X_add_number))
43b4c25e
MM
2183 ++tokidx;
2184 break;
2185
2186 /* leading comma with a parenthesized index register */
252b5132
RH
2187 case MACRO_CPIR:
2188 if (tokidx >= ntok || tok[tokidx].X_op != O_cpregister
32ff5c2e 2189 || !is_ir_num (tok[tokidx].X_add_number))
252b5132
RH
2190 goto match_failed;
2191 ++tokidx;
2192 break;
43b4c25e
MM
2193
2194 /* floating point register */
252b5132
RH
2195 case MACRO_FPR:
2196 if (tokidx >= ntok || tok[tokidx].X_op != O_register
32ff5c2e 2197 || !is_fpr_num (tok[tokidx].X_add_number))
252b5132
RH
2198 goto match_failed;
2199 ++tokidx;
2200 break;
2201
43b4c25e 2202 /* normal expression */
252b5132
RH
2203 case MACRO_EXP:
2204 if (tokidx >= ntok)
2205 goto match_failed;
2206 switch (tok[tokidx].X_op)
2207 {
2208 case O_illegal:
2209 case O_absent:
2210 case O_register:
2211 case O_pregister:
2212 case O_cpregister:
43b4c25e
MM
2213 case O_literal:
2214 case O_lituse_base:
2215 case O_lituse_bytoff:
2216 case O_lituse_jsr:
2217 case O_gpdisp:
2218 case O_gprelhigh:
2219 case O_gprellow:
19f78583 2220 case O_gprel:
543833df 2221 case O_samegp:
252b5132
RH
2222 goto match_failed;
2223
2224 default:
2225 break;
2226 }
2227 ++tokidx;
2228 break;
2229
2230 match_failed:
2231 while (*arg != MACRO_EOA)
2232 ++arg;
2233 tokidx = 0;
2234 break;
2235 }
2236 ++arg;
2237 }
2238 }
66498417 2239 while (++macro - alpha_macros < alpha_num_macros
32ff5c2e 2240 && !strcmp (macro->name, first_macro->name));
252b5132
RH
2241
2242 return NULL;
2243}
2244
2245/* Insert an operand value into an instruction. */
2246
2247static unsigned
32ff5c2e 2248insert_operand (insn, operand, val, file, line)
252b5132
RH
2249 unsigned insn;
2250 const struct alpha_operand *operand;
2251 offsetT val;
2252 char *file;
2253 unsigned line;
2254{
2255 if (operand->bits != 32 && !(operand->flags & AXP_OPERAND_NOOVERFLOW))
2256 {
2257 offsetT min, max;
2258
2259 if (operand->flags & AXP_OPERAND_SIGNED)
2260 {
2261 max = (1 << (operand->bits - 1)) - 1;
2262 min = -(1 << (operand->bits - 1));
2263 }
2264 else
2265 {
2266 max = (1 << operand->bits) - 1;
2267 min = 0;
2268 }
2269
2270 if (val < min || val > max)
2271 {
2272 const char *err =
2273 _("operand out of range (%s not between %d and %d)");
2274 char buf[sizeof (val) * 3 + 2];
2275
32ff5c2e 2276 sprint_value (buf, val);
252b5132 2277 if (file)
32ff5c2e 2278 as_warn_where (file, line, err, buf, min, max);
252b5132 2279 else
32ff5c2e 2280 as_warn (err, buf, min, max);
252b5132
RH
2281 }
2282 }
2283
2284 if (operand->insert)
2285 {
2286 const char *errmsg = NULL;
2287
2288 insn = (*operand->insert) (insn, val, &errmsg);
2289 if (errmsg)
2290 as_warn (errmsg);
2291 }
2292 else
2293 insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
2294
2295 return insn;
2296}
2297
2298/*
2299 * Turn an opcode description and a set of arguments into
2300 * an instruction and a fixup.
2301 */
2302
2303static void
19f78583 2304assemble_insn (opcode, tok, ntok, insn, reloc)
252b5132
RH
2305 const struct alpha_opcode *opcode;
2306 const expressionS *tok;
2307 int ntok;
2308 struct alpha_insn *insn;
19f78583 2309 bfd_reloc_code_real_type reloc;
252b5132 2310{
19f78583
RH
2311 const struct alpha_operand *reloc_operand = NULL;
2312 const expressionS *reloc_exp = NULL;
252b5132
RH
2313 const unsigned char *argidx;
2314 unsigned image;
2315 int tokidx = 0;
2316
2317 memset (insn, 0, sizeof (*insn));
2318 image = opcode->opcode;
2319
2320 for (argidx = opcode->operands; *argidx; ++argidx)
2321 {
2322 const struct alpha_operand *operand = &alpha_operands[*argidx];
32ff5c2e 2323 const expressionS *t = (const expressionS *) 0;
252b5132
RH
2324
2325 if (operand->flags & AXP_OPERAND_FAKE)
2326 {
2327 /* fake operands take no value and generate no fixup */
32ff5c2e 2328 image = insert_operand (image, operand, 0, NULL, 0);
252b5132
RH
2329 continue;
2330 }
2331
2332 if (tokidx >= ntok)
2333 {
2334 switch (operand->flags & AXP_OPERAND_OPTIONAL_MASK)
2335 {
2336 case AXP_OPERAND_DEFAULT_FIRST:
2337 t = &tok[0];
2338 break;
2339 case AXP_OPERAND_DEFAULT_SECOND:
2340 t = &tok[1];
2341 break;
2342 case AXP_OPERAND_DEFAULT_ZERO:
2343 {
446a06c9 2344 static expressionS zero_exp;
252b5132 2345 t = &zero_exp;
446a06c9
MM
2346 zero_exp.X_op = O_constant;
2347 zero_exp.X_unsigned = 1;
252b5132
RH
2348 }
2349 break;
2350 default:
bc805888 2351 abort ();
252b5132
RH
2352 }
2353 }
2354 else
2355 t = &tok[tokidx++];
2356
2357 switch (t->X_op)
2358 {
2359 case O_register:
2360 case O_pregister:
2361 case O_cpregister:
32ff5c2e
KH
2362 image = insert_operand (image, operand, regno (t->X_add_number),
2363 NULL, 0);
252b5132
RH
2364 break;
2365
2366 case O_constant:
32ff5c2e 2367 image = insert_operand (image, operand, t->X_add_number, NULL, 0);
19f78583
RH
2368 assert (reloc_operand == NULL);
2369 reloc_operand = operand;
2370 reloc_exp = t;
252b5132
RH
2371 break;
2372
2373 default:
19f78583
RH
2374 /* This is only 0 for fields that should contain registers,
2375 which means this pattern shouldn't have matched. */
2376 if (operand->default_reloc == 0)
2377 abort ();
252b5132 2378
19f78583
RH
2379 /* There is one special case for which an insn receives two
2380 relocations, and thus the user-supplied reloc does not
2381 override the operand reloc. */
2382 if (operand->default_reloc == BFD_RELOC_ALPHA_HINT)
2383 {
2384 struct alpha_fixup *fixup;
252b5132 2385
19f78583
RH
2386 if (insn->nfixups >= MAX_INSN_FIXUPS)
2387 as_fatal (_("too many fixups"));
252b5132 2388
19f78583
RH
2389 fixup = &insn->fixups[insn->nfixups++];
2390 fixup->exp = *t;
2391 fixup->reloc = BFD_RELOC_ALPHA_HINT;
2392 }
2393 else
2394 {
2395 if (reloc == BFD_RELOC_UNUSED)
2396 reloc = operand->default_reloc;
2397
2398 assert (reloc_operand == NULL);
2399 reloc_operand = operand;
2400 reloc_exp = t;
2401 }
252b5132
RH
2402 break;
2403 }
2404 }
2405
19f78583
RH
2406 if (reloc != BFD_RELOC_UNUSED)
2407 {
2408 struct alpha_fixup *fixup;
2409
2410 if (insn->nfixups >= MAX_INSN_FIXUPS)
2411 as_fatal (_("too many fixups"));
2412
2413 /* ??? My but this is hacky. But the OSF/1 assembler uses the same
2414 relocation tag for both ldah and lda with gpdisp. Choose the
2415 correct internal relocation based on the opcode. */
2416 if (reloc == BFD_RELOC_ALPHA_GPDISP)
2417 {
2418 if (strcmp (opcode->name, "ldah") == 0)
2419 reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
2420 else if (strcmp (opcode->name, "lda") == 0)
2421 reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
2422 else
2423 as_bad (_("invalid relocation for instruction"));
2424 }
2425
2426 /* If this is a real relocation (as opposed to a lituse hint), then
2427 the relocation width should match the operand width. */
2428 else if (reloc < BFD_RELOC_UNUSED)
2429 {
2430 reloc_howto_type *reloc_howto
2431 = bfd_reloc_type_lookup (stdoutput, reloc);
2432 if (reloc_howto->bitsize != reloc_operand->bits)
2433 {
2434 as_bad (_("invalid relocation for field"));
2435 return;
2436 }
2437 }
2438
2439 fixup = &insn->fixups[insn->nfixups++];
2440 if (reloc_exp)
2441 fixup->exp = *reloc_exp;
2442 else
2443 fixup->exp.X_op = O_absent;
2444 fixup->reloc = reloc;
2445 }
2446
252b5132
RH
2447 insn->insn = image;
2448}
2449
2450/*
2451 * Actually output an instruction with its fixup.
2452 */
2453
2454static void
2455emit_insn (insn)
66498417 2456 struct alpha_insn *insn;
252b5132
RH
2457{
2458 char *f;
2459 int i;
2460
66498417 2461 /* Take care of alignment duties. */
252b5132
RH
2462 if (alpha_auto_align_on && alpha_current_align < 2)
2463 alpha_align (2, (char *) NULL, alpha_insn_label, 0);
2464 if (alpha_current_align > 2)
2465 alpha_current_align = 2;
2466 alpha_insn_label = NULL;
2467
2468 /* Write out the instruction. */
2469 f = frag_more (4);
2470 md_number_to_chars (f, insn->insn, 4);
2471
4dc7ead9
RH
2472#ifdef OBJ_ELF
2473 dwarf2_emit_insn (4);
2474#endif
2475
252b5132
RH
2476 /* Apply the fixups in order */
2477 for (i = 0; i < insn->nfixups; ++i)
2478 {
32ff5c2e 2479 const struct alpha_operand *operand = (const struct alpha_operand *) 0;
252b5132 2480 struct alpha_fixup *fixup = &insn->fixups[i];
19f78583 2481 struct alpha_reloc_tag *info;
252b5132
RH
2482 int size, pcrel;
2483 fixS *fixP;
2484
2485 /* Some fixups are only used internally and so have no howto */
32ff5c2e 2486 if ((int) fixup->reloc < 0)
252b5132 2487 {
32ff5c2e 2488 operand = &alpha_operands[-(int) fixup->reloc];
252b5132
RH
2489 size = 4;
2490 pcrel = ((operand->flags & AXP_OPERAND_RELATIVE) != 0);
2491 }
19f78583
RH
2492 else if (fixup->reloc > BFD_RELOC_UNUSED
2493 || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_HI16
2494 || fixup->reloc == BFD_RELOC_ALPHA_GPDISP_LO16)
2495 {
2496 size = 2;
2497 pcrel = 0;
2498 }
1aad8cf8 2499 else
19f78583
RH
2500 {
2501 reloc_howto_type *reloc_howto
2502 = bfd_reloc_type_lookup (stdoutput, fixup->reloc);
2503 assert (reloc_howto);
252b5132 2504
19f78583
RH
2505 size = bfd_get_reloc_size (reloc_howto);
2506 assert (size >= 1 && size <= 4);
43b4c25e 2507
19f78583
RH
2508 pcrel = reloc_howto->pc_relative;
2509 }
252b5132
RH
2510
2511 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal, size,
2512 &fixup->exp, pcrel, fixup->reloc);
2513
43b4c25e
MM
2514 /* Turn off complaints that the addend is too large for some fixups,
2515 and copy in the sequence number for the explicit relocations. */
252b5132
RH
2516 switch (fixup->reloc)
2517 {
19f78583 2518 case BFD_RELOC_ALPHA_HINT:
252b5132 2519 case BFD_RELOC_GPREL32:
19f78583
RH
2520 case BFD_RELOC_GPREL16:
2521 case BFD_RELOC_ALPHA_GPREL_HI16:
2522 case BFD_RELOC_ALPHA_GPREL_LO16:
252b5132
RH
2523 fixP->fx_no_overflow = 1;
2524 break;
2525
19f78583 2526 case BFD_RELOC_ALPHA_GPDISP_HI16:
43b4c25e 2527 fixP->fx_no_overflow = 1;
19f78583
RH
2528 fixP->fx_addsy = section_symbol (now_seg);
2529 fixP->fx_offset = 0;
43b4c25e 2530
19f78583
RH
2531 info = get_alpha_reloc_tag (insn->sequence);
2532 if (++info->n_master > 1)
2533 as_bad (_("too many ldah insns for !gpdisp!%ld"), insn->sequence);
2534 if (info->segment != now_seg)
2535 as_bad (_("both insns for !gpdisp!%ld must be in the same section"),
2536 insn->sequence);
2537 fixP->tc_fix_data.info = info;
2538 break;
43b4c25e 2539
19f78583
RH
2540 case BFD_RELOC_ALPHA_GPDISP_LO16:
2541 fixP->fx_no_overflow = 1;
43b4c25e 2542
19f78583
RH
2543 info = get_alpha_reloc_tag (insn->sequence);
2544 if (++info->n_slaves > 1)
2545 as_bad (_("too many lda insns for !gpdisp!%ld"), insn->sequence);
43b4c25e 2546 if (info->segment != now_seg)
19f78583
RH
2547 as_bad (_("both insns for !gpdisp!%ld must be in the same section"),
2548 insn->sequence);
43b4c25e 2549 fixP->tc_fix_data.info = info;
19f78583 2550 info->slaves = fixP;
43b4c25e
MM
2551 break;
2552
19f78583
RH
2553 case BFD_RELOC_ALPHA_LITERAL:
2554 case BFD_RELOC_ALPHA_ELF_LITERAL:
2555 fixP->fx_no_overflow = 1;
43b4c25e 2556
19f78583
RH
2557 info = get_alpha_reloc_tag (insn->sequence);
2558 info->n_master++;
43b4c25e
MM
2559 if (info->segment != now_seg)
2560 info->multi_section_p = 1;
19f78583
RH
2561 fixP->tc_fix_data.info = info;
2562 break;
43b4c25e 2563
19f78583
RH
2564 case DUMMY_RELOC_LITUSE_ADDR:
2565 fixP->fx_offset = LITUSE_ADDR;
2566 goto do_lituse;
2567 case DUMMY_RELOC_LITUSE_BASE:
2568 fixP->fx_offset = LITUSE_BASE;
2569 goto do_lituse;
2570 case DUMMY_RELOC_LITUSE_BYTOFF:
2571 fixP->fx_offset = LITUSE_BYTOFF;
2572 goto do_lituse;
2573 case DUMMY_RELOC_LITUSE_JSR:
2574 fixP->fx_offset = LITUSE_JSR;
2575 do_lituse:
2576 fixP->fx_addsy = section_symbol (now_seg);
2577 fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE;
2578
2579 info = get_alpha_reloc_tag (insn->sequence);
2580 info->n_slaves++;
2581 fixP->tc_fix_data.info = info;
2582 fixP->tc_fix_data.next_reloc = info->slaves;
2583 info->slaves = fixP;
2584 if (info->segment != now_seg)
2585 info->multi_section_p = 1;
43b4c25e 2586 break;
43b4c25e 2587
252b5132 2588 default:
32ff5c2e 2589 if ((int) fixup->reloc < 0)
252b5132
RH
2590 {
2591 if (operand->flags & AXP_OPERAND_NOOVERFLOW)
2592 fixP->fx_no_overflow = 1;
2593 }
2594 break;
2595 }
2596 }
2597}
2598
2599/* Given an opcode name and a pre-tokenized set of arguments, assemble
2600 the insn, but do not emit it.
2601
2602 Note that this implies no macros allowed, since we can't store more
2603 than one insn in an insn structure. */
2604
2605static void
32ff5c2e 2606assemble_tokens_to_insn (opname, tok, ntok, insn)
252b5132
RH
2607 const char *opname;
2608 const expressionS *tok;
2609 int ntok;
2610 struct alpha_insn *insn;
2611{
2612 const struct alpha_opcode *opcode;
2613
2614 /* search opcodes */
2615 opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
2616 if (opcode)
2617 {
2618 int cpumatch;
2619 opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
2620 if (opcode)
2621 {
19f78583 2622 assemble_insn (opcode, tok, ntok, insn, BFD_RELOC_UNUSED);
252b5132
RH
2623 return;
2624 }
2625 else if (cpumatch)
2626 as_bad (_("inappropriate arguments for opcode `%s'"), opname);
2627 else
2628 as_bad (_("opcode `%s' not supported for target %s"), opname,
1aad8cf8 2629 alpha_target_name);
252b5132
RH
2630 }
2631 else
2632 as_bad (_("unknown opcode `%s'"), opname);
2633}
2634
2635/* Given an opcode name and a pre-tokenized set of arguments, take the
2636 opcode all the way through emission. */
2637
2638static void
2639assemble_tokens (opname, tok, ntok, local_macros_on)
2640 const char *opname;
2641 const expressionS *tok;
2642 int ntok;
2643 int local_macros_on;
2644{
2645 int found_something = 0;
2646 const struct alpha_opcode *opcode;
2647 const struct alpha_macro *macro;
2648 int cpumatch = 1;
19f78583 2649 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
252b5132 2650
19f78583
RH
2651 /* If a user-specified relocation is present, this is not a macro. */
2652 if (ntok && USER_RELOC_P (tok[ntok - 1].X_op))
2653 {
2654 reloc = ALPHA_RELOC_TABLE (tok[ntok - 1].X_op)->reloc;
2655 ntok--;
2656 }
2657 else if (local_macros_on)
252b5132
RH
2658 {
2659 macro = ((const struct alpha_macro *)
2660 hash_find (alpha_macro_hash, opname));
2661 if (macro)
2662 {
2663 found_something = 1;
2664 macro = find_macro_match (macro, tok, &ntok);
2665 if (macro)
2666 {
2667 (*macro->emit) (tok, ntok, macro->arg);
2668 return;
2669 }
2670 }
2671 }
2672
2673 /* search opcodes */
2674 opcode = (const struct alpha_opcode *) hash_find (alpha_opcode_hash, opname);
2675 if (opcode)
2676 {
2677 found_something = 1;
2678 opcode = find_opcode_match (opcode, tok, &ntok, &cpumatch);
2679 if (opcode)
2680 {
2681 struct alpha_insn insn;
19f78583
RH
2682 assemble_insn (opcode, tok, ntok, &insn, reloc);
2683
2684 /* Copy the sequence number for the reloc from the reloc token. */
2685 if (reloc != BFD_RELOC_UNUSED)
2686 insn.sequence = tok[ntok].X_add_number;
2687
252b5132
RH
2688 emit_insn (&insn);
2689 return;
2690 }
2691 }
2692
2693 if (found_something)
19f78583
RH
2694 {
2695 if (cpumatch)
2696 as_bad (_("inappropriate arguments for opcode `%s'"), opname);
2697 else
2698 as_bad (_("opcode `%s' not supported for target %s"), opname,
2699 alpha_target_name);
2700 }
252b5132
RH
2701 else
2702 as_bad (_("unknown opcode `%s'"), opname);
2703}
252b5132
RH
2704\f
2705/* Some instruction sets indexed by lg(size) */
2706static const char * const sextX_op[] = { "sextb", "sextw", "sextl", NULL };
2707static const char * const insXl_op[] = { "insbl", "inswl", "insll", "insql" };
2708static const char * const insXh_op[] = { NULL, "inswh", "inslh", "insqh" };
2709static const char * const extXl_op[] = { "extbl", "extwl", "extll", "extql" };
2710static const char * const extXh_op[] = { NULL, "extwh", "extlh", "extqh" };
2711static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" };
2712static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" };
2713static const char * const stX_op[] = { "stb", "stw", "stl", "stq" };
2714static const char * const ldX_op[] = { "ldb", "ldw", "ldll", "ldq" };
2715static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL };
2716
2717/* Implement the ldgp macro. */
2718
2719static void
2720emit_ldgp (tok, ntok, unused)
2721 const expressionS *tok;
446a06c9
MM
2722 int ntok ATTRIBUTE_UNUSED;
2723 const PTR unused ATTRIBUTE_UNUSED;
252b5132
RH
2724{
2725#ifdef OBJ_AOUT
2726FIXME
2727#endif
2728#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
2729 /* from "ldgp r1,n(r2)", generate "ldah r1,X(R2); lda r1,Y(r1)"
2730 with appropriate constants and relocations. */
2731 struct alpha_insn insn;
2732 expressionS newtok[3];
2733 expressionS addend;
2734
252b5132
RH
2735#ifdef OBJ_ECOFF
2736 if (regno (tok[2].X_add_number) == AXP_REG_PV)
2737 ecoff_set_gp_prolog_size (0);
2738#endif
2739
2740 newtok[0] = tok[0];
2741 set_tok_const (newtok[1], 0);
2742 newtok[2] = tok[2];
2743
2744 assemble_tokens_to_insn ("ldah", newtok, 3, &insn);
2745
2746 addend = tok[1];
2747
2748#ifdef OBJ_ECOFF
2749 if (addend.X_op != O_constant)
2750 as_bad (_("can not resolve expression"));
2751 addend.X_op = O_symbol;
2752 addend.X_add_symbol = alpha_gp_symbol;
2753#endif
2754
2755 insn.nfixups = 1;
2756 insn.fixups[0].exp = addend;
2757 insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_HI16;
19f78583 2758 insn.sequence = next_sequence_num;
252b5132
RH
2759
2760 emit_insn (&insn);
2761
2762 set_tok_preg (newtok[2], tok[0].X_add_number);
2763
2764 assemble_tokens_to_insn ("lda", newtok, 3, &insn);
2765
2766#ifdef OBJ_ECOFF
2767 addend.X_add_number += 4;
2768#endif
2769
2770 insn.nfixups = 1;
2771 insn.fixups[0].exp = addend;
2772 insn.fixups[0].reloc = BFD_RELOC_ALPHA_GPDISP_LO16;
19f78583 2773 insn.sequence = next_sequence_num--;
252b5132
RH
2774
2775 emit_insn (&insn);
2776#endif /* OBJ_ECOFF || OBJ_ELF */
2777}
2778
2779#ifdef OBJ_EVAX
2780
2781/* Add symbol+addend to link pool.
2782 Return offset from basesym to entry in link pool.
2783
2784 Add new fixup only if offset isn't 16bit. */
2785
2786valueT
2787add_to_link_pool (basesym, sym, addend)
2788 symbolS *basesym;
2789 symbolS *sym;
2790 offsetT addend;
2791{
2792 segT current_section = now_seg;
2793 int current_subsec = now_subseg;
2794 valueT offset;
2795 bfd_reloc_code_real_type reloc_type;
2796 char *p;
2797 segment_info_type *seginfo = seg_info (alpha_link_section);
2798 fixS *fixp;
2799
7dcc9865 2800 offset = - *symbol_get_obj (basesym);
252b5132
RH
2801
2802 /* @@ This assumes all entries in a given section will be of the same
2803 size... Probably correct, but unwise to rely on. */
2804 /* This must always be called with the same subsegment. */
2805
2806 if (seginfo->frchainP)
2807 for (fixp = seginfo->frchainP->fix_root;
2808 fixp != (fixS *) NULL;
2809 fixp = fixp->fx_next, offset += 8)
2810 {
2811 if (fixp->fx_addsy == sym && fixp->fx_offset == addend)
2812 {
2813 if (range_signed_16 (offset))
2814 {
1aad8cf8 2815 return offset;
252b5132
RH
2816 }
2817 }
2818 }
2819
2820 /* Not found in 16bit signed range. */
2821
2822 subseg_set (alpha_link_section, 0);
2823 p = frag_more (8);
2824 memset (p, 0, 8);
2825
2826 fix_new (frag_now, p - frag_now->fr_literal, 8, sym, addend, 0,
2827 BFD_RELOC_64);
2828
2829 subseg_set (current_section, current_subsec);
2830 seginfo->literal_pool_size += 8;
2831 return offset;
2832}
2833
2834#endif /* OBJ_EVAX */
2835
2836/* Load a (partial) expression into a target register.
2837
2838 If poffset is not null, after the call it will either contain
2839 O_constant 0, or a 16-bit offset appropriate for any MEM format
2840 instruction. In addition, pbasereg will be modified to point to
2841 the base register to use in that MEM format instruction.
2842
2843 In any case, *pbasereg should contain a base register to add to the
2844 expression. This will normally be either AXP_REG_ZERO or
2845 alpha_gp_register. Symbol addresses will always be loaded via $gp,
2846 so "foo($0)" is interpreted as adding the address of foo to $0;
2847 i.e. "ldq $targ, LIT($gp); addq $targ, $0, $targ". Odd, perhaps,
2848 but this is what OSF/1 does.
2849
43b4c25e
MM
2850 If explicit relocations of the form !literal!<number> are allowed,
2851 and used, then explict_reloc with be an expression pointer.
2852
19f78583
RH
2853 Finally, the return value is nonzero if the calling macro may emit
2854 a LITUSE reloc if otherwise appropriate; the return value is the
2855 sequence number to use. */
252b5132 2856
19f78583
RH
2857static long
2858load_expression (targreg, exp, pbasereg, poffset)
252b5132
RH
2859 int targreg;
2860 const expressionS *exp;
2861 int *pbasereg;
2862 expressionS *poffset;
2863{
19f78583 2864 long emit_lituse = 0;
252b5132
RH
2865 offsetT addend = exp->X_add_number;
2866 int basereg = *pbasereg;
2867 struct alpha_insn insn;
2868 expressionS newtok[3];
2869
2870 switch (exp->X_op)
2871 {
2872 case O_symbol:
2873 {
2874#ifdef OBJ_ECOFF
2875 offsetT lit;
2876
2877 /* attempt to reduce .lit load by splitting the offset from
2878 its symbol when possible, but don't create a situation in
2879 which we'd fail. */
2880 if (!range_signed_32 (addend) &&
2881 (alpha_noat_on || targreg == AXP_REG_AT))
2882 {
2883 lit = add_to_literal_pool (exp->X_add_symbol, addend,
2884 alpha_lita_section, 8);
2885 addend = 0;
2886 }
2887 else
2888 {
2889 lit = add_to_literal_pool (exp->X_add_symbol, 0,
2890 alpha_lita_section, 8);
2891 }
2892
2893 if (lit >= 0x8000)
2894 as_fatal (_("overflow in literal (.lita) table"));
2895
2896 /* emit "ldq r, lit(gp)" */
2897
2898 if (basereg != alpha_gp_register && targreg == basereg)
2899 {
2900 if (alpha_noat_on)
2901 as_bad (_("macro requires $at register while noat in effect"));
2902 if (targreg == AXP_REG_AT)
2903 as_bad (_("macro requires $at while $at in use"));
2904
2905 set_tok_reg (newtok[0], AXP_REG_AT);
2906 }
2907 else
2908 set_tok_reg (newtok[0], targreg);
2909 set_tok_sym (newtok[1], alpha_lita_symbol, lit);
2910 set_tok_preg (newtok[2], alpha_gp_register);
2911
2912 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
2913
2914 assert (insn.nfixups == 1);
2915 insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
19f78583 2916 insn.sequence = emit_lituse = next_sequence_num--;
252b5132
RH
2917#endif /* OBJ_ECOFF */
2918#ifdef OBJ_ELF
2919 /* emit "ldq r, gotoff(gp)" */
2920
2921 if (basereg != alpha_gp_register && targreg == basereg)
2922 {
2923 if (alpha_noat_on)
2924 as_bad (_("macro requires $at register while noat in effect"));
2925 if (targreg == AXP_REG_AT)
2926 as_bad (_("macro requires $at while $at in use"));
2927
2928 set_tok_reg (newtok[0], AXP_REG_AT);
2929 }
2930 else
2931 set_tok_reg (newtok[0], targreg);
2932
2933 /* XXX: Disable this .got minimizing optimization so that we can get
2934 better instruction offset knowledge in the compiler. This happens
2935 very infrequently anyway. */
66498417
KH
2936 if (1
2937 || (!range_signed_32 (addend)
2938 && (alpha_noat_on || targreg == AXP_REG_AT)))
252b5132
RH
2939 {
2940 newtok[1] = *exp;
2941 addend = 0;
2942 }
2943 else
2944 {
2945 set_tok_sym (newtok[1], exp->X_add_symbol, 0);
2946 }
2947
2948 set_tok_preg (newtok[2], alpha_gp_register);
2949
2950 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
2951
2952 assert (insn.nfixups == 1);
19f78583
RH
2953 insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
2954 insn.sequence = emit_lituse = next_sequence_num--;
252b5132
RH
2955#endif /* OBJ_ELF */
2956#ifdef OBJ_EVAX
2957 offsetT link;
2958
2959 /* Find symbol or symbol pointer in link section. */
2960
2961 if (exp->X_add_symbol == alpha_evax_proc.symbol)
2962 {
2963 if (range_signed_16 (addend))
2964 {
2965 set_tok_reg (newtok[0], targreg);
2966 set_tok_const (newtok[1], addend);
2967 set_tok_preg (newtok[2], basereg);
2968 assemble_tokens_to_insn ("lda", newtok, 3, &insn);
2969 addend = 0;
2970 }
2971 else
2972 {
2973 set_tok_reg (newtok[0], targreg);
2974 set_tok_const (newtok[1], 0);
2975 set_tok_preg (newtok[2], basereg);
2976 assemble_tokens_to_insn ("lda", newtok, 3, &insn);
2977 }
2978 }
2979 else
2980 {
2981 if (!range_signed_32 (addend))
2982 {
2983 link = add_to_link_pool (alpha_evax_proc.symbol,
2984 exp->X_add_symbol, addend);
2985 addend = 0;
2986 }
2987 else
2988 {
2989 link = add_to_link_pool (alpha_evax_proc.symbol,
2990 exp->X_add_symbol, 0);
2991 }
2992 set_tok_reg (newtok[0], targreg);
2993 set_tok_const (newtok[1], link);
2994 set_tok_preg (newtok[2], basereg);
2995 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
2996 }
2997#endif /* OBJ_EVAX */
2998
32ff5c2e 2999 emit_insn (&insn);
252b5132
RH
3000
3001#ifndef OBJ_EVAX
252b5132
RH
3002 if (basereg != alpha_gp_register && basereg != AXP_REG_ZERO)
3003 {
3004 /* emit "addq r, base, r" */
3005
3006 set_tok_reg (newtok[1], basereg);
3007 set_tok_reg (newtok[2], targreg);
3008 assemble_tokens ("addq", newtok, 3, 0);
3009 }
3010#endif
3011
3012 basereg = targreg;
3013 }
3014 break;
3015
3016 case O_constant:
3017 break;
3018
3019 case O_subtract:
3020 /* Assume that this difference expression will be resolved to an
1dab94dd 3021 absolute value and that that value will fit in 16 bits. */
252b5132
RH
3022
3023 set_tok_reg (newtok[0], targreg);
3024 newtok[1] = *exp;
3025 set_tok_preg (newtok[2], basereg);
3026 assemble_tokens ("lda", newtok, 3, 0);
3027
3028 if (poffset)
3029 set_tok_const (*poffset, 0);
3030 return 0;
3031
3032 case O_big:
3033 if (exp->X_add_number > 0)
3034 as_bad (_("bignum invalid; zero assumed"));
3035 else
3036 as_bad (_("floating point number invalid; zero assumed"));
3037 addend = 0;
3038 break;
3039
3040 default:
3041 as_bad (_("can't handle expression"));
3042 addend = 0;
3043 break;
3044 }
3045
3046 if (!range_signed_32 (addend))
3047 {
3048 offsetT lit;
19f78583 3049 long seq_num = next_sequence_num--;
252b5132 3050
19f78583 3051 /* For 64-bit addends, just put it in the literal pool. */
252b5132
RH
3052
3053#ifdef OBJ_EVAX
3054 /* emit "ldq targreg, lit(basereg)" */
3055 lit = add_to_link_pool (alpha_evax_proc.symbol,
3056 section_symbol (absolute_section), addend);
3057 set_tok_reg (newtok[0], targreg);
3058 set_tok_const (newtok[1], lit);
3059 set_tok_preg (newtok[2], alpha_gp_register);
3060 assemble_tokens ("ldq", newtok, 3, 0);
3061#else
3062
3063 if (alpha_lit8_section == NULL)
3064 {
3065 create_literal_section (".lit8",
3066 &alpha_lit8_section,
3067 &alpha_lit8_symbol);
3068
3069#ifdef OBJ_ECOFF
3070 alpha_lit8_literal = add_to_literal_pool (alpha_lit8_symbol, 0x8000,
3071 alpha_lita_section, 8);
3072 if (alpha_lit8_literal >= 0x8000)
3073 as_fatal (_("overflow in literal (.lita) table"));
3074#endif
3075 }
3076
3077 lit = add_to_literal_pool (NULL, addend, alpha_lit8_section, 8) - 0x8000;
3078 if (lit >= 0x8000)
3079 as_fatal (_("overflow in literal (.lit8) table"));
3080
3081 /* emit "lda litreg, .lit8+0x8000" */
3082
3083 if (targreg == basereg)
3084 {
3085 if (alpha_noat_on)
3086 as_bad (_("macro requires $at register while noat in effect"));
3087 if (targreg == AXP_REG_AT)
3088 as_bad (_("macro requires $at while $at in use"));
3089
3090 set_tok_reg (newtok[0], AXP_REG_AT);
3091 }
3092 else
3093 set_tok_reg (newtok[0], targreg);
3094#ifdef OBJ_ECOFF
3095 set_tok_sym (newtok[1], alpha_lita_symbol, alpha_lit8_literal);
3096#endif
3097#ifdef OBJ_ELF
3098 set_tok_sym (newtok[1], alpha_lit8_symbol, 0x8000);
3099#endif
3100 set_tok_preg (newtok[2], alpha_gp_register);
3101
3102 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
3103
3104 assert (insn.nfixups == 1);
3105#ifdef OBJ_ECOFF
3106 insn.fixups[0].reloc = BFD_RELOC_ALPHA_LITERAL;
3107#endif
3108#ifdef OBJ_ELF
3109 insn.fixups[0].reloc = BFD_RELOC_ALPHA_ELF_LITERAL;
3110#endif
19f78583 3111 insn.sequence = seq_num;
252b5132
RH
3112
3113 emit_insn (&insn);
3114
3115 /* emit "ldq litreg, lit(litreg)" */
3116
3117 set_tok_const (newtok[1], lit);
3118 set_tok_preg (newtok[2], newtok[0].X_add_number);
3119
3120 assemble_tokens_to_insn ("ldq", newtok, 3, &insn);
3121
3122 assert (insn.nfixups < MAX_INSN_FIXUPS);
19f78583
RH
3123 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3124 insn.fixups[insn.nfixups].exp.X_op = O_absent;
252b5132 3125 insn.nfixups++;
19f78583 3126 insn.sequence = seq_num;
252b5132
RH
3127 emit_lituse = 0;
3128
3129 emit_insn (&insn);
3130
3131 /* emit "addq litreg, base, target" */
3132
3133 if (basereg != AXP_REG_ZERO)
3134 {
3135 set_tok_reg (newtok[1], basereg);
3136 set_tok_reg (newtok[2], targreg);
3137 assemble_tokens ("addq", newtok, 3, 0);
3138 }
3139#endif /* !OBJ_EVAX */
3140
3141 if (poffset)
3142 set_tok_const (*poffset, 0);
3143 *pbasereg = targreg;
3144 }
3145 else
3146 {
3147 offsetT low, high, extra, tmp;
3148
3149 /* for 32-bit operands, break up the addend */
3150
3151 low = sign_extend_16 (addend);
3152 tmp = addend - low;
3153 high = sign_extend_16 (tmp >> 16);
3154
3155 if (tmp - (high << 16))
3156 {
3157 extra = 0x4000;
3158 tmp -= 0x40000000;
3159 high = sign_extend_16 (tmp >> 16);
3160 }
3161 else
3162 extra = 0;
3163
3164 set_tok_reg (newtok[0], targreg);
3165 set_tok_preg (newtok[2], basereg);
3166
3167 if (extra)
3168 {
3169 /* emit "ldah r, extra(r) */
3170 set_tok_const (newtok[1], extra);
3171 assemble_tokens ("ldah", newtok, 3, 0);
3172 set_tok_preg (newtok[2], basereg = targreg);
3173 }
3174
3175 if (high)
3176 {
3177 /* emit "ldah r, high(r) */
3178 set_tok_const (newtok[1], high);
3179 assemble_tokens ("ldah", newtok, 3, 0);
3180 basereg = targreg;
3181 set_tok_preg (newtok[2], basereg);
3182 }
3183
3184 if ((low && !poffset) || (!poffset && basereg != targreg))
3185 {
3186 /* emit "lda r, low(base)" */
3187 set_tok_const (newtok[1], low);
3188 assemble_tokens ("lda", newtok, 3, 0);
3189 basereg = targreg;
3190 low = 0;
3191 }
3192
3193 if (poffset)
3194 set_tok_const (*poffset, low);
3195 *pbasereg = basereg;
3196 }
3197
3198 return emit_lituse;
3199}
3200
3201/* The lda macro differs from the lda instruction in that it handles
3202 most simple expressions, particualrly symbol address loads and
3203 large constants. */
3204
3205static void
19f78583 3206emit_lda (tok, ntok, unused)
252b5132
RH
3207 const expressionS *tok;
3208 int ntok;
19f78583 3209 const PTR unused ATTRIBUTE_UNUSED;
252b5132
RH
3210{
3211 int basereg;
3212
3213 if (ntok == 2)
3214 basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
3215 else
3216 basereg = tok[2].X_add_number;
3217
19f78583 3218 (void) load_expression (tok[0].X_add_number, &tok[1], &basereg, NULL);
252b5132
RH
3219}
3220
3221/* The ldah macro differs from the ldah instruction in that it has $31
3222 as an implied base register. */
3223
3224static void
3225emit_ldah (tok, ntok, unused)
3226 const expressionS *tok;
446a06c9
MM
3227 int ntok ATTRIBUTE_UNUSED;
3228 const PTR unused ATTRIBUTE_UNUSED;
252b5132
RH
3229{
3230 expressionS newtok[3];
3231
3232 newtok[0] = tok[0];
3233 newtok[1] = tok[1];
3234 set_tok_preg (newtok[2], AXP_REG_ZERO);
3235
3236 assemble_tokens ("ldah", newtok, 3, 0);
3237}
3238
3239/* Handle all "simple" integer register loads -- ldq, ldq_l, ldq_u,
3240 etc. They differ from the real instructions in that they do simple
3241 expressions like the lda macro. */
3242
3243static void
3244emit_ir_load (tok, ntok, opname)
3245 const expressionS *tok;
3246 int ntok;
3247 const PTR opname;
3248{
19f78583
RH
3249 int basereg;
3250 long lituse;
252b5132
RH
3251 expressionS newtok[3];
3252 struct alpha_insn insn;
3253
3254 if (ntok == 2)
3255 basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
3256 else
3257 basereg = tok[2].X_add_number;
3258
3259 lituse = load_expression (tok[0].X_add_number, &tok[1], &basereg,
19f78583 3260 &newtok[1]);
252b5132
RH
3261
3262 newtok[0] = tok[0];
3263 set_tok_preg (newtok[2], basereg);
3264
32ff5c2e 3265 assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn);
252b5132
RH
3266
3267 if (lituse)
3268 {
3269 assert (insn.nfixups < MAX_INSN_FIXUPS);
19f78583
RH
3270 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3271 insn.fixups[insn.nfixups].exp.X_op = O_absent;
252b5132 3272 insn.nfixups++;
19f78583 3273 insn.sequence = lituse;
252b5132
RH
3274 }
3275
3276 emit_insn (&insn);
3277}
3278
3279/* Handle fp register loads, and both integer and fp register stores.
3280 Again, we handle simple expressions. */
3281
3282static void
3283emit_loadstore (tok, ntok, opname)
3284 const expressionS *tok;
3285 int ntok;
3286 const PTR opname;
3287{
19f78583
RH
3288 int basereg;
3289 long lituse;
252b5132
RH
3290 expressionS newtok[3];
3291 struct alpha_insn insn;
3292
3293 if (ntok == 2)
3294 basereg = (tok[1].X_op == O_constant ? AXP_REG_ZERO : alpha_gp_register);
3295 else
3296 basereg = tok[2].X_add_number;
3297
32ff5c2e 3298 if (tok[1].X_op != O_constant || !range_signed_16 (tok[1].X_add_number))
252b5132
RH
3299 {
3300 if (alpha_noat_on)
3301 as_bad (_("macro requires $at register while noat in effect"));
3302
19f78583 3303 lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, &newtok[1]);
252b5132
RH
3304 }
3305 else
3306 {
3307 newtok[1] = tok[1];
3308 lituse = 0;
3309 }
3310
3311 newtok[0] = tok[0];
3312 set_tok_preg (newtok[2], basereg);
3313
32ff5c2e 3314 assemble_tokens_to_insn ((const char *) opname, newtok, 3, &insn);
252b5132
RH
3315
3316 if (lituse)
3317 {
3318 assert (insn.nfixups < MAX_INSN_FIXUPS);
19f78583
RH
3319 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3320 insn.fixups[insn.nfixups].exp.X_op = O_absent;
252b5132 3321 insn.nfixups++;
19f78583 3322 insn.sequence = lituse;
252b5132
RH
3323 }
3324
3325 emit_insn (&insn);
3326}
3327
3328/* Load a half-word or byte as an unsigned value. */
3329
3330static void
3331emit_ldXu (tok, ntok, vlgsize)
3332 const expressionS *tok;
3333 int ntok;
3334 const PTR vlgsize;
3335{
3336 if (alpha_target & AXP_OPCODE_BWX)
32ff5c2e 3337 emit_ir_load (tok, ntok, ldXu_op[(long) vlgsize]);
252b5132
RH
3338 else
3339 {
3340 expressionS newtok[3];
19f78583
RH
3341 struct alpha_insn insn;
3342 int basereg;
3343 long lituse;
43b4c25e 3344
252b5132
RH
3345 if (alpha_noat_on)
3346 as_bad (_("macro requires $at register while noat in effect"));
3347
19f78583
RH
3348 if (ntok == 2)
3349 basereg = (tok[1].X_op == O_constant
3350 ? AXP_REG_ZERO : alpha_gp_register);
3351 else
3352 basereg = tok[2].X_add_number;
3353
252b5132
RH
3354 /* emit "lda $at, exp" */
3355
19f78583 3356 lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL);
252b5132
RH
3357
3358 /* emit "ldq_u targ, 0($at)" */
3359
3360 newtok[0] = tok[0];
3361 set_tok_const (newtok[1], 0);
19f78583
RH
3362 set_tok_preg (newtok[2], basereg);
3363 assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn);
3364
3365 if (lituse)
3366 {
3367 assert (insn.nfixups < MAX_INSN_FIXUPS);
3368 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3369 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3370 insn.nfixups++;
3371 insn.sequence = lituse;
3372 }
3373
3374 emit_insn (&insn);
252b5132
RH
3375
3376 /* emit "extXl targ, $at, targ" */
3377
19f78583 3378 set_tok_reg (newtok[1], basereg);
252b5132 3379 newtok[2] = newtok[0];
19f78583
RH
3380 assemble_tokens_to_insn (extXl_op[(long) vlgsize], newtok, 3, &insn);
3381
3382 if (lituse)
3383 {
3384 assert (insn.nfixups < MAX_INSN_FIXUPS);
3385 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
3386 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3387 insn.nfixups++;
3388 insn.sequence = lituse;
3389 }
3390
3391 emit_insn (&insn);
252b5132
RH
3392 }
3393}
3394
3395/* Load a half-word or byte as a signed value. */
3396
3397static void
3398emit_ldX (tok, ntok, vlgsize)
3399 const expressionS *tok;
3400 int ntok;
3401 const PTR vlgsize;
3402{
3403 emit_ldXu (tok, ntok, vlgsize);
32ff5c2e 3404 assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1);
252b5132
RH
3405}
3406
3407/* Load an integral value from an unaligned address as an unsigned
3408 value. */
3409
3410static void
3411emit_uldXu (tok, ntok, vlgsize)
3412 const expressionS *tok;
3413 int ntok;
3414 const PTR vlgsize;
3415{
32ff5c2e 3416 long lgsize = (long) vlgsize;
252b5132
RH
3417 expressionS newtok[3];
3418
3419 if (alpha_noat_on)
3420 as_bad (_("macro requires $at register while noat in effect"));
3421
3422 /* emit "lda $at, exp" */
3423
3424 memcpy (newtok, tok, sizeof (expressionS) * ntok);
3425 newtok[0].X_add_number = AXP_REG_AT;
3426 assemble_tokens ("lda", newtok, ntok, 1);
3427
3428 /* emit "ldq_u $t9, 0($at)" */
3429
3430 set_tok_reg (newtok[0], AXP_REG_T9);
3431 set_tok_const (newtok[1], 0);
3432 set_tok_preg (newtok[2], AXP_REG_AT);
3433 assemble_tokens ("ldq_u", newtok, 3, 1);
3434
3435 /* emit "ldq_u $t10, size-1($at)" */
3436
3437 set_tok_reg (newtok[0], AXP_REG_T10);
66498417 3438 set_tok_const (newtok[1], (1 << lgsize) - 1);
252b5132
RH
3439 assemble_tokens ("ldq_u", newtok, 3, 1);
3440
3441 /* emit "extXl $t9, $at, $t9" */
3442
3443 set_tok_reg (newtok[0], AXP_REG_T9);
3444 set_tok_reg (newtok[1], AXP_REG_AT);
3445 set_tok_reg (newtok[2], AXP_REG_T9);
3446 assemble_tokens (extXl_op[lgsize], newtok, 3, 1);
3447
3448 /* emit "extXh $t10, $at, $t10" */
3449
3450 set_tok_reg (newtok[0], AXP_REG_T10);
3451 set_tok_reg (newtok[2], AXP_REG_T10);
3452 assemble_tokens (extXh_op[lgsize], newtok, 3, 1);
3453
3454 /* emit "or $t9, $t10, targ" */
3455
3456 set_tok_reg (newtok[0], AXP_REG_T9);
3457 set_tok_reg (newtok[1], AXP_REG_T10);
3458 newtok[2] = tok[0];
3459 assemble_tokens ("or", newtok, 3, 1);
3460}
3461
3462/* Load an integral value from an unaligned address as a signed value.
3463 Note that quads should get funneled to the unsigned load since we
3464 don't have to do the sign extension. */
3465
3466static void
3467emit_uldX (tok, ntok, vlgsize)
3468 const expressionS *tok;
3469 int ntok;
3470 const PTR vlgsize;
3471{
3472 emit_uldXu (tok, ntok, vlgsize);
32ff5c2e 3473 assemble_tokens (sextX_op[(long) vlgsize], tok, 1, 1);
252b5132
RH
3474}
3475
3476/* Implement the ldil macro. */
3477
3478static void
3479emit_ldil (tok, ntok, unused)
3480 const expressionS *tok;
3481 int ntok;
446a06c9 3482 const PTR unused ATTRIBUTE_UNUSED;
252b5132
RH
3483{
3484 expressionS newtok[2];
3485
bc805888 3486 memcpy (newtok, tok, sizeof (newtok));
252b5132
RH
3487 newtok[1].X_add_number = sign_extend_32 (tok[1].X_add_number);
3488
3489 assemble_tokens ("lda", newtok, ntok, 1);
3490}
3491
3492/* Store a half-word or byte. */
3493
3494static void
3495emit_stX (tok, ntok, vlgsize)
3496 const expressionS *tok;
3497 int ntok;
3498 const PTR vlgsize;
3499{
32ff5c2e 3500 int lgsize = (int) (long) vlgsize;
252b5132
RH
3501
3502 if (alpha_target & AXP_OPCODE_BWX)
3503 emit_loadstore (tok, ntok, stX_op[lgsize]);
3504 else
3505 {
3506 expressionS newtok[3];
19f78583
RH
3507 struct alpha_insn insn;
3508 int basereg;
3509 long lituse;
252b5132
RH
3510
3511 if (alpha_noat_on)
32ff5c2e 3512 as_bad (_("macro requires $at register while noat in effect"));
252b5132 3513
19f78583
RH
3514 if (ntok == 2)
3515 basereg = (tok[1].X_op == O_constant
3516 ? AXP_REG_ZERO : alpha_gp_register);
3517 else
3518 basereg = tok[2].X_add_number;
3519
252b5132
RH
3520 /* emit "lda $at, exp" */
3521
19f78583 3522 lituse = load_expression (AXP_REG_AT, &tok[1], &basereg, NULL);
252b5132
RH
3523
3524 /* emit "ldq_u $t9, 0($at)" */
3525
3526 set_tok_reg (newtok[0], AXP_REG_T9);
3527 set_tok_const (newtok[1], 0);
19f78583
RH
3528 set_tok_preg (newtok[2], basereg);
3529 assemble_tokens_to_insn ("ldq_u", newtok, 3, &insn);
3530
3531 if (lituse)
3532 {
3533 assert (insn.nfixups < MAX_INSN_FIXUPS);
3534 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3535 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3536 insn.nfixups++;
3537 insn.sequence = lituse;
3538 }
3539
3540 emit_insn (&insn);
252b5132
RH
3541
3542 /* emit "insXl src, $at, $t10" */
3543
3544 newtok[0] = tok[0];
19f78583 3545 set_tok_reg (newtok[1], basereg);
252b5132 3546 set_tok_reg (newtok[2], AXP_REG_T10);
19f78583
RH
3547 assemble_tokens_to_insn (insXl_op[lgsize], newtok, 3, &insn);
3548
3549 if (lituse)
3550 {
3551 assert (insn.nfixups < MAX_INSN_FIXUPS);
3552 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
3553 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3554 insn.nfixups++;
3555 insn.sequence = lituse;
3556 }
3557
3558 emit_insn (&insn);
252b5132
RH
3559
3560 /* emit "mskXl $t9, $at, $t9" */
3561
3562 set_tok_reg (newtok[0], AXP_REG_T9);
3563 newtok[2] = newtok[0];
19f78583
RH
3564 assemble_tokens_to_insn (mskXl_op[lgsize], newtok, 3, &insn);
3565
3566 if (lituse)
3567 {
3568 assert (insn.nfixups < MAX_INSN_FIXUPS);
3569 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BYTOFF;
3570 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3571 insn.nfixups++;
3572 insn.sequence = lituse;
3573 }
3574
3575 emit_insn (&insn);
252b5132
RH
3576
3577 /* emit "or $t9, $t10, $t9" */
3578
3579 set_tok_reg (newtok[1], AXP_REG_T10);
3580 assemble_tokens ("or", newtok, 3, 1);
3581
3582 /* emit "stq_u $t9, 0($at) */
3583
19f78583 3584 set_tok_const(newtok[1], 0);
252b5132 3585 set_tok_preg (newtok[2], AXP_REG_AT);
19f78583
RH
3586 assemble_tokens_to_insn ("stq_u", newtok, 3, &insn);
3587
3588 if (lituse)
3589 {
3590 assert (insn.nfixups < MAX_INSN_FIXUPS);
3591 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_BASE;
3592 insn.fixups[insn.nfixups].exp.X_op = O_absent;
3593 insn.nfixups++;
3594 insn.sequence = lituse;
3595 }
3596
3597 emit_insn (&insn);
252b5132
RH
3598 }
3599}
3600
3601/* Store an integer to an unaligned address. */
3602
3603static void
3604emit_ustX (tok, ntok, vlgsize)
3605 const expressionS *tok;
3606 int ntok;
3607 const PTR vlgsize;
3608{
32ff5c2e 3609 int lgsize = (int) (long) vlgsize;
252b5132
RH
3610 expressionS newtok[3];
3611
3612 /* emit "lda $at, exp" */
3613
3614 memcpy (newtok, tok, sizeof (expressionS) * ntok);
3615 newtok[0].X_add_number = AXP_REG_AT;
3616 assemble_tokens ("lda", newtok, ntok, 1);
3617
3618 /* emit "ldq_u $9, 0($at)" */
3619
3620 set_tok_reg (newtok[0], AXP_REG_T9);
3621 set_tok_const (newtok[1], 0);
3622 set_tok_preg (newtok[2], AXP_REG_AT);
3623 assemble_tokens ("ldq_u", newtok, 3, 1);
3624
3625 /* emit "ldq_u $10, size-1($at)" */
3626
3627 set_tok_reg (newtok[0], AXP_REG_T10);
66498417 3628 set_tok_const (newtok[1], (1 << lgsize) - 1);
252b5132
RH
3629 assemble_tokens ("ldq_u", newtok, 3, 1);
3630
3631 /* emit "insXl src, $at, $t11" */
3632
3633 newtok[0] = tok[0];
3634 set_tok_reg (newtok[1], AXP_REG_AT);
3635 set_tok_reg (newtok[2], AXP_REG_T11);
3636 assemble_tokens (insXl_op[lgsize], newtok, 3, 1);
3637
3638 /* emit "insXh src, $at, $t12" */
3639
3640 set_tok_reg (newtok[2], AXP_REG_T12);
3641 assemble_tokens (insXh_op[lgsize], newtok, 3, 1);
3642
3643 /* emit "mskXl $t9, $at, $t9" */
3644
3645 set_tok_reg (newtok[0], AXP_REG_T9);
3646 newtok[2] = newtok[0];
3647 assemble_tokens (mskXl_op[lgsize], newtok, 3, 1);
3648
3649 /* emit "mskXh $t10, $at, $t10" */
3650
3651 set_tok_reg (newtok[0], AXP_REG_T10);
3652 newtok[2] = newtok[0];
3653 assemble_tokens (mskXh_op[lgsize], newtok, 3, 1);
3654
3655 /* emit "or $t9, $t11, $t9" */
3656
3657 set_tok_reg (newtok[0], AXP_REG_T9);
3658 set_tok_reg (newtok[1], AXP_REG_T11);
3659 newtok[2] = newtok[0];
3660 assemble_tokens ("or", newtok, 3, 1);
3661
3662 /* emit "or $t10, $t12, $t10" */
3663
3664 set_tok_reg (newtok[0], AXP_REG_T10);
3665 set_tok_reg (newtok[1], AXP_REG_T12);
3666 newtok[2] = newtok[0];
3667 assemble_tokens ("or", newtok, 3, 1);
3668
3669 /* emit "stq_u $t9, 0($at)" */
3670
3671 set_tok_reg (newtok[0], AXP_REG_T9);
3672 set_tok_const (newtok[1], 0);
3673 set_tok_preg (newtok[2], AXP_REG_AT);
3674 assemble_tokens ("stq_u", newtok, 3, 1);
3675
3676 /* emit "stq_u $t10, size-1($at)" */
3677
3678 set_tok_reg (newtok[0], AXP_REG_T10);
66498417 3679 set_tok_const (newtok[1], (1 << lgsize) - 1);
252b5132
RH
3680 assemble_tokens ("stq_u", newtok, 3, 1);
3681}
3682
3683/* Sign extend a half-word or byte. The 32-bit sign extend is
3684 implemented as "addl $31, $r, $t" in the opcode table. */
3685
3686static void
3687emit_sextX (tok, ntok, vlgsize)
3688 const expressionS *tok;
3689 int ntok;
3690 const PTR vlgsize;
3691{
32ff5c2e 3692 long lgsize = (long) vlgsize;
252b5132
RH
3693
3694 if (alpha_target & AXP_OPCODE_BWX)
3695 assemble_tokens (sextX_op[lgsize], tok, ntok, 0);
3696 else
3697 {
3698 int bitshift = 64 - 8 * (1 << lgsize);
3699 expressionS newtok[3];
3700
3701 /* emit "sll src,bits,dst" */
3702
3703 newtok[0] = tok[0];
3704 set_tok_const (newtok[1], bitshift);
3705 newtok[2] = tok[ntok - 1];
3706 assemble_tokens ("sll", newtok, 3, 1);
3707
3708 /* emit "sra dst,bits,dst" */
3709
3710 newtok[0] = newtok[2];
3711 assemble_tokens ("sra", newtok, 3, 1);
3712 }
3713}
3714
3715/* Implement the division and modulus macros. */
3716
3717#ifdef OBJ_EVAX
3718
3719/* Make register usage like in normal procedure call.
3720 Don't clobber PV and RA. */
3721
3722static void
3723emit_division (tok, ntok, symname)
3724 const expressionS *tok;
3725 int ntok;
3726 const PTR symname;
3727{
3728 /* DIVISION and MODULUS. Yech.
3729 *
3730 * Convert
3731 * OP x,y,result
3732 * to
3733 * mov x,R16 # if x != R16
3734 * mov y,R17 # if y != R17
3735 * lda AT,__OP
3736 * jsr AT,(AT),0
3737 * mov R0,result
3738 *
3739 * with appropriate optimizations if R0,R16,R17 are the registers
3740 * specified by the compiler.
3741 */
3742
3743 int xr, yr, rr;
3744 symbolS *sym;
3745 expressionS newtok[3];
3746
3747 xr = regno (tok[0].X_add_number);
3748 yr = regno (tok[1].X_add_number);
3749
3750 if (ntok < 3)
3751 rr = xr;
3752 else
3753 rr = regno (tok[2].X_add_number);
3754
3755 /* Move the operands into the right place */
3756 if (yr == AXP_REG_R16 && xr == AXP_REG_R17)
3757 {
3758 /* They are in exactly the wrong order -- swap through AT */
3759
3760 if (alpha_noat_on)
3761 as_bad (_("macro requires $at register while noat in effect"));
3762
3763 set_tok_reg (newtok[0], AXP_REG_R16);
3764 set_tok_reg (newtok[1], AXP_REG_AT);
3765 assemble_tokens ("mov", newtok, 2, 1);
3766
3767 set_tok_reg (newtok[0], AXP_REG_R17);
3768 set_tok_reg (newtok[1], AXP_REG_R16);
3769 assemble_tokens ("mov", newtok, 2, 1);
3770
3771 set_tok_reg (newtok[0], AXP_REG_AT);
3772 set_tok_reg (newtok[1], AXP_REG_R17);
3773 assemble_tokens ("mov", newtok, 2, 1);
3774 }
3775 else
3776 {
3777 if (yr == AXP_REG_R16)
3778 {
3779 set_tok_reg (newtok[0], AXP_REG_R16);
3780 set_tok_reg (newtok[1], AXP_REG_R17);
3781 assemble_tokens ("mov", newtok, 2, 1);
3782 }
3783
3784 if (xr != AXP_REG_R16)
3785 {
3786 set_tok_reg (newtok[0], xr);
3787 set_tok_reg (newtok[1], AXP_REG_R16);
1aad8cf8 3788 assemble_tokens ("mov", newtok, 2, 1);
252b5132
RH
3789 }
3790
3791 if (yr != AXP_REG_R16 && yr != AXP_REG_R17)
3792 {
3793 set_tok_reg (newtok[0], yr);
3794 set_tok_reg (newtok[1], AXP_REG_R17);
3795 assemble_tokens ("mov", newtok, 2, 1);
3796 }
3797 }
3798
32ff5c2e 3799 sym = symbol_find_or_make ((const char *) symname);
252b5132
RH
3800
3801 set_tok_reg (newtok[0], AXP_REG_AT);
3802 set_tok_sym (newtok[1], sym, 0);
3803 assemble_tokens ("lda", newtok, 2, 1);
3804
3805 /* Call the division routine */
3806 set_tok_reg (newtok[0], AXP_REG_AT);
3807 set_tok_cpreg (newtok[1], AXP_REG_AT);
3808 set_tok_const (newtok[2], 0);
3809 assemble_tokens ("jsr", newtok, 3, 1);
3810
3811 /* Move the result to the right place */
3812 if (rr != AXP_REG_R0)
3813 {
3814 set_tok_reg (newtok[0], AXP_REG_R0);
3815 set_tok_reg (newtok[1], rr);
3816 assemble_tokens ("mov", newtok, 2, 1);
3817 }
3818}
3819
3820#else /* !OBJ_EVAX */
3821
3822static void
3823emit_division (tok, ntok, symname)
3824 const expressionS *tok;
3825 int ntok;
3826 const PTR symname;
3827{
3828 /* DIVISION and MODULUS. Yech.
3829 * Convert
3830 * OP x,y,result
3831 * to
3832 * lda pv,__OP
3833 * mov x,t10
3834 * mov y,t11
3835 * jsr t9,(pv),__OP
3836 * mov t12,result
3837 *
3838 * with appropriate optimizations if t10,t11,t12 are the registers
3839 * specified by the compiler.
3840 */
3841
3842 int xr, yr, rr;
3843 symbolS *sym;
3844 expressionS newtok[3];
3845
3846 xr = regno (tok[0].X_add_number);
3847 yr = regno (tok[1].X_add_number);
3848
3849 if (ntok < 3)
3850 rr = xr;
3851 else
3852 rr = regno (tok[2].X_add_number);
3853
32ff5c2e 3854 sym = symbol_find_or_make ((const char *) symname);
252b5132
RH
3855
3856 /* Move the operands into the right place */
3857 if (yr == AXP_REG_T10 && xr == AXP_REG_T11)
3858 {
3859 /* They are in exactly the wrong order -- swap through AT */
3860
3861 if (alpha_noat_on)
3862 as_bad (_("macro requires $at register while noat in effect"));
3863
3864 set_tok_reg (newtok[0], AXP_REG_T10);
3865 set_tok_reg (newtok[1], AXP_REG_AT);
3866 assemble_tokens ("mov", newtok, 2, 1);
3867
3868 set_tok_reg (newtok[0], AXP_REG_T11);
3869 set_tok_reg (newtok[1], AXP_REG_T10);
3870 assemble_tokens ("mov", newtok, 2, 1);
3871
3872 set_tok_reg (newtok[0], AXP_REG_AT);
3873 set_tok_reg (newtok[1], AXP_REG_T11);
3874 assemble_tokens ("mov", newtok, 2, 1);
3875 }
3876 else
3877 {
3878 if (yr == AXP_REG_T10)
3879 {
3880 set_tok_reg (newtok[0], AXP_REG_T10);
3881 set_tok_reg (newtok[1], AXP_REG_T11);
3882 assemble_tokens ("mov", newtok, 2, 1);
3883 }
3884
3885 if (xr != AXP_REG_T10)
3886 {
3887 set_tok_reg (newtok[0], xr);
3888 set_tok_reg (newtok[1], AXP_REG_T10);
1aad8cf8 3889 assemble_tokens ("mov", newtok, 2, 1);
252b5132
RH
3890 }
3891
3892 if (yr != AXP_REG_T10 && yr != AXP_REG_T11)
3893 {
3894 set_tok_reg (newtok[0], yr);
3895 set_tok_reg (newtok[1], AXP_REG_T11);
3896 assemble_tokens ("mov", newtok, 2, 1);
3897 }
3898 }
3899
3900 /* Call the division routine */
3901 set_tok_reg (newtok[0], AXP_REG_T9);
3902 set_tok_sym (newtok[1], sym, 0);
3903 assemble_tokens ("jsr", newtok, 2, 1);
3904
3905 /* Reload the GP register */
3906#ifdef OBJ_AOUT
3907FIXME
3908#endif
3909#if defined(OBJ_ECOFF) || defined(OBJ_ELF)
3910 set_tok_reg (newtok[0], alpha_gp_register);
3911 set_tok_const (newtok[1], 0);
3912 set_tok_preg (newtok[2], AXP_REG_T9);
3913 assemble_tokens ("ldgp", newtok, 3, 1);
3914#endif
3915
3916 /* Move the result to the right place */
3917 if (rr != AXP_REG_T12)
3918 {
3919 set_tok_reg (newtok[0], AXP_REG_T12);
3920 set_tok_reg (newtok[1], rr);
3921 assemble_tokens ("mov", newtok, 2, 1);
3922 }
3923}
3924
3925#endif /* !OBJ_EVAX */
3926
3927/* The jsr and jmp macros differ from their instruction counterparts
3928 in that they can load the target address and default most
3929 everything. */
3930
3931static void
3932emit_jsrjmp (tok, ntok, vopname)
3933 const expressionS *tok;
3934 int ntok;
3935 const PTR vopname;
3936{
3937 const char *opname = (const char *) vopname;
3938 struct alpha_insn insn;
3939 expressionS newtok[3];
19f78583
RH
3940 int r, tokidx = 0;
3941 long lituse = 0;
43b4c25e 3942
252b5132
RH
3943 if (tokidx < ntok && tok[tokidx].X_op == O_register)
3944 r = regno (tok[tokidx++].X_add_number);
3945 else
3946 r = strcmp (opname, "jmp") == 0 ? AXP_REG_ZERO : AXP_REG_RA;
3947
3948 set_tok_reg (newtok[0], r);
3949
3950 if (tokidx < ntok &&
3951 (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
3952 r = regno (tok[tokidx++].X_add_number);
3953#ifdef OBJ_EVAX
3954 /* keep register if jsr $n.<sym> */
3955#else
3956 else
3957 {
3958 int basereg = alpha_gp_register;
19f78583 3959 lituse = load_expression (r = AXP_REG_PV, &tok[tokidx], &basereg, NULL);
252b5132
RH
3960 }
3961#endif
3962
3963 set_tok_cpreg (newtok[1], r);
3964
3965#ifdef OBJ_EVAX
3966 /* FIXME: Add hint relocs to BFD for evax. */
3967#else
3968 if (tokidx < ntok)
3969 newtok[2] = tok[tokidx];
3970 else
3971#endif
3972 set_tok_const (newtok[2], 0);
3973
3974 assemble_tokens_to_insn (opname, newtok, 3, &insn);
3975
252b5132
RH
3976 if (lituse)
3977 {
3978 assert (insn.nfixups < MAX_INSN_FIXUPS);
19f78583
RH
3979 insn.fixups[insn.nfixups].reloc = DUMMY_RELOC_LITUSE_JSR;
3980 insn.fixups[insn.nfixups].exp.X_op = O_absent;
252b5132 3981 insn.nfixups++;
19f78583 3982 insn.sequence = lituse;
252b5132
RH
3983 }
3984
3985 emit_insn (&insn);
3986}
3987
3988/* The ret and jcr instructions differ from their instruction
3989 counterparts in that everything can be defaulted. */
3990
3991static void
3992emit_retjcr (tok, ntok, vopname)
3993 const expressionS *tok;
3994 int ntok;
3995 const PTR vopname;
3996{
32ff5c2e 3997 const char *opname = (const char *) vopname;
252b5132
RH
3998 expressionS newtok[3];
3999 int r, tokidx = 0;
4000
4001 if (tokidx < ntok && tok[tokidx].X_op == O_register)
4002 r = regno (tok[tokidx++].X_add_number);
4003 else
4004 r = AXP_REG_ZERO;
4005
4006 set_tok_reg (newtok[0], r);
4007
4008 if (tokidx < ntok &&
4009 (tok[tokidx].X_op == O_pregister || tok[tokidx].X_op == O_cpregister))
4010 r = regno (tok[tokidx++].X_add_number);
4011 else
4012 r = AXP_REG_RA;
4013
4014 set_tok_cpreg (newtok[1], r);
4015
4016 if (tokidx < ntok)
4017 newtok[2] = tok[tokidx];
4018 else
32ff5c2e 4019 set_tok_const (newtok[2], strcmp (opname, "ret") == 0);
252b5132
RH
4020
4021 assemble_tokens (opname, newtok, 3, 0);
4022}
4023\f
4024/* Assembler directives */
4025
4026/* Handle the .text pseudo-op. This is like the usual one, but it
4027 clears alpha_insn_label and restores auto alignment. */
4028
4029static void
4030s_alpha_text (i)
4031 int i;
4032
4033{
4034 s_text (i);
4035 alpha_insn_label = NULL;
4036 alpha_auto_align_on = 1;
4037 alpha_current_align = 0;
4038}
4039
4040/* Handle the .data pseudo-op. This is like the usual one, but it
4041 clears alpha_insn_label and restores auto alignment. */
4042
4043static void
4044s_alpha_data (i)
4045 int i;
4046{
4047 s_data (i);
4048 alpha_insn_label = NULL;
4049 alpha_auto_align_on = 1;
4050 alpha_current_align = 0;
4051}
4052
4053#if defined (OBJ_ECOFF) || defined (OBJ_EVAX)
4054
4055/* Handle the OSF/1 and openVMS .comm pseudo quirks.
4056 openVMS constructs a section for every common symbol. */
4057
4058static void
4059s_alpha_comm (ignore)
4060 int ignore;
4061{
4062 register char *name;
4063 register char c;
4064 register char *p;
4065 offsetT temp;
4066 register symbolS *symbolP;
4067
4068#ifdef OBJ_EVAX
4069 segT current_section = now_seg;
4070 int current_subsec = now_subseg;
4071 segT new_seg;
4072#endif
4073
4074 name = input_line_pointer;
4075 c = get_symbol_end ();
4076
4077 /* just after name is now '\0' */
4078 p = input_line_pointer;
4079 *p = c;
4080
4081 SKIP_WHITESPACE ();
4082
4083 /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */
4084 if (*input_line_pointer == ',')
4085 {
4086 input_line_pointer++;
4087 SKIP_WHITESPACE ();
4088 }
4089 if ((temp = get_absolute_expression ()) < 0)
4090 {
4091 as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
4092 ignore_rest_of_line ();
4093 return;
4094 }
4095
4096 *p = 0;
4097 symbolP = symbol_find_or_make (name);
4098
4099#ifdef OBJ_EVAX
4100 /* Make a section for the common symbol. */
4101 new_seg = subseg_new (xstrdup (name), 0);
4102#endif
4103
4104 *p = c;
4105
4106#ifdef OBJ_EVAX
4107 /* alignment might follow */
4108 if (*input_line_pointer == ',')
4109 {
4110 offsetT align;
4111
1dab94dd 4112 input_line_pointer++;
252b5132
RH
4113 align = get_absolute_expression ();
4114 bfd_set_section_alignment (stdoutput, new_seg, align);
4115 }
4116#endif
4117
4118 if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
4119 {
4120 as_bad (_("Ignoring attempt to re-define symbol"));
4121 ignore_rest_of_line ();
4122 return;
4123 }
4124
4125#ifdef OBJ_EVAX
4126 if (bfd_section_size (stdoutput, new_seg) > 0)
1dab94dd 4127 {
252b5132
RH
4128 if (bfd_section_size (stdoutput, new_seg) != temp)
4129 as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
4130 S_GET_NAME (symbolP),
4131 (long) bfd_section_size (stdoutput, new_seg),
4132 (long) temp);
4133 }
4134#else
4135 if (S_GET_VALUE (symbolP))
4136 {
4137 if (S_GET_VALUE (symbolP) != (valueT) temp)
4138 as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
4139 S_GET_NAME (symbolP),
4140 (long) S_GET_VALUE (symbolP),
4141 (long) temp);
4142 }
4143#endif
4144 else
4145 {
1dab94dd 4146#ifdef OBJ_EVAX
252b5132
RH
4147 subseg_set (new_seg, 0);
4148 p = frag_more (temp);
4149 new_seg->flags |= SEC_IS_COMMON;
4150 if (! S_IS_DEFINED (symbolP))
9de8d8f1 4151 S_SET_SEGMENT (symbolP, new_seg);
252b5132
RH
4152#else
4153 S_SET_VALUE (symbolP, (valueT) temp);
4154#endif
4155 S_SET_EXTERNAL (symbolP);
4156 }
4157
4158#ifdef OBJ_EVAX
4159 subseg_set (current_section, current_subsec);
4160#endif
4161
7dcc9865 4162 know (symbol_get_frag (symbolP) == &zero_address_frag);
252b5132
RH
4163
4164 demand_empty_rest_of_line ();
4165}
4166
4167#endif /* ! OBJ_ELF */
4168
4169#ifdef OBJ_ECOFF
4170
4171/* Handle the .rdata pseudo-op. This is like the usual one, but it
4172 clears alpha_insn_label and restores auto alignment. */
4173
4174static void
4175s_alpha_rdata (ignore)
4176 int ignore;
4177{
4178 int temp;
4179
4180 temp = get_absolute_expression ();
4181 subseg_new (".rdata", 0);
4182 demand_empty_rest_of_line ();
4183 alpha_insn_label = NULL;
4184 alpha_auto_align_on = 1;
4185 alpha_current_align = 0;
4186}
4187
4188#endif
4189
4190#ifdef OBJ_ECOFF
4191
4192/* Handle the .sdata pseudo-op. This is like the usual one, but it
4193 clears alpha_insn_label and restores auto alignment. */
4194
4195static void
4196s_alpha_sdata (ignore)
4197 int ignore;
4198{
4199 int temp;
4200
4201 temp = get_absolute_expression ();
4202 subseg_new (".sdata", 0);
4203 demand_empty_rest_of_line ();
4204 alpha_insn_label = NULL;
4205 alpha_auto_align_on = 1;
4206 alpha_current_align = 0;
4207}
4208#endif
4209
4210#ifdef OBJ_ELF
4211
4212/* Handle the .section pseudo-op. This is like the usual one, but it
4213 clears alpha_insn_label and restores auto alignment. */
4214
4215static void
4216s_alpha_section (ignore)
4217 int ignore;
4218{
4219 obj_elf_section (ignore);
4220
4221 alpha_insn_label = NULL;
4222 alpha_auto_align_on = 1;
4223 alpha_current_align = 0;
4224}
4225
4226static void
4227s_alpha_ent (dummy)
446a06c9 4228 int dummy ATTRIBUTE_UNUSED;
252b5132
RH
4229{
4230 if (ECOFF_DEBUGGING)
4231 ecoff_directive_ent (0);
4232 else
4233 {
4234 char *name, name_end;
4235 name = input_line_pointer;
4236 name_end = get_symbol_end ();
4237
4238 if (! is_name_beginner (*name))
4239 {
4240 as_warn (_(".ent directive has no name"));
4241 *input_line_pointer = name_end;
4242 }
4243 else
4244 {
4245 symbolS *sym;
4246
4247 if (alpha_cur_ent_sym)
4248 as_warn (_("nested .ent directives"));
4249
4250 sym = symbol_find_or_make (name);
49309057 4251 symbol_get_bfdsym (sym)->flags |= BSF_FUNCTION;
252b5132
RH
4252 alpha_cur_ent_sym = sym;
4253
4254 /* The .ent directive is sometimes followed by a number. Not sure
4255 what it really means, but ignore it. */
4256 *input_line_pointer = name_end;
4257 SKIP_WHITESPACE ();
4258 if (*input_line_pointer == ',')
4259 {
4260 input_line_pointer++;
4261 SKIP_WHITESPACE ();
4262 }
3882b010 4263 if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
252b5132
RH
4264 (void) get_absolute_expression ();
4265 }
4266 demand_empty_rest_of_line ();
4267 }
4268}
4269
4270static void
4271s_alpha_end (dummy)
446a06c9 4272 int dummy ATTRIBUTE_UNUSED;
252b5132
RH
4273{
4274 if (ECOFF_DEBUGGING)
4275 ecoff_directive_end (0);
4276 else
4277 {
4278 char *name, name_end;
4279 name = input_line_pointer;
4280 name_end = get_symbol_end ();
4281
4282 if (! is_name_beginner (*name))
4283 {
4284 as_warn (_(".end directive has no name"));
4285 *input_line_pointer = name_end;
4286 }
4287 else
4288 {
4289 symbolS *sym;
4290
4291 sym = symbol_find (name);
4292 if (sym != alpha_cur_ent_sym)
4293 as_warn (_(".end directive names different symbol than .ent"));
4294
4295 /* Create an expression to calculate the size of the function. */
4296 if (sym)
4297 {
49309057
ILT
4298 symbol_get_obj (sym)->size =
4299 (expressionS *) xmalloc (sizeof (expressionS));
4300 symbol_get_obj (sym)->size->X_op = O_subtract;
4301 symbol_get_obj (sym)->size->X_add_symbol
66498417 4302 = symbol_new ("L0\001", now_seg, frag_now_fix (), frag_now);
49309057
ILT
4303 symbol_get_obj (sym)->size->X_op_symbol = sym;
4304 symbol_get_obj (sym)->size->X_add_number = 0;
252b5132
RH
4305 }
4306
4307 alpha_cur_ent_sym = NULL;
4308
4309 *input_line_pointer = name_end;
4310 }
4311 demand_empty_rest_of_line ();
4312 }
4313}
4314
4315static void
4316s_alpha_mask (fp)
4317 int fp;
4318{
4319 if (ECOFF_DEBUGGING)
4320 {
4321 if (fp)
1aad8cf8 4322 ecoff_directive_fmask (0);
252b5132 4323 else
1aad8cf8 4324 ecoff_directive_mask (0);
252b5132
RH
4325 }
4326 else
4327 discard_rest_of_line ();
4328}
4329
4330static void
4331s_alpha_frame (dummy)
446a06c9 4332 int dummy ATTRIBUTE_UNUSED;
252b5132
RH
4333{
4334 if (ECOFF_DEBUGGING)
4335 ecoff_directive_frame (0);
4336 else
4337 discard_rest_of_line ();
4338}
4339
4340static void
4341s_alpha_prologue (ignore)
446a06c9 4342 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4343{
4344 symbolS *sym;
4345 int arg;
4346
4347 arg = get_absolute_expression ();
4348 demand_empty_rest_of_line ();
4349
4350 if (ECOFF_DEBUGGING)
4351 sym = ecoff_get_cur_proc_sym ();
4352 else
4353 sym = alpha_cur_ent_sym;
4354 know (sym != NULL);
4355
4356 switch (arg)
4357 {
1aad8cf8
KH
4358 case 0: /* No PV required. */
4359 S_SET_OTHER (sym, STO_ALPHA_NOPV
4360 | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD));
4361 break;
4362 case 1: /* Std GP load. */
4363 S_SET_OTHER (sym, STO_ALPHA_STD_GPLOAD
4364 | (S_GET_OTHER (sym) & ~STO_ALPHA_STD_GPLOAD));
4365 break;
4366 case 2: /* Non-std use of PV. */
4367 break;
4368
4369 default:
4370 as_bad (_("Invalid argument %d to .prologue."), arg);
4371 break;
1dab94dd 4372 }
252b5132
RH
4373}
4374
66498417 4375static char *first_file_directive;
a8316fe2 4376
4dc7ead9
RH
4377static void
4378s_alpha_file (ignore)
4379 int ignore ATTRIBUTE_UNUSED;
4380{
a8316fe2
RH
4381 /* Save the first .file directive we see, so that we can change our
4382 minds about whether ecoff debugging should or shouldn't be enabled. */
4383 if (alpha_flag_mdebug < 0 && ! first_file_directive)
4384 {
4385 char *start = input_line_pointer;
4386 size_t len;
4387
4388 discard_rest_of_line ();
4389
4390 len = input_line_pointer - start;
4391 first_file_directive = xmalloc (len + 1);
4392 memcpy (first_file_directive, start, len);
4393 first_file_directive[len] = '\0';
4394
4395 input_line_pointer = start;
4396 }
4397
4dc7ead9
RH
4398 if (ECOFF_DEBUGGING)
4399 ecoff_directive_file (0);
4400 else
4401 dwarf2_directive_file (0);
4402}
4403
4404static void
4405s_alpha_loc (ignore)
4406 int ignore ATTRIBUTE_UNUSED;
4407{
4408 if (ECOFF_DEBUGGING)
4409 ecoff_directive_loc (0);
4410 else
4411 dwarf2_directive_loc (0);
4412}
4413
a8316fe2
RH
4414static void
4415s_alpha_stab (n)
4416 int n;
4417{
4418 /* If we've been undecided about mdebug, make up our minds in favour. */
4419 if (alpha_flag_mdebug < 0)
4420 {
32ff5c2e 4421 segT sec = subseg_new (".mdebug", 0);
66498417 4422 bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY);
32ff5c2e 4423 bfd_set_section_alignment (stdoutput, sec, 3);
a8316fe2
RH
4424
4425 ecoff_read_begin_hook ();
4426
4427 if (first_file_directive)
4428 {
4429 char *save_ilp = input_line_pointer;
66498417 4430 input_line_pointer = first_file_directive;
a8316fe2
RH
4431 ecoff_directive_file (0);
4432 input_line_pointer = save_ilp;
4433 free (first_file_directive);
4434 }
4435
4436 alpha_flag_mdebug = 1;
4437 }
4438 s_stab (n);
4439}
4440
252b5132
RH
4441static void
4442s_alpha_coff_wrapper (which)
4443 int which;
4444{
4445 static void (* const fns[]) PARAMS ((int)) = {
4446 ecoff_directive_begin,
4447 ecoff_directive_bend,
4448 ecoff_directive_def,
4449 ecoff_directive_dim,
4450 ecoff_directive_endef,
252b5132
RH
4451 ecoff_directive_scl,
4452 ecoff_directive_tag,
4453 ecoff_directive_val,
252b5132
RH
4454 };
4455
bc805888 4456 assert (which >= 0 && which < (int) (sizeof (fns)/sizeof (*fns)));
252b5132
RH
4457
4458 if (ECOFF_DEBUGGING)
bc805888 4459 (*fns[which]) (0);
252b5132
RH
4460 else
4461 {
4462 as_bad (_("ECOFF debugging is disabled."));
4463 ignore_rest_of_line ();
4464 }
4465}
4466#endif /* OBJ_ELF */
4467
4468#ifdef OBJ_EVAX
1dab94dd 4469
252b5132 4470/* Handle the section specific pseudo-op. */
1dab94dd 4471
252b5132
RH
4472static void
4473s_alpha_section (secid)
4474 int secid;
4475{
4476 int temp;
4477#define EVAX_SECTION_COUNT 5
66498417 4478 static char *section_name[EVAX_SECTION_COUNT + 1] =
252b5132
RH
4479 { "NULL", ".rdata", ".comm", ".link", ".ctors", ".dtors" };
4480
4481 if ((secid <= 0) || (secid > EVAX_SECTION_COUNT))
4482 {
4483 as_fatal (_("Unknown section directive"));
4484 demand_empty_rest_of_line ();
4485 return;
4486 }
4487 temp = get_absolute_expression ();
4488 subseg_new (section_name[secid], 0);
4489 demand_empty_rest_of_line ();
4490 alpha_insn_label = NULL;
4491 alpha_auto_align_on = 1;
4492 alpha_current_align = 0;
4493}
4494
252b5132
RH
4495/* Parse .ent directives. */
4496
4497static void
4498s_alpha_ent (ignore)
4499 int ignore;
4500{
4501 symbolS *symbol;
4502 expressionS symexpr;
4503
4504 alpha_evax_proc.pdsckind = 0;
4505 alpha_evax_proc.framereg = -1;
4506 alpha_evax_proc.framesize = 0;
4507 alpha_evax_proc.rsa_offset = 0;
4508 alpha_evax_proc.ra_save = AXP_REG_RA;
4509 alpha_evax_proc.fp_save = -1;
4510 alpha_evax_proc.imask = 0;
4511 alpha_evax_proc.fmask = 0;
4512 alpha_evax_proc.prologue = 0;
4513 alpha_evax_proc.type = 0;
4514
4515 expression (&symexpr);
4516
4517 if (symexpr.X_op != O_symbol)
4518 {
4519 as_fatal (_(".ent directive has no symbol"));
4520 demand_empty_rest_of_line ();
4521 return;
4522 }
4523
4524 symbol = make_expr_symbol (&symexpr);
9de8d8f1 4525 symbol_get_bfdsym (symbol)->flags |= BSF_FUNCTION;
252b5132
RH
4526 alpha_evax_proc.symbol = symbol;
4527
4528 demand_empty_rest_of_line ();
4529 return;
4530}
4531
252b5132
RH
4532/* Parse .frame <framreg>,<framesize>,RA,<rsa_offset> directives. */
4533
4534static void
4535s_alpha_frame (ignore)
4536 int ignore;
4537{
4538 long val;
4539
4540 alpha_evax_proc.framereg = tc_get_register (1);
4541
4542 SKIP_WHITESPACE ();
4543 if (*input_line_pointer++ != ','
4544 || get_absolute_expression_and_terminator (&val) != ',')
4545 {
4546 as_warn (_("Bad .frame directive 1./2. param"));
4547 --input_line_pointer;
4548 demand_empty_rest_of_line ();
4549 return;
4550 }
4551
4552 alpha_evax_proc.framesize = val;
4553
4554 (void) tc_get_register (1);
4555 SKIP_WHITESPACE ();
4556 if (*input_line_pointer++ != ',')
4557 {
4558 as_warn (_("Bad .frame directive 3./4. param"));
4559 --input_line_pointer;
4560 demand_empty_rest_of_line ();
4561 return;
4562 }
4563 alpha_evax_proc.rsa_offset = get_absolute_expression ();
4564
4565 return;
4566}
4567
4568static void
4569s_alpha_pdesc (ignore)
4570 int ignore;
4571{
4572 char *name;
4573 char name_end;
4574 long val;
4575 register char *p;
4576 expressionS exp;
4577 symbolS *entry_sym;
4578 fixS *fixp;
4579 segment_info_type *seginfo = seg_info (alpha_link_section);
4580
4581 if (now_seg != alpha_link_section)
4582 {
4583 as_bad (_(".pdesc directive not in link (.link) section"));
4584 demand_empty_rest_of_line ();
4585 return;
4586 }
4587
4588 if ((alpha_evax_proc.symbol == 0)
4589 || (!S_IS_DEFINED (alpha_evax_proc.symbol)))
4590 {
4591 as_fatal (_(".pdesc has no matching .ent"));
4592 demand_empty_rest_of_line ();
4593 return;
4594 }
4595
7dcc9865
ILT
4596 *symbol_get_obj (alpha_evax_proc.symbol) =
4597 (valueT) seginfo->literal_pool_size;
252b5132
RH
4598
4599 expression (&exp);
4600 if (exp.X_op != O_symbol)
4601 {
4602 as_warn (_(".pdesc directive has no entry symbol"));
4603 demand_empty_rest_of_line ();
4604 return;
4605 }
4606
4607 entry_sym = make_expr_symbol (&exp);
4608 /* Save bfd symbol of proc desc in function symbol. */
9de8d8f1
RH
4609 symbol_get_bfdsym (alpha_evax_proc.symbol)->udata.p
4610 = symbol_get_bfdsym (entry_sym);
252b5132
RH
4611
4612 SKIP_WHITESPACE ();
4613 if (*input_line_pointer++ != ',')
4614 {
4615 as_warn (_("No comma after .pdesc <entryname>"));
4616 demand_empty_rest_of_line ();
4617 return;
4618 }
4619
4620 SKIP_WHITESPACE ();
4621 name = input_line_pointer;
4622 name_end = get_symbol_end ();
4623
32ff5c2e 4624 if (strncmp (name, "stack", 5) == 0)
252b5132
RH
4625 {
4626 alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_STACK;
4627 }
32ff5c2e 4628 else if (strncmp (name, "reg", 3) == 0)
252b5132
RH
4629 {
4630 alpha_evax_proc.pdsckind = PDSC_S_K_KIND_FP_REGISTER;
4631 }
32ff5c2e 4632 else if (strncmp (name, "null", 4) == 0)
252b5132
RH
4633 {
4634 alpha_evax_proc.pdsckind = PDSC_S_K_KIND_NULL;
4635 }
4636 else
4637 {
4638 as_fatal (_("unknown procedure kind"));
4639 demand_empty_rest_of_line ();
4640 return;
4641 }
4642
4643 *input_line_pointer = name_end;
4644 demand_empty_rest_of_line ();
4645
4646#ifdef md_flush_pending_output
4647 md_flush_pending_output ();
4648#endif
4649
4650 frag_align (3, 0, 0);
4651 p = frag_more (16);
4652 fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
4653 fixp->fx_done = 1;
4654 seginfo->literal_pool_size += 16;
4655
4656 *p = alpha_evax_proc.pdsckind
1aad8cf8 4657 | ((alpha_evax_proc.framereg == 29) ? PDSC_S_M_BASE_REG_IS_FP : 0);
66498417 4658 *(p + 1) = PDSC_S_M_NATIVE | PDSC_S_M_NO_JACKET;
252b5132
RH
4659
4660 switch (alpha_evax_proc.pdsckind)
4661 {
1aad8cf8 4662 case PDSC_S_K_KIND_NULL:
66498417
KH
4663 *(p + 2) = 0;
4664 *(p + 3) = 0;
1aad8cf8
KH
4665 break;
4666 case PDSC_S_K_KIND_FP_REGISTER:
66498417
KH
4667 *(p + 2) = alpha_evax_proc.fp_save;
4668 *(p + 3) = alpha_evax_proc.ra_save;
1aad8cf8
KH
4669 break;
4670 case PDSC_S_K_KIND_FP_STACK:
66498417 4671 md_number_to_chars (p + 2, (valueT) alpha_evax_proc.rsa_offset, 2);
1aad8cf8
KH
4672 break;
4673 default: /* impossible */
4674 break;
252b5132
RH
4675 }
4676
66498417
KH
4677 *(p + 4) = 0;
4678 *(p + 5) = alpha_evax_proc.type & 0x0f;
252b5132
RH
4679
4680 /* Signature offset. */
66498417 4681 md_number_to_chars (p + 6, (valueT) 0, 2);
252b5132 4682
66498417 4683 fix_new_exp (frag_now, p - frag_now->fr_literal+8, 8, &exp, 0, BFD_RELOC_64);
252b5132
RH
4684
4685 if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_NULL)
4686 return;
4687
4688 /* Add dummy fix to make add_to_link_pool work. */
4689 p = frag_more (8);
4690 fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
4691 fixp->fx_done = 1;
4692 seginfo->literal_pool_size += 8;
4693
4694 /* pdesc+16: Size. */
32ff5c2e 4695 md_number_to_chars (p, (valueT) alpha_evax_proc.framesize, 4);
252b5132 4696
66498417 4697 md_number_to_chars (p + 4, (valueT) 0, 2);
252b5132
RH
4698
4699 /* Entry length. */
66498417 4700 md_number_to_chars (p + 6, alpha_evax_proc.prologue, 2);
252b5132
RH
4701
4702 if (alpha_evax_proc.pdsckind == PDSC_S_K_KIND_FP_REGISTER)
4703 return;
4704
4705 /* Add dummy fix to make add_to_link_pool work. */
4706 p = frag_more (8);
4707 fixp = fix_new (frag_now, p - frag_now->fr_literal, 8, 0, 0, 0, 0);
4708 fixp->fx_done = 1;
4709 seginfo->literal_pool_size += 8;
4710
4711 /* pdesc+24: register masks. */
4712
4713 md_number_to_chars (p, alpha_evax_proc.imask, 4);
66498417 4714 md_number_to_chars (p + 4, alpha_evax_proc.fmask, 4);
252b5132
RH
4715
4716 return;
4717}
4718
252b5132
RH
4719/* Support for crash debug on vms. */
4720
4721static void
4722s_alpha_name (ignore)
4723 int ignore;
4724{
4725 register char *p;
4726 expressionS exp;
4727 segment_info_type *seginfo = seg_info (alpha_link_section);
4728
4729 if (now_seg != alpha_link_section)
4730 {
4731 as_bad (_(".name directive not in link (.link) section"));
4732 demand_empty_rest_of_line ();
4733 return;
4734 }
4735
4736 expression (&exp);
4737 if (exp.X_op != O_symbol)
4738 {
4739 as_warn (_(".name directive has no symbol"));
4740 demand_empty_rest_of_line ();
4741 return;
4742 }
4743
4744 demand_empty_rest_of_line ();
4745
4746#ifdef md_flush_pending_output
4747 md_flush_pending_output ();
4748#endif
4749
4750 frag_align (3, 0, 0);
4751 p = frag_more (8);
4752 seginfo->literal_pool_size += 8;
4753
66498417 4754 fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0, BFD_RELOC_64);
252b5132
RH
4755
4756 return;
4757}
4758
252b5132
RH
4759static void
4760s_alpha_linkage (ignore)
4761 int ignore;
4762{
4763 expressionS exp;
4764 char *p;
4765
4766#ifdef md_flush_pending_output
4767 md_flush_pending_output ();
4768#endif
4769
4770 expression (&exp);
4771 if (exp.X_op != O_symbol)
4772 {
4773 as_fatal (_("No symbol after .linkage"));
4774 }
4775 else
4776 {
4777 p = frag_more (LKP_S_K_SIZE);
4778 memset (p, 0, LKP_S_K_SIZE);
4779 fix_new_exp (frag_now, p - frag_now->fr_literal, LKP_S_K_SIZE, &exp, 0,\
4780 BFD_RELOC_ALPHA_LINKAGE);
4781 }
4782 demand_empty_rest_of_line ();
4783
4784 return;
4785}
4786
252b5132
RH
4787static void
4788s_alpha_code_address (ignore)
4789 int ignore;
4790{
4791 expressionS exp;
4792 char *p;
4793
4794#ifdef md_flush_pending_output
4795 md_flush_pending_output ();
4796#endif
4797
4798 expression (&exp);
4799 if (exp.X_op != O_symbol)
4800 {
4801 as_fatal (_("No symbol after .code_address"));
4802 }
4803 else
4804 {
4805 p = frag_more (8);
4806 memset (p, 0, 8);
4807 fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &exp, 0,\
4808 BFD_RELOC_ALPHA_CODEADDR);
4809 }
4810 demand_empty_rest_of_line ();
4811
4812 return;
4813}
4814
252b5132
RH
4815static void
4816s_alpha_fp_save (ignore)
4817 int ignore;
4818{
4819
4820 alpha_evax_proc.fp_save = tc_get_register (1);
4821
4822 demand_empty_rest_of_line ();
4823 return;
4824}
4825
252b5132
RH
4826static void
4827s_alpha_mask (ignore)
4828 int ignore;
4829{
4830 long val;
4831
4832 if (get_absolute_expression_and_terminator (&val) != ',')
4833 {
4834 as_warn (_("Bad .mask directive"));
4835 --input_line_pointer;
4836 }
4837 else
4838 {
4839 alpha_evax_proc.imask = val;
32ff5c2e 4840 (void) get_absolute_expression ();
252b5132
RH
4841 }
4842 demand_empty_rest_of_line ();
4843
4844 return;
4845}
4846
252b5132
RH
4847static void
4848s_alpha_fmask (ignore)
4849 int ignore;
4850{
4851 long val;
4852
4853 if (get_absolute_expression_and_terminator (&val) != ',')
4854 {
4855 as_warn (_("Bad .fmask directive"));
4856 --input_line_pointer;
4857 }
4858 else
4859 {
4860 alpha_evax_proc.fmask = val;
4861 (void) get_absolute_expression ();
4862 }
4863 demand_empty_rest_of_line ();
4864
4865 return;
4866}
4867
4868static void
4869s_alpha_end (ignore)
4870 int ignore;
4871{
4872 char c;
4873
4874 c = get_symbol_end ();
4875 *input_line_pointer = c;
4876 demand_empty_rest_of_line ();
4877 alpha_evax_proc.symbol = 0;
4878
4879 return;
4880}
4881
252b5132
RH
4882static void
4883s_alpha_file (ignore)
4884 int ignore;
4885{
4886 symbolS *s;
4887 int length;
4888 static char case_hack[32];
4889
4890 extern char *demand_copy_string PARAMS ((int *lenP));
4891
4892 sprintf (case_hack, "<CASE:%01d%01d>",
9de8d8f1 4893 alpha_flag_hash_long_names, alpha_flag_show_after_trunc);
252b5132
RH
4894
4895 s = symbol_find_or_make (case_hack);
9de8d8f1 4896 symbol_get_bfdsym (s)->flags |= BSF_FILE;
252b5132
RH
4897
4898 get_absolute_expression ();
4899 s = symbol_find_or_make (demand_copy_string (&length));
9de8d8f1 4900 symbol_get_bfdsym (s)->flags |= BSF_FILE;
252b5132
RH
4901 demand_empty_rest_of_line ();
4902
4903 return;
4904}
4905#endif /* OBJ_EVAX */
4906
4907/* Handle the .gprel32 pseudo op. */
4908
4909static void
4910s_alpha_gprel32 (ignore)
446a06c9 4911 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
4912{
4913 expressionS e;
4914 char *p;
4915
4916 SKIP_WHITESPACE ();
4917 expression (&e);
4918
4919#ifdef OBJ_ELF
4920 switch (e.X_op)
4921 {
4922 case O_constant:
32ff5c2e 4923 e.X_add_symbol = section_symbol (absolute_section);
252b5132
RH
4924 e.X_op = O_symbol;
4925 /* FALLTHRU */
4926 case O_symbol:
4927 break;
4928 default:
bc805888 4929 abort ();
252b5132
RH
4930 }
4931#else
4932#ifdef OBJ_ECOFF
4933 switch (e.X_op)
4934 {
4935 case O_constant:
4936 e.X_add_symbol = section_symbol (absolute_section);
4937 /* fall through */
4938 case O_symbol:
4939 e.X_op = O_subtract;
4940 e.X_op_symbol = alpha_gp_symbol;
4941 break;
4942 default:
4943 abort ();
4944 }
4945#endif
4946#endif
4947
4948 if (alpha_auto_align_on && alpha_current_align < 2)
4949 alpha_align (2, (char *) NULL, alpha_insn_label, 0);
4950 if (alpha_current_align > 2)
4951 alpha_current_align = 2;
4952 alpha_insn_label = NULL;
4953
4954 p = frag_more (4);
4955 memset (p, 0, 4);
66498417 4956 fix_new_exp (frag_now, p - frag_now->fr_literal, 4,
252b5132
RH
4957 &e, 0, BFD_RELOC_GPREL32);
4958}
4959
4960/* Handle floating point allocation pseudo-ops. This is like the
4961 generic vresion, but it makes sure the current label, if any, is
4962 correctly aligned. */
4963
4964static void
4965s_alpha_float_cons (type)
4966 int type;
4967{
4968 int log_size;
4969
4970 switch (type)
4971 {
4972 default:
4973 case 'f':
4974 case 'F':
4975 log_size = 2;
4976 break;
4977
4978 case 'd':
4979 case 'D':
4980 case 'G':
4981 log_size = 3;
4982 break;
4983
4984 case 'x':
4985 case 'X':
4986 case 'p':
4987 case 'P':
4988 log_size = 4;
4989 break;
4990 }
4991
4992 if (alpha_auto_align_on && alpha_current_align < log_size)
4993 alpha_align (log_size, (char *) NULL, alpha_insn_label, 0);
4994 if (alpha_current_align > log_size)
4995 alpha_current_align = log_size;
4996 alpha_insn_label = NULL;
4997
4998 float_cons (type);
4999}
5000
5001/* Handle the .proc pseudo op. We don't really do much with it except
5002 parse it. */
5003
5004static void
5005s_alpha_proc (is_static)
446a06c9 5006 int is_static ATTRIBUTE_UNUSED;
252b5132
RH
5007{
5008 char *name;
5009 char c;
5010 char *p;
5011 symbolS *symbolP;
5012 int temp;
5013
5014 /* Takes ".proc name,nargs" */
5015 SKIP_WHITESPACE ();
5016 name = input_line_pointer;
5017 c = get_symbol_end ();
5018 p = input_line_pointer;
5019 symbolP = symbol_find_or_make (name);
5020 *p = c;
5021 SKIP_WHITESPACE ();
5022 if (*input_line_pointer != ',')
5023 {
5024 *p = 0;
5025 as_warn (_("Expected comma after name \"%s\""), name);
5026 *p = c;
5027 temp = 0;
5028 ignore_rest_of_line ();
5029 }
5030 else
5031 {
5032 input_line_pointer++;
5033 temp = get_absolute_expression ();
5034 }
7dcc9865 5035 /* *symbol_get_obj (symbolP) = (signed char) temp; */
252b5132
RH
5036 as_warn (_("unhandled: .proc %s,%d"), name, temp);
5037 demand_empty_rest_of_line ();
5038}
5039
5040/* Handle the .set pseudo op. This is used to turn on and off most of
5041 the assembler features. */
5042
5043static void
5044s_alpha_set (x)
446a06c9 5045 int x ATTRIBUTE_UNUSED;
252b5132
RH
5046{
5047 char *name, ch, *s;
5048 int yesno = 1;
5049
5050 SKIP_WHITESPACE ();
5051 name = input_line_pointer;
5052 ch = get_symbol_end ();
5053
5054 s = name;
5055 if (s[0] == 'n' && s[1] == 'o')
5056 {
5057 yesno = 0;
5058 s += 2;
5059 }
5060 if (!strcmp ("reorder", s))
5061 /* ignore */ ;
5062 else if (!strcmp ("at", s))
5063 alpha_noat_on = !yesno;
5064 else if (!strcmp ("macro", s))
5065 alpha_macros_on = yesno;
5066 else if (!strcmp ("move", s))
5067 /* ignore */ ;
5068 else if (!strcmp ("volatile", s))
5069 /* ignore */ ;
5070 else
5071 as_warn (_("Tried to .set unrecognized mode `%s'"), name);
5072
5073 *input_line_pointer = ch;
5074 demand_empty_rest_of_line ();
5075}
5076
5077/* Handle the .base pseudo op. This changes the assembler's notion of
5078 the $gp register. */
5079
5080static void
5081s_alpha_base (ignore)
446a06c9 5082 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5083{
5084#if 0
5085 if (first_32bit_quadrant)
5086 {
5087 /* not fatal, but it might not work in the end */
5088 as_warn (_("File overrides no-base-register option."));
5089 first_32bit_quadrant = 0;
5090 }
5091#endif
5092
5093 SKIP_WHITESPACE ();
5094 if (*input_line_pointer == '$')
5095 { /* $rNN form */
5096 input_line_pointer++;
5097 if (*input_line_pointer == 'r')
5098 input_line_pointer++;
5099 }
5100
5101 alpha_gp_register = get_absolute_expression ();
5102 if (alpha_gp_register < 0 || alpha_gp_register > 31)
5103 {
5104 alpha_gp_register = AXP_REG_GP;
5105 as_warn (_("Bad base register, using $%d."), alpha_gp_register);
5106 }
5107
5108 demand_empty_rest_of_line ();
5109}
5110
5111/* Handle the .align pseudo-op. This aligns to a power of two. It
5112 also adjusts any current instruction label. We treat this the same
5113 way the MIPS port does: .align 0 turns off auto alignment. */
5114
5115static void
5116s_alpha_align (ignore)
446a06c9 5117 int ignore ATTRIBUTE_UNUSED;
252b5132
RH
5118{
5119 int align;
5120 char fill, *pfill;
5121 long max_alignment = 15;
5122
5123 align = get_absolute_expression ();
5124 if (align > max_alignment)
5125 {
5126 align = max_alignment;
5127 as_bad (_("Alignment too large: %d. assumed"), align);
5128 }
5129 else if (align < 0)
5130 {
5131 as_warn (_("Alignment negative: 0 assumed"));
5132 align = 0;
5133 }
5134
5135 if (*input_line_pointer == ',')
5136 {
5137 input_line_pointer++;
5138 fill = get_absolute_expression ();
5139 pfill = &fill;
5140 }
5141 else
5142 pfill = NULL;
5143
5144 if (align != 0)
5145 {
5146 alpha_auto_align_on = 1;
5147 alpha_align (align, pfill, alpha_insn_label, 1);
5148 }
5149 else
5150 {
5151 alpha_auto_align_on = 0;
5152 }
5153
5154 demand_empty_rest_of_line ();
5155}
5156
5157/* Hook the normal string processor to reset known alignment. */
5158
5159static void
5160s_alpha_stringer (terminate)
5161 int terminate;
5162{
5163 alpha_current_align = 0;
5164 alpha_insn_label = NULL;
5165 stringer (terminate);
5166}
5167
5168/* Hook the normal space processing to reset known alignment. */
5169
5170static void
5171s_alpha_space (ignore)
5172 int ignore;
5173{
5174 alpha_current_align = 0;
5175 alpha_insn_label = NULL;
5176 s_space (ignore);
5177}
5178
5179/* Hook into cons for auto-alignment. */
5180
5181void
5182alpha_cons_align (size)
5183 int size;
5184{
5185 int log_size;
5186
5187 log_size = 0;
5188 while ((size >>= 1) != 0)
5189 ++log_size;
5190
5191 if (alpha_auto_align_on && alpha_current_align < log_size)
5192 alpha_align (log_size, (char *) NULL, alpha_insn_label, 0);
5193 if (alpha_current_align > log_size)
5194 alpha_current_align = log_size;
5195 alpha_insn_label = NULL;
5196}
5197
5198/* Here come the .uword, .ulong, and .uquad explicitly unaligned
5199 pseudos. We just turn off auto-alignment and call down to cons. */
5200
5201static void
5202s_alpha_ucons (bytes)
5203 int bytes;
5204{
5205 int hold = alpha_auto_align_on;
5206 alpha_auto_align_on = 0;
5207 cons (bytes);
5208 alpha_auto_align_on = hold;
5209}
5210
5211/* Switch the working cpu type. */
5212
5213static void
5214s_alpha_arch (ignored)
446a06c9 5215 int ignored ATTRIBUTE_UNUSED;
252b5132
RH
5216{
5217 char *name, ch;
5218 const struct cpu_type *p;
5219
5220 SKIP_WHITESPACE ();
5221 name = input_line_pointer;
5222 ch = get_symbol_end ();
5223
5224 for (p = cpu_types; p->name; ++p)
32ff5c2e 5225 if (strcmp (name, p->name) == 0)
252b5132 5226 {
1aad8cf8 5227 alpha_target_name = p->name, alpha_target = p->flags;
252b5132
RH
5228 goto found;
5229 }
32ff5c2e 5230 as_warn ("Unknown CPU identifier `%s'", name);
252b5132
RH
5231
5232found:
5233 *input_line_pointer = ch;
5234 demand_empty_rest_of_line ();
5235}
252b5132 5236\f
252b5132
RH
5237#ifdef DEBUG1
5238/* print token expression with alpha specific extension. */
5239
5240static void
32ff5c2e 5241alpha_print_token (f, exp)
1aad8cf8
KH
5242 FILE *f;
5243 const expressionS *exp;
252b5132
RH
5244{
5245 switch (exp->X_op)
5246 {
1aad8cf8
KH
5247 case O_cpregister:
5248 putc (',', f);
5249 /* FALLTHRU */
5250 case O_pregister:
5251 putc ('(', f);
5252 {
5253 expressionS nexp = *exp;
5254 nexp.X_op = O_register;
5255 print_expr (f, &nexp);
5256 }
5257 putc (')', f);
5258 break;
5259 default:
5260 print_expr (f, exp);
5261 break;
252b5132
RH
5262 }
5263 return;
5264}
5265#endif
5266\f
5267/* The target specific pseudo-ops which we support. */
5268
66498417 5269const pseudo_typeS md_pseudo_table[] = {
252b5132
RH
5270#ifdef OBJ_ECOFF
5271 {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */
5272 {"rdata", s_alpha_rdata, 0},
5273#endif
5274 {"text", s_alpha_text, 0},
5275 {"data", s_alpha_data, 0},
5276#ifdef OBJ_ECOFF
5277 {"sdata", s_alpha_sdata, 0},
5278#endif
5279#ifdef OBJ_ELF
5280 {"section", s_alpha_section, 0},
5281 {"section.s", s_alpha_section, 0},
5282 {"sect", s_alpha_section, 0},
5283 {"sect.s", s_alpha_section, 0},
5284#endif
5285#ifdef OBJ_EVAX
5286 { "pdesc", s_alpha_pdesc, 0},
5287 { "name", s_alpha_name, 0},
5288 { "linkage", s_alpha_linkage, 0},
5289 { "code_address", s_alpha_code_address, 0},
5290 { "ent", s_alpha_ent, 0},
5291 { "frame", s_alpha_frame, 0},
5292 { "fp_save", s_alpha_fp_save, 0},
5293 { "mask", s_alpha_mask, 0},
5294 { "fmask", s_alpha_fmask, 0},
5295 { "end", s_alpha_end, 0},
5296 { "file", s_alpha_file, 0},
5297 { "rdata", s_alpha_section, 1},
5298 { "comm", s_alpha_comm, 0},
5299 { "link", s_alpha_section, 3},
5300 { "ctors", s_alpha_section, 4},
5301 { "dtors", s_alpha_section, 5},
5302#endif
5303#ifdef OBJ_ELF
5304 /* Frame related pseudos. */
5305 {"ent", s_alpha_ent, 0},
5306 {"end", s_alpha_end, 0},
5307 {"mask", s_alpha_mask, 0},
5308 {"fmask", s_alpha_mask, 1},
5309 {"frame", s_alpha_frame, 0},
5310 {"prologue", s_alpha_prologue, 0},
4dc7ead9
RH
5311 {"file", s_alpha_file, 5},
5312 {"loc", s_alpha_loc, 9},
a8316fe2
RH
5313 {"stabs", s_alpha_stab, 's'},
5314 {"stabn", s_alpha_stab, 'n'},
252b5132
RH
5315 /* COFF debugging related pseudos. */
5316 {"begin", s_alpha_coff_wrapper, 0},
5317 {"bend", s_alpha_coff_wrapper, 1},
5318 {"def", s_alpha_coff_wrapper, 2},
5319 {"dim", s_alpha_coff_wrapper, 3},
5320 {"endef", s_alpha_coff_wrapper, 4},
4dc7ead9
RH
5321 {"scl", s_alpha_coff_wrapper, 5},
5322 {"tag", s_alpha_coff_wrapper, 6},
5323 {"val", s_alpha_coff_wrapper, 7},
252b5132
RH
5324#else
5325 {"prologue", s_ignore, 0},
5326#endif
5327 {"gprel32", s_alpha_gprel32, 0},
5328 {"t_floating", s_alpha_float_cons, 'd'},
5329 {"s_floating", s_alpha_float_cons, 'f'},
5330 {"f_floating", s_alpha_float_cons, 'F'},
5331 {"g_floating", s_alpha_float_cons, 'G'},
5332 {"d_floating", s_alpha_float_cons, 'D'},
5333
5334 {"proc", s_alpha_proc, 0},
5335 {"aproc", s_alpha_proc, 1},
5336 {"set", s_alpha_set, 0},
5337 {"reguse", s_ignore, 0},
5338 {"livereg", s_ignore, 0},
5339 {"base", s_alpha_base, 0}, /*??*/
5340 {"option", s_ignore, 0},
5341 {"aent", s_ignore, 0},
5342 {"ugen", s_ignore, 0},
5343 {"eflag", s_ignore, 0},
5344
5345 {"align", s_alpha_align, 0},
5346 {"double", s_alpha_float_cons, 'd'},
5347 {"float", s_alpha_float_cons, 'f'},
5348 {"single", s_alpha_float_cons, 'f'},
5349 {"ascii", s_alpha_stringer, 0},
5350 {"asciz", s_alpha_stringer, 1},
5351 {"string", s_alpha_stringer, 1},
5352 {"space", s_alpha_space, 0},
5353 {"skip", s_alpha_space, 0},
5354 {"zero", s_alpha_space, 0},
5355
5356/* Unaligned data pseudos. */
5357 {"uword", s_alpha_ucons, 2},
5358 {"ulong", s_alpha_ucons, 4},
5359 {"uquad", s_alpha_ucons, 8},
5360
5361#ifdef OBJ_ELF
5362/* Dwarf wants these versions of unaligned. */
5363 {"2byte", s_alpha_ucons, 2},
5364 {"4byte", s_alpha_ucons, 4},
5365 {"8byte", s_alpha_ucons, 8},
5366#endif
5367
5368/* We don't do any optimizing, so we can safely ignore these. */
5369 {"noalias", s_ignore, 0},
5370 {"alias", s_ignore, 0},
5371
5372 {"arch", s_alpha_arch, 0},
5373
5374 {NULL, 0, 0},
5375};
252b5132
RH
5376\f
5377/* Build a BFD section with its flags set appropriately for the .lita,
5378 .lit8, or .lit4 sections. */
5379
5380static void
5381create_literal_section (name, secp, symp)
5382 const char *name;
5383 segT *secp;
5384 symbolS **symp;
5385{
5386 segT current_section = now_seg;
5387 int current_subsec = now_subseg;
5388 segT new_sec;
5389
5390 *secp = new_sec = subseg_new (name, 0);
5391 subseg_set (current_section, current_subsec);
5392 bfd_set_section_alignment (stdoutput, new_sec, 4);
5393 bfd_set_section_flags (stdoutput, new_sec,
5394 SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY
5395 | SEC_DATA);
5396
5397 S_CLEAR_EXTERNAL (*symp = section_symbol (new_sec));
5398}
5399
5400#ifdef OBJ_ECOFF
5401
5402/* @@@ GP selection voodoo. All of this seems overly complicated and
5403 unnecessary; which is the primary reason it's for ECOFF only. */
5404
5405static inline void
5406maybe_set_gp (sec)
5407 asection *sec;
5408{
5409 bfd_vma vma;
5410 if (!sec)
5411 return;
5412 vma = bfd_get_section_vma (foo, sec);
5413 if (vma && vma < alpha_gp_value)
5414 alpha_gp_value = vma;
5415}
5416
5417static void
5418select_gp_value ()
5419{
5420 assert (alpha_gp_value == 0);
5421
5422 /* Get minus-one in whatever width... */
66498417
KH
5423 alpha_gp_value = 0;
5424 alpha_gp_value--;
252b5132
RH
5425
5426 /* Select the smallest VMA of these existing sections. */
5427 maybe_set_gp (alpha_lita_section);
5428#if 0
5429 /* These were disabled before -- should we use them? */
5430 maybe_set_gp (sdata);
5431 maybe_set_gp (lit8_sec);
5432 maybe_set_gp (lit4_sec);
5433#endif
5434
5435/* @@ Will a simple 0x8000 work here? If not, why not? */
5436#define GP_ADJUSTMENT (0x8000 - 0x10)
5437
5438 alpha_gp_value += GP_ADJUSTMENT;
5439
5440 S_SET_VALUE (alpha_gp_symbol, alpha_gp_value);
5441
5442#ifdef DEBUG1
5443 printf (_("Chose GP value of %lx\n"), alpha_gp_value);
5444#endif
5445}
5446#endif /* OBJ_ECOFF */
5447
d61a78a7
RH
5448#ifdef OBJ_ELF
5449/* Map 's' to SHF_ALPHA_GPREL. */
5450
5451int
5452alpha_elf_section_letter (letter, ptr_msg)
5453 int letter;
5454 char **ptr_msg;
5455{
5456 if (letter == 's')
5457 return SHF_ALPHA_GPREL;
5458
5459 *ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string");
5460 return 0;
5461}
5462
5463/* Map SHF_ALPHA_GPREL to SEC_SMALL_DATA. */
5464
5465flagword
5466alpha_elf_section_flags (flags, attr, type)
5467 flagword flags;
5468 int attr, type ATTRIBUTE_UNUSED;
5469{
5470 if (attr & SHF_ALPHA_GPREL)
5471 flags |= SEC_SMALL_DATA;
5472 return flags;
5473}
5474#endif /* OBJ_ELF */
5475
252b5132
RH
5476/* Called internally to handle all alignment needs. This takes care
5477 of eliding calls to frag_align if'n the cached current alignment
5478 says we've already got it, as well as taking care of the auto-align
5479 feature wrt labels. */
5480
5481static void
5482alpha_align (n, pfill, label, force)
5483 int n;
5484 char *pfill;
5485 symbolS *label;
446a06c9 5486 int force ATTRIBUTE_UNUSED;
252b5132
RH
5487{
5488 if (alpha_current_align >= n)
5489 return;
5490
5491 if (pfill == NULL)
5492 {
0a9ef439
RH
5493 if (subseg_text_p (now_seg))
5494 frag_align_code (n, 0);
252b5132
RH
5495 else
5496 frag_align (n, 0, 0);
5497 }
5498 else
5499 frag_align (n, *pfill, 0);
5500
5501 alpha_current_align = n;
5502
98007ce7 5503 if (label != NULL && S_GET_SEGMENT (label) == now_seg)
252b5132 5504 {
49309057 5505 symbol_set_frag (label, frag_now);
252b5132
RH
5506 S_SET_VALUE (label, (valueT) frag_now_fix ());
5507 }
5508
98007ce7 5509 record_alignment (now_seg, n);
252b5132 5510
0a9ef439 5511 /* ??? If alpha_flag_relax && force && elf, record the requested alignment
252b5132
RH
5512 in a reloc for the linker to see. */
5513}
5514
0a9ef439
RH
5515/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
5516 of an rs_align_code fragment. */
5517
bfb32b52 5518void
0a9ef439
RH
5519alpha_handle_align (fragp)
5520 fragS *fragp;
5521{
84b229ef 5522 static char const unop[4] = { 0x00, 0x00, 0xfe, 0x2f };
0a9ef439 5523 static char const nopunop[8] = {
1aad8cf8 5524 0x1f, 0x04, 0xff, 0x47,
84b229ef 5525 0x00, 0x00, 0xfe, 0x2f
0a9ef439
RH
5526 };
5527
5528 int bytes, fix;
5529 char *p;
5530
5531 if (fragp->fr_type != rs_align_code)
5532 return;
5533
5534 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
5535 p = fragp->fr_literal + fragp->fr_fix;
5536 fix = 0;
5537
5538 if (bytes & 3)
5539 {
5540 fix = bytes & 3;
5541 memset (p, 0, fix);
5542 p += fix;
5543 bytes -= fix;
5544 }
5545
5546 if (bytes & 4)
5547 {
5548 memcpy (p, unop, 4);
5549 p += 4;
5550 bytes -= 4;
5551 fix += 4;
5552 }
5553
5554 memcpy (p, nopunop, 8);
5555
5556 fragp->fr_fix += fix;
5557 fragp->fr_var = 8;
5558}
5559
252b5132
RH
5560/* The Alpha has support for some VAX floating point types, as well as for
5561 IEEE floating point. We consider IEEE to be the primary floating point
5562 format, and sneak in the VAX floating point support here. */
5563#define md_atof vax_md_atof
5564#include "config/atof-vax.c"
This page took 0.364844 seconds and 4 git commands to generate.