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