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