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