Commit | Line | Data |
---|---|---|
5749c497 KR |
1 | /* tc-alpha.c - Processor-specific code for the DEC Alpha CPU. |
2 | Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc. | |
3 | Contributed by Carnegie Mellon University, 1993. | |
4 | Written by Alessandro Forin, based on earlier gas-1.38 target CPU files. | |
5 | Modified by Ken Raeburn for gas-2.x and ECOFF support. | |
6 | ||
7 | This file is part of GAS, the GNU Assembler. | |
8 | ||
9 | GAS is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2, or (at your option) | |
12 | any later version. | |
13 | ||
14 | GAS is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with GAS; see the file COPYING. If not, write to | |
21 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
22 | ||
23 | /* | |
24 | * Mach Operating System | |
25 | * Copyright (c) 1993 Carnegie Mellon University | |
26 | * All Rights Reserved. | |
27 | * | |
28 | * Permission to use, copy, modify and distribute this software and its | |
29 | * documentation is hereby granted, provided that both the copyright | |
30 | * notice and this permission notice appear in all copies of the | |
31 | * software, derivative works or modified versions, and any portions | |
32 | * thereof, and that both notices appear in supporting documentation. | |
33 | * | |
34 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS | |
35 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
36 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
37 | * | |
38 | * Carnegie Mellon requests users of this software to return to | |
39 | * | |
40 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
41 | * School of Computer Science | |
42 | * Carnegie Mellon University | |
43 | * Pittsburgh PA 15213-3890 | |
44 | * | |
45 | * any improvements or extensions that they make and grant Carnegie the | |
46 | * rights to redistribute these changes. | |
47 | */ | |
48 | /* | |
49 | * HISTORY | |
50 | * 5-Oct-93 Alessandro Forin (af) at Carnegie-Mellon University | |
51 | * First Checkin | |
52 | * | |
5749c497 KR |
53 | * Author: Alessandro Forin, Carnegie Mellon University |
54 | * Date: Jan 1993 | |
55 | */ | |
56 | ||
a2a1a548 ILT |
57 | #include <ctype.h> |
58 | ||
5749c497 KR |
59 | #include "as.h" |
60 | #include "alpha-opcode.h" | |
61 | #include "subsegs.h" | |
62 | ||
30869211 KR |
63 | /* @@ Will a simple 0x8000 work here? If not, why not? */ |
64 | #define GP_ADJUSTMENT (0x8000 - 0x10) | |
65 | ||
0952861c KR |
66 | /* Which machine type is this? Currently stores an integer for the |
67 | model, one of: 21064, 21066, 21164. */ | |
68 | static unsigned long machine; | |
69 | ||
5749c497 KR |
70 | /* These are exported to relaxing code, even though we don't do any |
71 | relaxing on this processor currently. */ | |
72 | const relax_typeS md_relax_table[1]; | |
73 | int md_short_jump_size = 4; | |
74 | int md_long_jump_size = 4; | |
75 | ||
76 | /* handle of the OPCODE hash table */ | |
77 | static struct hash_control *op_hash; | |
78 | ||
40cd35ff KR |
79 | /* Sections and symbols we'll want to keep track of. */ |
80 | static segT lita_sec, rdata, sdata, lit8_sec, lit4_sec; | |
81 | static symbolS *lit8_sym, *lit4_sym; | |
5749c497 | 82 | |
40cd35ff | 83 | /* Setting for ".set [no]{at,macro}". */ |
5749c497 KR |
84 | static int at_ok = 1, macro_ok = 1; |
85 | ||
86 | /* Keep track of global pointer. */ | |
c79e67a3 | 87 | valueT alpha_gp_value; |
5749c497 KR |
88 | static symbolS *gp; |
89 | ||
90 | /* We'll probably be using this relocation frequently, and we | |
91 | will want to compare for it. */ | |
a2a1a548 | 92 | static const reloc_howto_type *gpdisp_hi16_howto; |
5749c497 KR |
93 | |
94 | /* These are exported to ECOFF code. */ | |
95 | unsigned long alpha_gprmask, alpha_fprmask; | |
96 | ||
97 | /* Used for LITUSE relocations. */ | |
98 | static expressionS lituse_basereg, lituse_byteoff, lituse_jsr; | |
99 | ||
cf272f02 KR |
100 | /* Address size: In OSF/1 1.3, an undocumented "-32addr" option will |
101 | cause all addresses to be treated as 32-bit values in memory. (The | |
102 | in-register versions are all sign-extended to 64 bits, of course.) | |
103 | Some other systems may want this option too. */ | |
104 | static int addr32; | |
105 | ||
5749c497 KR |
106 | /* Imported functions -- they should be defined in header files somewhere. */ |
107 | extern segT subseg_get (); | |
108 | extern PTR bfd_alloc_by_size_t (); | |
109 | extern void s_globl (), s_long (), s_short (), s_space (), cons (), s_text (), | |
110 | s_data (), float_cons (); | |
111 | ||
c79e67a3 | 112 | /* Static functions, needing forward declarations. */ |
a2a1a548 | 113 | static void s_base (), s_proc (), s_alpha_set (); |
5749c497 KR |
114 | static void s_gprel32 (), s_rdata (), s_sdata (), s_alpha_comm (); |
115 | static int alpha_ip (); | |
116 | ||
117 | const pseudo_typeS md_pseudo_table[] = | |
118 | { | |
119 | {"common", s_comm, 0}, /* is this used? */ | |
120 | {"comm", s_alpha_comm, 0}, /* osf1 compiler does this */ | |
121 | {"rdata", s_rdata, 0}, | |
122 | {"sdata", s_sdata, 0}, | |
123 | {"gprel32", s_gprel32, 0}, | |
124 | {"t_floating", float_cons, 'd'}, | |
125 | {"s_floating", float_cons, 'f'}, | |
126 | {"f_floating", float_cons, 'F'}, | |
127 | {"g_floating", float_cons, 'G'}, | |
128 | {"d_floating", float_cons, 'D'}, | |
129 | ||
130 | {"proc", s_proc, 0}, | |
131 | {"aproc", s_proc, 1}, | |
132 | {"set", s_alpha_set, 0}, | |
133 | {"reguse", s_ignore, 0}, | |
134 | {"livereg", s_ignore, 0}, | |
135 | {"extern", s_ignore, 0}, /*??*/ | |
136 | {"base", s_base, 0}, /*??*/ | |
137 | {"option", s_ignore, 0}, | |
138 | {"prologue", s_ignore, 0}, | |
139 | {"aent", s_ignore, 0}, | |
140 | {"ugen", s_ignore, 0}, | |
141 | ||
142 | /* We don't do any optimizing, so we can safely ignore these. */ | |
143 | {"noalias", s_ignore, 0}, | |
144 | {"alias", s_ignore, 0}, | |
145 | ||
146 | {NULL, 0, 0}, | |
147 | }; | |
148 | ||
149 | #define SA 21 /* shift for register Ra */ | |
150 | #define SB 16 /* shift for register Rb */ | |
151 | #define SC 0 /* shift for register Rc */ | |
152 | #define SN 13 /* shift for 8 bit immediate # */ | |
153 | ||
154 | #define T9 23 | |
155 | #define T10 24 | |
156 | #define T11 25 | |
0952861c KR |
157 | #define T12 26 |
158 | #define RA 26 /* note: same as T12 */ | |
5749c497 KR |
159 | #define PV 27 |
160 | #define AT 28 | |
161 | #define GP 29 | |
162 | #define SP 30 | |
163 | #define ZERO 31 | |
164 | ||
165 | #define OPCODE(X) (((X) >> 26) & 0x3f) | |
166 | #define OP_FCN(X) (((X) >> 5) & 0x7f) | |
167 | ||
168 | #ifndef FIRST_32BIT_QUADRANT | |
169 | #define FIRST_32BIT_QUADRANT 0 | |
170 | #endif | |
171 | ||
172 | int first_32bit_quadrant = FIRST_32BIT_QUADRANT; | |
173 | int base_register = FIRST_32BIT_QUADRANT ? ZERO : GP; | |
174 | ||
175 | int no_mixed_code = 0; | |
176 | int nofloats = 0; | |
177 | ||
178 | /* This array holds the chars that always start a comment. If the | |
179 | pre-processor is disabled, these aren't very useful */ | |
180 | const char comment_chars[] = "#"; | |
181 | ||
182 | /* This array holds the chars that only start a comment at the beginning of | |
183 | a line. If the line seems to have the form '# 123 filename' | |
184 | .line and .file directives will appear in the pre-processed output */ | |
185 | /* Note that input_file.c hand checks for '#' at the beginning of the | |
186 | first line of the input file. This is because the compiler outputs | |
187 | #NO_APP at the beginning of its output. */ | |
a2a1a548 | 188 | /* Also note that C style comments are always recognized. */ |
30869211 | 189 | const char line_comment_chars[] = "#!"; |
5749c497 KR |
190 | |
191 | /* Chars that can be used to separate mant from exp in floating point nums */ | |
192 | const char EXP_CHARS[] = "eE"; | |
193 | ||
194 | const char line_separator_chars[1]; | |
195 | ||
196 | /* Chars that mean this number is a floating point constant, as in | |
197 | "0f12.456" or "0d1.2345e12". */ | |
0952861c | 198 | /* @@ Do all of these really get used on the alpha?? */ |
5749c497 KR |
199 | char FLT_CHARS[] = "rRsSfFdDxXpP"; |
200 | ||
201 | /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be | |
202 | changed in read.c. Ideally it shouldn't have to know about it at all, | |
203 | but nothing is ideal around here. */ | |
204 | ||
205 | struct reloc_data { | |
206 | expressionS exp; | |
207 | int pcrel; | |
208 | bfd_reloc_code_real_type code; | |
209 | }; | |
210 | ||
211 | /* Occasionally, two relocations will be desired for one address. | |
212 | Mainly only in cases like "jsr $r,foo" where we want both a LITUSE | |
213 | and a HINT reloc. */ | |
214 | #define MAX_RELOCS 2 | |
215 | ||
216 | struct alpha_it { | |
217 | unsigned long opcode; /* need at least 32 bits */ | |
218 | struct reloc_data reloc[MAX_RELOCS]; | |
219 | }; | |
220 | ||
c79e67a3 | 221 | static void getExpression (char *str, struct alpha_it *insn); |
5749c497 KR |
222 | static char *expr_end; |
223 | ||
224 | #define note_gpreg(R) (alpha_gprmask |= (1 << (R))) | |
225 | #define note_fpreg(R) (alpha_fprmask |= (1 << (R))) | |
226 | ||
227 | int | |
228 | tc_get_register (frame) | |
229 | int frame; | |
230 | { | |
5749c497 KR |
231 | int framereg = SP; |
232 | ||
233 | SKIP_WHITESPACE (); | |
234 | if (*input_line_pointer == '$') | |
235 | { | |
236 | input_line_pointer++; | |
237 | if (input_line_pointer[0] == 's' | |
238 | && input_line_pointer[1] == 'p') | |
239 | { | |
240 | input_line_pointer += 2; | |
241 | framereg = SP; | |
242 | } | |
243 | else | |
244 | framereg = get_absolute_expression (); | |
245 | framereg &= 31; /* ? */ | |
246 | } | |
247 | else | |
248 | as_warn ("frame reg expected, using $%d.", framereg); | |
249 | ||
250 | note_gpreg (framereg); | |
251 | return framereg; | |
252 | } | |
253 | ||
254 | static void | |
255 | s_rdata (ignore) | |
256 | int ignore; | |
257 | { | |
258 | int temp; | |
259 | ||
260 | temp = get_absolute_expression (); | |
261 | #if 0 | |
262 | if (!rdata) | |
263 | rdata = subseg_get (".rdata", 0); | |
264 | subseg_set (rdata, (subsegT) temp); | |
265 | #else | |
266 | rdata = subseg_new (".rdata", 0); | |
267 | #endif | |
268 | demand_empty_rest_of_line (); | |
269 | } | |
270 | ||
271 | static void | |
272 | s_sdata (ignore) | |
273 | int ignore; | |
274 | { | |
275 | int temp; | |
276 | ||
277 | temp = get_absolute_expression (); | |
278 | #if 0 | |
279 | if (!sdata) | |
280 | sdata = subseg_get (".sdata", 0); | |
281 | subseg_set (sdata, (subsegT) temp); | |
282 | #else | |
283 | sdata = subseg_new (".sdata", 0); | |
284 | #endif | |
285 | demand_empty_rest_of_line (); | |
286 | } | |
287 | ||
288 | static void | |
289 | s_alpha_comm (ignore) | |
290 | int ignore; | |
291 | { | |
292 | register char *name; | |
293 | register char c; | |
294 | register char *p; | |
295 | offsetT temp; | |
296 | register symbolS *symbolP; | |
297 | ||
298 | name = input_line_pointer; | |
299 | c = get_symbol_end (); | |
300 | /* just after name is now '\0' */ | |
301 | p = input_line_pointer; | |
302 | *p = c; | |
303 | SKIP_WHITESPACE (); | |
304 | /* Alpha OSF/1 compiler doesn't provide the comma, gcc does. */ | |
305 | if (*input_line_pointer == ',') | |
306 | { | |
307 | input_line_pointer++; | |
308 | SKIP_WHITESPACE (); | |
309 | } | |
310 | if ((temp = get_absolute_expression ()) < 0) | |
311 | { | |
312 | as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp); | |
313 | ignore_rest_of_line (); | |
314 | return; | |
315 | } | |
316 | *p = 0; | |
317 | symbolP = symbol_find_or_make (name); | |
318 | *p = c; | |
319 | if (S_IS_DEFINED (symbolP)) | |
320 | { | |
321 | as_bad ("Ignoring attempt to re-define symbol"); | |
322 | ignore_rest_of_line (); | |
323 | return; | |
324 | } | |
325 | if (S_GET_VALUE (symbolP)) | |
326 | { | |
327 | if (S_GET_VALUE (symbolP) != (valueT) temp) | |
328 | as_bad ("Length of .comm \"%s\" is already %ld. Not changed to %ld.", | |
329 | S_GET_NAME (symbolP), | |
330 | (long) S_GET_VALUE (symbolP), | |
331 | (long) temp); | |
332 | } | |
333 | else | |
334 | { | |
335 | S_SET_VALUE (symbolP, (valueT) temp); | |
336 | S_SET_EXTERNAL (symbolP); | |
337 | } | |
338 | ||
339 | know (symbolP->sy_frag == &zero_address_frag); | |
340 | demand_empty_rest_of_line (); | |
341 | } | |
342 | ||
5749c497 KR |
343 | arelent * |
344 | tc_gen_reloc (sec, fixp) | |
345 | asection *sec; | |
346 | fixS *fixp; | |
347 | { | |
348 | arelent *reloc; | |
5749c497 KR |
349 | |
350 | reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent)); | |
351 | reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym; | |
352 | reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; | |
353 | ||
a2a1a548 | 354 | if (fixp->fx_r_type > BFD_RELOC_UNUSED) |
5749c497 KR |
355 | abort (); |
356 | ||
357 | if (fixp->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16) | |
358 | { | |
359 | if (!gpdisp_hi16_howto) | |
360 | gpdisp_hi16_howto = bfd_reloc_type_lookup (stdoutput, | |
361 | fixp->fx_r_type); | |
362 | reloc->howto = gpdisp_hi16_howto; | |
363 | } | |
364 | else | |
365 | reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); | |
366 | assert (reloc->howto != 0); | |
367 | if (!fixp->fx_pcrel != !reloc->howto->pc_relative) | |
368 | { | |
369 | as_fatal ("bug in handling type-%d relocs", fixp->fx_r_type); | |
370 | abort (); | |
371 | } | |
372 | assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); | |
373 | ||
30869211 KR |
374 | if (fixp->fx_r_type == BFD_RELOC_ALPHA_LITERAL) |
375 | { | |
376 | /* fake out bfd_perform_relocation. sigh */ | |
377 | reloc->addend = -alpha_gp_value; | |
378 | } | |
379 | else if (reloc->howto->pc_relative && reloc->howto->pcrel_offset) | |
5749c497 KR |
380 | { |
381 | reloc->addend = fixp->fx_offset - reloc->address; | |
382 | } | |
383 | else | |
384 | reloc->addend = fixp->fx_offset; | |
385 | return reloc; | |
386 | } | |
387 | ||
388 | static void | |
389 | s_base () | |
390 | { | |
391 | if (first_32bit_quadrant) | |
392 | { | |
393 | /* not fatal, but it might not work in the end */ | |
394 | as_warn ("File overrides no-base-register option."); | |
395 | first_32bit_quadrant = 0; | |
396 | } | |
397 | ||
398 | SKIP_WHITESPACE (); | |
399 | if (*input_line_pointer == '$') | |
400 | { /* $rNN form */ | |
401 | input_line_pointer++; | |
402 | if (*input_line_pointer == 'r') | |
403 | input_line_pointer++; | |
404 | } | |
405 | ||
406 | base_register = get_absolute_expression (); | |
407 | if (base_register < 0 || base_register > 31) | |
408 | { | |
409 | base_register = GP; | |
a2a1a548 | 410 | as_warn ("Bad base register, using $%d.", base_register); |
5749c497 KR |
411 | } |
412 | demand_empty_rest_of_line (); | |
413 | } | |
414 | ||
415 | static void | |
416 | s_gprel32 () | |
417 | { | |
418 | expressionS e; | |
419 | char *p; | |
420 | ||
421 | SKIP_WHITESPACE (); | |
422 | expression (&e); | |
423 | switch (e.X_op) | |
424 | { | |
425 | case O_constant: | |
426 | e.X_add_symbol = section_symbol (absolute_section); | |
427 | /* fall through */ | |
428 | case O_symbol: | |
429 | e.X_op = O_subtract; | |
430 | e.X_op_symbol = gp; | |
431 | break; | |
432 | default: | |
433 | abort (); | |
434 | } | |
435 | p = frag_more (4); | |
436 | memset (p, 0, 4); | |
437 | fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &e, 0, | |
438 | BFD_RELOC_GPREL32); | |
439 | } | |
440 | ||
441 | static void | |
40cd35ff KR |
442 | create_literal_section (secp, name) |
443 | segT *secp; | |
444 | const char *name; | |
5749c497 KR |
445 | { |
446 | segT current_section = now_seg; | |
447 | int current_subsec = now_subseg; | |
40cd35ff | 448 | segT new_sec; |
5749c497 | 449 | |
40cd35ff | 450 | *secp = new_sec = subseg_new (name, 0); |
5749c497 | 451 | subseg_set (current_section, current_subsec); |
40cd35ff KR |
452 | bfd_set_section_alignment (stdoutput, new_sec, 3); |
453 | bfd_set_section_flags (stdoutput, new_sec, | |
5749c497 KR |
454 | SEC_RELOC | SEC_ALLOC | SEC_LOAD | SEC_READONLY |
455 | | SEC_DATA); | |
40cd35ff KR |
456 | } |
457 | ||
458 | #define create_lita_section() create_literal_section (&lita_sec, ".lita") | |
459 | ||
460 | static valueT | |
461 | get_lit8_offset (val) | |
462 | bfd_vma val; | |
463 | { | |
464 | valueT retval; | |
465 | if (lit8_sec == 0) | |
466 | { | |
467 | create_literal_section (&lit8_sec, ".lit8"); | |
468 | lit8_sym = section_symbol (lit8_sec); | |
469 | } | |
470 | retval = add_to_literal_pool ((symbolS *) 0, val, lit8_sec, 8); | |
471 | if (retval >= 0xfff0) | |
472 | as_fatal ("overflow in fp literal (.lit8) table"); | |
473 | return retval; | |
474 | } | |
475 | ||
476 | static valueT | |
477 | get_lit4_offset (val) | |
478 | bfd_vma val; | |
479 | { | |
480 | valueT retval; | |
481 | if (lit4_sec == 0) | |
482 | { | |
483 | create_literal_section (&lit4_sec, ".lit4"); | |
484 | lit4_sym = section_symbol (lit4_sec); | |
485 | } | |
486 | retval = add_to_literal_pool ((symbolS *) 0, val, lit4_sec, 4); | |
487 | if (retval >= 0xfff0) | |
488 | as_fatal ("overflow in fp literal (.lit4) table"); | |
489 | return retval; | |
5749c497 KR |
490 | } |
491 | ||
0952861c | 492 | #define load_insn(NAME, OP) (hash_insert (op_hash, (NAME), (PTR) (OP))) |
5749c497 | 493 | |
0952861c KR |
494 | static void |
495 | load_insn_table (ops, size) | |
496 | struct alpha_opcode *ops; | |
497 | int size; | |
498 | { | |
499 | struct alpha_opcode *end = ops + size; | |
500 | struct alpha_opcode *op; | |
501 | const char *name; | |
5749c497 | 502 | |
0952861c | 503 | for (op = ops; op < end; ) |
5749c497 | 504 | { |
0952861c KR |
505 | const char *retval; |
506 | ||
507 | name = op->name; | |
508 | ||
509 | retval = load_insn (op->name, op); | |
5749c497 | 510 | if (retval) |
0952861c KR |
511 | as_fatal ("internal error: can't hash opcode `%s': %s", |
512 | op->name, retval); | |
513 | ||
5749c497 | 514 | do |
0952861c KR |
515 | op++; |
516 | while (op < end | |
517 | && (op->name == name | |
518 | || !strcmp (op->name, name))); | |
5749c497 KR |
519 | } |
520 | /* Some opcodes include modifiers of various sorts with a "/mod" | |
521 | syntax, like the architecture documentation suggests. However, | |
522 | for use with gcc at least, we also need to access those same | |
523 | opcodes without the "/". */ | |
0952861c | 524 | for (op = ops; op < end; ) |
5749c497 | 525 | { |
0952861c KR |
526 | name = op->name; |
527 | ||
5749c497 KR |
528 | if (strchr (name, '/')) |
529 | { | |
a2a1a548 ILT |
530 | char *name2, *p; |
531 | const char *q; | |
0952861c KR |
532 | |
533 | name2 = xmalloc (strlen (name)); | |
534 | p = name2; | |
535 | q = name; | |
536 | ||
537 | while (*q) | |
538 | if (*q == '/') | |
539 | q++; | |
540 | else | |
541 | *p++ = *q++; | |
542 | *p = 0; | |
543 | /* Ignore failures -- the opcode table does duplicate some | |
544 | variants in different forms, like "hw_stq" and "hw_st/q". | |
545 | Maybe the variants can be eliminated, and this error checking | |
546 | restored. */ | |
547 | load_insn (name2, op); | |
5749c497 | 548 | } |
0952861c | 549 | |
5749c497 | 550 | do |
0952861c KR |
551 | op++; |
552 | while (op < end | |
553 | && (op->name == name | |
554 | || !strcmp (op->name, name))); | |
5749c497 | 555 | } |
0952861c | 556 | } |
5749c497 | 557 | |
0952861c KR |
558 | /* This function is called once, at assembler startup time. It should |
559 | set up all the tables, etc. that the MD part of the assembler will | |
560 | need, that can be determined before arguments are parsed. */ | |
561 | void | |
562 | md_begin () | |
563 | { | |
0952861c KR |
564 | op_hash = hash_new (); |
565 | load_insn_table (alpha_opcodes, NUMOPCODES); | |
566 | ||
567 | /* Default to 21064 PAL instructions. */ | |
568 | if (machine == 0) | |
569 | machine = 21064; | |
570 | ||
571 | switch (machine) | |
572 | { | |
573 | case 21064: | |
574 | case 21066: | |
575 | load_insn_table (alpha_pal21064_opcodes, NUM21064OPCODES); | |
576 | break; | |
577 | case 21164: | |
578 | load_insn_table (alpha_pal21164_opcodes, NUM21164OPCODES); | |
579 | break; | |
580 | default: | |
581 | as_fatal ("palcode set unknown (internal error)"); | |
582 | } | |
5749c497 KR |
583 | |
584 | lituse_basereg.X_op = O_constant; | |
585 | lituse_basereg.X_add_number = 1; | |
586 | lituse_byteoff.X_op = O_constant; | |
587 | lituse_byteoff.X_add_number = 2; | |
588 | lituse_jsr.X_op = O_constant; | |
589 | lituse_jsr.X_add_number = 3; | |
590 | ||
591 | /* So .sbss will get used for tiny objects. */ | |
592 | bfd_set_gp_size (stdoutput, 8); | |
593 | create_lita_section (); | |
594 | /* For handling the GP, create a symbol that won't be output in the | |
595 | symbol table. We'll edit it out of relocs later. */ | |
596 | gp = symbol_new ("<GP value>", lita_sec, 0x8000, &zero_address_frag); | |
597 | symbol_remove (gp, &symbol_rootP, &symbol_lastP); | |
598 | } | |
599 | ||
600 | int optnum = 1; | |
601 | ||
0952861c KR |
602 | static void |
603 | emit_insn (insn) | |
604 | struct alpha_it *insn; | |
605 | { | |
606 | char *toP; | |
607 | int j; | |
608 | ||
609 | toP = frag_more (4); | |
610 | ||
611 | /* put out the opcode */ | |
612 | md_number_to_chars (toP, insn->opcode, 4); | |
613 | ||
614 | /* put out the symbol-dependent stuff */ | |
615 | for (j = 0; j < MAX_RELOCS; j++) | |
616 | { | |
617 | struct reloc_data *r = &insn->reloc[j]; | |
618 | fixS *f; | |
619 | ||
620 | if (r->code != BFD_RELOC_NONE) | |
621 | { | |
622 | if (r->exp.X_op == O_constant) | |
623 | { | |
624 | r->exp.X_add_symbol = section_symbol (absolute_section); | |
625 | r->exp.X_op = O_symbol; | |
626 | } | |
627 | f = fix_new_exp (frag_now, (toP - frag_now->fr_literal), 4, | |
628 | &r->exp, r->pcrel, r->code); | |
629 | } | |
630 | if (r->code == BFD_RELOC_ALPHA_GPDISP_LO16) | |
631 | { | |
632 | static bit_fixS cookie; | |
633 | /* @@ This'll make the range checking in write.c shut up. */ | |
634 | f->fx_bit_fixP = &cookie; | |
635 | } | |
636 | } | |
637 | } | |
638 | ||
5749c497 KR |
639 | void |
640 | md_assemble (str) | |
641 | char *str; | |
642 | { | |
0952861c | 643 | int i, count; |
5749c497 KR |
644 | #define MAX_INSNS 5 |
645 | struct alpha_it insns[MAX_INSNS]; | |
646 | ||
647 | count = alpha_ip (str, insns); | |
648 | if (count <= 0) | |
649 | return; | |
650 | ||
651 | for (i = 0; i < count; i++) | |
0952861c | 652 | emit_insn (&insns[i]); |
5749c497 KR |
653 | } |
654 | ||
40cd35ff KR |
655 | static inline void |
656 | maybe_set_gp (sec) | |
657 | asection *sec; | |
658 | { | |
659 | bfd_vma vma; | |
660 | if (!sec) | |
661 | return; | |
662 | vma = bfd_get_section_vma (foo, sec); | |
663 | if (vma && vma < alpha_gp_value) | |
664 | alpha_gp_value = vma; | |
665 | } | |
666 | ||
5749c497 KR |
667 | static void |
668 | select_gp_value () | |
669 | { | |
c79e67a3 KR |
670 | if (alpha_gp_value != 0) |
671 | abort (); | |
672 | ||
40cd35ff KR |
673 | /* Get minus-one in whatever width... */ |
674 | alpha_gp_value = 0; alpha_gp_value--; | |
675 | ||
676 | /* Select the smallest VMA of these existing sections. */ | |
677 | maybe_set_gp (lita_sec); | |
678 | /* maybe_set_gp (sdata); Was disabled before -- should we use it? */ | |
5749c497 | 679 | #if 0 |
40cd35ff KR |
680 | maybe_set_gp (lit8_sec); |
681 | maybe_set_gp (lit4_sec); | |
5749c497 | 682 | #endif |
5749c497 | 683 | |
c79e67a3 | 684 | alpha_gp_value += GP_ADJUSTMENT; |
5749c497 | 685 | |
c79e67a3 | 686 | S_SET_VALUE (gp, alpha_gp_value); |
5749c497 KR |
687 | |
688 | #ifdef DEBUG1 | |
c79e67a3 | 689 | printf ("Chose GP value of %lx\n", alpha_gp_value); |
5749c497 | 690 | #endif |
5749c497 KR |
691 | } |
692 | ||
693 | int | |
694 | alpha_force_relocation (f) | |
695 | fixS *f; | |
696 | { | |
697 | switch (f->fx_r_type) | |
698 | { | |
699 | case BFD_RELOC_ALPHA_GPDISP_HI16: | |
700 | case BFD_RELOC_ALPHA_GPDISP_LO16: | |
701 | case BFD_RELOC_ALPHA_LITERAL: | |
702 | case BFD_RELOC_ALPHA_LITUSE: | |
703 | case BFD_RELOC_GPREL32: | |
704 | return 1; | |
705 | case BFD_RELOC_ALPHA_HINT: | |
706 | case BFD_RELOC_64: | |
707 | case BFD_RELOC_32: | |
708 | case BFD_RELOC_16: | |
709 | case BFD_RELOC_8: | |
710 | case BFD_RELOC_23_PCREL_S2: | |
711 | case BFD_RELOC_14: | |
0952861c | 712 | case BFD_RELOC_26: |
5749c497 KR |
713 | return 0; |
714 | default: | |
715 | abort (); | |
716 | return 0; | |
717 | } | |
718 | } | |
719 | ||
720 | int | |
721 | alpha_fix_adjustable (f) | |
722 | fixS *f; | |
723 | { | |
724 | /* Are there any relocation types for which we must generate a reloc | |
725 | but we can adjust the values contained within it? */ | |
726 | switch (f->fx_r_type) | |
727 | { | |
728 | case BFD_RELOC_ALPHA_GPDISP_HI16: | |
729 | case BFD_RELOC_ALPHA_GPDISP_LO16: | |
730 | return 0; | |
731 | case BFD_RELOC_GPREL32: | |
732 | return 1; | |
a2a1a548 ILT |
733 | default: |
734 | return !alpha_force_relocation (f); | |
5749c497 | 735 | } |
a2a1a548 | 736 | /*NOTREACHED*/ |
5749c497 KR |
737 | } |
738 | ||
4a6e1a39 | 739 | valueT |
5749c497 KR |
740 | md_section_align (seg, size) |
741 | segT seg; | |
4a6e1a39 | 742 | valueT size; |
5749c497 KR |
743 | { |
744 | #ifdef OBJ_ECOFF | |
745 | /* This should probably be handled within BFD, or by pulling the | |
746 | number from BFD at least. */ | |
747 | #define MIN 15 | |
748 | size += MIN; | |
749 | size &= ~MIN; | |
750 | #endif | |
751 | return size; | |
752 | } | |
753 | ||
754 | /* Add this thing to the .lita section and produce a LITERAL reloc referring | |
0952861c | 755 | to it. */ |
5749c497 | 756 | |
0952861c KR |
757 | /* Are we currently eligible to emit a LITUSE reloc for the literal |
758 | references just generated? */ | |
759 | static int lituse_pending; | |
5749c497 KR |
760 | |
761 | static void | |
762 | load_symbol_address (reg, insn) | |
763 | int reg; | |
764 | struct alpha_it *insn; | |
765 | { | |
766 | static symbolS *lita_sym; | |
767 | ||
768 | int x; | |
5749c497 | 769 | valueT retval; |
5749c497 KR |
770 | |
771 | if (!lita_sym) | |
772 | { | |
773 | lita_sym = section_symbol (lita_sec); | |
774 | S_CLEAR_EXTERNAL (lita_sym); | |
775 | } | |
776 | ||
777 | retval = add_to_literal_pool (insn->reloc[0].exp.X_add_symbol, | |
778 | insn->reloc[0].exp.X_add_number, | |
779 | lita_sec, 8); | |
780 | ||
5749c497 KR |
781 | /* Now emit a LITERAL relocation for the original section. */ |
782 | insn->reloc[0].exp.X_op = O_symbol; | |
783 | insn->reloc[0].exp.X_add_symbol = lita_sym; | |
784 | insn->reloc[0].exp.X_add_number = retval; | |
785 | insn->reloc[0].code = BFD_RELOC_ALPHA_LITERAL; | |
0952861c | 786 | lituse_pending = 1; |
5749c497 KR |
787 | |
788 | if (retval == 0x8000) | |
789 | /* Overflow? */ | |
790 | as_fatal ("overflow in literal (.lita) table"); | |
791 | x = retval; | |
cf272f02 KR |
792 | if (addr32) |
793 | insn->opcode = (0xa0000000 /* ldl */ | |
794 | | (reg << SA) | |
795 | | (base_register << SB) | |
796 | | (x & 0xffff)); | |
797 | else | |
798 | insn->opcode = (0xa4000000 /* ldq */ | |
799 | | (reg << SA) | |
800 | | (base_register << SB) | |
801 | | (x & 0xffff)); | |
5749c497 KR |
802 | note_gpreg (base_register); |
803 | } | |
804 | ||
805 | /* To load an address with a single instruction, | |
806 | emit a LITERAL reloc in this section, and a REFQUAD | |
807 | for the .lita section, so that we'll be able to access | |
808 | it via $gp: | |
809 | lda REG, xx -> ldq REG, -32752(gp) | |
810 | lda REG, xx+4 -> ldq REG, -32752(gp) | |
811 | lda REG, 4(REG) | |
812 | ||
813 | The offsets need to start near -0x8000, and the generated LITERAL | |
814 | relocations should negate the offset. I don't completely grok the | |
815 | scheme yet. */ | |
816 | ||
817 | static int | |
818 | load_expression (reg, insn) | |
819 | int reg; | |
820 | struct alpha_it *insn; | |
821 | { | |
a2a1a548 | 822 | valueT addend, addendhi, addendlo; |
5749c497 KR |
823 | int num_insns = 1; |
824 | ||
40cd35ff KR |
825 | if (insn->reloc[0].exp.X_add_symbol->bsym->flags & BSF_SECTION_SYM) |
826 | { | |
827 | addend = 0; | |
828 | } | |
829 | else | |
830 | { | |
831 | addend = insn->reloc[0].exp.X_add_number; | |
832 | insn->reloc[0].exp.X_add_number = 0; | |
833 | } | |
5749c497 KR |
834 | load_symbol_address (reg, insn); |
835 | if (addend) | |
836 | { | |
a2a1a548 ILT |
837 | if ((addend & ~0x7fffffff) != 0 |
838 | && (addend & ~0x7fffffff) + 0x80000000 != 0) | |
839 | { | |
840 | as_bad ("assembler not prepared to handle constants >32 bits yet"); | |
841 | addend = 0; | |
842 | } | |
843 | addendlo = addend & 0xffff; | |
844 | addend -= addendlo; | |
845 | addendhi = addend >> 16; | |
846 | if (addendlo & 0x8000) | |
847 | addendhi++; | |
848 | /* It appears that the BASEREG LITUSE reloc should not be used on | |
849 | an LDAH instruction. */ | |
850 | if (addendlo) | |
851 | { | |
852 | insn[1].opcode = (0x20000000 /* lda */ | |
853 | | (reg << SA) | |
854 | | (reg << SB) | |
855 | | (addendlo & 0xffff)); | |
856 | insn[1].reloc[0].code = BFD_RELOC_ALPHA_LITUSE; | |
857 | insn[1].reloc[0].exp = lituse_basereg; | |
858 | num_insns++; | |
859 | } | |
860 | if (addendhi) | |
861 | { | |
862 | insn[num_insns].opcode = (0x24000000 | |
863 | | (reg << SA) | |
864 | | (reg << SB) | |
865 | | (addendhi & 0xffff)); | |
866 | num_insns++; | |
867 | } | |
868 | if (num_insns == 1) | |
869 | abort (); | |
0952861c | 870 | lituse_pending = 0; |
5749c497 KR |
871 | } |
872 | return num_insns; | |
873 | } | |
874 | ||
c79e67a3 | 875 | static inline void |
5749c497 KR |
876 | getExpression (str, this_insn) |
877 | char *str; | |
878 | struct alpha_it *this_insn; | |
879 | { | |
880 | char *save_in; | |
881 | segT seg; | |
882 | ||
883 | #if 0 /* Not converted to bfd yet, and I don't think we need them | |
884 | for ECOFF. Re-adding a.out support will probably require | |
885 | them though. */ | |
886 | static const struct am { | |
887 | char *name; | |
888 | bfd_reloc_code_real_type reloc; | |
889 | } macro[] = { | |
890 | { "hi", RELOC_48_63 }, | |
891 | { "lo", RELOC_0_15 }, | |
892 | { "ml", RELOC_16_31 }, | |
893 | { "mh", RELOC_32_47 }, | |
894 | { "uhi", RELOC_U_48_63 }, | |
895 | { "uml", RELOC_U_16_31 }, | |
896 | { "umh", RELOC_U_32_47 }, | |
897 | { 0, } | |
898 | }; | |
899 | ||
900 | /* Handle macros: "%macroname(expr)" */ | |
901 | if (*str == '%') | |
902 | { | |
903 | struct am *m; | |
904 | char *p, *q; | |
905 | ||
906 | str++; | |
907 | m = ¯o[0]; | |
908 | while (q = m->name) | |
909 | { | |
910 | p = str; | |
911 | while (*q && *p == *q) | |
912 | p++, q++; | |
913 | if (*q == 0) | |
914 | break; | |
915 | m++; | |
916 | } | |
917 | if (q) | |
918 | { | |
919 | str = p; /* keep the '(' */ | |
920 | this_insn->reloc = m->reloc; | |
921 | } | |
922 | } | |
923 | #endif | |
924 | ||
925 | save_in = input_line_pointer; | |
926 | input_line_pointer = str; | |
927 | ||
928 | seg = expression (&this_insn->reloc[0].exp); | |
929 | /* XXX validate seg and exp, make sure they're reasonable */ | |
930 | expr_end = input_line_pointer; | |
931 | input_line_pointer = save_in; | |
5749c497 KR |
932 | } |
933 | ||
0952861c KR |
934 | /* All of these should soon be changed to just emit words to the |
935 | output frag... */ | |
936 | static void | |
937 | emit_unaligned_io (dir, addr_reg, addr_offset, reg) | |
938 | char *dir; | |
939 | int addr_reg, reg; | |
940 | valueT addr_offset; | |
941 | { | |
942 | char buf[90]; | |
943 | sprintf (buf, "%sq_u $%d,%ld($%d)", dir, reg, (long) addr_offset, addr_reg); | |
944 | md_assemble (buf); | |
945 | } | |
946 | ||
947 | static void | |
948 | emit_load_unal (addr_reg, addr_offset, reg) | |
949 | int addr_reg, reg; | |
950 | valueT addr_offset; | |
951 | { | |
952 | emit_unaligned_io ("ld", addr_reg, addr_offset, reg); | |
953 | } | |
954 | ||
955 | static void | |
956 | emit_store_unal (addr_reg, addr_offset, reg) | |
957 | int addr_reg, reg; | |
958 | valueT addr_offset; | |
959 | { | |
960 | emit_unaligned_io ("st", addr_reg, addr_offset, reg); | |
961 | } | |
962 | ||
963 | static void | |
964 | emit_byte_manip_r (op, in, mask, out, mode, which) | |
965 | char *op; | |
a2a1a548 | 966 | int in, mask, out, mode, which; |
0952861c KR |
967 | { |
968 | char buf[90]; | |
969 | sprintf (buf, "%s%c%c $%d,$%d,$%d", op, mode, which, in, mask, out); | |
970 | md_assemble (buf); | |
971 | } | |
972 | ||
973 | static void | |
974 | emit_extract_r (in, mask, out, mode, which) | |
a2a1a548 | 975 | int in, mask, out, mode, which; |
0952861c KR |
976 | { |
977 | emit_byte_manip_r ("ext", in, mask, out, mode, which); | |
978 | } | |
979 | ||
980 | static void | |
981 | emit_insert_r (in, mask, out, mode, which) | |
a2a1a548 | 982 | int in, mask, out, mode, which; |
0952861c KR |
983 | { |
984 | emit_byte_manip_r ("ins", in, mask, out, mode, which); | |
985 | } | |
986 | ||
987 | static void | |
988 | emit_mask_r (in, mask, out, mode, which) | |
a2a1a548 | 989 | int in, mask, out, mode, which; |
0952861c KR |
990 | { |
991 | emit_byte_manip_r ("msk", in, mask, out, mode, which); | |
992 | } | |
993 | ||
994 | static void | |
995 | emit_sign_extend (reg, size) | |
a2a1a548 | 996 | int reg, size; |
0952861c KR |
997 | { |
998 | char buf[90]; | |
999 | sprintf (buf, "sll $%d,0x%x,$%d", reg, 64 - size, reg); | |
1000 | md_assemble (buf); | |
1001 | sprintf (buf, "sra $%d,0x%x,$%d", reg, 64 - size, reg); | |
1002 | md_assemble (buf); | |
1003 | } | |
1004 | ||
1005 | static void | |
1006 | emit_bis_r (in1, in2, out) | |
a2a1a548 | 1007 | int in1, in2, out; |
0952861c KR |
1008 | { |
1009 | char buf[90]; | |
1010 | sprintf (buf, "bis $%d,$%d,$%d", in1, in2, out); | |
1011 | md_assemble (buf); | |
1012 | } | |
1013 | ||
c79e67a3 KR |
1014 | /* Note that for now, this function is called recursively (by way of |
1015 | calling md_assemble again). Some of the macros defined as part of | |
1016 | the assembly language are currently rewritten as sequences of | |
1017 | strings to be assembled. See, for example, the handling of "divq". | |
5749c497 KR |
1018 | |
1019 | For efficiency, this should be fixed someday. */ | |
1020 | static int | |
1021 | alpha_ip (str, insns) | |
1022 | char *str; | |
1023 | struct alpha_it insns[]; | |
1024 | { | |
1025 | char *s; | |
1026 | const char *args; | |
1027 | char c; | |
1028 | unsigned long i; | |
1029 | struct alpha_opcode *pattern; | |
1030 | char *argsStart; | |
1031 | unsigned int opcode; | |
1032 | unsigned int mask; | |
1033 | int match = 0, num_gen = 1; | |
1034 | int comma = 0; | |
1035 | ||
1036 | for (s = str; | |
1037 | islower (*s) || *s == '_' || *s == '/' || *s == '4' || *s == '8'; | |
1038 | ++s) | |
1039 | ; | |
1040 | switch (*s) | |
1041 | { | |
1042 | ||
1043 | case '\0': | |
1044 | break; | |
1045 | ||
1046 | case ',': | |
1047 | comma = 1; | |
1048 | ||
1049 | /*FALLTHROUGH*/ | |
1050 | ||
1051 | case ' ': | |
1052 | *s++ = '\0'; | |
1053 | break; | |
1054 | ||
1055 | default: | |
1056 | as_warn ("Unknown opcode: `%s'", str); | |
1057 | exit (1); | |
1058 | } | |
1059 | if ((pattern = (struct alpha_opcode *) hash_find (op_hash, str)) == NULL) | |
1060 | { | |
1061 | as_warn ("Unknown opcode: `%s'", str); | |
1062 | return -1; | |
1063 | } | |
1064 | if (comma) | |
1065 | *--s = ','; | |
1066 | ||
1067 | argsStart = s; | |
1068 | for (;;) | |
1069 | { | |
1070 | opcode = pattern->match; | |
1071 | num_gen = 1; | |
1072 | memset (insns, 0, sizeof (*insns)); | |
1073 | for (i = 0; i < MAX_RELOCS; i++) | |
1074 | insns[0].reloc[i].code = BFD_RELOC_NONE; | |
1075 | for (i = 1; i < MAX_INSNS; i++) | |
1076 | insns[i] = insns[0]; | |
1077 | ||
1078 | /* Build the opcode, checking as we go to make sure that the | |
1079 | operands match. */ | |
1080 | for (args = pattern->args;; ++args) | |
1081 | { | |
1082 | switch (*args) | |
1083 | { | |
1084 | ||
1085 | case '\0': /* end of args */ | |
1086 | if (*s == '\0') | |
1087 | { | |
1088 | match = 1; | |
1089 | } | |
1090 | break; | |
1091 | ||
1092 | case '+': | |
1093 | if (*s == '+') | |
1094 | { | |
1095 | ++s; | |
1096 | continue; | |
1097 | } | |
1098 | if (*s == '-') | |
1099 | { | |
1100 | continue; | |
1101 | } | |
1102 | break; | |
1103 | ||
1104 | case '(': /* these must match exactly */ | |
1105 | case ')': | |
1106 | case ',': | |
1107 | case ' ': | |
1108 | case '0': | |
1109 | if (*s++ == *args) | |
1110 | continue; | |
1111 | break; | |
1112 | ||
1113 | case '1': /* next operand must be a register */ | |
1114 | case '2': | |
1115 | case '3': | |
1116 | case 'r': | |
1117 | case 'R': | |
1118 | if (*s++ == '$') | |
1119 | { | |
1120 | switch (c = *s++) | |
1121 | { | |
1122 | ||
1123 | case 'a': /* $at: as temporary */ | |
1124 | if (*s++ != 't') | |
1125 | goto error; | |
1126 | mask = AT; | |
1127 | break; | |
1128 | ||
1129 | case 'g': /* $gp: base register */ | |
1130 | if (*s++ != 'p') | |
1131 | goto error; | |
1132 | mask = base_register; | |
1133 | break; | |
1134 | ||
1135 | case 's': /* $sp: stack pointer */ | |
1136 | if (*s++ != 'p') | |
1137 | goto error; | |
1138 | mask = SP; | |
1139 | break; | |
1140 | ||
1141 | ||
1142 | case 'r': /* any register */ | |
1143 | if (!isdigit (c = *s++)) | |
1144 | { | |
1145 | goto error; | |
1146 | } | |
1147 | /* FALLTHROUGH */ | |
1148 | case '0': | |
1149 | case '1': | |
1150 | case '2': | |
1151 | case '3': | |
1152 | case '4': | |
1153 | case '5': | |
1154 | case '6': | |
1155 | case '7': | |
1156 | case '8': | |
1157 | case '9': | |
1158 | if (isdigit (*s)) | |
1159 | { | |
1160 | if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) | |
1161 | { | |
1162 | goto error; | |
1163 | } | |
1164 | } | |
1165 | else | |
1166 | { | |
1167 | c -= '0'; | |
1168 | } | |
1169 | if ((c == GP) && first_32bit_quadrant) | |
1170 | c = ZERO; | |
1171 | ||
1172 | mask = c; | |
1173 | break; | |
1174 | ||
1175 | default: | |
1176 | goto error; | |
1177 | } | |
1178 | note_gpreg (mask); | |
1179 | /* Got the register, now figure out where it goes in | |
1180 | the opcode. */ | |
1181 | doregister: | |
1182 | switch (*args) | |
1183 | { | |
1184 | ||
1185 | case '1': | |
1186 | case 'e': | |
1187 | opcode |= mask << SA; | |
1188 | continue; | |
1189 | ||
1190 | case '2': | |
1191 | case 'f': | |
1192 | opcode |= mask << SB; | |
1193 | continue; | |
1194 | ||
1195 | case '3': | |
1196 | case 'g': | |
1197 | opcode |= mask; | |
1198 | continue; | |
1199 | ||
1200 | case 'r': | |
1201 | opcode |= (mask << SA) | mask; | |
1202 | continue; | |
1203 | ||
1204 | case 'R': /* ra and rb are the same */ | |
1205 | opcode |= (mask << SA) | (mask << SB); | |
1206 | continue; | |
1207 | ||
1208 | case 'E': | |
1209 | opcode |= (mask << SA) | (mask << SB) | (mask); | |
1210 | continue; | |
1211 | } | |
1212 | } | |
1213 | break; | |
1214 | ||
1215 | case 'e': /* next operand is a floating point register */ | |
1216 | case 'f': | |
1217 | case 'g': | |
1218 | case 'E': | |
1219 | if (*s++ == '$' && *s++ == 'f' && isdigit (*s)) | |
1220 | { | |
1221 | mask = *s++; | |
1222 | if (isdigit (*s)) | |
1223 | { | |
1224 | mask = 10 * (mask - '0') + (*s++ - '0'); | |
1225 | if (mask >= 32) | |
1226 | { | |
1227 | break; | |
1228 | } | |
1229 | } | |
1230 | else | |
1231 | { | |
1232 | mask -= '0'; | |
1233 | } | |
1234 | note_fpreg (mask); | |
1235 | /* same encoding as gp registers */ | |
1236 | goto doregister; | |
1237 | } | |
1238 | break; | |
1239 | ||
1240 | #if 0 | |
1241 | case 'h': /* bits 16..31 */ | |
1242 | insns[0].reloc = RELOC_16_31; | |
1243 | goto immediate; | |
1244 | #endif | |
1245 | ||
1246 | case 'l': /* bits 0..15 */ | |
1247 | insns[0].reloc[0].code = BFD_RELOC_16; | |
1248 | goto immediate; | |
1249 | ||
1250 | case 'L': /* 21 bit PC relative immediate */ | |
1251 | insns[0].reloc[0].code = BFD_RELOC_23_PCREL_S2; | |
1252 | insns[0].reloc[0].pcrel = 1; | |
1253 | goto immediate; | |
1254 | ||
1255 | case 'i': /* 14 bit immediate */ | |
1256 | if (OPCODE (opcode) != 0x1a) | |
1257 | /* Not a jmp variant?? */ | |
1258 | abort (); | |
1259 | else if (opcode & 0x8000) | |
1260 | /* ret or jsr_coroutine */ | |
1261 | { | |
1262 | insns[0].reloc[0].code = BFD_RELOC_14; | |
1263 | insns[0].reloc[0].pcrel = 0; | |
1264 | } | |
1265 | else | |
1266 | /* jmp or jsr */ | |
1267 | { | |
1268 | insns[0].reloc[0].code = BFD_RELOC_ALPHA_HINT; | |
1269 | insns[0].reloc[0].pcrel = 1; | |
1270 | } | |
1271 | goto immediate; | |
1272 | ||
1273 | case 'b': /* 8 bit immediate */ | |
1274 | insns[0].reloc[0].code = BFD_RELOC_8; | |
1275 | goto immediate; | |
1276 | ||
0952861c KR |
1277 | case 'I': /* 26 bit immediate, for PALcode */ |
1278 | insns[0].reloc[0].code = BFD_RELOC_26; | |
1279 | goto immediate; | |
1280 | ||
5749c497 KR |
1281 | #if 0 |
1282 | case 't': /* 12 bit 0...11 */ | |
1283 | insns[0].reloc = RELOC_0_12; | |
1284 | goto immediate; | |
1285 | ||
1286 | case '8': /* 8 bit 0...7 */ | |
1287 | insns[0].reloc = RELOC_0_8; | |
1288 | goto immediate; | |
1289 | ||
1290 | case 'I': /* 26 bit immediate */ | |
1291 | insns[0].reloc = RELOC_0_25; | |
1292 | #else | |
1293 | case 't': | |
1294 | case '8': | |
5749c497 KR |
1295 | abort (); |
1296 | #endif | |
1297 | /*FALLTHROUGH*/ | |
1298 | ||
1299 | immediate: | |
1300 | if (*s == ' ') | |
1301 | s++; | |
c79e67a3 | 1302 | getExpression (s, &insns[0]); |
5749c497 KR |
1303 | s = expr_end; |
1304 | /* Handle overflow in certain instructions by converting | |
1305 | to other instructions. */ | |
1306 | if (insns[0].reloc[0].code == BFD_RELOC_8 | |
1307 | && insns[0].reloc[0].exp.X_op == O_constant | |
1308 | && (insns[0].reloc[0].exp.X_add_number < 0 | |
1309 | || insns[0].reloc[0].exp.X_add_number > 0xff)) | |
1310 | { | |
1311 | if (OPCODE (opcode) == 0x10 | |
1312 | && (OP_FCN (opcode) == 0x00 /* addl */ | |
1313 | || OP_FCN (opcode) == 0x40 /* addl/v */ | |
1314 | || OP_FCN (opcode) == 0x20 /* addq */ | |
1315 | || OP_FCN (opcode) == 0x60 /* addq/v */ | |
1316 | || OP_FCN (opcode) == 0x09 /* subl */ | |
1317 | || OP_FCN (opcode) == 0x49 /* subl/v */ | |
1318 | || OP_FCN (opcode) == 0x29 /* subq */ | |
1319 | || OP_FCN (opcode) == 0x69 /* subq/v */ | |
1320 | || OP_FCN (opcode) == 0x02 /* s4addl */ | |
1321 | || OP_FCN (opcode) == 0x22 /* s4addq */ | |
1322 | || OP_FCN (opcode) == 0x0b /* s4subl */ | |
1323 | || OP_FCN (opcode) == 0x2b /* s4subq */ | |
1324 | || OP_FCN (opcode) == 0x12 /* s8addl */ | |
1325 | || OP_FCN (opcode) == 0x32 /* s8addq */ | |
1326 | || OP_FCN (opcode) == 0x1b /* s8subl */ | |
1327 | || OP_FCN (opcode) == 0x3b /* s8subq */ | |
1328 | ) | |
1329 | /* Can we make it fit by negating? */ | |
1330 | && -insns[0].reloc[0].exp.X_add_number < 0xff | |
1331 | && -insns[0].reloc[0].exp.X_add_number > 0) | |
1332 | { | |
1333 | opcode ^= 0x120; /* convert add<=>sub */ | |
1334 | insns[0].reloc[0].exp.X_add_number *= -1; | |
1335 | } | |
1336 | else if (at_ok && macro_ok) | |
1337 | { | |
1338 | /* Constant value supplied, but it's too large. */ | |
a2a1a548 | 1339 | char buf[50]; |
5749c497 | 1340 | char expansion[64]; |
a2a1a548 ILT |
1341 | sprint_value (buf, insns[0].reloc[0].exp.X_add_number); |
1342 | sprintf (expansion, "lda $%d,%s($%d)", AT, buf, ZERO); | |
5749c497 KR |
1343 | md_assemble (expansion); |
1344 | opcode |= 0x1000 /* use reg */ | (AT << SB); | |
1345 | insns[0].reloc[0].code = BFD_RELOC_NONE; | |
1346 | } | |
1347 | else | |
1348 | as_bad ("overflow in 8-bit literal field in `operate' format insn"); | |
1349 | } | |
1350 | continue; | |
1351 | ||
40cd35ff KR |
1352 | case 'F': |
1353 | { | |
a2a1a548 | 1354 | int format, length, mode, i; |
40cd35ff KR |
1355 | char temp[20 /*MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT*/]; |
1356 | char *err; | |
1357 | static const char formats[4] = "FGfd"; | |
1358 | bfd_vma bits, offset; | |
1359 | char *old_input_line_pointer = input_line_pointer; | |
1360 | ||
1361 | input_line_pointer = s; | |
1362 | SKIP_WHITESPACE (); | |
1363 | memset (temp, 0, sizeof (temp)); | |
1364 | mode = (opcode >> 26) & 3; | |
1365 | format = formats[mode]; | |
1366 | err = md_atof (format, temp, &length); | |
1367 | if (err) | |
1368 | { | |
1369 | as_bad ("Bad floating literal: %s", err); | |
1370 | bits = 0; | |
1371 | } | |
1372 | else | |
1373 | { | |
1374 | /* Generate little-endian number from byte sequence. */ | |
1375 | bits = 0; | |
1376 | for (i = length - 1; i >= 0; i--) | |
1377 | bits += ((bfd_vma)(temp[i] & 0xff)) << (i * 8); | |
1378 | } | |
1379 | switch (length) | |
1380 | { | |
1381 | case 8: | |
1382 | offset = get_lit8_offset (bits) - 0x8000; | |
1383 | insns[0].reloc[0].exp.X_add_symbol = lit8_sym; | |
1384 | insns[0].reloc[0].exp.X_add_number = 0x8000; | |
1385 | break; | |
1386 | case 4: | |
1387 | offset = get_lit4_offset (bits) - 0x8000; | |
1388 | insns[0].reloc[0].exp.X_add_symbol = lit4_sym; | |
1389 | insns[0].reloc[0].exp.X_add_number = 0x8000; | |
1390 | break; | |
1391 | default: | |
1392 | abort (); | |
1393 | } | |
1394 | insns[0].reloc[0].exp.X_op = O_symbol; | |
1395 | offset &= 0xffff; | |
1396 | num_gen = load_expression (AT, &insns[0]); | |
0952861c KR |
1397 | if (lituse_pending) |
1398 | { | |
1399 | insns[num_gen].reloc[0].code = BFD_RELOC_ALPHA_LITUSE; | |
1400 | insns[num_gen].reloc[0].exp = lituse_basereg; | |
1401 | lituse_pending = 0; | |
1402 | } | |
40cd35ff KR |
1403 | insns[num_gen++].opcode = opcode | (AT << SB) | offset; |
1404 | opcode = insns[0].opcode; | |
1405 | s = input_line_pointer; | |
1406 | input_line_pointer = old_input_line_pointer; | |
1407 | } | |
1408 | continue; | |
1409 | ||
5749c497 KR |
1410 | /* The following two.. take advantage of the fact that |
1411 | opcode already contains most of what we need to know. | |
1412 | We just prepend to the instr an "ldah | |
1413 | $r,%ml(expr)($base)" and turn this one (done later | |
1414 | after we return) into something like "stq | |
1415 | $r,%lo(expr)(at)" or "ldq $r,%lo(expr)($r)". | |
1416 | ||
1417 | NOTE: This can fail later on at link time if the | |
1418 | offset from $base actually turns out to be more than | |
1419 | 2**31 or 2**47 if use_large_offsets is set. */ | |
1420 | case 'P': /* Addressing macros: PUT */ | |
1421 | mask = AT; /* register 'at' */ | |
1422 | /* fall through */ | |
1423 | ||
1424 | case 'G': /* Addressing macros: GET */ | |
5749c497 KR |
1425 | /* All it is missing is the expression, which is what we |
1426 | will get now */ | |
1427 | ||
1428 | if (*s == ' ') | |
1429 | s++; | |
c79e67a3 | 1430 | getExpression (s, &insns[0]); |
5749c497 KR |
1431 | s = expr_end; |
1432 | ||
1433 | /* Must check for "lda ..,number" too */ | |
1434 | if (insns[0].reloc[0].exp.X_op == O_big) | |
1435 | { | |
1436 | as_warn ("Sorry, not yet. Put bignums in .data section yourself."); | |
1437 | return -1; | |
1438 | } | |
1439 | if (insns[0].reloc[0].exp.X_op == O_constant) | |
1440 | { | |
1441 | /* This only handles 32bit numbers */ | |
1442 | register int val = insns[0].reloc[0].exp.X_add_number; | |
1443 | register short sval; | |
1444 | ||
1445 | insns[0].reloc[0].code = BFD_RELOC_NONE; | |
1446 | insns[1].reloc[0].code = BFD_RELOC_NONE; | |
1447 | ||
1448 | sval = val; | |
5749c497 KR |
1449 | if ((sval != val) && (val & 0x8000)) |
1450 | { | |
1451 | val += 0x10000; | |
1452 | sval = val; | |
1453 | } | |
1454 | ||
1455 | if (optnum && (sval == val)) | |
1456 | { | |
1457 | /* optimize away the ldah */ | |
1458 | num_gen = 1; | |
1459 | opcode |= (ZERO << SB) | (val & 0xffff); | |
1460 | } | |
1461 | else | |
1462 | { | |
1463 | num_gen = 2; | |
1464 | insns[1].opcode = opcode | (mask << SB) | (val & 0xffff); | |
1465 | opcode = 0x24000000 /*ldah*/ | | |
1466 | mask << SA | (ZERO << SB) | | |
1467 | ((val >> 16) & 0xffff); | |
1468 | } | |
1469 | } | |
1470 | else if (insns[0].reloc[0].exp.X_op == O_symbol) | |
1471 | { | |
1472 | unsigned long old_opcode = opcode; | |
1473 | int tmp_reg; | |
1474 | ||
1475 | if (!macro_ok) | |
1476 | as_bad ("insn requires expansion but `nomacro' specified"); | |
1477 | else if (*args == 'G') | |
1478 | tmp_reg = mask; | |
1479 | else if (!at_ok) | |
1480 | as_bad ("insn expansion requires AT use, but `noat' specified"); | |
1481 | else | |
1482 | tmp_reg = AT; | |
1483 | num_gen = load_expression (tmp_reg, insns); | |
1484 | opcode = insns[0].opcode; | |
0952861c KR |
1485 | /* lda is opcode 8, 0x20000000, and the macros that use |
1486 | this code have an opcode field of 0. The latter | |
1487 | require further processing, and we don't have the | |
1488 | true opcode here. */ | |
1489 | if (OPCODE (old_opcode) != 0 | |
1490 | && OPCODE (old_opcode) != 0x08) | |
5749c497 KR |
1491 | { |
1492 | struct alpha_it *i; | |
1493 | i = &insns[num_gen++]; | |
5749c497 | 1494 | i->opcode = old_opcode | (tmp_reg << SB); |
40cd35ff | 1495 | |
0952861c KR |
1496 | if (lituse_pending) |
1497 | { | |
1498 | i->reloc[0].code = BFD_RELOC_ALPHA_LITUSE; | |
1499 | i->reloc[0].exp = lituse_basereg; | |
1500 | lituse_pending = 0; | |
1501 | } | |
5749c497 KR |
1502 | } |
1503 | } | |
1504 | else | |
1505 | { | |
1506 | /* Not a number */ | |
1507 | num_gen = 2; | |
1508 | insns[1].reloc[0].exp = insns[0].reloc[0].exp; | |
1509 | ||
1510 | /* Generate: ldah REG,x1(GP); OP ?,x0(REG) */ | |
1511 | ||
1512 | abort (); /* relocs need fixing */ | |
1513 | #if 0 | |
1514 | insns[1].reloc = RELOC_0_15; | |
1515 | insns[1].opcode = opcode | mask << SB; | |
1516 | ||
1517 | insns[0].reloc = RELOC_16_31; | |
1518 | opcode = 0x24000000 /*ldah*/ | mask << SA | (base_register << SB); | |
1519 | #endif | |
1520 | } | |
1521 | ||
1522 | continue; | |
1523 | ||
1524 | /* Same failure modes as above, actually most of the | |
40cd35ff | 1525 | same code shared. */ |
5749c497 KR |
1526 | case 'B': /* Builtins */ |
1527 | args++; | |
1528 | switch (*args) | |
1529 | { | |
1530 | ||
1531 | case 'a': /* ldgp */ | |
1532 | ||
1533 | if (first_32bit_quadrant || no_mixed_code) | |
1534 | return -1; | |
1535 | switch (OUTPUT_FLAVOR) | |
1536 | { | |
1537 | case bfd_target_aout_flavour: | |
1538 | /* this is cmu's a.out version */ | |
1539 | insns[0].reloc[0].code = BFD_RELOC_NONE; | |
1540 | /* generate "zap %r,0xf,%r" to take high 32 bits */ | |
1541 | opcode |= 0x48001600 /* zap ?,#,?*/ | (0xf << SN); | |
1542 | break; | |
1543 | case bfd_target_ecoff_flavour: | |
1544 | /* Given "ldgp R1,N(R2)", turn it into something | |
1545 | like "ldah R1,###(R2) ; lda R1,###(R1)" with | |
1546 | appropriate constants and relocations. */ | |
1547 | { | |
1548 | unsigned long r1, r2; | |
1549 | unsigned long addend = 0; | |
1550 | ||
1551 | num_gen = 2; | |
1552 | r2 = mask; | |
1553 | r1 = opcode & 0x3f; | |
1554 | insns[0].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_HI16; | |
1555 | insns[0].reloc[0].pcrel = 1; | |
1556 | insns[0].reloc[0].exp.X_op = O_symbol; | |
1557 | insns[0].reloc[0].exp.X_add_symbol = gp; | |
1558 | insns[0].reloc[0].exp.X_add_number = 0; | |
1559 | insns[0].opcode = (0x24000000 /* ldah */ | |
1560 | | (r1 << SA) | |
1561 | | (r2 << SB)); | |
1562 | insns[1].reloc[0].code = BFD_RELOC_ALPHA_GPDISP_LO16; | |
1563 | insns[1].reloc[0].exp.X_op = O_symbol; | |
1564 | insns[1].reloc[0].exp.X_add_symbol = gp; | |
1565 | insns[1].reloc[0].exp.X_add_number = 4; | |
1566 | insns[1].reloc[0].pcrel = 1; | |
1567 | insns[1].opcode = 0x20000000 | (r1 << SA) | (r1 << SB); | |
1568 | opcode = insns[0].opcode; | |
1569 | /* merge in addend */ | |
1570 | insns[1].opcode |= addend & 0xffff; | |
1571 | insns[0].opcode |= ((addend >> 16) | |
1572 | + (addend & 0x8000 ? 1 : 0)); | |
0952861c KR |
1573 | if (r2 == PV) |
1574 | ecoff_set_gp_prolog_size (0); | |
5749c497 KR |
1575 | } |
1576 | break; | |
1577 | default: | |
1578 | abort (); | |
1579 | } | |
1580 | continue; | |
1581 | ||
1582 | ||
1583 | case 'b': /* setgp */ | |
1584 | switch (OUTPUT_FLAVOR) | |
1585 | { | |
1586 | case bfd_target_aout_flavour: | |
1587 | /* generate "zap %r,0xf,$gp" to take high 32 bits */ | |
1588 | opcode |= 0x48001600 /* zap ?,#,?*/ | |
1589 | | (0xf << SN) | (base_register); | |
1590 | break; | |
1591 | default: | |
1592 | abort (); | |
1593 | } | |
1594 | continue; | |
1595 | ||
1596 | case 'c': /* jsr $r,foo becomes | |
1597 | lda $27,foo | |
1598 | jsr $r,($27),foo | |
1599 | Register 27, t12, is used by convention | |
1600 | here. */ | |
1601 | { | |
1602 | struct alpha_it *jsr; | |
1603 | expressionS etmp; | |
1604 | struct reloc_data *r; | |
1605 | ||
1606 | /* We still have to parse the function name */ | |
1607 | if (*s == ' ') | |
1608 | s++; | |
c79e67a3 | 1609 | getExpression (s, &insns[0]); |
5749c497 KR |
1610 | etmp = insns[0].reloc[0].exp; |
1611 | s = expr_end; | |
1612 | num_gen = load_expression (PV, &insns[0]); | |
1613 | note_gpreg (PV); | |
1614 | ||
1615 | jsr = &insns[num_gen++]; | |
1616 | jsr->opcode = (0x68004000 /* jsr */ | |
1617 | | (mask << SA) | |
1618 | | (PV << SB) | |
1619 | | 0); | |
0952861c | 1620 | if (lituse_pending) |
5749c497 KR |
1621 | { |
1622 | /* LITUSE wasn't emitted yet */ | |
1623 | jsr->reloc[0].code = BFD_RELOC_ALPHA_LITUSE; | |
1624 | jsr->reloc[0].exp = lituse_jsr; | |
1625 | r = &jsr->reloc[1]; | |
0952861c | 1626 | lituse_pending = 0; |
5749c497 KR |
1627 | } |
1628 | else | |
1629 | r = &jsr->reloc[0]; | |
1630 | r->exp = etmp; | |
1631 | r->code = BFD_RELOC_ALPHA_HINT; | |
1632 | r->pcrel = 1; | |
1633 | opcode = insns[0].opcode; | |
1634 | } | |
1635 | continue; | |
1636 | ||
0952861c KR |
1637 | case 'd': |
1638 | /* Sub-word loads and stores. We load the address into | |
1639 | $at, which might involve using the `P' parameter | |
1640 | processing too, then emit a sequence to get the job | |
1641 | done, using unaligned memory accesses and byte | |
1642 | manipulation, with t9 and t10 as temporaries. */ | |
1643 | { | |
1644 | /* Characteristics of access. */ | |
1645 | int is_load, is_unsigned = 0, is_unaligned = 0; | |
1646 | int mode_size, mode; | |
1647 | /* Register operand. */ | |
1648 | int reg; | |
1649 | /* Addend for loads and stores. */ | |
1650 | valueT addend; | |
1651 | /* Which register do we use for the address? */ | |
1652 | int addr; | |
1653 | ||
1654 | { | |
1655 | /* Pick apart name and set flags. */ | |
a2a1a548 | 1656 | const char *s = pattern->name; |
0952861c KR |
1657 | |
1658 | if (*s == 'u') | |
1659 | { | |
1660 | is_unaligned = 1; | |
1661 | s++; | |
1662 | } | |
1663 | ||
1664 | if (s[0] == 'l' && s[1] == 'd') | |
1665 | is_load = 1; | |
1666 | else if (s[0] == 's' && s[1] == 't') | |
1667 | is_load = 0; | |
1668 | else | |
1669 | as_fatal ("unrecognized sub-word access insn `%s'", | |
1670 | str); | |
1671 | s += 2; | |
1672 | ||
1673 | mode = *s++; | |
1674 | if (mode == 'b') mode_size = 1; | |
1675 | else if (mode == 'w') mode_size = 2; | |
1676 | else if (mode == 'l') mode_size = 4; | |
1677 | else if (mode == 'q') mode_size = 8; | |
1678 | else abort (); | |
1679 | ||
1680 | if (*s == 'u') | |
1681 | { | |
1682 | is_unsigned = 1; | |
1683 | s++; | |
1684 | } | |
1685 | ||
1686 | assert (*s == 0); | |
1687 | ||
1688 | /* Longwords are always kept sign-extended. */ | |
1689 | if (mode == 'l' && is_unsigned) | |
1690 | abort (); | |
1691 | /* There's no special unaligned byte handling. */ | |
1692 | if (mode == 'b' && is_unaligned) | |
1693 | abort (); | |
1694 | /* Stores don't care about signedness. */ | |
1695 | if (!is_load && is_unsigned) | |
1696 | abort (); | |
1697 | } | |
1698 | ||
1699 | if (args[-2] == 'P') | |
1700 | { | |
1701 | addr = AT; | |
1702 | addend = 0; | |
1703 | } | |
1704 | else | |
1705 | { | |
1706 | /* foo r1,num(r2) | |
1707 | r2 -> mask | |
1708 | r1 -> (opcode >> SA) & 31 | |
1709 | num -> insns->reloc[0].* | |
1710 | ||
1711 | We want to emit "lda at,num(r2)", since these | |
1712 | operations require the use of a single register | |
1713 | with the starting address of the memory operand | |
1714 | we want to access. | |
1715 | ||
1716 | We could probably get away without doing this | |
1717 | (and use r2 below, with the addend for the | |
1718 | actual reads and writes) in cases where the | |
1719 | addend is known to be a multiple of 8. */ | |
1720 | int r2 = mask; | |
1721 | int r1 = (opcode >> SA) & 31; | |
1722 | ||
1723 | if (insns[0].reloc[0].code == BFD_RELOC_NONE) | |
1724 | addend = 0; | |
1725 | else if (insns[0].reloc[0].code == BFD_RELOC_16) | |
1726 | { | |
1727 | if (insns[0].reloc[0].exp.X_op != O_constant) | |
1728 | abort (); | |
1729 | addend = insns[0].reloc[0].exp.X_add_number; | |
1730 | } | |
1731 | else | |
1732 | abort (); | |
1733 | ||
1734 | if (addend + mode_size - 1 < 0x7fff | |
1735 | && (addend % 8) == 0 | |
1736 | && (r2 < T9 || r2 > T12)) | |
1737 | { | |
1738 | addr = r2; | |
1739 | num_gen = 0; | |
1740 | } | |
1741 | else | |
1742 | { | |
1743 | /* Let later relocation processing deal | |
1744 | with the addend field. */ | |
1745 | insns[num_gen-1].opcode = (0x20000000 /* lda */ | |
1746 | | (AT << SA) | |
1747 | | (r2 << SB)); | |
1748 | addr = AT; | |
1749 | addend = 0; | |
1750 | } | |
1751 | reg = r1; | |
1752 | } | |
1753 | ||
1754 | /* Because the emit_* routines append directly to | |
1755 | the current frag, we now need to flush any | |
1756 | pending insns. */ | |
1757 | { | |
1758 | int i; | |
1759 | for (i = 0; i < num_gen; i++) | |
1760 | emit_insn (&insns[i]); | |
1761 | num_gen = 0; | |
1762 | } | |
1763 | ||
1764 | if (is_load) | |
1765 | { | |
1766 | int reg2, reg3; | |
1767 | ||
1768 | if (is_unaligned) | |
1769 | reg2 = T9, reg3 = T10; | |
1770 | else | |
1771 | reg2 = reg; | |
1772 | ||
1773 | emit_load_unal (addr, addend, T9); | |
1774 | if (is_unaligned) | |
1775 | emit_load_unal (addr, addend + mode_size - 1, T10); | |
1776 | emit_extract_r (T9, addr, reg2, mode, 'l'); | |
1777 | if (is_unaligned) | |
1778 | { | |
1779 | emit_extract_r (T10, addr, reg3, mode, 'h'); | |
1780 | emit_bis_r (T9, T10, reg); | |
1781 | } | |
1782 | if (!is_unsigned) | |
1783 | emit_sign_extend (reg, mode_size * 8); | |
1784 | } | |
1785 | else | |
1786 | { | |
1787 | /* The second word gets processed first | |
1788 | because if the address does turn out to be | |
1789 | aligned, the processing for the second word | |
1790 | will be pushing around all-zeros, and the | |
1791 | entire value will be handled as the `first' | |
1792 | word. So we want to store the `first' word | |
1793 | last. */ | |
1794 | /* Pair these up so that the memory loads get | |
1795 | separated from each other, as well as being | |
1796 | well in advance of the uses of the values | |
1797 | loaded. */ | |
1798 | if (is_unaligned) | |
1799 | { | |
1800 | emit_load_unal (addr, addend + mode_size - 1, T11); | |
1801 | emit_insert_r (reg, addr, T12, mode, 'h'); | |
1802 | } | |
1803 | emit_load_unal (addr, addend, T9); | |
1804 | emit_insert_r (reg, addr, T10, mode, 'l'); | |
1805 | if (is_unaligned) | |
1806 | emit_mask_r (T12, addr, T12, mode, 'h'); | |
1807 | emit_mask_r (T10, addr, T10, mode, 'l'); | |
1808 | if (is_unaligned) | |
1809 | emit_bis_r (T11, T12, T11); | |
1810 | emit_bis_r (T9, T10, T9); | |
1811 | if (is_unaligned) | |
1812 | emit_store_unal (addr, addend + mode_size - 1, T11); | |
1813 | emit_store_unal (addr, addend, T9); | |
1814 | } | |
1815 | } | |
1816 | return 0; | |
1817 | ||
5749c497 KR |
1818 | /* DIVISION and MODULUS. Yech. |
1819 | Convert OP x,y,result | |
1820 | to mov x,t10 | |
1821 | mov y,t11 | |
1822 | jsr t9, __OP | |
1823 | mov t12,result | |
1824 | ||
1825 | with appropriate optimizations if t10,t11,t12 | |
1826 | are the registers specified by the compiler. | |
1827 | We are missing an obvious optimization | |
1828 | opportunity here; if the ldq generated by the | |
1829 | jsr assembly requires a cycle or two to make | |
1830 | the value available, initiating it before one | |
1831 | or two of the mov instructions would result in | |
1832 | faster execution. */ | |
1833 | case '0': /* reml */ | |
1834 | case '1': /* divl */ | |
1835 | case '2': /* remq */ | |
1836 | case '3': /* divq */ | |
1837 | case '4': /* remlu */ | |
1838 | case '5': /* divlu */ | |
1839 | case '6': /* remqu */ | |
1840 | case '7': /* divqu */ | |
1841 | { | |
1842 | static char func[8][6] = { | |
1843 | "reml", "divl", "remq", "divq", | |
1844 | "remlu", "divlu", "remqu", "divqu" | |
1845 | }; | |
1846 | char expansion[64]; | |
1847 | int reg; | |
1848 | ||
1849 | /* All regs parsed, in opcode */ | |
1850 | ||
1851 | /* Do the expansions, one instr at a time */ | |
1852 | ||
1853 | reg = (opcode >> SA) & 31; | |
1854 | if (reg != T10) | |
1855 | { | |
1856 | /* x->t10 */ | |
1857 | sprintf (expansion, "mov $%d,$%d", reg, T10); | |
1858 | md_assemble (expansion); | |
1859 | } | |
1860 | reg = (opcode >> SB) & 31; | |
1861 | if (reg == T10) | |
1862 | /* we already overwrote it! */ | |
1863 | abort (); | |
1864 | else if (reg != T11) | |
1865 | { | |
1866 | /* y->t11 */ | |
1867 | sprintf (expansion, "mov $%d,$%d", reg, T11); | |
1868 | md_assemble (expansion); | |
1869 | } | |
1870 | sprintf (expansion, "lda $%d,__%s", PV, func[*args - '0']); | |
1871 | md_assemble (expansion); | |
1872 | sprintf (expansion, "jsr $%d,($%d),__%s", T9, PV, | |
1873 | func[*args - '0']); | |
1874 | md_assemble (expansion); | |
1875 | #if 0 /* huh? */ | |
1876 | if (!first_32bit_quadrant) | |
1877 | { | |
1878 | sprintf (expansion, | |
1879 | "zap $%d,0xf,$%d", | |
1880 | T9, base_register); | |
1881 | md_assemble (expansion); | |
1882 | } | |
1883 | #endif | |
1884 | sprintf (expansion, "ldgp $%d,0($%d)", | |
1885 | base_register, T9); | |
1886 | md_assemble (expansion); | |
1887 | ||
1888 | /* Use insns[0] to get at the result */ | |
1889 | if ((reg = (opcode & 31)) != PV) | |
1890 | opcode = (0x47e00400 /* or zero,zero,zero */ | |
1891 | | (PV << SB) | |
1892 | | reg /* Rc */ ); /* pv->z */ | |
1893 | else | |
1894 | num_gen = 0; | |
1895 | } | |
1896 | continue; | |
1897 | } | |
1898 | /* fall through */ | |
1899 | ||
1900 | default: | |
1901 | abort (); | |
1902 | } | |
1903 | break; | |
1904 | } | |
1905 | error: | |
1906 | if (match == 0) | |
1907 | { | |
1908 | /* Args don't match. */ | |
1909 | if (&pattern[1] - alpha_opcodes < NUMOPCODES | |
1910 | && !strcmp (pattern->name, pattern[1].name)) | |
1911 | { | |
1912 | ++pattern; | |
1913 | s = argsStart; | |
1914 | continue; | |
1915 | } | |
1916 | else | |
1917 | { | |
1918 | as_warn ("Illegal operands"); | |
1919 | return -1; | |
1920 | } | |
1921 | } | |
1922 | else | |
1923 | { | |
1924 | /* Args match, see if a float instructions and -nofloats */ | |
1925 | if (nofloats && pattern->isa_float) | |
1926 | return -1; | |
1927 | } | |
1928 | break; | |
1929 | } | |
1930 | ||
1931 | insns[0].opcode = opcode; | |
1932 | return num_gen; | |
1933 | } | |
1934 | ||
1935 | /* Turn a string in input_line_pointer into a floating point constant | |
1936 | of type type, and store the appropriate bytes in *litP. The number | |
1937 | of LITTLENUMS emitted is stored in *sizeP. An error message is | |
1938 | returned, or NULL on OK. */ | |
1939 | ||
1940 | /* Equal to MAX_PRECISION in atof-ieee.c */ | |
1941 | #define MAX_LITTLENUMS 6 | |
1942 | ||
1943 | char * | |
1944 | md_atof (type, litP, sizeP) | |
1945 | char type; | |
1946 | char *litP; | |
1947 | int *sizeP; | |
1948 | { | |
1949 | int prec; | |
1950 | LITTLENUM_TYPE words[MAX_LITTLENUMS]; | |
1951 | LITTLENUM_TYPE *wordP; | |
1952 | char *t; | |
1953 | char *atof_ieee (), *vax_md_atof (); | |
1954 | ||
1955 | switch (type) | |
1956 | { | |
1957 | /* VAX floats */ | |
1958 | case 'G': | |
c79e67a3 | 1959 | /* VAX md_atof doesn't like "G" for some reason. */ |
5749c497 KR |
1960 | type = 'g'; |
1961 | case 'F': | |
1962 | case 'D': | |
1963 | return vax_md_atof (type, litP, sizeP); | |
1964 | ||
1965 | /* IEEE floats */ | |
1966 | case 'f': | |
1967 | prec = 2; | |
1968 | break; | |
1969 | ||
1970 | case 'd': | |
1971 | prec = 4; | |
1972 | break; | |
1973 | ||
1974 | case 'x': | |
1975 | case 'X': | |
1976 | prec = 6; | |
1977 | break; | |
1978 | ||
1979 | case 'p': | |
1980 | case 'P': | |
1981 | prec = 6; | |
1982 | break; | |
1983 | ||
1984 | default: | |
1985 | *sizeP = 0; | |
1986 | return "Bad call to MD_ATOF()"; | |
1987 | } | |
1988 | t = atof_ieee (input_line_pointer, type, words); | |
1989 | if (t) | |
1990 | input_line_pointer = t; | |
1991 | *sizeP = prec * sizeof (LITTLENUM_TYPE); | |
1992 | ||
1993 | for (wordP = words + prec - 1; prec--;) | |
1994 | { | |
1995 | md_number_to_chars (litP, (long) (*wordP--), sizeof (LITTLENUM_TYPE)); | |
1996 | litP += sizeof (LITTLENUM_TYPE); | |
1997 | } | |
1998 | ||
1999 | return 0; | |
2000 | } | |
2001 | ||
2002 | void | |
2003 | md_bignum_to_chars (buf, bignum, nchars) | |
2004 | char *buf; | |
2005 | LITTLENUM_TYPE *bignum; | |
2006 | int nchars; | |
2007 | { | |
2008 | while (nchars) | |
2009 | { | |
2010 | LITTLENUM_TYPE work = *bignum++; | |
2011 | int nb = CHARS_PER_LITTLENUM; | |
2012 | ||
2013 | do | |
2014 | { | |
2015 | *buf++ = work & ((1 << BITS_PER_CHAR) - 1); | |
2016 | if (--nchars == 0) | |
2017 | return; | |
2018 | work >>= BITS_PER_CHAR; | |
2019 | } | |
2020 | while (--nb); | |
2021 | } | |
2022 | } | |
f3d817d8 DM |
2023 | \f |
2024 | CONST char *md_shortopts = "Fm:"; | |
2025 | struct option md_longopts[] = { | |
2026 | #define OPTION_32ADDR (OPTION_MD_BASE) | |
2027 | {"32addr", no_argument, NULL, OPTION_32ADDR}, | |
2028 | {NULL, no_argument, NULL, 0} | |
2029 | }; | |
2030 | size_t md_longopts_size = sizeof(md_longopts); | |
5749c497 KR |
2031 | |
2032 | int | |
f3d817d8 DM |
2033 | md_parse_option (c, arg) |
2034 | int c; | |
2035 | char *arg; | |
5749c497 | 2036 | { |
f3d817d8 | 2037 | switch (c) |
5749c497 | 2038 | { |
f3d817d8 | 2039 | case 'F': |
5749c497 | 2040 | nofloats = 1; |
f3d817d8 DM |
2041 | break; |
2042 | ||
2043 | case OPTION_32ADDR: | |
cf272f02 | 2044 | addr32 = 1; |
f3d817d8 | 2045 | break; |
0952861c | 2046 | |
f3d817d8 DM |
2047 | case 'm': |
2048 | { | |
2049 | unsigned long mach; | |
2050 | ||
2051 | if (!strcmp (arg, "21064")) | |
2052 | mach = 21064; | |
2053 | else if (!strcmp (arg, "21066")) | |
2054 | mach = 21066; | |
2055 | else if (!strcmp (arg, "21164")) | |
2056 | mach = 21164; | |
2057 | else | |
2058 | { | |
2059 | as_bad ("invalid architecture %s", arg); | |
2060 | return 0; | |
2061 | } | |
0952861c | 2062 | |
f3d817d8 DM |
2063 | if (machine != 0 && machine != mach) |
2064 | { | |
2065 | as_warn ("machine type %lu already chosen, overriding with %lu", | |
2066 | machine, mach); | |
2067 | } | |
2068 | machine = mach; | |
2069 | } | |
2070 | break; | |
2071 | ||
2072 | default: | |
2073 | return 0; | |
5749c497 | 2074 | } |
f3d817d8 DM |
2075 | |
2076 | return 1; | |
5749c497 KR |
2077 | } |
2078 | ||
f3d817d8 DM |
2079 | void |
2080 | md_show_usage (stream) | |
2081 | FILE *stream; | |
2082 | { | |
2083 | fprintf(stream, "\ | |
2084 | Alpha options:\n\ | |
2085 | -32addr treat addresses as 32-bit values\n\ | |
2086 | -F lack floating point instructions support\n\ | |
2087 | -m21064 | -m21066 | -m21164\n\ | |
a2a1a548 | 2088 | specify variant of Alpha architecture\n"); |
f3d817d8 DM |
2089 | } |
2090 | \f | |
5749c497 KR |
2091 | static void |
2092 | s_proc (is_static) | |
a2a1a548 | 2093 | int is_static; |
5749c497 KR |
2094 | { |
2095 | /* XXXX Align to cache linesize XXXXX */ | |
2096 | char *name; | |
2097 | char c; | |
2098 | char *p; | |
2099 | symbolS *symbolP; | |
2100 | int temp; | |
2101 | ||
2102 | /* Takes ".proc name,nargs" */ | |
2103 | name = input_line_pointer; | |
2104 | c = get_symbol_end (); | |
2105 | p = input_line_pointer; | |
2106 | symbolP = symbol_find_or_make (name); | |
2107 | *p = c; | |
2108 | SKIP_WHITESPACE (); | |
2109 | if (*input_line_pointer != ',') | |
2110 | { | |
2111 | *p = 0; | |
2112 | as_warn ("Expected comma after name \"%s\"", name); | |
2113 | *p = c; | |
2114 | temp = 0; | |
2115 | ignore_rest_of_line (); | |
2116 | } | |
2117 | else | |
2118 | { | |
2119 | input_line_pointer++; | |
2120 | temp = get_absolute_expression (); | |
2121 | } | |
2122 | /* symbolP->sy_other = (signed char) temp; */ | |
2123 | as_warn ("unhandled: .proc %s,%d", name, temp); | |
2124 | demand_empty_rest_of_line (); | |
2125 | } | |
2126 | ||
2127 | static void | |
2128 | s_alpha_set (x) | |
2129 | int x; | |
2130 | { | |
2131 | char *name = input_line_pointer, ch, *s; | |
2132 | int yesno = 1; | |
2133 | ||
2134 | while (!is_end_of_line[(unsigned char) *input_line_pointer]) | |
2135 | input_line_pointer++; | |
2136 | ch = *input_line_pointer; | |
2137 | *input_line_pointer = '\0'; | |
2138 | ||
2139 | s = name; | |
2140 | if (s[0] == 'n' && s[1] == 'o') | |
2141 | { | |
2142 | yesno = 0; | |
2143 | s += 2; | |
2144 | } | |
2145 | if (!strcmp ("reorder", s)) | |
2146 | /* ignore */ ; | |
2147 | else if (!strcmp ("at", s)) | |
2148 | at_ok = yesno; | |
2149 | else if (!strcmp ("macro", s)) | |
2150 | macro_ok = yesno; | |
2151 | else | |
2152 | as_warn ("Tried to set unrecognized symbol: %s", name); | |
2153 | *input_line_pointer = ch; | |
2154 | demand_empty_rest_of_line (); | |
2155 | } | |
2156 | ||
2157 | /* @@ Is this right?? */ | |
2158 | long | |
2159 | md_pcrel_from (fixP) | |
2160 | fixS *fixP; | |
2161 | { | |
2162 | valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; | |
2163 | switch (fixP->fx_r_type) | |
2164 | { | |
2165 | case BFD_RELOC_ALPHA_GPDISP_HI16: | |
2166 | case BFD_RELOC_ALPHA_GPDISP_LO16: | |
2167 | return addr; | |
2168 | default: | |
2169 | return fixP->fx_size + addr; | |
2170 | } | |
2171 | } | |
2172 | ||
2173 | int | |
2174 | alpha_do_align (n, fill) | |
2175 | int n; | |
a2a1a548 | 2176 | const char *fill; |
5749c497 KR |
2177 | { |
2178 | if (!fill | |
2179 | && (now_seg == text_section | |
2180 | || !strcmp (now_seg->name, ".init") | |
2181 | || !strcmp (now_seg->name, ".fini"))) | |
2182 | { | |
4a6e1a39 | 2183 | static const unsigned char nop_pattern[] = { 0x1f, 0x04, 0xff, 0x47 }; |
5749c497 KR |
2184 | frag_align_pattern (n, nop_pattern, sizeof (nop_pattern)); |
2185 | return 1; | |
2186 | } | |
2187 | return 0; | |
2188 | } | |
2189 | ||
2190 | int | |
2191 | md_apply_fix (fixP, valueP) | |
2192 | fixS *fixP; | |
2193 | valueT *valueP; | |
2194 | { | |
2195 | valueT value; | |
2196 | int size; | |
2197 | valueT addend; | |
2198 | char *p = fixP->fx_frag->fr_literal + fixP->fx_where; | |
2199 | ||
2200 | value = *valueP; | |
2201 | ||
2202 | switch (fixP->fx_r_type) | |
2203 | { | |
2204 | /* The GPDISP relocations are processed internally with a symbol | |
2205 | referring to the current function; we need to drop in a value | |
2206 | which, when added to the address of the start of the function, | |
2207 | gives the desired GP. */ | |
2208 | case BFD_RELOC_ALPHA_GPDISP_HI16: | |
2209 | case BFD_RELOC_ALPHA_GPDISP_LO16: | |
2210 | addend = value; | |
2211 | if (fixP->fx_r_type == BFD_RELOC_ALPHA_GPDISP_HI16) | |
2212 | { | |
2213 | assert (fixP->fx_next->fx_r_type == BFD_RELOC_ALPHA_GPDISP_LO16); | |
2214 | #ifdef DEBUG1 | |
2215 | printf ("hi16: "); | |
2216 | fprintf_vma (stdout, addend); | |
2217 | printf ("\n"); | |
2218 | #endif | |
2219 | if (addend & 0x8000) | |
2220 | addend += 0x10000; | |
2221 | addend >>= 16; | |
2222 | fixP->fx_offset = 4; /* @@ Compute this using fx_next. */ | |
2223 | } | |
2224 | else | |
2225 | { | |
2226 | #ifdef DEBUG1 | |
2227 | printf ("lo16: "); | |
2228 | fprintf_vma (stdout, addend); | |
2229 | printf ("\n"); | |
2230 | #endif | |
2231 | addend &= 0xffff; | |
2232 | fixP->fx_offset = 0; | |
2233 | } | |
2234 | md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, | |
2235 | addend, 2); | |
2236 | fixP->fx_addsy = section_symbol (absolute_section); | |
2237 | fixP->fx_offset += fixP->fx_frag->fr_address + fixP->fx_where; | |
2238 | break; | |
2239 | ||
2240 | case BFD_RELOC_8: | |
2241 | /* Write 8 bits, shifted left 13 bit positions. */ | |
2242 | value &= 0xff; | |
2243 | p++; | |
2244 | *p &= 0x1f; | |
2245 | *p |= (value << 5) & 0xe0; | |
2246 | value >>= 3; | |
2247 | p++; | |
2248 | *p &= 0xe0; | |
2249 | *p |= value; | |
2250 | value >>= 5; | |
2251 | fixP->fx_done = 1; | |
5749c497 KR |
2252 | if (value != 0) |
2253 | as_bad_where (fixP->fx_file, fixP->fx_line, | |
2254 | "overflow in type-%d reloc", (int) fixP->fx_r_type); | |
2255 | return 3; | |
2256 | ||
2257 | case BFD_RELOC_32: | |
30869211 KR |
2258 | size = 4; |
2259 | goto do_it; | |
5749c497 | 2260 | case BFD_RELOC_64: |
30869211 KR |
2261 | size = 8; |
2262 | goto do_it; | |
5749c497 KR |
2263 | case BFD_RELOC_16: |
2264 | /* Don't want overflow checking. */ | |
2265 | size = 2; | |
2266 | do_it: | |
2267 | if (fixP->fx_pcrel == 0 | |
2268 | && fixP->fx_addsy == 0) | |
2269 | { | |
2270 | md_number_to_chars (p, value, size); | |
2271 | /* @@ Overflow checks?? */ | |
2272 | goto done; | |
2273 | } | |
2274 | break; | |
2275 | ||
0952861c KR |
2276 | case BFD_RELOC_26: |
2277 | if (fixP->fx_addsy != 0 | |
2278 | && fixP->fx_addsy->bsym->section != absolute_section) | |
2279 | as_bad_where (fixP->fx_file, fixP->fx_line, | |
2280 | "PALcode instructions require immediate constant function code"); | |
2281 | else if (value >> 26 != 0) | |
2282 | as_bad_where (fixP->fx_file, fixP->fx_line, | |
2283 | "overflow in 26-bit PALcode function field"); | |
2284 | *p++ = value & 0xff; | |
2285 | value >>= 8; | |
2286 | *p++ = value & 0xff; | |
2287 | value >>= 8; | |
2288 | *p++ = value & 0xff; | |
2289 | value >>= 8; | |
2290 | { | |
2291 | char x = *p; | |
2292 | x &= ~3; | |
2293 | x |= (value & 3); | |
2294 | *p++ = x; | |
2295 | } | |
2296 | goto done; | |
2297 | ||
5749c497 KR |
2298 | case BFD_RELOC_14: |
2299 | if (fixP->fx_addsy != 0 | |
2300 | && fixP->fx_addsy->bsym->section != absolute_section) | |
2301 | as_bad_where (fixP->fx_file, fixP->fx_line, | |
2302 | "ret/jsr_coroutine requires constant in displacement field"); | |
2303 | else if (value >> 14 != 0) | |
2304 | as_bad_where (fixP->fx_file, fixP->fx_line, | |
2305 | "overflow in 14-bit operand field of ret or jsr_coroutine"); | |
2306 | *p++ = value & 0xff; | |
2307 | value >>= 8; | |
2308 | *p = (*p & 0xc0) | (value & 0x3f); | |
2309 | goto done; | |
2310 | ||
2311 | case BFD_RELOC_23_PCREL_S2: | |
2312 | /* Write 21 bits only. */ | |
2313 | value >>= 2; | |
2314 | *p++ = value & 0xff; | |
2315 | value >>= 8; | |
2316 | *p++ = value & 0xff; | |
2317 | value >>= 8; | |
2318 | *p &= 0xe0; | |
2319 | *p |= (value & 0x1f); | |
2320 | goto done; | |
2321 | ||
2322 | case BFD_RELOC_ALPHA_LITERAL: | |
2323 | case BFD_RELOC_ALPHA_LITUSE: | |
2324 | return 2; | |
2325 | ||
2326 | case BFD_RELOC_GPREL32: | |
2327 | assert (fixP->fx_subsy == gp); | |
c79e67a3 | 2328 | value = - alpha_gp_value; /* huh? this works... */ |
5749c497 KR |
2329 | fixP->fx_subsy = 0; |
2330 | md_number_to_chars (p, value, 4); | |
2331 | break; | |
2332 | ||
2333 | case BFD_RELOC_ALPHA_HINT: | |
2334 | if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) | |
2335 | { | |
2336 | size = 2; | |
2337 | goto do_it; | |
2338 | } | |
2339 | return 2; | |
2340 | ||
2341 | default: | |
2342 | as_fatal ("unknown relocation type %d?", fixP->fx_r_type); | |
2343 | return 9; | |
2344 | } | |
2345 | ||
2346 | if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0) | |
2347 | { | |
2348 | printf ("type %d reloc done?\n", fixP->fx_r_type); | |
2349 | done: | |
2350 | fixP->fx_done = 1; | |
2351 | return 42; | |
2352 | } | |
2353 | ||
2354 | return 0x12345678; | |
2355 | } | |
2356 | ||
2357 | void | |
4a6e1a39 | 2358 | alpha_frob_ecoff_data () |
5749c497 | 2359 | { |
c79e67a3 | 2360 | select_gp_value (); |
5749c497 | 2361 | /* $zero and $f31 are read-only */ |
c79e67a3 KR |
2362 | alpha_gprmask &= ~1; |
2363 | alpha_fprmask &= ~1; | |
5749c497 KR |
2364 | } |
2365 | ||
2366 | /* The Alpha has support for some VAX floating point types, as well as for | |
2367 | IEEE floating point. We consider IEEE to be the primary floating point | |
2368 | format, and sneak in the VAX floating point support here. */ | |
2369 | #define md_atof vax_md_atof | |
2370 | #include "config/atof-vax.c" |