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