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