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