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