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