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