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