Update year range in copyright notice of binutils files
[deliverable/binutils-gdb.git] / gas / config / tc-microblaze.c
CommitLineData
7ba29e2a
NC
1/* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
2
82704155 3 Copyright (C) 2009-2019 Free Software Foundation, Inc.
7ba29e2a
NC
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
21
7ba29e2a 22#include "as.h"
df7b86aa 23#include <stdio.h>
7ba29e2a
NC
24#include "bfd.h"
25#include "subsegs.h"
26#define DEFINE_TABLE
27#include "../opcodes/microblaze-opc.h"
28#include "../opcodes/microblaze-opcm.h"
e23c5ac0 29#include "safe-ctype.h"
7ba29e2a
NC
30#include <string.h>
31#include <dwarf2dbg.h>
32#include "aout/stab_gnu.h"
33
34#ifndef streq
35#define streq(a,b) (strcmp (a, b) == 0)
36#endif
37
f23200ad
ME
38#define OPTION_EB (OPTION_MD_BASE + 0)
39#define OPTION_EL (OPTION_MD_BASE + 1)
40
7ba29e2a
NC
41void microblaze_generate_symbol (char *sym);
42static bfd_boolean check_spl_reg (unsigned *);
43
44/* Several places in this file insert raw instructions into the
45 object. They should generate the instruction
46 and then use these four macros to crack the instruction value into
47 the appropriate byte values. */
48#define INST_BYTE0(x) (target_big_endian ? (((x) >> 24) & 0xFF) : ((x) & 0xFF))
49#define INST_BYTE1(x) (target_big_endian ? (((x) >> 16) & 0xFF) : (((x) >> 8) & 0xFF))
50#define INST_BYTE2(x) (target_big_endian ? (((x) >> 8) & 0xFF) : (((x) >> 16) & 0xFF))
51#define INST_BYTE3(x) (target_big_endian ? ((x) & 0xFF) : (((x) >> 24) & 0xFF))
52
53/* This array holds the chars that always start a comment. If the
54 pre-processor is disabled, these aren't very useful. */
55const char comment_chars[] = "#";
56
57const char line_separator_chars[] = ";";
58
59/* This array holds the chars that only start a comment at the beginning of
60 a line. */
61const char line_comment_chars[] = "#";
62
63const int md_reloc_size = 8; /* Size of relocation record. */
64
65/* Chars that can be used to separate mant
66 from exp in floating point numbers. */
67const char EXP_CHARS[] = "eE";
68
69/* Chars that mean this number is a floating point constant
70 As in 0f12.456
71 or 0d1.2345e12. */
72const char FLT_CHARS[] = "rRsSfFdDxXpP";
73
74/* INST_PC_OFFSET and INST_NO_OFFSET are 0 and 1. */
75#define UNDEFINED_PC_OFFSET 2
76#define DEFINED_ABS_SEGMENT 3
77#define DEFINED_PC_OFFSET 4
78#define DEFINED_RO_SEGMENT 5
79#define DEFINED_RW_SEGMENT 6
80#define LARGE_DEFINED_PC_OFFSET 7
81#define GOT_OFFSET 8
82#define PLT_OFFSET 9
83#define GOTOFF_OFFSET 10
69b06cc8
ME
84#define TLSGD_OFFSET 11
85#define TLSLD_OFFSET 12
86#define TLSDTPMOD_OFFSET 13
87#define TLSDTPREL_OFFSET 14
88#define TLSGOTTPREL_OFFSET 15
89#define TLSTPREL_OFFSET 16
3f0a5f17
ME
90#define TEXT_OFFSET 17
91#define TEXT_PC_OFFSET 18
7ba29e2a
NC
92
93/* Initialize the relax table. */
94const relax_typeS md_relax_table[] =
95{
96 { 1, 1, 0, 0 }, /* 0: Unused. */
97 { 1, 1, 0, 0 }, /* 1: Unused. */
98 { 1, 1, 0, 0 }, /* 2: Unused. */
99 { 1, 1, 0, 0 }, /* 3: Unused. */
100 { 32767, -32768, INST_WORD_SIZE, LARGE_DEFINED_PC_OFFSET }, /* 4: DEFINED_PC_OFFSET. */
101 { 1, 1, 0, 0 }, /* 5: Unused. */
102 { 1, 1, 0, 0 }, /* 6: Unused. */
103 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 7: LARGE_DEFINED_PC_OFFSET. */
104 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 8: GOT_OFFSET. */
105 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 9: PLT_OFFSET. */
106 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 10: GOTOFF_OFFSET. */
69b06cc8
ME
107 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 11: TLSGD_OFFSET. */
108 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 12: TLSLD_OFFSET. */
109 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*1, 0 }, /* 13: TLSDTPMOD_OFFSET. */
110 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 14: TLSDTPREL_OFFSET. */
111 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 15: TLSGOTTPREL_OFFSET. */
3f0a5f17
ME
112 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 16: TLSTPREL_OFFSET. */
113 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 17: TEXT_OFFSET. */
114 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 18: TEXT_PC_OFFSET. */
7ba29e2a
NC
115};
116
117static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */
118
119static segT sbss_segment = 0; /* Small bss section. */
120static segT sbss2_segment = 0; /* Section not used. */
121static segT sdata_segment = 0; /* Small data section. */
122static segT sdata2_segment = 0; /* Small read-only section. */
123static segT rodata_segment = 0; /* read-only section. */
124
125/* Generate a symbol for stabs information. */
126
127void
128microblaze_generate_symbol (char *sym)
129{
130#define MICROBLAZE_FAKE_LABEL_NAME "XL0\001"
131 static int microblaze_label_count;
132 sprintf (sym, "%sL%d", MICROBLAZE_FAKE_LABEL_NAME, microblaze_label_count);
133 ++microblaze_label_count;
134}
135
136/* Handle the section changing pseudo-ops. */
137
138static void
139microblaze_s_text (int ignore ATTRIBUTE_UNUSED)
140{
141#ifdef OBJ_ELF
142 obj_elf_text (ignore);
143#else
144 s_text (ignore);
145#endif
146}
147
148static void
149microblaze_s_data (int ignore ATTRIBUTE_UNUSED)
150{
151#ifdef OBJ_ELF
a91e1603
L
152 obj_elf_change_section (".data", SHT_PROGBITS, 0, SHF_ALLOC+SHF_WRITE,
153 0, 0, 0, 0);
7ba29e2a
NC
154#else
155 s_data (ignore);
156#endif
157}
158
159/* Things in the .sdata segment are always considered to be in the small data section. */
160
161static void
162microblaze_s_sdata (int ignore ATTRIBUTE_UNUSED)
163{
164#ifdef OBJ_ELF
a91e1603
L
165 obj_elf_change_section (".sdata", SHT_PROGBITS, 0, SHF_ALLOC+SHF_WRITE,
166 0, 0, 0, 0);
7ba29e2a
NC
167#else
168 s_data (ignore);
169#endif
170}
171
172/* Pseudo op to make file scope bss items. */
173
174static void
175microblaze_s_lcomm (int xxx ATTRIBUTE_UNUSED)
176{
177 char *name;
178 char c;
179 char *p;
180 offsetT size;
181 symbolS *symbolP;
182 offsetT align;
7ba29e2a
NC
183 char *pfrag;
184 int align2;
185 segT current_seg = now_seg;
186 subsegT current_subseg = now_subseg;
187
d02603dc 188 c = get_symbol_name (&name);
7ba29e2a
NC
189
190 /* Just after name is now '\0'. */
191 p = input_line_pointer;
d02603dc 192 (void) restore_line_pointer (c);
7ba29e2a
NC
193 SKIP_WHITESPACE ();
194 if (*input_line_pointer != ',')
195 {
196 as_bad (_("Expected comma after symbol-name: rest of line ignored."));
197 ignore_rest_of_line ();
198 return;
199 }
200
201 input_line_pointer++; /* skip ',' */
202 if ((size = get_absolute_expression ()) < 0)
203 {
204 as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size);
205 ignore_rest_of_line ();
206 return;
207 }
208
209 /* The third argument to .lcomm is the alignment. */
210 if (*input_line_pointer != ',')
211 align = 8;
212 else
213 {
214 ++input_line_pointer;
215 align = get_absolute_expression ();
216 if (align <= 0)
217 {
218 as_warn (_("ignoring bad alignment"));
219 align = 8;
220 }
221 }
222
223 *p = 0;
224 symbolP = symbol_find_or_make (name);
225 *p = c;
226
227 if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
228 {
229 as_bad (_("Ignoring attempt to re-define symbol `%s'."),
230 S_GET_NAME (symbolP));
231 ignore_rest_of_line ();
232 return;
233 }
234
235 if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
236 {
237 as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."),
238 S_GET_NAME (symbolP),
239 (long) S_GET_VALUE (symbolP),
240 (long) size);
241
242 ignore_rest_of_line ();
243 return;
244 }
245
246 /* Allocate_bss. */
7ba29e2a
NC
247 if (align)
248 {
249 /* Convert to a power of 2 alignment. */
250 for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
251 if (align != 1)
252 {
253 as_bad (_("Common alignment not a power of 2"));
254 ignore_rest_of_line ();
255 return;
256 }
257 }
258 else
259 align2 = 0;
260
261 record_alignment (current_seg, align2);
262 subseg_set (current_seg, current_subseg);
263 if (align2)
264 frag_align (align2, 0, 0);
265 if (S_GET_SEGMENT (symbolP) == current_seg)
266 symbol_get_frag (symbolP)->fr_symbol = 0;
267 symbol_set_frag (symbolP, frag_now);
268 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
269 (char *) 0);
270 *pfrag = 0;
271 S_SET_SIZE (symbolP, size);
272 S_SET_SEGMENT (symbolP, current_seg);
273 subseg_set (current_seg, current_subseg);
274 demand_empty_rest_of_line ();
275}
276
277static void
278microblaze_s_rdata (int localvar)
279{
280#ifdef OBJ_ELF
281 if (localvar == 0)
282 {
283 /* rodata. */
a91e1603
L
284 obj_elf_change_section (".rodata", SHT_PROGBITS, 0, SHF_ALLOC,
285 0, 0, 0, 0);
7ba29e2a
NC
286 if (rodata_segment == 0)
287 rodata_segment = subseg_new (".rodata", 0);
288 }
289 else
290 {
291 /* 1 .sdata2. */
a91e1603
L
292 obj_elf_change_section (".sdata2", SHT_PROGBITS, 0, SHF_ALLOC,
293 0, 0, 0, 0);
7ba29e2a
NC
294 }
295#else
296 s_data (ignore);
297#endif
298}
299
300static void
301microblaze_s_bss (int localvar)
302{
303#ifdef OBJ_ELF
304 if (localvar == 0) /* bss. */
a91e1603
L
305 obj_elf_change_section (".bss", SHT_NOBITS, 0, SHF_ALLOC+SHF_WRITE,
306 0, 0, 0, 0);
7ba29e2a
NC
307 else if (localvar == 1)
308 {
309 /* sbss. */
a91e1603
L
310 obj_elf_change_section (".sbss", SHT_NOBITS, 0, SHF_ALLOC+SHF_WRITE,
311 0, 0, 0, 0);
7ba29e2a
NC
312 if (sbss_segment == 0)
313 sbss_segment = subseg_new (".sbss", 0);
314 }
315#else
316 s_data (ignore);
317#endif
318}
319
320/* endp_p is always 1 as this func is called only for .end <funcname>
321 This func consumes the <funcname> and calls regular processing
322 s_func(1) with arg 1 (1 for end). */
323
324static void
325microblaze_s_func (int end_p ATTRIBUTE_UNUSED)
326{
d02603dc
NC
327 char *name;
328 restore_line_pointer (get_symbol_name (&name));
7ba29e2a
NC
329 s_func (1);
330}
331
332/* Handle the .weakext pseudo-op as defined in Kane and Heinrich. */
333
334static void
335microblaze_s_weakext (int ignore ATTRIBUTE_UNUSED)
336{
337 char *name;
338 int c;
339 symbolS *symbolP;
340 expressionS exp;
341
d02603dc 342 c = get_symbol_name (&name);
7ba29e2a
NC
343 symbolP = symbol_find_or_make (name);
344 S_SET_WEAK (symbolP);
d02603dc 345 (void) restore_line_pointer (c);
7ba29e2a
NC
346
347 SKIP_WHITESPACE ();
348
349 if (!is_end_of_line[(unsigned char) *input_line_pointer])
350 {
351 if (S_IS_DEFINED (symbolP))
352 {
353 as_bad ("Ignoring attempt to redefine symbol `%s'.",
354 S_GET_NAME (symbolP));
355 ignore_rest_of_line ();
356 return;
357 }
358
359 if (*input_line_pointer == ',')
360 {
361 ++input_line_pointer;
362 SKIP_WHITESPACE ();
363 }
364
365 expression (&exp);
366 if (exp.X_op != O_symbol)
367 {
368 as_bad ("bad .weakext directive");
369 ignore_rest_of_line ();
370 return;
371 }
372 symbol_set_value_expression (symbolP, &exp);
373 }
374
375 demand_empty_rest_of_line ();
376}
377
378/* This table describes all the machine specific pseudo-ops the assembler
379 has to support. The fields are:
380 Pseudo-op name without dot
381 Function to call to execute this pseudo-op
382 Integer arg to pass to the function. */
383/* If the pseudo-op is not found in this table, it searches in the obj-elf.c,
384 and then in the read.c table. */
385const pseudo_typeS md_pseudo_table[] =
386{
387 {"lcomm", microblaze_s_lcomm, 1},
388 {"data", microblaze_s_data, 0},
389 {"data8", cons, 1}, /* Same as byte. */
390 {"data16", cons, 2}, /* Same as hword. */
391 {"data32", cons, 4}, /* Same as word. */
392 {"ent", s_func, 0}, /* Treat ent as function entry point. */
393 {"end", microblaze_s_func, 1}, /* Treat end as function end point. */
394 {"gpword", s_rva, 4}, /* gpword label => store resolved label address in data section. */
395 {"weakext", microblaze_s_weakext, 0},
396 {"rodata", microblaze_s_rdata, 0},
397 {"sdata2", microblaze_s_rdata, 1},
398 {"sdata", microblaze_s_sdata, 0},
399 {"bss", microblaze_s_bss, 0},
400 {"sbss", microblaze_s_bss, 1},
401 {"text", microblaze_s_text, 0},
402 {"word", cons, 4},
403 {"frame", s_ignore, 0},
404 {"mask", s_ignore, 0}, /* Emitted by gcc. */
405 {NULL, NULL, 0}
406};
407
408/* This function is called once, at assembler startup time. This should
409 set up all the tables, etc that the MD part of the assembler needs. */
410
411void
412md_begin (void)
413{
414 struct op_code_struct * opcode;
415
416 opcode_hash_control = hash_new ();
417
418 /* Insert unique names into hash table. */
419 for (opcode = opcodes; opcode->name; opcode ++)
420 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
421}
422
423/* Try to parse a reg name. */
424
425static char *
426parse_reg (char * s, unsigned * reg)
427{
428 unsigned tmpreg = 0;
429
430 /* Strip leading whitespace. */
e23c5ac0 431 while (ISSPACE (* s))
7ba29e2a
NC
432 ++ s;
433
434 if (strncasecmp (s, "rpc", 3) == 0)
435 {
436 *reg = REG_PC;
437 return s + 3;
438 }
439 else if (strncasecmp (s, "rmsr", 4) == 0)
440 {
441 *reg = REG_MSR;
442 return s + 4;
443 }
444 else if (strncasecmp (s, "rear", 4) == 0)
445 {
446 *reg = REG_EAR;
447 return s + 4;
448 }
449 else if (strncasecmp (s, "resr", 4) == 0)
450 {
451 *reg = REG_ESR;
452 return s + 4;
453 }
454 else if (strncasecmp (s, "rfsr", 4) == 0)
455 {
456 *reg = REG_FSR;
457 return s + 4;
458 }
459 else if (strncasecmp (s, "rbtr", 4) == 0)
460 {
461 *reg = REG_BTR;
462 return s + 4;
463 }
464 else if (strncasecmp (s, "redr", 4) == 0)
465 {
466 *reg = REG_EDR;
467 return s + 4;
468 }
469 /* MMU registers start. */
470 else if (strncasecmp (s, "rpid", 4) == 0)
471 {
472 *reg = REG_PID;
473 return s + 4;
474 }
475 else if (strncasecmp (s, "rzpr", 4) == 0)
476 {
477 *reg = REG_ZPR;
478 return s + 4;
479 }
480 else if (strncasecmp (s, "rtlbx", 5) == 0)
481 {
482 *reg = REG_TLBX;
483 return s + 5;
484 }
485 else if (strncasecmp (s, "rtlblo", 6) == 0)
486 {
487 *reg = REG_TLBLO;
488 return s + 6;
489 }
490 else if (strncasecmp (s, "rtlbhi", 6) == 0)
491 {
492 *reg = REG_TLBHI;
493 return s + 6;
494 }
495 else if (strncasecmp (s, "rtlbsx", 6) == 0)
496 {
497 *reg = REG_TLBSX;
498 return s + 6;
499 }
500 /* MMU registers end. */
501 else if (strncasecmp (s, "rpvr", 4) == 0)
502 {
e23c5ac0 503 if (ISDIGIT (s[4]) && ISDIGIT (s[5]))
7ba29e2a
NC
504 {
505 tmpreg = (s[4]-'0')*10 + s[5] - '0';
506 s += 6;
507 }
508
e23c5ac0 509 else if (ISDIGIT (s[4]))
7ba29e2a
NC
510 {
511 tmpreg = s[4] - '0';
512 s += 5;
513 }
514 else
515 as_bad (_("register expected, but saw '%.6s'"), s);
516 if ((int) tmpreg >= MIN_PVR_REGNUM && tmpreg <= MAX_PVR_REGNUM)
517 *reg = REG_PVR + tmpreg;
518 else
519 {
520 as_bad (_("Invalid register number at '%.6s'"), s);
521 *reg = REG_PVR;
522 }
523 return s;
524 }
525 else if (strncasecmp (s, "rsp", 3) == 0)
526 {
527 *reg = REG_SP;
528 return s + 3;
529 }
530 else if (strncasecmp (s, "rfsl", 4) == 0)
531 {
e23c5ac0 532 if (ISDIGIT (s[4]) && ISDIGIT (s[5]))
7ba29e2a
NC
533 {
534 tmpreg = (s[4] - '0') * 10 + s[5] - '0';
535 s += 6;
536 }
e23c5ac0 537 else if (ISDIGIT (s[4]))
7ba29e2a
NC
538 {
539 tmpreg = s[4] - '0';
540 s += 5;
541 }
542 else
543 as_bad (_("register expected, but saw '%.6s'"), s);
544
e23c5ac0 545 if ((int) tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM)
7ba29e2a
NC
546 *reg = tmpreg;
547 else
548 {
549 as_bad (_("Invalid register number at '%.6s'"), s);
550 *reg = 0;
551 }
552 return s;
553 }
0db4b326
ME
554 /* Stack protection registers. */
555 else if (strncasecmp (s, "rshr", 4) == 0)
556 {
557 *reg = REG_SHR;
558 return s + 4;
559 }
560 else if (strncasecmp (s, "rslr", 4) == 0)
561 {
562 *reg = REG_SLR;
563 return s + 4;
564 }
7ba29e2a
NC
565 else
566 {
e23c5ac0 567 if (TOLOWER (s[0]) == 'r')
7ba29e2a 568 {
e23c5ac0 569 if (ISDIGIT (s[1]) && ISDIGIT (s[2]))
7ba29e2a
NC
570 {
571 tmpreg = (s[1] - '0') * 10 + s[2] - '0';
572 s += 3;
573 }
e23c5ac0 574 else if (ISDIGIT (s[1]))
7ba29e2a
NC
575 {
576 tmpreg = s[1] - '0';
577 s += 2;
578 }
579 else
580 as_bad (_("register expected, but saw '%.6s'"), s);
581
582 if ((int)tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM)
583 *reg = tmpreg;
584 else
585 {
586 as_bad (_("Invalid register number at '%.6s'"), s);
587 *reg = 0;
588 }
589 return s;
590 }
591 }
592 as_bad (_("register expected, but saw '%.6s'"), s);
593 *reg = 0;
594 return s;
595}
596
597static char *
598parse_exp (char *s, expressionS *e)
599{
600 char *save;
d3ce72d0 601 char *new_pointer;
7ba29e2a
NC
602
603 /* Skip whitespace. */
e23c5ac0 604 while (ISSPACE (* s))
7ba29e2a
NC
605 ++ s;
606
607 save = input_line_pointer;
608 input_line_pointer = s;
609
610 expression (e);
611
612 if (e->X_op == O_absent)
613 as_fatal (_("missing operand"));
614
d3ce72d0 615 new_pointer = input_line_pointer;
7ba29e2a
NC
616 input_line_pointer = save;
617
d3ce72d0 618 return new_pointer;
7ba29e2a
NC
619}
620
621/* Symbol modifiers (@GOT, @PLT, @GOTOFF). */
69b06cc8 622#define IMM_NONE 0
7ba29e2a
NC
623#define IMM_GOT 1
624#define IMM_PLT 2
625#define IMM_GOTOFF 3
69b06cc8
ME
626#define IMM_TLSGD 4
627#define IMM_TLSLD 5
628#define IMM_TLSDTPMOD 6
629#define IMM_TLSDTPREL 7
630#define IMM_TLSTPREL 8
3f0a5f17
ME
631#define IMM_TXTREL 9
632#define IMM_TXTPCREL 10
633#define IMM_MAX 11
69b06cc8
ME
634
635struct imm_type {
e0471c16 636 const char *isuffix; /* Suffix String */
69b06cc8
ME
637 int itype; /* Suffix Type */
638 int otype; /* Offset Type */
639};
640
33eaf5de 641/* These are NOT in ascending order of type, GOTOFF is ahead to make
69b06cc8
ME
642 sure @GOTOFF does not get matched with @GOT */
643static struct imm_type imm_types[] = {
644 { "NONE", IMM_NONE , 0 },
645 { "GOTOFF", IMM_GOTOFF , GOTOFF_OFFSET },
646 { "GOT", IMM_GOT , GOT_OFFSET },
647 { "PLT", IMM_PLT , PLT_OFFSET },
648 { "TLSGD", IMM_TLSGD , TLSGD_OFFSET },
649 { "TLSLDM", IMM_TLSLD, TLSLD_OFFSET },
650 { "TLSDTPMOD", IMM_TLSDTPMOD, TLSDTPMOD_OFFSET },
651 { "TLSDTPREL", IMM_TLSDTPREL, TLSDTPREL_OFFSET },
3f0a5f17
ME
652 { "TLSTPREL", IMM_TLSTPREL, TLSTPREL_OFFSET },
653 { "TXTREL", IMM_TXTREL, TEXT_OFFSET },
654 { "TXTPCREL", IMM_TXTPCREL, TEXT_PC_OFFSET }
69b06cc8
ME
655};
656
657static int
658match_imm (const char *s, int *ilen)
659{
660 int i;
661 int slen;
662
663 /* Check for matching suffix */
664 for (i = 1; i < IMM_MAX; i++)
665 {
666 slen = strlen (imm_types[i].isuffix);
667
668 if (strncmp (imm_types[i].isuffix, s, slen) == 0)
669 {
670 *ilen = slen;
671 return imm_types[i].itype;
672 }
673 } /* for */
674 *ilen = 0;
675 return 0;
676}
677
678static int
679get_imm_otype (int itype)
680{
681 int i, otype;
682
683 otype = 0;
684 /* Check for matching itype */
685 for (i = 1; i < IMM_MAX; i++)
686 {
687 if (imm_types[i].itype == itype)
688 {
689 otype = imm_types[i].otype;
690 break;
691 }
692 }
693 return otype;
694}
7ba29e2a
NC
695
696static symbolS * GOT_symbol;
697
698#define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_"
699
700static char *
03e08038 701parse_imm (char * s, expressionS * e, offsetT min, offsetT max)
7ba29e2a 702{
d3ce72d0 703 char *new_pointer;
7ba29e2a 704 char *atp;
69b06cc8
ME
705 int itype, ilen;
706
707 ilen = 0;
7ba29e2a
NC
708
709 /* Find the start of "@GOT" or "@PLT" suffix (if any) */
710 for (atp = s; *atp != '@'; atp++)
711 if (is_end_of_line[(unsigned char) *atp])
712 break;
713
714 if (*atp == '@')
715 {
69b06cc8
ME
716 itype = match_imm (atp + 1, &ilen);
717 if (itype != 0)
718 {
719 *atp = 0;
720 e->X_md = itype;
721 }
7ba29e2a 722 else
69b06cc8
ME
723 {
724 atp = NULL;
725 e->X_md = 0;
726 ilen = 0;
727 }
7ba29e2a
NC
728 *atp = 0;
729 }
730 else
731 {
732 atp = NULL;
733 e->X_md = 0;
734 }
735
736 if (atp && !GOT_symbol)
737 {
738 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
739 }
740
d3ce72d0 741 new_pointer = parse_exp (s, e);
7ba29e2a 742
69b06cc8
ME
743 if (!GOT_symbol && ! strncmp (s, GOT_SYMBOL_NAME, 20))
744 {
745 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
746 }
747
7ba29e2a
NC
748 if (e->X_op == O_absent)
749 ; /* An error message has already been emitted. */
750 else if ((e->X_op != O_constant && e->X_op != O_symbol) )
751 as_fatal (_("operand must be a constant or a label"));
f66adc4e 752 else if (e->X_op == O_constant)
7ba29e2a 753 {
ac0d427f 754 /* Special case: sign extend negative 32-bit values to offsetT size. */
f66adc4e 755 if ((e->X_add_number >> 31) == 1)
ac0d427f 756 e->X_add_number |= -((addressT) (1U << 31));
f66adc4e
NC
757
758 if (e->X_add_number < min || e->X_add_number > max)
759 {
760 as_fatal (_("operand must be absolute in range %lx..%lx, not %lx"),
761 (long) min, (long) max, (long) e->X_add_number);
762 }
7ba29e2a
NC
763 }
764
765 if (atp)
766 {
767 *atp = '@'; /* restore back (needed?) */
d3ce72d0 768 if (new_pointer >= atp)
69b06cc8 769 new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */
7ba29e2a 770 }
d3ce72d0 771 return new_pointer;
7ba29e2a
NC
772}
773
774static char *
775check_got (int * got_type, int * got_len)
776{
d3ce72d0 777 char *new_pointer;
7ba29e2a
NC
778 char *atp;
779 char *past_got;
780 int first, second;
781 char *tmpbuf;
782
783 /* Find the start of "@GOT" or "@PLT" suffix (if any). */
784 for (atp = input_line_pointer; *atp != '@'; atp++)
785 if (is_end_of_line[(unsigned char) *atp])
786 return NULL;
787
788 if (strncmp (atp + 1, "GOTOFF", 5) == 0)
789 {
790 *got_len = 6;
791 *got_type = IMM_GOTOFF;
792 }
793 else if (strncmp (atp + 1, "GOT", 3) == 0)
794 {
795 *got_len = 3;
796 *got_type = IMM_GOT;
797 }
798 else if (strncmp (atp + 1, "PLT", 3) == 0)
799 {
800 *got_len = 3;
801 *got_type = IMM_PLT;
802 }
803 else
804 return NULL;
805
806 if (!GOT_symbol)
807 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
808
809 first = atp - input_line_pointer;
810
811 past_got = atp + *got_len + 1;
d3ce72d0 812 for (new_pointer = past_got; !is_end_of_line[(unsigned char) *new_pointer++];)
7ba29e2a 813 ;
d3ce72d0 814 second = new_pointer - past_got;
325801bd
TS
815 /* One extra byte for ' ' and one for NUL. */
816 tmpbuf = XNEWVEC (char, first + second + 2);
7ba29e2a
NC
817 memcpy (tmpbuf, input_line_pointer, first);
818 tmpbuf[first] = ' '; /* @GOTOFF is replaced with a single space. */
819 memcpy (tmpbuf + first + 1, past_got, second);
820 tmpbuf[first + second + 1] = '\0';
821
822 return tmpbuf;
823}
824
62ebcb5c 825extern bfd_reloc_code_real_type
7ba29e2a
NC
826parse_cons_expression_microblaze (expressionS *exp, int size)
827{
828 if (size == 4)
829 {
830 /* Handle @GOTOFF et.al. */
831 char *save, *gotfree_copy;
832 int got_len, got_type;
833
834 save = input_line_pointer;
835 gotfree_copy = check_got (& got_type, & got_len);
836 if (gotfree_copy)
837 input_line_pointer = gotfree_copy;
838
839 expression (exp);
840
841 if (gotfree_copy)
842 {
843 exp->X_md = got_type;
844 input_line_pointer = save + (input_line_pointer - gotfree_copy)
845 + got_len;
846 free (gotfree_copy);
847 }
848 }
849 else
850 expression (exp);
62ebcb5c 851 return BFD_RELOC_NONE;
7ba29e2a
NC
852}
853
854/* This is the guts of the machine-dependent assembler. STR points to a
855 machine dependent instruction. This function is supposed to emit
856 the frags/bytes it assembles to. */
857
e742e119
TS
858static const char * str_microblaze_ro_anchor = "RO";
859static const char * str_microblaze_rw_anchor = "RW";
7ba29e2a
NC
860
861static bfd_boolean
862check_spl_reg (unsigned * reg)
863{
864 if ((*reg == REG_MSR) || (*reg == REG_PC)
865 || (*reg == REG_EAR) || (*reg == REG_ESR)
866 || (*reg == REG_FSR) || (*reg == REG_BTR) || (*reg == REG_EDR)
867 || (*reg == REG_PID) || (*reg == REG_ZPR)
868 || (*reg == REG_TLBX) || (*reg == REG_TLBLO)
869 || (*reg == REG_TLBHI) || (*reg == REG_TLBSX)
0db4b326 870 || (*reg == REG_SHR) || (*reg == REG_SLR)
7ba29e2a
NC
871 || (*reg >= REG_PVR+MIN_PVR_REGNUM && *reg <= REG_PVR+MAX_PVR_REGNUM))
872 return TRUE;
873
874 return FALSE;
875}
876
877/* Here we decide which fixups can be adjusted to make them relative to
878 the beginning of the section instead of the symbol. Basically we need
879 to make sure that the dynamic relocations are done correctly, so in
880 some cases we force the original symbol to be used. */
881
882int
883tc_microblaze_fix_adjustable (struct fix *fixP)
884{
885 if (GOT_symbol && fixP->fx_subsy == GOT_symbol)
886 return 0;
887
888 if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF
889 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF
890 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT
69b06cc8
ME
891 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PLT
892 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGD
893 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSLD
894 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPMOD
895 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPREL
896 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSDTPREL
897 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL
898 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSTPREL)
7ba29e2a
NC
899 return 0;
900
901 return 1;
902}
903
904void
905md_assemble (char * str)
906{
907 char * op_start;
908 char * op_end;
909 struct op_code_struct * opcode, *opcode1;
910 char * output = NULL;
911 int nlen = 0;
912 int i;
913 unsigned long inst, inst1;
914 unsigned reg1;
915 unsigned reg2;
916 unsigned reg3;
917 unsigned isize;
c7d6f518 918 unsigned int immed, temp;
7ba29e2a
NC
919 expressionS exp;
920 char name[20];
921
922 /* Drop leading whitespace. */
e23c5ac0 923 while (ISSPACE (* str))
7ba29e2a
NC
924 str ++;
925
926 /* Find the op code end. */
927 for (op_start = op_end = str;
4ad7ac30 928 *op_end && !is_end_of_line[(unsigned char) *op_end] && *op_end != ' ';
7ba29e2a
NC
929 op_end++)
930 {
931 name[nlen] = op_start[nlen];
932 nlen++;
4ad7ac30
AM
933 if (nlen == sizeof (name) - 1)
934 break;
7ba29e2a
NC
935 }
936
937 name [nlen] = 0;
938
939 if (nlen == 0)
940 {
941 as_bad (_("can't find opcode "));
942 return;
943 }
944
945 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, name);
946 if (opcode == NULL)
947 {
948 as_bad (_("unknown opcode \"%s\""), name);
949 return;
950 }
951
952 inst = opcode->bit_sequence;
953 isize = 4;
954
955 switch (opcode->inst_type)
956 {
957 case INST_TYPE_RD_R1_R2:
958 if (strcmp (op_end, ""))
959 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
960 else
961 {
962 as_fatal (_("Error in statement syntax"));
963 reg1 = 0;
964 }
965 if (strcmp (op_end, ""))
966 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
967 else
968 {
969 as_fatal (_("Error in statement syntax"));
970 reg2 = 0;
971 }
972 if (strcmp (op_end, ""))
973 op_end = parse_reg (op_end + 1, &reg3); /* Get r2. */
974 else
975 {
976 as_fatal (_("Error in statement syntax"));
977 reg3 = 0;
978 }
979
980 /* Check for spl registers. */
981 if (check_spl_reg (& reg1))
982 as_fatal (_("Cannot use special register with this instruction"));
983 if (check_spl_reg (& reg2))
984 as_fatal (_("Cannot use special register with this instruction"));
985 if (check_spl_reg (& reg3))
986 as_fatal (_("Cannot use special register with this instruction"));
987
988 if (streq (name, "sub"))
989 {
990 /* sub rd, r1, r2 becomes rsub rd, r2, r1. */
991 inst |= (reg1 << RD_LOW) & RD_MASK;
992 inst |= (reg3 << RA_LOW) & RA_MASK;
993 inst |= (reg2 << RB_LOW) & RB_MASK;
994 }
995 else
996 {
997 inst |= (reg1 << RD_LOW) & RD_MASK;
998 inst |= (reg2 << RA_LOW) & RA_MASK;
999 inst |= (reg3 << RB_LOW) & RB_MASK;
1000 }
1001 output = frag_more (isize);
1002 break;
1003
1004 case INST_TYPE_RD_R1_IMM:
1005 if (strcmp (op_end, ""))
1006 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1007 else
1008 {
1009 as_fatal (_("Error in statement syntax"));
1010 reg1 = 0;
1011 }
1012 if (strcmp (op_end, ""))
1013 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1014 else
1015 {
1016 as_fatal (_("Error in statement syntax"));
1017 reg2 = 0;
1018 }
1019 if (strcmp (op_end, ""))
1020 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1021 else
1022 as_fatal (_("Error in statement syntax"));
1023
1024 /* Check for spl registers. */
1025 if (check_spl_reg (& reg1))
1026 as_fatal (_("Cannot use special register with this instruction"));
1027 if (check_spl_reg (& reg2))
1028 as_fatal (_("Cannot use special register with this instruction"));
1029
3f0a5f17 1030 if (exp.X_op != O_constant || exp.X_md == IMM_TXTPCREL)
7ba29e2a 1031 {
e742e119 1032 const char *opc;
7ba29e2a
NC
1033 relax_substateT subtype;
1034
1035 if (streq (name, "lmi"))
1036 as_fatal (_("lmi pseudo instruction should not use a label in imm field"));
1037 else if (streq (name, "smi"))
1038 as_fatal (_("smi pseudo instruction should not use a label in imm field"));
1039
1040 if (reg2 == REG_ROSDP)
1041 opc = str_microblaze_ro_anchor;
1042 else if (reg2 == REG_RWSDP)
1043 opc = str_microblaze_rw_anchor;
1044 else
1045 opc = NULL;
69b06cc8
ME
1046 if (exp.X_md != 0)
1047 subtype = get_imm_otype(exp.X_md);
7ba29e2a
NC
1048 else
1049 subtype = opcode->inst_offset_type;
1050
1051 output = frag_var (rs_machine_dependent,
1052 isize * 2, /* maxm of 2 words. */
1053 isize, /* minm of 1 word. */
1054 subtype, /* PC-relative or not. */
1055 exp.X_add_symbol,
1056 exp.X_add_number,
e742e119 1057 (char *) opc);
c7d6f518 1058 immed = 0;
7ba29e2a
NC
1059 }
1060 else
1061 {
1062 output = frag_more (isize);
c7d6f518 1063 immed = exp.X_add_number;
7ba29e2a
NC
1064 }
1065
1066 if (streq (name, "lmi") || streq (name, "smi"))
1067 {
1068 /* Load/store 32-d consecutive registers. Used on exit/entry
1069 to subroutines to save and restore registers to stack.
1070 Generate 32-d insts. */
1071 int count;
1072
1073 count = 32 - reg1;
1074 if (streq (name, "lmi"))
1075 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, "lwi");
1076 else
1077 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, "swi");
1078 if (opcode == NULL)
1079 {
1080 as_bad (_("unknown opcode \"%s\""), "lwi");
1081 return;
1082 }
1083 inst = opcode->bit_sequence;
1084 inst |= (reg1 << RD_LOW) & RD_MASK;
1085 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1086 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1087
1088 for (i = 0; i < count - 1; i++)
1089 {
1090 output[0] = INST_BYTE0 (inst);
1091 output[1] = INST_BYTE1 (inst);
1092 output[2] = INST_BYTE2 (inst);
1093 output[3] = INST_BYTE3 (inst);
1094 output = frag_more (isize);
c7d6f518 1095 immed = immed + 4;
7ba29e2a
NC
1096 reg1++;
1097 inst = opcode->bit_sequence;
1098 inst |= (reg1 << RD_LOW) & RD_MASK;
1099 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1100 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1101 }
1102 }
1103 else
1104 {
c7d6f518 1105 temp = immed & 0xFFFF8000;
7ba29e2a
NC
1106 if ((temp != 0) && (temp != 0xFFFF8000))
1107 {
1108 /* Needs an immediate inst. */
1109 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1110 if (opcode1 == NULL)
1111 {
1112 as_bad (_("unknown opcode \"%s\""), "imm");
1113 return;
1114 }
1115
1116 inst1 = opcode1->bit_sequence;
c7d6f518 1117 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
7ba29e2a
NC
1118 output[0] = INST_BYTE0 (inst1);
1119 output[1] = INST_BYTE1 (inst1);
1120 output[2] = INST_BYTE2 (inst1);
1121 output[3] = INST_BYTE3 (inst1);
1122 output = frag_more (isize);
1123 }
1124 inst |= (reg1 << RD_LOW) & RD_MASK;
1125 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1126 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1127 }
1128 break;
1129
1130 case INST_TYPE_RD_R1_IMM5:
1131 if (strcmp (op_end, ""))
1132 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1133 else
1134 {
1135 as_fatal (_("Error in statement syntax"));
1136 reg1 = 0;
1137 }
1138 if (strcmp (op_end, ""))
1139 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1140 else
1141 {
1142 as_fatal (_("Error in statement syntax"));
1143 reg2 = 0;
1144 }
1145 if (strcmp (op_end, ""))
1146 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1147 else
1148 as_fatal (_("Error in statement syntax"));
1149
1150 /* Check for spl registers. */
1151 if (check_spl_reg (&reg1))
1152 as_fatal (_("Cannot use special register with this instruction"));
1153 if (check_spl_reg (&reg2))
1154 as_fatal (_("Cannot use special register with this instruction"));
1155
1156 if (exp.X_op != O_constant)
1157 as_warn (_("Symbol used as immediate for shift instruction"));
1158 else
1159 {
1160 output = frag_more (isize);
c7d6f518 1161 immed = exp.X_add_number;
7ba29e2a
NC
1162 }
1163
c7d6f518 1164 if (immed != (immed % 32))
7ba29e2a
NC
1165 {
1166 as_warn (_("Shift value > 32. using <value %% 32>"));
c7d6f518 1167 immed = immed % 32;
7ba29e2a
NC
1168 }
1169 inst |= (reg1 << RD_LOW) & RD_MASK;
1170 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1171 inst |= (immed << IMM_LOW) & IMM5_MASK;
7ba29e2a
NC
1172 break;
1173
1174 case INST_TYPE_R1_R2:
1175 if (strcmp (op_end, ""))
1176 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1177 else
1178 {
1179 as_fatal (_("Error in statement syntax"));
1180 reg1 = 0;
1181 }
1182 if (strcmp (op_end, ""))
1183 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1184 else
1185 {
1186 as_fatal (_("Error in statement syntax"));
1187 reg2 = 0;
1188 }
1189
1190 /* Check for spl registers. */
1191 if (check_spl_reg (& reg1))
1192 as_fatal (_("Cannot use special register with this instruction"));
1193 if (check_spl_reg (& reg2))
1194 as_fatal (_("Cannot use special register with this instruction"));
1195
1196 inst |= (reg1 << RA_LOW) & RA_MASK;
1197 inst |= (reg2 << RB_LOW) & RB_MASK;
1198 output = frag_more (isize);
1199 break;
1200
1201 case INST_TYPE_RD_R1:
1202 if (strcmp (op_end, ""))
1203 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1204 else
1205 {
1206 as_fatal (_("Error in statement syntax"));
1207 reg1 = 0;
1208 }
1209 if (strcmp (op_end, ""))
1210 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1211 else
1212 {
1213 as_fatal (_("Error in statement syntax"));
1214 reg2 =0;
1215 }
1216
1217 /* Check for spl registers. */
1218 if (check_spl_reg (&reg1))
1219 as_fatal (_("Cannot use special register with this instruction"));
1220 if (check_spl_reg (&reg2))
1221 as_fatal (_("Cannot use special register with this instruction"));
1222
1223 inst |= (reg1 << RD_LOW) & RD_MASK;
1224 inst |= (reg2 << RA_LOW) & RA_MASK;
1225 output = frag_more (isize);
1226 break;
1227
1228 case INST_TYPE_RD_RFSL:
1229 if (strcmp (op_end, ""))
1230 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1231 else
1232 {
1233 as_fatal (_("Error in statement syntax"));
1234 reg1 = 0;
1235 }
1236 if (strcmp (op_end, ""))
c7d6f518 1237 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
7ba29e2a
NC
1238 else
1239 {
1240 as_fatal (_("Error in statement syntax"));
c7d6f518 1241 immed = 0;
7ba29e2a
NC
1242 }
1243
1244 /* Check for spl registers. */
1245 if (check_spl_reg (&reg1))
1246 as_fatal (_("Cannot use special register with this instruction"));
1247
1248 inst |= (reg1 << RD_LOW) & RD_MASK;
c7d6f518 1249 inst |= (immed << IMM_LOW) & RFSL_MASK;
7ba29e2a
NC
1250 output = frag_more (isize);
1251 break;
1252
1253 case INST_TYPE_RD_IMM15:
1254 if (strcmp (op_end, ""))
1255 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1256 else
1257 {
1258 as_fatal (_("Error in statement syntax"));
1259 reg1 = 0;
1260 }
1261
1262 if (strcmp (op_end, ""))
1263 op_end = parse_imm (op_end + 1, & exp, MIN_IMM15, MAX_IMM15);
1264 else
1265 as_fatal (_("Error in statement syntax"));
1266
1267 /* Check for spl registers. */
1268 if (check_spl_reg (&reg1))
1269 as_fatal (_("Cannot use special register with this instruction"));
1270
1271 if (exp.X_op != O_constant)
1272 as_fatal (_("Symbol used as immediate value for msrset/msrclr instructions"));
1273 else
1274 {
1275 output = frag_more (isize);
c7d6f518 1276 immed = exp.X_add_number;
7ba29e2a
NC
1277 }
1278 inst |= (reg1 << RD_LOW) & RD_MASK;
c7d6f518 1279 inst |= (immed << IMM_LOW) & IMM15_MASK;
7ba29e2a
NC
1280 break;
1281
1282 case INST_TYPE_R1_RFSL:
1283 if (strcmp (op_end, ""))
1284 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1285 else
1286 {
1287 as_fatal (_("Error in statement syntax"));
1288 reg1 = 0;
1289 }
1290 if (strcmp (op_end, ""))
c7d6f518 1291 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
7ba29e2a
NC
1292 else
1293 {
1294 as_fatal (_("Error in statement syntax"));
c7d6f518 1295 immed = 0;
7ba29e2a
NC
1296 }
1297
1298 /* Check for spl registers. */
1299 if (check_spl_reg (&reg1))
1300 as_fatal (_("Cannot use special register with this instruction"));
1301
1302 inst |= (reg1 << RA_LOW) & RA_MASK;
c7d6f518 1303 inst |= (immed << IMM_LOW) & RFSL_MASK;
7ba29e2a
NC
1304 output = frag_more (isize);
1305 break;
1306
1307 case INST_TYPE_RFSL:
1308 if (strcmp (op_end, ""))
c7d6f518 1309 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
7ba29e2a
NC
1310 else
1311 {
1312 as_fatal (_("Error in statement syntax"));
c7d6f518 1313 immed = 0;
7ba29e2a 1314 }
c7d6f518 1315 inst |= (immed << IMM_LOW) & RFSL_MASK;
7ba29e2a
NC
1316 output = frag_more (isize);
1317 break;
1318
1319 case INST_TYPE_R1:
1320 if (strcmp (op_end, ""))
1321 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1322 else
1323 {
1324 as_fatal (_("Error in statement syntax"));
1325 reg1 = 0;
1326 }
1327
1328 /* Check for spl registers. */
1329 if (check_spl_reg (&reg1))
1330 as_fatal (_("Cannot use special register with this instruction"));
1331
1332 inst |= (reg1 << RA_LOW) & RA_MASK;
1333 output = frag_more (isize);
1334 break;
1335
1336 /* For tuqula insn...:) */
1337 case INST_TYPE_RD:
1338 if (strcmp (op_end, ""))
1339 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1340 else
1341 {
1342 as_fatal (_("Error in statement syntax"));
1343 reg1 = 0;
1344 }
1345
1346 /* Check for spl registers. */
1347 if (check_spl_reg (&reg1))
1348 as_fatal (_("Cannot use special register with this instruction"));
1349
1350 inst |= (reg1 << RD_LOW) & RD_MASK;
1351 output = frag_more (isize);
1352 break;
1353
1354 case INST_TYPE_RD_SPECIAL:
1355 if (strcmp (op_end, ""))
1356 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1357 else
1358 {
1359 as_fatal (_("Error in statement syntax"));
1360 reg1 = 0;
1361 }
1362 if (strcmp (op_end, ""))
1363 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1364 else
1365 {
1366 as_fatal (_("Error in statement syntax"));
1367 reg2 = 0;
1368 }
1369
1370 if (reg2 == REG_MSR)
c7d6f518 1371 immed = opcode->immval_mask | REG_MSR_MASK;
7ba29e2a 1372 else if (reg2 == REG_PC)
c7d6f518 1373 immed = opcode->immval_mask | REG_PC_MASK;
7ba29e2a 1374 else if (reg2 == REG_EAR)
c7d6f518 1375 immed = opcode->immval_mask | REG_EAR_MASK;
7ba29e2a 1376 else if (reg2 == REG_ESR)
c7d6f518 1377 immed = opcode->immval_mask | REG_ESR_MASK;
7ba29e2a 1378 else if (reg2 == REG_FSR)
c7d6f518 1379 immed = opcode->immval_mask | REG_FSR_MASK;
7ba29e2a 1380 else if (reg2 == REG_BTR)
c7d6f518 1381 immed = opcode->immval_mask | REG_BTR_MASK;
7ba29e2a 1382 else if (reg2 == REG_EDR)
c7d6f518 1383 immed = opcode->immval_mask | REG_EDR_MASK;
7ba29e2a 1384 else if (reg2 == REG_PID)
c7d6f518 1385 immed = opcode->immval_mask | REG_PID_MASK;
7ba29e2a 1386 else if (reg2 == REG_ZPR)
c7d6f518 1387 immed = opcode->immval_mask | REG_ZPR_MASK;
7ba29e2a 1388 else if (reg2 == REG_TLBX)
c7d6f518 1389 immed = opcode->immval_mask | REG_TLBX_MASK;
7ba29e2a 1390 else if (reg2 == REG_TLBLO)
c7d6f518 1391 immed = opcode->immval_mask | REG_TLBLO_MASK;
7ba29e2a 1392 else if (reg2 == REG_TLBHI)
c7d6f518 1393 immed = opcode->immval_mask | REG_TLBHI_MASK;
0db4b326
ME
1394 else if (reg2 == REG_SHR)
1395 immed = opcode->immval_mask | REG_SHR_MASK;
1396 else if (reg2 == REG_SLR)
1397 immed = opcode->immval_mask | REG_SLR_MASK;
7ba29e2a 1398 else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM))
c7d6f518 1399 immed = opcode->immval_mask | REG_PVR_MASK | reg2;
7ba29e2a
NC
1400 else
1401 as_fatal (_("invalid value for special purpose register"));
1402 inst |= (reg1 << RD_LOW) & RD_MASK;
c7d6f518 1403 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1404 output = frag_more (isize);
1405 break;
1406
1407 case INST_TYPE_SPECIAL_R1:
1408 if (strcmp (op_end, ""))
1409 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1410 else
1411 {
1412 as_fatal (_("Error in statement syntax"));
1413 reg1 = 0;
1414 }
1415 if (strcmp (op_end, ""))
1416 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1417 else
1418 {
1419 as_fatal (_("Error in statement syntax"));
1420 reg2 = 0;
1421 }
1422
1423 if (reg1 == REG_MSR)
c7d6f518 1424 immed = opcode->immval_mask | REG_MSR_MASK;
7ba29e2a 1425 else if (reg1 == REG_PC)
c7d6f518 1426 immed = opcode->immval_mask | REG_PC_MASK;
7ba29e2a 1427 else if (reg1 == REG_EAR)
c7d6f518 1428 immed = opcode->immval_mask | REG_EAR_MASK;
7ba29e2a 1429 else if (reg1 == REG_ESR)
c7d6f518 1430 immed = opcode->immval_mask | REG_ESR_MASK;
7ba29e2a 1431 else if (reg1 == REG_FSR)
c7d6f518 1432 immed = opcode->immval_mask | REG_FSR_MASK;
7ba29e2a 1433 else if (reg1 == REG_BTR)
c7d6f518 1434 immed = opcode->immval_mask | REG_BTR_MASK;
7ba29e2a 1435 else if (reg1 == REG_EDR)
c7d6f518 1436 immed = opcode->immval_mask | REG_EDR_MASK;
7ba29e2a 1437 else if (reg1 == REG_PID)
c7d6f518 1438 immed = opcode->immval_mask | REG_PID_MASK;
7ba29e2a 1439 else if (reg1 == REG_ZPR)
c7d6f518 1440 immed = opcode->immval_mask | REG_ZPR_MASK;
7ba29e2a 1441 else if (reg1 == REG_TLBX)
c7d6f518 1442 immed = opcode->immval_mask | REG_TLBX_MASK;
7ba29e2a 1443 else if (reg1 == REG_TLBLO)
c7d6f518 1444 immed = opcode->immval_mask | REG_TLBLO_MASK;
7ba29e2a 1445 else if (reg1 == REG_TLBHI)
c7d6f518 1446 immed = opcode->immval_mask | REG_TLBHI_MASK;
7ba29e2a 1447 else if (reg1 == REG_TLBSX)
c7d6f518 1448 immed = opcode->immval_mask | REG_TLBSX_MASK;
0db4b326
ME
1449 else if (reg1 == REG_SHR)
1450 immed = opcode->immval_mask | REG_SHR_MASK;
1451 else if (reg1 == REG_SLR)
1452 immed = opcode->immval_mask | REG_SLR_MASK;
7ba29e2a
NC
1453 else
1454 as_fatal (_("invalid value for special purpose register"));
1455 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1456 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1457 output = frag_more (isize);
1458 break;
1459
94dda8b7 1460 case INST_TYPE_R1_R2_SPECIAL:
7ba29e2a 1461 if (strcmp (op_end, ""))
94dda8b7 1462 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
7ba29e2a
NC
1463 else
1464 {
1465 as_fatal (_("Error in statement syntax"));
1466 reg1 = 0;
1467 }
1468 if (strcmp (op_end, ""))
94dda8b7 1469 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
7ba29e2a
NC
1470 else
1471 {
1472 as_fatal (_("Error in statement syntax"));
1473 reg2 =0;
1474 }
1475
1476 /* Check for spl registers. */
1477 if (check_spl_reg (&reg1))
1478 as_fatal (_("Cannot use special register with this instruction"));
1479 if (check_spl_reg (&reg2))
1480 as_fatal (_("Cannot use special register with this instruction"));
1481
1482 /* insn wic ra, rb => wic ra, ra, rb. */
7ba29e2a
NC
1483 inst |= (reg1 << RA_LOW) & RA_MASK;
1484 inst |= (reg2 << RB_LOW) & RB_MASK;
1485
1486 output = frag_more (isize);
1487 break;
1488
1489 case INST_TYPE_RD_R2:
1490 if (strcmp (op_end, ""))
1491 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1492 else
1493 {
1494 as_fatal (_("Error in statement syntax"));
1495 reg1 = 0;
1496 }
1497 if (strcmp (op_end, ""))
1498 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1499 else
1500 {
1501 as_fatal (_("Error in statement syntax"));
1502 reg2 = 0;
1503 }
1504
1505 /* Check for spl registers. */
1506 if (check_spl_reg (&reg1))
1507 as_fatal (_("Cannot use special register with this instruction"));
1508 if (check_spl_reg (&reg2))
1509 as_fatal (_("Cannot use special register with this instruction"));
1510
1511 inst |= (reg1 << RD_LOW) & RD_MASK;
1512 inst |= (reg2 << RB_LOW) & RB_MASK;
1513 output = frag_more (isize);
1514 break;
1515
1516 case INST_TYPE_R1_IMM:
1517 if (strcmp (op_end, ""))
1518 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1519 else
1520 {
1521 as_fatal (_("Error in statement syntax"));
1522 reg1 = 0;
1523 }
1524 if (strcmp (op_end, ""))
1525 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1526 else
1527 as_fatal (_("Error in statement syntax"));
1528
1529 /* Check for spl registers. */
1530 if (check_spl_reg (&reg1))
1531 as_fatal (_("Cannot use special register with this instruction"));
1532
1533 if (exp.X_op != O_constant)
1534 {
1535 char *opc = NULL;
1536 relax_substateT subtype;
1537
69b06cc8
ME
1538 if (exp.X_md != 0)
1539 subtype = get_imm_otype(exp.X_md);
7ba29e2a
NC
1540 else
1541 subtype = opcode->inst_offset_type;
69b06cc8 1542
7ba29e2a
NC
1543 output = frag_var (rs_machine_dependent,
1544 isize * 2, /* maxm of 2 words. */
1545 isize, /* minm of 1 word. */
1546 subtype, /* PC-relative or not. */
1547 exp.X_add_symbol,
1548 exp.X_add_number,
1549 opc);
c7d6f518 1550 immed = 0;
7ba29e2a
NC
1551 }
1552 else
1553 {
1554 output = frag_more (isize);
c7d6f518 1555 immed = exp.X_add_number;
7ba29e2a
NC
1556 }
1557
c7d6f518 1558 temp = immed & 0xFFFF8000;
7ba29e2a
NC
1559 if ((temp != 0) && (temp != 0xFFFF8000))
1560 {
1561 /* Needs an immediate inst. */
1562 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1563 if (opcode1 == NULL)
1564 {
1565 as_bad (_("unknown opcode \"%s\""), "imm");
1566 return;
1567 }
1568
1569 inst1 = opcode1->bit_sequence;
c7d6f518 1570 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
7ba29e2a
NC
1571 output[0] = INST_BYTE0 (inst1);
1572 output[1] = INST_BYTE1 (inst1);
1573 output[2] = INST_BYTE2 (inst1);
1574 output[3] = INST_BYTE3 (inst1);
1575 output = frag_more (isize);
1576 }
1577
1578 inst |= (reg1 << RA_LOW) & RA_MASK;
c7d6f518 1579 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1580 break;
1581
1582 case INST_TYPE_RD_IMM:
1583 if (strcmp (op_end, ""))
1584 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1585 else
1586 {
1587 as_fatal (_("Error in statement syntax"));
1588 reg1 = 0;
1589 }
1590 if (strcmp (op_end, ""))
1591 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1592 else
1593 as_fatal (_("Error in statement syntax"));
1594
1595 /* Check for spl registers. */
1596 if (check_spl_reg (&reg1))
1597 as_fatal (_("Cannot use special register with this instruction"));
1598
1599 if (exp.X_op != O_constant)
1600 {
1601 char *opc = NULL;
1602 relax_substateT subtype;
1603
69b06cc8
ME
1604 if (exp.X_md != 0)
1605 subtype = get_imm_otype(exp.X_md);
1606 else
7ba29e2a 1607 subtype = opcode->inst_offset_type;
69b06cc8 1608
7ba29e2a
NC
1609 output = frag_var (rs_machine_dependent,
1610 isize * 2, /* maxm of 2 words. */
1611 isize, /* minm of 1 word. */
1612 subtype, /* PC-relative or not. */
1613 exp.X_add_symbol,
1614 exp.X_add_number,
1615 opc);
c7d6f518 1616 immed = 0;
7ba29e2a
NC
1617 }
1618 else
1619 {
1620 output = frag_more (isize);
c7d6f518 1621 immed = exp.X_add_number;
7ba29e2a
NC
1622 }
1623
c7d6f518 1624 temp = immed & 0xFFFF8000;
7ba29e2a
NC
1625 if ((temp != 0) && (temp != 0xFFFF8000))
1626 {
1627 /* Needs an immediate inst. */
1628 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1629 if (opcode1 == NULL)
1630 {
1631 as_bad (_("unknown opcode \"%s\""), "imm");
1632 return;
1633 }
1634
1635 inst1 = opcode1->bit_sequence;
c7d6f518 1636 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
7ba29e2a
NC
1637 output[0] = INST_BYTE0 (inst1);
1638 output[1] = INST_BYTE1 (inst1);
1639 output[2] = INST_BYTE2 (inst1);
1640 output[3] = INST_BYTE3 (inst1);
1641 output = frag_more (isize);
1642 }
1643
1644 inst |= (reg1 << RD_LOW) & RD_MASK;
c7d6f518 1645 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1646 break;
1647
1648 case INST_TYPE_R2:
1649 if (strcmp (op_end, ""))
1650 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1651 else
1652 {
1653 as_fatal (_("Error in statement syntax"));
1654 reg2 = 0;
1655 }
1656
1657 /* Check for spl registers. */
1658 if (check_spl_reg (&reg2))
1659 as_fatal (_("Cannot use special register with this instruction"));
1660
1661 inst |= (reg2 << RB_LOW) & RB_MASK;
1662 output = frag_more (isize);
1663 break;
1664
1665 case INST_TYPE_IMM:
1666 if (streq (name, "imm"))
1667 as_fatal (_("An IMM instruction should not be present in the .s file"));
1668
1669 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1670
1671 if (exp.X_op != O_constant)
1672 {
1673 char *opc = NULL;
1674 relax_substateT subtype;
1675
69b06cc8
ME
1676 if (exp.X_md != 0)
1677 subtype = get_imm_otype(exp.X_md);
1678 else
1679 subtype = opcode->inst_offset_type;
1680
7ba29e2a
NC
1681 output = frag_var (rs_machine_dependent,
1682 isize * 2, /* maxm of 2 words. */
1683 isize, /* minm of 1 word. */
1684 subtype, /* PC-relative or not. */
1685 exp.X_add_symbol,
1686 exp.X_add_number,
1687 opc);
c7d6f518 1688 immed = 0;
7ba29e2a
NC
1689 }
1690 else
1691 {
1692 output = frag_more (isize);
c7d6f518 1693 immed = exp.X_add_number;
7ba29e2a
NC
1694 }
1695
1696
c7d6f518 1697 temp = immed & 0xFFFF8000;
7ba29e2a
NC
1698 if ((temp != 0) && (temp != 0xFFFF8000))
1699 {
1700 /* Needs an immediate inst. */
1701 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1702 if (opcode1 == NULL)
1703 {
1704 as_bad (_("unknown opcode \"%s\""), "imm");
1705 return;
1706 }
1707
1708 inst1 = opcode1->bit_sequence;
c7d6f518 1709 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
7ba29e2a
NC
1710 output[0] = INST_BYTE0 (inst1);
1711 output[1] = INST_BYTE1 (inst1);
1712 output[2] = INST_BYTE2 (inst1);
1713 output[3] = INST_BYTE3 (inst1);
1714 output = frag_more (isize);
1715 }
c7d6f518 1716 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1717 break;
1718
1719 case INST_TYPE_NONE:
1720 output = frag_more (isize);
1721 break;
1722
d3da7741
ME
1723 case INST_TYPE_IMM5:
1724 if (strcmp(op_end, ""))
1725 op_end = parse_imm (op_end + 1, & exp, MIN_IMM5, MAX_IMM5);
1726 else
1727 as_fatal(_("Error in statement syntax"));
1728 if (exp.X_op != O_constant) {
1729 as_warn(_("Symbol used as immediate for mbar instruction"));
1730 } else {
1731 output = frag_more (isize);
1732 immed = exp.X_add_number;
1733 }
1734 if (immed != (immed % 32)) {
1735 as_warn(_("Immediate value for mbar > 32. using <value %% 32>"));
1736 immed = immed % 32;
1737 }
1738 inst |= (immed << IMM_MBAR);
1739 break;
1740
7ba29e2a
NC
1741 default:
1742 as_fatal (_("unimplemented opcode \"%s\""), name);
1743 }
1744
1745 /* Drop whitespace after all the operands have been parsed. */
e23c5ac0 1746 while (ISSPACE (* op_end))
7ba29e2a
NC
1747 op_end ++;
1748
1749 /* Give warning message if the insn has more operands than required. */
1750 if (strcmp (op_end, opcode->name) && strcmp (op_end, ""))
1751 as_warn (_("ignoring operands: %s "), op_end);
1752
1753 output[0] = INST_BYTE0 (inst);
1754 output[1] = INST_BYTE1 (inst);
1755 output[2] = INST_BYTE2 (inst);
1756 output[3] = INST_BYTE3 (inst);
1757
1758#ifdef OBJ_ELF
1759 dwarf2_emit_insn (4);
1760#endif
1761}
1762
1763symbolS *
1764md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
1765{
1766 return NULL;
1767}
1768
1769/* Various routines to kill one day. */
1770/* Equal to MAX_PRECISION in atof-ieee.c */
1771#define MAX_LITTLENUMS 6
1772
1773/* Turn a string in input_line_pointer into a floating point constant of type
1774 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1775 emitted is stored in *sizeP. An error message is returned, or NULL on OK.*/
6d4af3c2 1776const char *
7ba29e2a
NC
1777md_atof (int type, char * litP, int * sizeP)
1778{
1779 int prec;
1780 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1781 int i;
1782 char * t;
1783
1784 switch (type)
1785 {
1786 case 'f':
1787 case 'F':
1788 case 's':
1789 case 'S':
1790 prec = 2;
1791 break;
1792
1793 case 'd':
1794 case 'D':
1795 case 'r':
1796 case 'R':
1797 prec = 4;
1798 break;
1799
1800 case 'x':
1801 case 'X':
1802 prec = 6;
1803 break;
1804
1805 case 'p':
1806 case 'P':
1807 prec = 6;
1808 break;
1809
1810 default:
1811 *sizeP = 0;
1812 return _("Bad call to MD_NTOF()");
1813 }
1814
1815 t = atof_ieee (input_line_pointer, type, words);
1816
1817 if (t)
1818 input_line_pointer = t;
1819
1820 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1821
1822 if (! target_big_endian)
1823 {
1824 for (i = prec - 1; i >= 0; i--)
1825 {
1826 md_number_to_chars (litP, (valueT) words[i],
1827 sizeof (LITTLENUM_TYPE));
1828 litP += sizeof (LITTLENUM_TYPE);
1829 }
1830 }
1831 else
1832 for (i = 0; i < prec; i++)
1833 {
1834 md_number_to_chars (litP, (valueT) words[i],
1835 sizeof (LITTLENUM_TYPE));
1836 litP += sizeof (LITTLENUM_TYPE);
1837 }
1838
1839 return NULL;
1840}
1841\f
1842const char * md_shortopts = "";
1843
1844struct option md_longopts[] =
1845{
f23200ad
ME
1846 {"EB", no_argument, NULL, OPTION_EB},
1847 {"EL", no_argument, NULL, OPTION_EL},
7ba29e2a
NC
1848 { NULL, no_argument, NULL, 0}
1849};
1850
1851size_t md_longopts_size = sizeof (md_longopts);
1852
1853int md_short_jump_size;
1854
1855void
1856md_create_short_jump (char * ptr ATTRIBUTE_UNUSED,
1857 addressT from_Nddr ATTRIBUTE_UNUSED,
1858 addressT to_Nddr ATTRIBUTE_UNUSED,
1859 fragS * frag ATTRIBUTE_UNUSED,
1860 symbolS * to_symbol ATTRIBUTE_UNUSED)
1861{
1862 as_fatal (_("failed sanity check: short_jump"));
1863}
1864
1865void
1866md_create_long_jump (char * ptr ATTRIBUTE_UNUSED,
1867 addressT from_Nddr ATTRIBUTE_UNUSED,
1868 addressT to_Nddr ATTRIBUTE_UNUSED,
1869 fragS * frag ATTRIBUTE_UNUSED,
1870 symbolS * to_symbol ATTRIBUTE_UNUSED)
1871{
1872 as_fatal (_("failed sanity check: long_jump"));
1873}
1874
1875/* Called after relaxing, change the frags so they know how big they are. */
1876
1877void
1878md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
1879 segT sec ATTRIBUTE_UNUSED,
1880 fragS * fragP)
1881{
1882 fixS *fixP;
1883
1884 switch (fragP->fr_subtype)
1885 {
1886 case UNDEFINED_PC_OFFSET:
1887 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1888 fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL);
1889 fragP->fr_fix += INST_WORD_SIZE * 2;
1890 fragP->fr_var = 0;
1891 break;
1892 case DEFINED_ABS_SEGMENT:
1893 if (fragP->fr_symbol == GOT_symbol)
1894 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1895 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GOTPC);
1896 else
1897 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1898 fragP->fr_offset, FALSE, BFD_RELOC_64);
1899 fragP->fr_fix += INST_WORD_SIZE * 2;
1900 fragP->fr_var = 0;
1901 break;
1902 case DEFINED_RO_SEGMENT:
1903 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1904 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_ROSDA);
1905 fragP->fr_fix += INST_WORD_SIZE;
1906 fragP->fr_var = 0;
1907 break;
1908 case DEFINED_RW_SEGMENT:
1909 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1910 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_RWSDA);
1911 fragP->fr_fix += INST_WORD_SIZE;
1912 fragP->fr_var = 0;
1913 break;
1914 case DEFINED_PC_OFFSET:
1915 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1916 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_32_LO_PCREL);
1917 fragP->fr_fix += INST_WORD_SIZE;
1918 fragP->fr_var = 0;
1919 break;
1920 case LARGE_DEFINED_PC_OFFSET:
1921 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1922 fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL);
1923 fragP->fr_fix += INST_WORD_SIZE * 2;
1924 fragP->fr_var = 0;
1925 break;
1926 case GOT_OFFSET:
1927 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1928 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOT);
1929 fragP->fr_fix += INST_WORD_SIZE * 2;
1930 fragP->fr_var = 0;
1931 break;
3f0a5f17
ME
1932 case TEXT_OFFSET:
1933 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1934 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TEXTREL);
1935 fragP->fr_fix += INST_WORD_SIZE * 2;
1936 fragP->fr_var = 0;
1937 break;
1938 case TEXT_PC_OFFSET:
1939 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1940 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TEXTPCREL);
1941 fragP->fr_fix += INST_WORD_SIZE * 2;
1942 fragP->fr_var = 0;
1943 break;
7ba29e2a
NC
1944 case PLT_OFFSET:
1945 fixP = fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1946 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_PLT);
1947 /* fixP->fx_plt = 1; */
87975d2a 1948 (void) fixP;
7ba29e2a
NC
1949 fragP->fr_fix += INST_WORD_SIZE * 2;
1950 fragP->fr_var = 0;
1951 break;
1952 case GOTOFF_OFFSET:
1953 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1954 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOTOFF);
1955 fragP->fr_fix += INST_WORD_SIZE * 2;
1956 fragP->fr_var = 0;
1957 break;
69b06cc8
ME
1958 case TLSGD_OFFSET:
1959 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1960 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSGD);
1961 fragP->fr_fix += INST_WORD_SIZE * 2;
1962 fragP->fr_var = 0;
1963 break;
1964 case TLSLD_OFFSET:
1965 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1966 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSLD);
1967 fragP->fr_fix += INST_WORD_SIZE * 2;
1968 fragP->fr_var = 0;
1969 break;
1970 case TLSDTPREL_OFFSET:
1971 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1972 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSDTPREL);
1973 fragP->fr_fix += INST_WORD_SIZE * 2;
1974 fragP->fr_var = 0;
1975 break;
7ba29e2a
NC
1976
1977 default:
1978 abort ();
1979 }
1980}
1981
1982/* Applies the desired value to the specified location.
1983 Also sets up addends for 'rela' type relocations. */
1984void
1985md_apply_fix (fixS * fixP,
1986 valueT * valp,
1987 segT segment)
1988{
1989 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
3b4dbbbf 1990 const char * file = fixP->fx_file ? fixP->fx_file : _("unknown");
7ba29e2a
NC
1991 const char * symname;
1992 /* Note: use offsetT because it is signed, valueT is unsigned. */
1993 offsetT val = (offsetT) * valp;
1994 int i;
1995 struct op_code_struct * opcode1;
1996 unsigned long inst1;
1997
1998 symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
1999
2000 /* fixP->fx_offset is supposed to be set up correctly for all
2001 symbol relocations. */
2002 if (fixP->fx_addsy == NULL)
2003 {
2004 if (!fixP->fx_pcrel)
2005 fixP->fx_offset = val; /* Absolute relocation. */
2006 else
2007 fprintf (stderr, "NULL symbol PC-relative relocation? offset = %08x, val = %08x\n",
2008 (unsigned int) fixP->fx_offset, (unsigned int) val);
2009 }
2010
2011 /* If we aren't adjusting this fixup to be against the section
2012 symbol, we need to adjust the value. */
2013 if (fixP->fx_addsy != NULL)
2014 {
2015 if (S_IS_WEAK (fixP->fx_addsy)
2016 || (symbol_used_in_reloc_p (fixP->fx_addsy)
2017 && (((bfd_get_section_flags (stdoutput,
2018 S_GET_SEGMENT (fixP->fx_addsy))
2019 & SEC_LINK_ONCE) != 0)
2020 || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
2021 ".gnu.linkonce",
2022 sizeof (".gnu.linkonce") - 1))))
2023 {
2024 val -= S_GET_VALUE (fixP->fx_addsy);
2025 if (val != 0 && ! fixP->fx_pcrel)
2026 {
2027 /* In this case, the bfd_install_relocation routine will
2028 incorrectly add the symbol value back in. We just want
2029 the addend to appear in the object file.
2030 FIXME: If this makes VALUE zero, we're toast. */
2031 val -= S_GET_VALUE (fixP->fx_addsy);
2032 }
2033 }
2034 }
2035
2036 /* If the fix is relative to a symbol which is not defined, or not
2037 in the same segment as the fix, we cannot resolve it here. */
2038 /* fixP->fx_addsy is NULL if valp contains the entire relocation. */
2039 if (fixP->fx_addsy != NULL
2040 && (!S_IS_DEFINED (fixP->fx_addsy)
2041 || (S_GET_SEGMENT (fixP->fx_addsy) != segment)))
2042 {
2043 fixP->fx_done = 0;
2044#ifdef OBJ_ELF
2045 /* For ELF we can just return and let the reloc that will be generated
2046 take care of everything. For COFF we still have to insert 'val'
2047 into the insn since the addend field will be ignored. */
2048 /* return; */
2049#endif
2050 }
2051 /* All fixups in the text section must be handled in the linker. */
2052 else if (segment->flags & SEC_CODE)
2053 fixP->fx_done = 0;
2054 else if (!fixP->fx_pcrel && fixP->fx_addsy != NULL)
2055 fixP->fx_done = 0;
2056 else
2057 fixP->fx_done = 1;
2058
2059 switch (fixP->fx_r_type)
2060 {
2061 case BFD_RELOC_MICROBLAZE_32_LO:
2062 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2063 if (target_big_endian)
2064 {
2065 buf[2] |= ((val >> 8) & 0xff);
2066 buf[3] |= (val & 0xff);
2067 }
2068 else
2069 {
2070 buf[1] |= ((val >> 8) & 0xff);
2071 buf[0] |= (val & 0xff);
2072 }
2073 break;
2074 case BFD_RELOC_MICROBLAZE_32_ROSDA:
2075 case BFD_RELOC_MICROBLAZE_32_RWSDA:
2076 /* Don't do anything if the symbol is not defined. */
2077 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2078 {
2079 if (((val & 0xFFFF8000) != 0) && ((val & 0xFFFF8000) != 0xFFFF8000))
2080 as_bad_where (file, fixP->fx_line,
2081 _("pcrel for branch to %s too far (0x%x)"),
2082 symname, (int) val);
2083 if (target_big_endian)
2084 {
2085 buf[2] |= ((val >> 8) & 0xff);
2086 buf[3] |= (val & 0xff);
2087 }
2088 else
2089 {
2090 buf[1] |= ((val >> 8) & 0xff);
2091 buf[0] |= (val & 0xff);
2092 }
2093 }
2094 break;
2095 case BFD_RELOC_32:
2096 case BFD_RELOC_RVA:
2097 case BFD_RELOC_32_PCREL:
2098 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2099 /* Don't do anything if the symbol is not defined. */
2100 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2101 {
2102 if (target_big_endian)
2103 {
2104 buf[0] |= ((val >> 24) & 0xff);
2105 buf[1] |= ((val >> 16) & 0xff);
2106 buf[2] |= ((val >> 8) & 0xff);
2107 buf[3] |= (val & 0xff);
2108 }
2109 else
2110 {
2111 buf[3] |= ((val >> 24) & 0xff);
2112 buf[2] |= ((val >> 16) & 0xff);
2113 buf[1] |= ((val >> 8) & 0xff);
2114 buf[0] |= (val & 0xff);
2115 }
2116 }
2117 break;
2118 case BFD_RELOC_64_PCREL:
2119 case BFD_RELOC_64:
3f0a5f17 2120 case BFD_RELOC_MICROBLAZE_64_TEXTREL:
7ba29e2a
NC
2121 /* Add an imm instruction. First save the current instruction. */
2122 for (i = 0; i < INST_WORD_SIZE; i++)
2123 buf[i + INST_WORD_SIZE] = buf[i];
2124
2125 /* Generate the imm instruction. */
2126 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
2127 if (opcode1 == NULL)
2128 {
2129 as_bad (_("unknown opcode \"%s\""), "imm");
2130 return;
2131 }
2132
2133 inst1 = opcode1->bit_sequence;
2134 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2135 inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
2136
2137 buf[0] = INST_BYTE0 (inst1);
2138 buf[1] = INST_BYTE1 (inst1);
2139 buf[2] = INST_BYTE2 (inst1);
2140 buf[3] = INST_BYTE3 (inst1);
2141
2142 /* Add the value only if the symbol is defined. */
2143 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2144 {
2145 if (target_big_endian)
2146 {
2147 buf[6] |= ((val >> 8) & 0xff);
2148 buf[7] |= (val & 0xff);
2149 }
2150 else
2151 {
2152 buf[5] |= ((val >> 8) & 0xff);
2153 buf[4] |= (val & 0xff);
2154 }
2155 }
2156 break;
2157
69b06cc8
ME
2158 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2159 case BFD_RELOC_MICROBLAZE_64_TLSGD:
2160 case BFD_RELOC_MICROBLAZE_64_TLSLD:
2161 S_SET_THREAD_LOCAL (fixP->fx_addsy);
1a0670f3 2162 /* Fall through. */
69b06cc8 2163
7ba29e2a
NC
2164 case BFD_RELOC_MICROBLAZE_64_GOTPC:
2165 case BFD_RELOC_MICROBLAZE_64_GOT:
2166 case BFD_RELOC_MICROBLAZE_64_PLT:
2167 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
3f0a5f17 2168 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
7ba29e2a
NC
2169 /* Add an imm instruction. First save the current instruction. */
2170 for (i = 0; i < INST_WORD_SIZE; i++)
2171 buf[i + INST_WORD_SIZE] = buf[i];
2172
2173 /* Generate the imm instruction. */
2174 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
2175 if (opcode1 == NULL)
2176 {
2177 as_bad (_("unknown opcode \"%s\""), "imm");
2178 return;
2179 }
2180
2181 inst1 = opcode1->bit_sequence;
2182
2183 /* We can fixup call to a defined non-global address
2184 within the same section only. */
2185 buf[0] = INST_BYTE0 (inst1);
2186 buf[1] = INST_BYTE1 (inst1);
2187 buf[2] = INST_BYTE2 (inst1);
2188 buf[3] = INST_BYTE3 (inst1);
2189 return;
2190
2191 default:
2192 break;
2193 }
2194
2195 if (fixP->fx_addsy == NULL)
2196 {
2197 /* This fixup has been resolved. Create a reloc in case the linker
2198 moves code around due to relaxing. */
2199 if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
2200 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
2201 else
2202 fixP->fx_r_type = BFD_RELOC_NONE;
2203 fixP->fx_addsy = section_symbol (absolute_section);
2204 }
2205 return;
2206}
2207
2208void
2209md_operand (expressionS * expressionP)
2210{
2211 /* Ignore leading hash symbol, if present. */
2212 if (*input_line_pointer == '#')
2213 {
2214 input_line_pointer ++;
2215 expression (expressionP);
2216 }
2217}
2218
2219/* Called just before address relaxation, return the length
2220 by which a fragment must grow to reach it's destination. */
2221
2222int
2223md_estimate_size_before_relax (fragS * fragP,
2224 segT segment_type)
2225{
2226 sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss");
2227 sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2");
2228 sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata");
2229 sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2");
2230
2231 switch (fragP->fr_subtype)
2232 {
2233 case INST_PC_OFFSET:
2234 /* Used to be a PC-relative branch. */
2235 if (!fragP->fr_symbol)
2236 {
2237 /* We know the abs value: Should never happen. */
2238 as_bad (_("Absolute PC-relative value in relaxation code. Assembler error....."));
2239 abort ();
2240 }
28ad2e2d
ME
2241 else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
2242 !S_IS_WEAK (fragP->fr_symbol))
7ba29e2a
NC
2243 {
2244 fragP->fr_subtype = DEFINED_PC_OFFSET;
2245 /* Don't know now whether we need an imm instruction. */
2246 fragP->fr_var = INST_WORD_SIZE;
2247 }
2248 else if (S_IS_DEFINED (fragP->fr_symbol)
2249 && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
2250 {
2251 /* Cannot have a PC-relative branch to a diff segment. */
2252 as_bad (_("PC relative branch to label %s which is not in the instruction space"),
2253 S_GET_NAME (fragP->fr_symbol));
2254 fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2255 fragP->fr_var = INST_WORD_SIZE*2;
2256 }
2257 else
2258 {
2259 fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2260 fragP->fr_var = INST_WORD_SIZE*2;
2261 }
2262 break;
2263
2264 case INST_NO_OFFSET:
3f0a5f17 2265 case TEXT_OFFSET:
7ba29e2a
NC
2266 /* Used to be a reference to somewhere which was unknown. */
2267 if (fragP->fr_symbol)
2268 {
2269 if (fragP->fr_opcode == NULL)
2270 {
3f0a5f17
ME
2271 /* Used as an absolute value. */
2272 if (fragP->fr_subtype == INST_NO_OFFSET)
2273 fragP->fr_subtype = DEFINED_ABS_SEGMENT;
2274 /* Variable part does not change. */
2275 fragP->fr_var = INST_WORD_SIZE*2;
2276 }
7ba29e2a
NC
2277 else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
2278 {
2279 /* It is accessed using the small data read only anchor. */
45dfa85a 2280 if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
7ba29e2a
NC
2281 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment)
2282 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment)
2283 || (! S_IS_DEFINED (fragP->fr_symbol)))
2284 {
2285 fragP->fr_subtype = DEFINED_RO_SEGMENT;
2286 fragP->fr_var = INST_WORD_SIZE;
2287 }
2288 else
2289 {
2290 /* Variable not in small data read only segment accessed
2291 using small data read only anchor. */
3b4dbbbf 2292 const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
7ba29e2a
NC
2293
2294 as_bad_where (file, fragP->fr_line,
2295 _("Variable is accessed using small data read "
2296 "only anchor, but it is not in the small data "
2297 "read only section"));
2298 fragP->fr_subtype = DEFINED_RO_SEGMENT;
2299 fragP->fr_var = INST_WORD_SIZE;
2300 }
2301 }
2302 else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor))
2303 {
45dfa85a 2304 if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
7ba29e2a
NC
2305 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment)
2306 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment)
2307 || (!S_IS_DEFINED (fragP->fr_symbol)))
2308 {
2309 /* It is accessed using the small data read write anchor. */
2310 fragP->fr_subtype = DEFINED_RW_SEGMENT;
2311 fragP->fr_var = INST_WORD_SIZE;
2312 }
2313 else
2314 {
3b4dbbbf 2315 const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
7ba29e2a
NC
2316
2317 as_bad_where (file, fragP->fr_line,
2318 _("Variable is accessed using small data read "
2319 "write anchor, but it is not in the small data "
2320 "read write section"));
2321 fragP->fr_subtype = DEFINED_RW_SEGMENT;
2322 fragP->fr_var = INST_WORD_SIZE;
2323 }
2324 }
2325 else
2326 {
2327 as_bad (_("Incorrect fr_opcode value in frag. Internal error....."));
2328 abort ();
2329 }
2330 }
2331 else
2332 {
2333 /* We know the abs value: Should never happen. */
2334 as_bad (_("Absolute value in relaxation code. Assembler error....."));
2335 abort ();
2336 }
2337 break;
2338
2339 case UNDEFINED_PC_OFFSET:
2340 case LARGE_DEFINED_PC_OFFSET:
2341 case DEFINED_ABS_SEGMENT:
2342 case GOT_OFFSET:
2343 case PLT_OFFSET:
2344 case GOTOFF_OFFSET:
3f0a5f17 2345 case TEXT_PC_OFFSET:
69b06cc8
ME
2346 case TLSGD_OFFSET:
2347 case TLSLD_OFFSET:
2348 case TLSTPREL_OFFSET:
2349 case TLSDTPREL_OFFSET:
7ba29e2a
NC
2350 fragP->fr_var = INST_WORD_SIZE*2;
2351 break;
2352 case DEFINED_RO_SEGMENT:
2353 case DEFINED_RW_SEGMENT:
2354 case DEFINED_PC_OFFSET:
69b06cc8 2355 case TLSDTPMOD_OFFSET:
7ba29e2a
NC
2356 fragP->fr_var = INST_WORD_SIZE;
2357 break;
2358 default:
2359 abort ();
2360 }
2361
2362 return fragP->fr_var;
2363}
2364
2365/* Put number into target byte order. */
2366
2367void
2368md_number_to_chars (char * ptr, valueT use, int nbytes)
2369{
2370 if (target_big_endian)
2371 number_to_chars_bigendian (ptr, use, nbytes);
2372 else
2373 number_to_chars_littleendian (ptr, use, nbytes);
2374}
2375
2376/* Round up a section size to the appropriate boundary. */
2377
2378valueT
2379md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
2380{
2381 return size; /* Byte alignment is fine. */
2382}
2383
2384
2385/* The location from which a PC relative jump should be calculated,
2386 given a PC relative reloc. */
2387
2388long
2389md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
2390{
2391#ifdef OBJ_ELF
2392 /* If the symbol is undefined or defined in another section
2393 we leave the add number alone for the linker to fix it later.
2394 Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */
2395
2396 if (fixp->fx_addsy != (symbolS *) NULL
2397 && (!S_IS_DEFINED (fixp->fx_addsy)
2398 || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
2399 return 0;
2400 else
2401 {
2402 /* The case where we are going to resolve things... */
2403 if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
2404 return fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
2405 else
2406 return fixp->fx_where + fixp->fx_frag->fr_address;
2407 }
2408#endif
2409}
2410
2411
2412#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
2413#define MAP(SZ,PCREL,TYPE) case F (SZ, PCREL): code = (TYPE); break
2414
2415arelent *
2416tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
2417{
2418 arelent * rel;
2419 bfd_reloc_code_real_type code;
2420
2421 switch (fixp->fx_r_type)
2422 {
2423 case BFD_RELOC_NONE:
2424 case BFD_RELOC_MICROBLAZE_64_NONE:
2425 case BFD_RELOC_32:
2426 case BFD_RELOC_MICROBLAZE_32_LO:
2427 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2428 case BFD_RELOC_RVA:
2429 case BFD_RELOC_64:
2430 case BFD_RELOC_64_PCREL:
2431 case BFD_RELOC_MICROBLAZE_32_ROSDA:
2432 case BFD_RELOC_MICROBLAZE_32_RWSDA:
2433 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2434 case BFD_RELOC_MICROBLAZE_64_GOTPC:
2435 case BFD_RELOC_MICROBLAZE_64_GOT:
2436 case BFD_RELOC_MICROBLAZE_64_PLT:
2437 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2438 case BFD_RELOC_MICROBLAZE_32_GOTOFF:
69b06cc8
ME
2439 case BFD_RELOC_MICROBLAZE_64_TLSGD:
2440 case BFD_RELOC_MICROBLAZE_64_TLSLD:
2441 case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
2442 case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
2443 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2444 case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
2445 case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
3f0a5f17
ME
2446 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2447 case BFD_RELOC_MICROBLAZE_64_TEXTREL:
7ba29e2a
NC
2448 code = fixp->fx_r_type;
2449 break;
2450
2451 default:
2452 switch (F (fixp->fx_size, fixp->fx_pcrel))
2453 {
2454 MAP (1, 0, BFD_RELOC_8);
2455 MAP (2, 0, BFD_RELOC_16);
2456 MAP (4, 0, BFD_RELOC_32);
2457 MAP (1, 1, BFD_RELOC_8_PCREL);
2458 MAP (2, 1, BFD_RELOC_16_PCREL);
2459 MAP (4, 1, BFD_RELOC_32_PCREL);
2460 default:
2461 code = fixp->fx_r_type;
2462 as_bad (_("Can not do %d byte %srelocation"),
2463 fixp->fx_size,
33eaf5de 2464 fixp->fx_pcrel ? _("pc-relative ") : "");
7ba29e2a
NC
2465 }
2466 break;
2467 }
2468
add39d23
TS
2469 rel = XNEW (arelent);
2470 rel->sym_ptr_ptr = XNEW (asymbol *);
7ba29e2a
NC
2471
2472 if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM)
2473 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
2474 else
2475 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2476
2477 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
2478 /* Always pass the addend along! */
2479 rel->addend = fixp->fx_offset;
2480 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
2481
2482 if (rel->howto == NULL)
2483 {
2484 as_bad_where (fixp->fx_file, fixp->fx_line,
2485 _("Cannot represent relocation type %s"),
2486 bfd_get_reloc_code_name (code));
2487
2488 /* Set howto to a garbage value so that we can keep going. */
2489 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
2490 gas_assert (rel->howto != NULL);
2491 }
2492 return rel;
2493}
2494
2495int
17b9d67d 2496md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
7ba29e2a
NC
2497{
2498 switch (c)
2499 {
f23200ad
ME
2500 case OPTION_EB:
2501 target_big_endian = 1;
2502 break;
2503 case OPTION_EL:
2504 target_big_endian = 0;
2505 break;
7ba29e2a
NC
2506 default:
2507 return 0;
2508 }
2509 return 1;
2510}
2511
2512void
2513md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
2514{
2515 /* fprintf(stream, _("\
2516 MicroBlaze options:\n\
2517 -noSmall Data in the comm and data sections do not go into the small data section\n")); */
2518}
2519
2520
2521/* Create a fixup for a cons expression. If parse_cons_expression_microblaze
2522 found a machine specific op in an expression,
2523 then we create relocs accordingly. */
2524
2525void
2526cons_fix_new_microblaze (fragS * frag,
2527 int where,
2528 int size,
62ebcb5c
AM
2529 expressionS *exp,
2530 bfd_reloc_code_real_type r)
7ba29e2a 2531{
7ba29e2a
NC
2532 if ((exp->X_op == O_subtract) && (exp->X_add_symbol) &&
2533 (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4)
2534 && (!S_IS_LOCAL (exp->X_op_symbol)))
2535 r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM;
2536 else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva)
2537 {
2538 exp->X_op = O_symbol;
2539 r = BFD_RELOC_MICROBLAZE_32_GOTOFF;
2540 }
2541 else
2542 {
2543 switch (size)
2544 {
2545 case 1:
2546 r = BFD_RELOC_8;
2547 break;
2548 case 2:
2549 r = BFD_RELOC_16;
2550 break;
2551 case 4:
2552 r = BFD_RELOC_32;
2553 break;
2554 case 8:
2555 r = BFD_RELOC_64;
2556 break;
2557 default:
2558 as_bad (_("unsupported BFD relocation size %u"), size);
2559 r = BFD_RELOC_32;
2560 break;
2561 }
2562 }
2563 fix_new_exp (frag, where, size, exp, 0, r);
2564}
This page took 0.725893 seconds and 4 git commands to generate.