Update year range in copyright notice of binutils files
[binutils-gdb.git] / gas / config / tc-microblaze.c
blob6a002a2e152e1297af01d0dbd0cb7ac5380e1992
1 /* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
3 Copyright (C) 2009-2024 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
22 #include "as.h"
23 #include <stdio.h>
24 #include "bfd.h"
25 #include "subsegs.h"
26 #define DEFINE_TABLE
27 #include "../opcodes/microblaze-opc.h"
28 #include "../opcodes/microblaze-opcm.h"
29 #include "safe-ctype.h"
30 #include <string.h>
31 #include <dwarf2dbg.h>
32 #include "aout/stab_gnu.h"
34 #ifndef streq
35 #define streq(a,b) (strcmp (a, b) == 0)
36 #endif
38 #define OPTION_EB (OPTION_MD_BASE + 0)
39 #define OPTION_EL (OPTION_MD_BASE + 1)
41 void microblaze_generate_symbol (char *sym);
42 static bool check_spl_reg (unsigned *);
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))
53 /* This array holds the chars that always start a comment. If the
54 pre-processor is disabled, these aren't very useful. */
55 const char comment_chars[] = "#";
57 const char line_separator_chars[] = ";";
59 /* This array holds the chars that only start a comment at the beginning of
60 a line. */
61 const char line_comment_chars[] = "#";
63 const int md_reloc_size = 8; /* Size of relocation record. */
65 /* Chars that can be used to separate mant
66 from exp in floating point numbers. */
67 const char EXP_CHARS[] = "eE";
69 /* Chars that mean this number is a floating point constant
70 As in 0f12.456
71 or 0d1.2345e12. */
72 const char FLT_CHARS[] = "rRsSfFdDxXpP";
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
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
90 #define TEXT_OFFSET 17
91 #define TEXT_PC_OFFSET 18
93 /* Initialize the relax table. */
94 const relax_typeS md_relax_table[] =
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. */
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. */
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. */
117 static htab_t opcode_hash_control; /* Opcode mnemonics. */
119 static segT sbss_segment = 0; /* Small bss section. */
120 static segT sbss2_segment = 0; /* Section not used. */
121 static segT sdata_segment = 0; /* Small data section. */
122 static segT sdata2_segment = 0; /* Small read-only section. */
123 static segT rodata_segment = 0; /* read-only section. */
125 /* Generate a symbol for stabs information. */
127 void
128 microblaze_generate_symbol (char *sym)
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;
136 /* Handle the section changing pseudo-ops. */
138 static void
139 microblaze_s_text (int ignore ATTRIBUTE_UNUSED)
141 #ifdef OBJ_ELF
142 obj_elf_text (ignore);
143 #else
144 s_text (ignore);
145 #endif
148 static void
149 microblaze_s_data (int ignore ATTRIBUTE_UNUSED)
151 #ifdef OBJ_ELF
152 obj_elf_change_section (".data", SHT_PROGBITS, SHF_ALLOC+SHF_WRITE,
153 0, 0, false);
154 #else
155 s_data (ignore);
156 #endif
159 /* Things in the .sdata segment are always considered to be in the small data section. */
161 static void
162 microblaze_s_sdata (int ignore ATTRIBUTE_UNUSED)
164 #ifdef OBJ_ELF
165 obj_elf_change_section (".sdata", SHT_PROGBITS, SHF_ALLOC+SHF_WRITE,
166 0, 0, false);
167 #else
168 s_data (ignore);
169 #endif
172 /* Pseudo op to make file scope bss items. */
174 static void
175 microblaze_s_lcomm (int xxx ATTRIBUTE_UNUSED)
177 char *name;
178 char c;
179 char *p;
180 offsetT size;
181 symbolS *symbolP;
182 offsetT align;
183 char *pfrag;
184 int align2;
185 segT current_seg = now_seg;
186 subsegT current_subseg = now_subseg;
188 c = get_symbol_name (&name);
190 /* Just after name is now '\0'. */
191 p = input_line_pointer;
192 (void) restore_line_pointer (c);
193 SKIP_WHITESPACE ();
194 if (*input_line_pointer != ',')
196 as_bad (_("Expected comma after symbol-name: rest of line ignored."));
197 ignore_rest_of_line ();
198 return;
201 input_line_pointer++; /* skip ',' */
202 if ((size = get_absolute_expression ()) < 0)
204 as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size);
205 ignore_rest_of_line ();
206 return;
209 /* The third argument to .lcomm is the alignment. */
210 if (*input_line_pointer != ',')
211 align = 8;
212 else
214 ++input_line_pointer;
215 align = get_absolute_expression ();
216 if (align <= 0)
218 as_warn (_("ignoring bad alignment"));
219 align = 8;
223 *p = 0;
224 symbolP = symbol_find_or_make (name);
225 *p = c;
227 if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
229 as_bad (_("Ignoring attempt to re-define symbol `%s'."),
230 S_GET_NAME (symbolP));
231 ignore_rest_of_line ();
232 return;
235 if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
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);
242 ignore_rest_of_line ();
243 return;
246 /* Allocate_bss. */
247 if (align)
249 /* Convert to a power of 2 alignment. */
250 for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
251 if (align != 1)
253 as_bad (_("Common alignment not a power of 2"));
254 ignore_rest_of_line ();
255 return;
258 else
259 align2 = 0;
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 ();
277 static void
278 microblaze_s_rdata (int localvar)
280 #ifdef OBJ_ELF
281 if (localvar == 0)
283 /* rodata. */
284 obj_elf_change_section (".rodata", SHT_PROGBITS, SHF_ALLOC,
285 0, 0, false);
286 if (rodata_segment == 0)
287 rodata_segment = subseg_new (".rodata", 0);
289 else
291 /* 1 .sdata2. */
292 obj_elf_change_section (".sdata2", SHT_PROGBITS, SHF_ALLOC,
293 0, 0, false);
295 #else
296 s_data (ignore);
297 #endif
300 static void
301 microblaze_s_bss (int localvar)
303 #ifdef OBJ_ELF
304 if (localvar == 0) /* bss. */
305 obj_elf_change_section (".bss", SHT_NOBITS, SHF_ALLOC+SHF_WRITE,
306 0, 0, false);
307 else if (localvar == 1)
309 /* sbss. */
310 obj_elf_change_section (".sbss", SHT_NOBITS, SHF_ALLOC+SHF_WRITE,
311 0, 0, false);
312 if (sbss_segment == 0)
313 sbss_segment = subseg_new (".sbss", 0);
315 #else
316 s_data (ignore);
317 #endif
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). */
324 static void
325 microblaze_s_func (int end_p ATTRIBUTE_UNUSED)
327 char *name;
328 restore_line_pointer (get_symbol_name (&name));
329 s_func (1);
332 /* Handle the .weakext pseudo-op as defined in Kane and Heinrich. */
334 static void
335 microblaze_s_weakext (int ignore ATTRIBUTE_UNUSED)
337 char *name;
338 int c;
339 symbolS *symbolP;
340 expressionS exp;
342 c = get_symbol_name (&name);
343 symbolP = symbol_find_or_make (name);
344 S_SET_WEAK (symbolP);
345 (void) restore_line_pointer (c);
347 SKIP_WHITESPACE ();
349 if (!is_end_of_line[(unsigned char) *input_line_pointer])
351 if (S_IS_DEFINED (symbolP))
353 as_bad ("Ignoring attempt to redefine symbol `%s'.",
354 S_GET_NAME (symbolP));
355 ignore_rest_of_line ();
356 return;
359 if (*input_line_pointer == ',')
361 ++input_line_pointer;
362 SKIP_WHITESPACE ();
365 expression (&exp);
366 if (exp.X_op != O_symbol)
368 as_bad ("bad .weakext directive");
369 ignore_rest_of_line ();
370 return;
372 symbol_set_value_expression (symbolP, &exp);
375 demand_empty_rest_of_line ();
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. */
385 const pseudo_typeS md_pseudo_table[] =
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}
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. */
411 void
412 md_begin (void)
414 const struct op_code_struct * opcode;
416 opcode_hash_control = str_htab_create ();
418 /* Insert unique names into hash table. */
419 for (opcode = microblaze_opcodes; opcode->name; opcode ++)
420 str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
423 /* Try to parse a reg name. */
425 static char *
426 parse_reg (char * s, unsigned * reg)
428 unsigned tmpreg = 0;
430 /* Strip leading whitespace. */
431 while (ISSPACE (* s))
432 ++ s;
434 if (strncasecmp (s, "rpc", 3) == 0)
436 *reg = REG_PC;
437 return s + 3;
439 else if (strncasecmp (s, "rmsr", 4) == 0)
441 *reg = REG_MSR;
442 return s + 4;
444 else if (strncasecmp (s, "rear", 4) == 0)
446 *reg = REG_EAR;
447 return s + 4;
449 else if (strncasecmp (s, "resr", 4) == 0)
451 *reg = REG_ESR;
452 return s + 4;
454 else if (strncasecmp (s, "rfsr", 4) == 0)
456 *reg = REG_FSR;
457 return s + 4;
459 else if (strncasecmp (s, "rbtr", 4) == 0)
461 *reg = REG_BTR;
462 return s + 4;
464 else if (strncasecmp (s, "redr", 4) == 0)
466 *reg = REG_EDR;
467 return s + 4;
469 /* MMU registers start. */
470 else if (strncasecmp (s, "rpid", 4) == 0)
472 *reg = REG_PID;
473 return s + 4;
475 else if (strncasecmp (s, "rzpr", 4) == 0)
477 *reg = REG_ZPR;
478 return s + 4;
480 else if (strncasecmp (s, "rtlbx", 5) == 0)
482 *reg = REG_TLBX;
483 return s + 5;
485 else if (strncasecmp (s, "rtlblo", 6) == 0)
487 *reg = REG_TLBLO;
488 return s + 6;
490 else if (strncasecmp (s, "rtlbhi", 6) == 0)
492 *reg = REG_TLBHI;
493 return s + 6;
495 else if (strncasecmp (s, "rtlbsx", 6) == 0)
497 *reg = REG_TLBSX;
498 return s + 6;
500 /* MMU registers end. */
501 else if (strncasecmp (s, "rpvr", 4) == 0)
503 if (ISDIGIT (s[4]) && ISDIGIT (s[5]))
505 tmpreg = (s[4]-'0')*10 + s[5] - '0';
506 s += 6;
509 else if (ISDIGIT (s[4]))
511 tmpreg = s[4] - '0';
512 s += 5;
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
520 as_bad (_("Invalid register number at '%.6s'"), s);
521 *reg = REG_PVR;
523 return s;
525 else if (strncasecmp (s, "rsp", 3) == 0)
527 *reg = REG_SP;
528 return s + 3;
530 else if (strncasecmp (s, "rfsl", 4) == 0)
532 if (ISDIGIT (s[4]) && ISDIGIT (s[5]))
534 tmpreg = (s[4] - '0') * 10 + s[5] - '0';
535 s += 6;
537 else if (ISDIGIT (s[4]))
539 tmpreg = s[4] - '0';
540 s += 5;
542 else
543 as_bad (_("register expected, but saw '%.6s'"), s);
545 if ((int) tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM)
546 *reg = tmpreg;
547 else
549 as_bad (_("Invalid register number at '%.6s'"), s);
550 *reg = 0;
552 return s;
554 /* Stack protection registers. */
555 else if (strncasecmp (s, "rshr", 4) == 0)
557 *reg = REG_SHR;
558 return s + 4;
560 else if (strncasecmp (s, "rslr", 4) == 0)
562 *reg = REG_SLR;
563 return s + 4;
565 else
567 if (TOLOWER (s[0]) == 'r')
569 if (ISDIGIT (s[1]) && ISDIGIT (s[2]))
571 tmpreg = (s[1] - '0') * 10 + s[2] - '0';
572 s += 3;
574 else if (ISDIGIT (s[1]))
576 tmpreg = s[1] - '0';
577 s += 2;
579 else
580 as_bad (_("register expected, but saw '%.6s'"), s);
582 if ((int)tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM)
583 *reg = tmpreg;
584 else
586 as_bad (_("Invalid register number at '%.6s'"), s);
587 *reg = 0;
589 return s;
592 as_bad (_("register expected, but saw '%.6s'"), s);
593 *reg = 0;
594 return s;
597 static char *
598 parse_exp (char *s, expressionS *e)
600 char *save;
601 char *new_pointer;
603 /* Skip whitespace. */
604 while (ISSPACE (* s))
605 ++ s;
607 save = input_line_pointer;
608 input_line_pointer = s;
610 expression (e);
612 if (e->X_op == O_absent)
613 as_fatal (_("missing operand"));
615 new_pointer = input_line_pointer;
616 input_line_pointer = save;
618 return new_pointer;
621 /* Symbol modifiers (@GOT, @PLT, @GOTOFF). */
622 #define IMM_NONE 0
623 #define IMM_GOT 1
624 #define IMM_PLT 2
625 #define IMM_GOTOFF 3
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
631 #define IMM_TXTREL 9
632 #define IMM_TXTPCREL 10
633 #define IMM_MAX 11
635 struct imm_type {
636 const char *isuffix; /* Suffix String */
637 int itype; /* Suffix Type */
638 int otype; /* Offset Type */
641 /* These are NOT in ascending order of type, GOTOFF is ahead to make
642 sure @GOTOFF does not get matched with @GOT */
643 static 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 },
652 { "TLSTPREL", IMM_TLSTPREL, TLSTPREL_OFFSET },
653 { "TXTREL", IMM_TXTREL, TEXT_OFFSET },
654 { "TXTPCREL", IMM_TXTPCREL, TEXT_PC_OFFSET }
657 static int
658 match_imm (const char *s, int *ilen)
660 int i;
661 int slen;
663 /* Check for matching suffix */
664 for (i = 1; i < IMM_MAX; i++)
666 slen = strlen (imm_types[i].isuffix);
668 if (strncmp (imm_types[i].isuffix, s, slen) == 0)
670 *ilen = slen;
671 return imm_types[i].itype;
673 } /* for */
674 *ilen = 0;
675 return 0;
678 static int
679 get_imm_otype (int itype)
681 int i, otype;
683 otype = 0;
684 /* Check for matching itype */
685 for (i = 1; i < IMM_MAX; i++)
687 if (imm_types[i].itype == itype)
689 otype = imm_types[i].otype;
690 break;
693 return otype;
696 static symbolS * GOT_symbol;
698 #define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_"
700 static char *
701 parse_imm (char * s, expressionS * e, offsetT min, offsetT max)
703 char *new_pointer;
704 char *atp;
705 int itype, ilen;
707 ilen = 0;
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;
714 if (*atp == '@')
716 itype = match_imm (atp + 1, &ilen);
717 if (itype != 0)
719 *atp = 0;
720 e->X_md = itype;
722 else
724 atp = NULL;
725 e->X_md = 0;
726 ilen = 0;
728 *atp = 0;
730 else
732 atp = NULL;
733 e->X_md = 0;
736 if (atp && !GOT_symbol)
738 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
741 new_pointer = parse_exp (s, e);
743 if (!GOT_symbol && startswith (s, GOT_SYMBOL_NAME))
745 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
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"));
752 else if (e->X_op == O_constant)
754 /* Special case: sign extend negative 32-bit values to offsetT size. */
755 if ((e->X_add_number >> 31) == 1)
756 e->X_add_number |= -((addressT) (1U << 31));
758 if ((int)e->X_add_number < min || (int)e->X_add_number > max)
760 as_fatal (_("operand must be absolute in range %lx..%lx, not %lx"),
761 (long) min, (long) max, (long) e->X_add_number);
765 if (atp)
767 *atp = '@'; /* restore back (needed?) */
768 if (new_pointer >= atp)
769 new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */
771 return new_pointer;
774 static char *
775 check_got (int * got_type, int * got_len)
777 char *new_pointer;
778 char *atp;
779 char *past_got;
780 int first, second;
781 char *tmpbuf;
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;
788 if (startswith (atp + 1, "GOTOFF"))
790 *got_len = 6;
791 *got_type = IMM_GOTOFF;
793 else if (startswith (atp + 1, "GOT"))
795 *got_len = 3;
796 *got_type = IMM_GOT;
798 else if (startswith (atp + 1, "PLT"))
800 *got_len = 3;
801 *got_type = IMM_PLT;
803 else
804 return NULL;
806 if (!GOT_symbol)
807 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
809 first = atp - input_line_pointer;
811 past_got = atp + *got_len + 1;
812 for (new_pointer = past_got; !is_end_of_line[(unsigned char) *new_pointer++];)
814 second = new_pointer - past_got;
815 /* One extra byte for ' ' and one for NUL. */
816 tmpbuf = XNEWVEC (char, first + second + 2);
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';
822 return tmpbuf;
825 extern bfd_reloc_code_real_type
826 parse_cons_expression_microblaze (expressionS *exp, int size)
828 if (size == 4)
830 /* Handle @GOTOFF et.al. */
831 char *save, *gotfree_copy;
832 int got_len, got_type;
834 save = input_line_pointer;
835 gotfree_copy = check_got (& got_type, & got_len);
836 if (gotfree_copy)
837 input_line_pointer = gotfree_copy;
839 expression (exp);
841 if (gotfree_copy)
843 exp->X_md = got_type;
844 input_line_pointer = save + (input_line_pointer - gotfree_copy)
845 + got_len;
846 free (gotfree_copy);
849 else
850 expression (exp);
851 return BFD_RELOC_NONE;
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. */
858 static const char * str_microblaze_ro_anchor = "RO";
859 static const char * str_microblaze_rw_anchor = "RW";
861 static bool
862 check_spl_reg (unsigned * reg)
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)
870 || (*reg == REG_SHR) || (*reg == REG_SLR)
871 || (*reg >= REG_PVR+MIN_PVR_REGNUM && *reg <= REG_PVR+MAX_PVR_REGNUM))
872 return true;
874 return false;
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. */
883 tc_microblaze_fix_adjustable (struct fix *fixP)
885 if (GOT_symbol && fixP->fx_subsy == GOT_symbol)
886 return 0;
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
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)
899 return 0;
901 return 1;
904 void
905 md_assemble (char * str)
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;
918 unsigned int immed = 0, immed2 = 0, temp;
919 expressionS exp;
920 char name[20];
922 /* Drop leading whitespace. */
923 while (ISSPACE (* str))
924 str ++;
926 /* Find the op code end. */
927 for (op_start = op_end = str;
928 *op_end && !is_end_of_line[(unsigned char) *op_end] && *op_end != ' ';
929 op_end++)
931 name[nlen] = op_start[nlen];
932 nlen++;
933 if (nlen == sizeof (name) - 1)
934 break;
937 name [nlen] = 0;
939 if (nlen == 0)
941 as_bad (_("can't find opcode "));
942 return;
945 opcode = (struct op_code_struct *) str_hash_find (opcode_hash_control, name);
946 if (opcode == NULL)
948 as_bad (_("unknown opcode \"%s\""), name);
949 return;
952 inst = opcode->bit_sequence;
953 isize = 4;
955 switch (opcode->inst_type)
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
962 as_fatal (_("Error in statement syntax"));
963 reg1 = 0;
965 if (strcmp (op_end, ""))
966 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
967 else
969 as_fatal (_("Error in statement syntax"));
970 reg2 = 0;
972 if (strcmp (op_end, ""))
973 op_end = parse_reg (op_end + 1, &reg3); /* Get r2. */
974 else
976 as_fatal (_("Error in statement syntax"));
977 reg3 = 0;
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"));
988 if (streq (name, "sub"))
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;
995 else
997 inst |= (reg1 << RD_LOW) & RD_MASK;
998 inst |= (reg2 << RA_LOW) & RA_MASK;
999 inst |= (reg3 << RB_LOW) & RB_MASK;
1001 output = frag_more (isize);
1002 break;
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
1009 as_fatal (_("Error in statement syntax"));
1010 reg1 = 0;
1012 if (strcmp (op_end, ""))
1013 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1014 else
1016 as_fatal (_("Error in statement syntax"));
1017 reg2 = 0;
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"));
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"));
1030 if (exp.X_op != O_constant || exp.X_md == IMM_TXTPCREL)
1032 const char *opc;
1033 relax_substateT subtype;
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"));
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;
1046 if (exp.X_md != 0)
1047 subtype = get_imm_otype(exp.X_md);
1048 else
1049 subtype = opcode->inst_offset_type;
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,
1057 (char *) opc);
1058 immed = 0;
1060 else
1062 output = frag_more (isize);
1063 immed = exp.X_add_number;
1066 if (streq (name, "lmi") || streq (name, "smi"))
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;
1073 count = 32 - reg1;
1074 if (streq (name, "lmi"))
1075 opcode
1076 = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1077 "lwi");
1078 else
1079 opcode
1080 = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1081 "swi");
1082 if (opcode == NULL)
1084 as_bad (_("unknown opcode \"%s\""), "lwi");
1085 return;
1087 inst = opcode->bit_sequence;
1088 inst |= (reg1 << RD_LOW) & RD_MASK;
1089 inst |= (reg2 << RA_LOW) & RA_MASK;
1090 inst |= (immed << IMM_LOW) & IMM_MASK;
1092 for (i = 0; i < count - 1; i++)
1094 output[0] = INST_BYTE0 (inst);
1095 output[1] = INST_BYTE1 (inst);
1096 output[2] = INST_BYTE2 (inst);
1097 output[3] = INST_BYTE3 (inst);
1098 output = frag_more (isize);
1099 immed = immed + 4;
1100 reg1++;
1101 inst = opcode->bit_sequence;
1102 inst |= (reg1 << RD_LOW) & RD_MASK;
1103 inst |= (reg2 << RA_LOW) & RA_MASK;
1104 inst |= (immed << IMM_LOW) & IMM_MASK;
1107 else
1109 temp = immed & 0xFFFF8000;
1110 if ((temp != 0) && (temp != 0xFFFF8000))
1112 /* Needs an immediate inst. */
1113 opcode1
1114 = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1115 "imm");
1116 if (opcode1 == NULL)
1118 as_bad (_("unknown opcode \"%s\""), "imm");
1119 return;
1122 inst1 = opcode1->bit_sequence;
1123 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
1124 output[0] = INST_BYTE0 (inst1);
1125 output[1] = INST_BYTE1 (inst1);
1126 output[2] = INST_BYTE2 (inst1);
1127 output[3] = INST_BYTE3 (inst1);
1128 output = frag_more (isize);
1130 inst |= (reg1 << RD_LOW) & RD_MASK;
1131 inst |= (reg2 << RA_LOW) & RA_MASK;
1132 inst |= (immed << IMM_LOW) & IMM_MASK;
1134 break;
1136 case INST_TYPE_RD_R1_IMM5:
1137 if (strcmp (op_end, ""))
1138 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1139 else
1141 as_fatal (_("Error in statement syntax"));
1142 reg1 = 0;
1144 if (strcmp (op_end, ""))
1145 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1146 else
1148 as_fatal (_("Error in statement syntax"));
1149 reg2 = 0;
1151 if (strcmp (op_end, ""))
1152 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1153 else
1154 as_fatal (_("Error in statement syntax"));
1156 /* Check for spl registers. */
1157 if (check_spl_reg (&reg1))
1158 as_fatal (_("Cannot use special register with this instruction"));
1159 if (check_spl_reg (&reg2))
1160 as_fatal (_("Cannot use special register with this instruction"));
1162 if (exp.X_op != O_constant)
1163 as_warn (_("Symbol used as immediate for shift instruction"));
1164 else
1166 output = frag_more (isize);
1167 immed = exp.X_add_number;
1170 if (immed != (immed % 32))
1172 as_warn (_("Shift value > 32. using <value %% 32>"));
1173 immed = immed % 32;
1175 inst |= (reg1 << RD_LOW) & RD_MASK;
1176 inst |= (reg2 << RA_LOW) & RA_MASK;
1177 inst |= (immed << IMM_LOW) & IMM5_MASK;
1178 break;
1180 case INST_TYPE_RD_R1_IMMW_IMMS:
1181 if (strcmp (op_end, ""))
1182 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1183 else
1185 as_fatal (_("Error in statement syntax"));
1186 reg1 = 0;
1189 if (strcmp (op_end, ""))
1190 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1191 else
1193 as_fatal (_("Error in statement syntax"));
1194 reg2 = 0;
1197 /* Check for spl registers. */
1198 if (check_spl_reg (&reg1))
1199 as_fatal (_("Cannot use special register with this instruction"));
1200 if (check_spl_reg (&reg2))
1201 as_fatal (_("Cannot use special register with this instruction"));
1203 /* Width immediate value. */
1204 if (strcmp (op_end, ""))
1205 op_end = parse_imm (op_end + 1, &exp, MIN_IMM_WIDTH, MAX_IMM_WIDTH);
1206 else
1207 as_fatal (_("Error in statement syntax"));
1209 if (exp.X_op != O_constant)
1211 as_warn (_(
1212 "Symbol used as immediate width value for bit field instruction"));
1213 immed = 1;
1215 else
1216 immed = exp.X_add_number;
1218 if (opcode->instr == bsefi && immed > 31)
1219 as_fatal (_("Width value must be less than 32"));
1221 /* Shift immediate value. */
1222 if (strcmp (op_end, ""))
1223 op_end = parse_imm (op_end + 1, &exp, MIN_IMM, MAX_IMM);
1224 else
1225 as_fatal (_("Error in statement syntax"));
1227 if (exp.X_op != O_constant)
1229 as_warn (_(
1230 "Symbol used as immediate shift value for bit field instruction"));
1231 immed2 = 0;
1233 else
1235 output = frag_more (isize);
1236 immed2 = exp.X_add_number;
1239 if (immed2 != (immed2 % 32))
1241 as_warn (_("Shift value greater than 32. using <value %% 32>"));
1242 immed2 = immed2 % 32;
1245 /* Check combined value. */
1246 if (immed + immed2 > 32)
1247 as_fatal (_("Width value + shift value must not be greater than 32"));
1249 inst |= (reg1 << RD_LOW) & RD_MASK;
1250 inst |= (reg2 << RA_LOW) & RA_MASK;
1252 if (opcode->instr == bsefi)
1253 inst |= (immed & IMM5_MASK) << IMM_WIDTH_LOW; /* bsefi */
1254 else
1255 inst |= ((immed + immed2 - 1) & IMM5_MASK)
1256 << IMM_WIDTH_LOW; /* bsifi */
1258 inst |= (immed2 << IMM_LOW) & IMM5_MASK;
1259 break;
1261 case INST_TYPE_R1_R2:
1262 if (strcmp (op_end, ""))
1263 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1264 else
1266 as_fatal (_("Error in statement syntax"));
1267 reg1 = 0;
1269 if (strcmp (op_end, ""))
1270 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1271 else
1273 as_fatal (_("Error in statement syntax"));
1274 reg2 = 0;
1277 /* Check for spl registers. */
1278 if (check_spl_reg (& reg1))
1279 as_fatal (_("Cannot use special register with this instruction"));
1280 if (check_spl_reg (& reg2))
1281 as_fatal (_("Cannot use special register with this instruction"));
1283 inst |= (reg1 << RA_LOW) & RA_MASK;
1284 inst |= (reg2 << RB_LOW) & RB_MASK;
1285 output = frag_more (isize);
1286 break;
1288 case INST_TYPE_RD_R1:
1289 if (strcmp (op_end, ""))
1290 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1291 else
1293 as_fatal (_("Error in statement syntax"));
1294 reg1 = 0;
1296 if (strcmp (op_end, ""))
1297 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1298 else
1300 as_fatal (_("Error in statement syntax"));
1301 reg2 =0;
1304 /* Check for spl registers. */
1305 if (check_spl_reg (&reg1))
1306 as_fatal (_("Cannot use special register with this instruction"));
1307 if (check_spl_reg (&reg2))
1308 as_fatal (_("Cannot use special register with this instruction"));
1310 inst |= (reg1 << RD_LOW) & RD_MASK;
1311 inst |= (reg2 << RA_LOW) & RA_MASK;
1312 output = frag_more (isize);
1313 break;
1315 case INST_TYPE_RD_RFSL:
1316 if (strcmp (op_end, ""))
1317 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1318 else
1320 as_fatal (_("Error in statement syntax"));
1321 reg1 = 0;
1323 if (strcmp (op_end, ""))
1324 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
1325 else
1327 as_fatal (_("Error in statement syntax"));
1328 immed = 0;
1331 /* Check for spl registers. */
1332 if (check_spl_reg (&reg1))
1333 as_fatal (_("Cannot use special register with this instruction"));
1335 inst |= (reg1 << RD_LOW) & RD_MASK;
1336 inst |= (immed << IMM_LOW) & RFSL_MASK;
1337 output = frag_more (isize);
1338 break;
1340 case INST_TYPE_RD_IMM15:
1341 if (strcmp (op_end, ""))
1342 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1343 else
1345 as_fatal (_("Error in statement syntax"));
1346 reg1 = 0;
1349 if (strcmp (op_end, ""))
1350 op_end = parse_imm (op_end + 1, & exp, MIN_IMM15, MAX_IMM15);
1351 else
1352 as_fatal (_("Error in statement syntax"));
1354 /* Check for spl registers. */
1355 if (check_spl_reg (&reg1))
1356 as_fatal (_("Cannot use special register with this instruction"));
1358 if (exp.X_op != O_constant)
1359 as_fatal (_("Symbol used as immediate value for msrset/msrclr instructions"));
1360 else
1362 output = frag_more (isize);
1363 immed = exp.X_add_number;
1365 inst |= (reg1 << RD_LOW) & RD_MASK;
1366 inst |= (immed << IMM_LOW) & IMM15_MASK;
1367 break;
1369 case INST_TYPE_R1_RFSL:
1370 if (strcmp (op_end, ""))
1371 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1372 else
1374 as_fatal (_("Error in statement syntax"));
1375 reg1 = 0;
1377 if (strcmp (op_end, ""))
1378 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
1379 else
1381 as_fatal (_("Error in statement syntax"));
1382 immed = 0;
1385 /* Check for spl registers. */
1386 if (check_spl_reg (&reg1))
1387 as_fatal (_("Cannot use special register with this instruction"));
1389 inst |= (reg1 << RA_LOW) & RA_MASK;
1390 inst |= (immed << IMM_LOW) & RFSL_MASK;
1391 output = frag_more (isize);
1392 break;
1394 case INST_TYPE_RFSL:
1395 if (strcmp (op_end, ""))
1396 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
1397 else
1399 as_fatal (_("Error in statement syntax"));
1400 immed = 0;
1402 inst |= (immed << IMM_LOW) & RFSL_MASK;
1403 output = frag_more (isize);
1404 break;
1406 case INST_TYPE_R1:
1407 if (strcmp (op_end, ""))
1408 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1409 else
1411 as_fatal (_("Error in statement syntax"));
1412 reg1 = 0;
1415 /* Check for spl registers. */
1416 if (check_spl_reg (&reg1))
1417 as_fatal (_("Cannot use special register with this instruction"));
1419 inst |= (reg1 << RA_LOW) & RA_MASK;
1420 output = frag_more (isize);
1421 break;
1423 /* For tuqula insn...:) */
1424 case INST_TYPE_RD:
1425 if (strcmp (op_end, ""))
1426 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1427 else
1429 as_fatal (_("Error in statement syntax"));
1430 reg1 = 0;
1433 /* Check for spl registers. */
1434 if (check_spl_reg (&reg1))
1435 as_fatal (_("Cannot use special register with this instruction"));
1437 inst |= (reg1 << RD_LOW) & RD_MASK;
1438 output = frag_more (isize);
1439 break;
1441 case INST_TYPE_RD_SPECIAL:
1442 if (strcmp (op_end, ""))
1443 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1444 else
1446 as_fatal (_("Error in statement syntax"));
1447 reg1 = 0;
1449 if (strcmp (op_end, ""))
1450 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1451 else
1453 as_fatal (_("Error in statement syntax"));
1454 reg2 = 0;
1457 if (reg2 == REG_MSR)
1458 immed = opcode->immval_mask | REG_MSR_MASK;
1459 else if (reg2 == REG_PC)
1460 immed = opcode->immval_mask | REG_PC_MASK;
1461 else if (reg2 == REG_EAR)
1462 immed = opcode->immval_mask | REG_EAR_MASK;
1463 else if (reg2 == REG_ESR)
1464 immed = opcode->immval_mask | REG_ESR_MASK;
1465 else if (reg2 == REG_FSR)
1466 immed = opcode->immval_mask | REG_FSR_MASK;
1467 else if (reg2 == REG_BTR)
1468 immed = opcode->immval_mask | REG_BTR_MASK;
1469 else if (reg2 == REG_EDR)
1470 immed = opcode->immval_mask | REG_EDR_MASK;
1471 else if (reg2 == REG_PID)
1472 immed = opcode->immval_mask | REG_PID_MASK;
1473 else if (reg2 == REG_ZPR)
1474 immed = opcode->immval_mask | REG_ZPR_MASK;
1475 else if (reg2 == REG_TLBX)
1476 immed = opcode->immval_mask | REG_TLBX_MASK;
1477 else if (reg2 == REG_TLBLO)
1478 immed = opcode->immval_mask | REG_TLBLO_MASK;
1479 else if (reg2 == REG_TLBHI)
1480 immed = opcode->immval_mask | REG_TLBHI_MASK;
1481 else if (reg2 == REG_SHR)
1482 immed = opcode->immval_mask | REG_SHR_MASK;
1483 else if (reg2 == REG_SLR)
1484 immed = opcode->immval_mask | REG_SLR_MASK;
1485 else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM))
1486 immed = opcode->immval_mask | REG_PVR_MASK | reg2;
1487 else
1488 as_fatal (_("invalid value for special purpose register"));
1489 inst |= (reg1 << RD_LOW) & RD_MASK;
1490 inst |= (immed << IMM_LOW) & IMM_MASK;
1491 output = frag_more (isize);
1492 break;
1494 case INST_TYPE_SPECIAL_R1:
1495 if (strcmp (op_end, ""))
1496 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1497 else
1499 as_fatal (_("Error in statement syntax"));
1500 reg1 = 0;
1502 if (strcmp (op_end, ""))
1503 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1504 else
1506 as_fatal (_("Error in statement syntax"));
1507 reg2 = 0;
1510 if (reg1 == REG_MSR)
1511 immed = opcode->immval_mask | REG_MSR_MASK;
1512 else if (reg1 == REG_PC)
1513 immed = opcode->immval_mask | REG_PC_MASK;
1514 else if (reg1 == REG_EAR)
1515 immed = opcode->immval_mask | REG_EAR_MASK;
1516 else if (reg1 == REG_ESR)
1517 immed = opcode->immval_mask | REG_ESR_MASK;
1518 else if (reg1 == REG_FSR)
1519 immed = opcode->immval_mask | REG_FSR_MASK;
1520 else if (reg1 == REG_BTR)
1521 immed = opcode->immval_mask | REG_BTR_MASK;
1522 else if (reg1 == REG_EDR)
1523 immed = opcode->immval_mask | REG_EDR_MASK;
1524 else if (reg1 == REG_PID)
1525 immed = opcode->immval_mask | REG_PID_MASK;
1526 else if (reg1 == REG_ZPR)
1527 immed = opcode->immval_mask | REG_ZPR_MASK;
1528 else if (reg1 == REG_TLBX)
1529 immed = opcode->immval_mask | REG_TLBX_MASK;
1530 else if (reg1 == REG_TLBLO)
1531 immed = opcode->immval_mask | REG_TLBLO_MASK;
1532 else if (reg1 == REG_TLBHI)
1533 immed = opcode->immval_mask | REG_TLBHI_MASK;
1534 else if (reg1 == REG_TLBSX)
1535 immed = opcode->immval_mask | REG_TLBSX_MASK;
1536 else if (reg1 == REG_SHR)
1537 immed = opcode->immval_mask | REG_SHR_MASK;
1538 else if (reg1 == REG_SLR)
1539 immed = opcode->immval_mask | REG_SLR_MASK;
1540 else
1541 as_fatal (_("invalid value for special purpose register"));
1542 inst |= (reg2 << RA_LOW) & RA_MASK;
1543 inst |= (immed << IMM_LOW) & IMM_MASK;
1544 output = frag_more (isize);
1545 break;
1547 case INST_TYPE_R1_R2_SPECIAL:
1548 if (strcmp (op_end, ""))
1549 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1550 else
1552 as_fatal (_("Error in statement syntax"));
1553 reg1 = 0;
1555 if (strcmp (op_end, ""))
1556 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1557 else
1559 as_fatal (_("Error in statement syntax"));
1560 reg2 =0;
1563 /* Check for spl registers. */
1564 if (check_spl_reg (&reg1))
1565 as_fatal (_("Cannot use special register with this instruction"));
1566 if (check_spl_reg (&reg2))
1567 as_fatal (_("Cannot use special register with this instruction"));
1569 /* insn wic ra, rb => wic ra, ra, rb. */
1570 inst |= (reg1 << RA_LOW) & RA_MASK;
1571 inst |= (reg2 << RB_LOW) & RB_MASK;
1573 output = frag_more (isize);
1574 break;
1576 case INST_TYPE_RD_R2:
1577 if (strcmp (op_end, ""))
1578 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1579 else
1581 as_fatal (_("Error in statement syntax"));
1582 reg1 = 0;
1584 if (strcmp (op_end, ""))
1585 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1586 else
1588 as_fatal (_("Error in statement syntax"));
1589 reg2 = 0;
1592 /* Check for spl registers. */
1593 if (check_spl_reg (&reg1))
1594 as_fatal (_("Cannot use special register with this instruction"));
1595 if (check_spl_reg (&reg2))
1596 as_fatal (_("Cannot use special register with this instruction"));
1598 inst |= (reg1 << RD_LOW) & RD_MASK;
1599 inst |= (reg2 << RB_LOW) & RB_MASK;
1600 output = frag_more (isize);
1601 break;
1603 case INST_TYPE_R1_IMM:
1604 if (strcmp (op_end, ""))
1605 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1606 else
1608 as_fatal (_("Error in statement syntax"));
1609 reg1 = 0;
1611 if (strcmp (op_end, ""))
1612 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1613 else
1614 as_fatal (_("Error in statement syntax"));
1616 /* Check for spl registers. */
1617 if (check_spl_reg (&reg1))
1618 as_fatal (_("Cannot use special register with this instruction"));
1620 if (exp.X_op != O_constant)
1622 char *opc = NULL;
1623 relax_substateT subtype;
1625 if (exp.X_md != 0)
1626 subtype = get_imm_otype(exp.X_md);
1627 else
1628 subtype = opcode->inst_offset_type;
1630 output = frag_var (rs_machine_dependent,
1631 isize * 2, /* maxm of 2 words. */
1632 isize, /* minm of 1 word. */
1633 subtype, /* PC-relative or not. */
1634 exp.X_add_symbol,
1635 exp.X_add_number,
1636 opc);
1637 immed = 0;
1639 else
1641 output = frag_more (isize);
1642 immed = exp.X_add_number;
1645 temp = immed & 0xFFFF8000;
1646 if ((temp != 0) && (temp != 0xFFFF8000))
1648 /* Needs an immediate inst. */
1649 opcode1
1650 = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1651 "imm");
1652 if (opcode1 == NULL)
1654 as_bad (_("unknown opcode \"%s\""), "imm");
1655 return;
1658 inst1 = opcode1->bit_sequence;
1659 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
1660 output[0] = INST_BYTE0 (inst1);
1661 output[1] = INST_BYTE1 (inst1);
1662 output[2] = INST_BYTE2 (inst1);
1663 output[3] = INST_BYTE3 (inst1);
1664 output = frag_more (isize);
1667 inst |= (reg1 << RA_LOW) & RA_MASK;
1668 inst |= (immed << IMM_LOW) & IMM_MASK;
1669 break;
1671 case INST_TYPE_RD_IMM:
1672 if (strcmp (op_end, ""))
1673 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1674 else
1676 as_fatal (_("Error in statement syntax"));
1677 reg1 = 0;
1679 if (strcmp (op_end, ""))
1680 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1681 else
1682 as_fatal (_("Error in statement syntax"));
1684 /* Check for spl registers. */
1685 if (check_spl_reg (&reg1))
1686 as_fatal (_("Cannot use special register with this instruction"));
1688 if (exp.X_op != O_constant)
1690 char *opc = NULL;
1691 relax_substateT subtype;
1693 if (exp.X_md != 0)
1694 subtype = get_imm_otype(exp.X_md);
1695 else
1696 subtype = opcode->inst_offset_type;
1698 output = frag_var (rs_machine_dependent,
1699 isize * 2, /* maxm of 2 words. */
1700 isize, /* minm of 1 word. */
1701 subtype, /* PC-relative or not. */
1702 exp.X_add_symbol,
1703 exp.X_add_number,
1704 opc);
1705 immed = 0;
1707 else
1709 output = frag_more (isize);
1710 immed = exp.X_add_number;
1713 temp = immed & 0xFFFF8000;
1714 if ((temp != 0) && (temp != 0xFFFF8000))
1716 /* Needs an immediate inst. */
1717 opcode1
1718 = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1719 "imm");
1720 if (opcode1 == NULL)
1722 as_bad (_("unknown opcode \"%s\""), "imm");
1723 return;
1726 inst1 = opcode1->bit_sequence;
1727 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
1728 output[0] = INST_BYTE0 (inst1);
1729 output[1] = INST_BYTE1 (inst1);
1730 output[2] = INST_BYTE2 (inst1);
1731 output[3] = INST_BYTE3 (inst1);
1732 output = frag_more (isize);
1735 inst |= (reg1 << RD_LOW) & RD_MASK;
1736 inst |= (immed << IMM_LOW) & IMM_MASK;
1737 break;
1739 case INST_TYPE_R2:
1740 if (strcmp (op_end, ""))
1741 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1742 else
1744 as_fatal (_("Error in statement syntax"));
1745 reg2 = 0;
1748 /* Check for spl registers. */
1749 if (check_spl_reg (&reg2))
1750 as_fatal (_("Cannot use special register with this instruction"));
1752 inst |= (reg2 << RB_LOW) & RB_MASK;
1753 output = frag_more (isize);
1754 break;
1756 case INST_TYPE_IMM:
1757 if (streq (name, "imm"))
1758 as_fatal (_("An IMM instruction should not be present in the .s file"));
1760 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1762 if (exp.X_op != O_constant)
1764 char *opc = NULL;
1765 relax_substateT subtype;
1767 if (exp.X_md != 0)
1768 subtype = get_imm_otype(exp.X_md);
1769 else
1770 subtype = opcode->inst_offset_type;
1772 output = frag_var (rs_machine_dependent,
1773 isize * 2, /* maxm of 2 words. */
1774 isize, /* minm of 1 word. */
1775 subtype, /* PC-relative or not. */
1776 exp.X_add_symbol,
1777 exp.X_add_number,
1778 opc);
1779 immed = 0;
1781 else
1783 output = frag_more (isize);
1784 immed = exp.X_add_number;
1788 temp = immed & 0xFFFF8000;
1789 if ((temp != 0) && (temp != 0xFFFF8000))
1791 /* Needs an immediate inst. */
1792 opcode1
1793 = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1794 "imm");
1795 if (opcode1 == NULL)
1797 as_bad (_("unknown opcode \"%s\""), "imm");
1798 return;
1801 inst1 = opcode1->bit_sequence;
1802 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
1803 output[0] = INST_BYTE0 (inst1);
1804 output[1] = INST_BYTE1 (inst1);
1805 output[2] = INST_BYTE2 (inst1);
1806 output[3] = INST_BYTE3 (inst1);
1807 output = frag_more (isize);
1809 inst |= (immed << IMM_LOW) & IMM_MASK;
1810 break;
1812 case INST_TYPE_NONE:
1813 output = frag_more (isize);
1814 break;
1816 case INST_TYPE_IMM5:
1817 if (strcmp(op_end, ""))
1818 op_end = parse_imm (op_end + 1, & exp, MIN_IMM5, MAX_IMM5);
1819 else
1820 as_fatal(_("Error in statement syntax"));
1821 if (exp.X_op != O_constant) {
1822 as_warn(_("Symbol used as immediate for mbar instruction"));
1823 } else {
1824 output = frag_more (isize);
1825 immed = exp.X_add_number;
1827 if (immed != (immed % 32)) {
1828 as_warn(_("Immediate value for mbar > 32. using <value %% 32>"));
1829 immed = immed % 32;
1831 inst |= (immed << IMM_MBAR);
1832 break;
1834 default:
1835 as_fatal (_("unimplemented opcode \"%s\""), name);
1838 /* Drop whitespace after all the operands have been parsed. */
1839 while (ISSPACE (* op_end))
1840 op_end ++;
1842 /* Give warning message if the insn has more operands than required. */
1843 if (strcmp (op_end, opcode->name) && strcmp (op_end, ""))
1844 as_warn (_("ignoring operands: %s "), op_end);
1846 output[0] = INST_BYTE0 (inst);
1847 output[1] = INST_BYTE1 (inst);
1848 output[2] = INST_BYTE2 (inst);
1849 output[3] = INST_BYTE3 (inst);
1851 #ifdef OBJ_ELF
1852 dwarf2_emit_insn (4);
1853 #endif
1856 symbolS *
1857 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
1859 return NULL;
1862 /* Turn a string in input_line_pointer into a floating point constant of type
1863 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1864 emitted is stored in *sizeP. An error message is returned, or NULL on OK.*/
1866 const char *
1867 md_atof (int type, char * litP, int * sizeP)
1869 int prec;
1870 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1871 int i;
1872 char * t;
1874 switch (type)
1876 case 'f':
1877 case 'F':
1878 case 's':
1879 case 'S':
1880 prec = 2;
1881 break;
1883 case 'd':
1884 case 'D':
1885 case 'r':
1886 case 'R':
1887 prec = 4;
1888 break;
1890 case 'x':
1891 case 'X':
1892 prec = 6;
1893 break;
1895 case 'p':
1896 case 'P':
1897 prec = 6;
1898 break;
1900 default:
1901 *sizeP = 0;
1902 return _("Bad call to MD_NTOF()");
1905 t = atof_ieee (input_line_pointer, type, words);
1907 if (t)
1908 input_line_pointer = t;
1910 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1912 if (! target_big_endian)
1914 for (i = prec - 1; i >= 0; i--)
1916 md_number_to_chars (litP, (valueT) words[i],
1917 sizeof (LITTLENUM_TYPE));
1918 litP += sizeof (LITTLENUM_TYPE);
1921 else
1922 for (i = 0; i < prec; i++)
1924 md_number_to_chars (litP, (valueT) words[i],
1925 sizeof (LITTLENUM_TYPE));
1926 litP += sizeof (LITTLENUM_TYPE);
1929 return NULL;
1932 const char * md_shortopts = "";
1934 struct option md_longopts[] =
1936 {"EB", no_argument, NULL, OPTION_EB},
1937 {"EL", no_argument, NULL, OPTION_EL},
1938 {"mlittle-endian", no_argument, NULL, OPTION_EL},
1939 {"mbig-endian", no_argument, NULL, OPTION_EB},
1940 { NULL, no_argument, NULL, 0}
1943 size_t md_longopts_size = sizeof (md_longopts);
1945 int md_short_jump_size;
1947 void
1948 md_create_short_jump (char * ptr ATTRIBUTE_UNUSED,
1949 addressT from_Nddr ATTRIBUTE_UNUSED,
1950 addressT to_Nddr ATTRIBUTE_UNUSED,
1951 fragS * frag ATTRIBUTE_UNUSED,
1952 symbolS * to_symbol ATTRIBUTE_UNUSED)
1954 as_fatal (_("failed sanity check: short_jump"));
1957 void
1958 md_create_long_jump (char * ptr ATTRIBUTE_UNUSED,
1959 addressT from_Nddr ATTRIBUTE_UNUSED,
1960 addressT to_Nddr ATTRIBUTE_UNUSED,
1961 fragS * frag ATTRIBUTE_UNUSED,
1962 symbolS * to_symbol ATTRIBUTE_UNUSED)
1964 as_fatal (_("failed sanity check: long_jump"));
1967 /* Called after relaxing, change the frags so they know how big they are. */
1969 void
1970 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
1971 segT sec ATTRIBUTE_UNUSED,
1972 fragS * fragP)
1974 fixS *fixP;
1976 switch (fragP->fr_subtype)
1978 case UNDEFINED_PC_OFFSET:
1979 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1980 fragP->fr_offset, true, BFD_RELOC_64_PCREL);
1981 fragP->fr_fix += INST_WORD_SIZE * 2;
1982 fragP->fr_var = 0;
1983 break;
1984 case DEFINED_ABS_SEGMENT:
1985 if (fragP->fr_symbol == GOT_symbol)
1986 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1987 fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_64_GOTPC);
1988 else
1989 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1990 fragP->fr_offset, false, BFD_RELOC_64);
1991 fragP->fr_fix += INST_WORD_SIZE * 2;
1992 fragP->fr_var = 0;
1993 break;
1994 case DEFINED_RO_SEGMENT:
1995 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1996 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_32_ROSDA);
1997 fragP->fr_fix += INST_WORD_SIZE;
1998 fragP->fr_var = 0;
1999 break;
2000 case DEFINED_RW_SEGMENT:
2001 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
2002 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_32_RWSDA);
2003 fragP->fr_fix += INST_WORD_SIZE;
2004 fragP->fr_var = 0;
2005 break;
2006 case DEFINED_PC_OFFSET:
2007 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
2008 fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_32_LO_PCREL);
2009 fragP->fr_fix += INST_WORD_SIZE;
2010 fragP->fr_var = 0;
2011 break;
2012 case LARGE_DEFINED_PC_OFFSET:
2013 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2014 fragP->fr_offset, true, BFD_RELOC_64_PCREL);
2015 fragP->fr_fix += INST_WORD_SIZE * 2;
2016 fragP->fr_var = 0;
2017 break;
2018 case GOT_OFFSET:
2019 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2020 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_GOT);
2021 fragP->fr_fix += INST_WORD_SIZE * 2;
2022 fragP->fr_var = 0;
2023 break;
2024 case TEXT_OFFSET:
2025 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2026 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TEXTREL);
2027 fragP->fr_fix += INST_WORD_SIZE * 2;
2028 fragP->fr_var = 0;
2029 break;
2030 case TEXT_PC_OFFSET:
2031 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2032 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TEXTPCREL);
2033 fragP->fr_fix += INST_WORD_SIZE * 2;
2034 fragP->fr_var = 0;
2035 break;
2036 case PLT_OFFSET:
2037 fixP = fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2038 fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_64_PLT);
2039 /* fixP->fx_plt = 1; */
2040 (void) fixP;
2041 fragP->fr_fix += INST_WORD_SIZE * 2;
2042 fragP->fr_var = 0;
2043 break;
2044 case GOTOFF_OFFSET:
2045 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2046 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_GOTOFF);
2047 fragP->fr_fix += INST_WORD_SIZE * 2;
2048 fragP->fr_var = 0;
2049 break;
2050 case TLSGD_OFFSET:
2051 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2052 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TLSGD);
2053 fragP->fr_fix += INST_WORD_SIZE * 2;
2054 fragP->fr_var = 0;
2055 break;
2056 case TLSLD_OFFSET:
2057 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2058 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TLSLD);
2059 fragP->fr_fix += INST_WORD_SIZE * 2;
2060 fragP->fr_var = 0;
2061 break;
2062 case TLSDTPREL_OFFSET:
2063 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
2064 fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TLSDTPREL);
2065 fragP->fr_fix += INST_WORD_SIZE * 2;
2066 fragP->fr_var = 0;
2067 break;
2069 default:
2070 abort ();
2074 /* Applies the desired value to the specified location.
2075 Also sets up addends for 'rela' type relocations. */
2076 void
2077 md_apply_fix (fixS * fixP,
2078 valueT * valp,
2079 segT segment)
2081 char * buf = fixP->fx_where + &fixP->fx_frag->fr_literal[0];
2082 const char * file = fixP->fx_file ? fixP->fx_file : _("unknown");
2083 const char * symname;
2084 /* Note: use offsetT because it is signed, valueT is unsigned. */
2085 offsetT val = (offsetT) * valp;
2086 int i;
2087 struct op_code_struct * opcode1;
2088 unsigned long inst1;
2090 symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
2092 /* fixP->fx_offset is supposed to be set up correctly for all
2093 symbol relocations. */
2094 if (fixP->fx_addsy == NULL)
2096 if (!fixP->fx_pcrel)
2097 fixP->fx_offset = val; /* Absolute relocation. */
2098 else
2099 fprintf (stderr, "NULL symbol PC-relative relocation? offset = %08x, val = %08x\n",
2100 (unsigned int) fixP->fx_offset, (unsigned int) val);
2103 /* If we aren't adjusting this fixup to be against the section
2104 symbol, we need to adjust the value. */
2105 if (fixP->fx_addsy != NULL)
2107 if (S_IS_WEAK (fixP->fx_addsy)
2108 || (symbol_used_in_reloc_p (fixP->fx_addsy)
2109 && (((bfd_section_flags (S_GET_SEGMENT (fixP->fx_addsy))
2110 & SEC_LINK_ONCE) != 0)
2111 || startswith (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
2112 ".gnu.linkonce"))))
2114 val -= S_GET_VALUE (fixP->fx_addsy);
2115 if (val != 0 && ! fixP->fx_pcrel)
2117 /* In this case, the bfd_install_relocation routine will
2118 incorrectly add the symbol value back in. We just want
2119 the addend to appear in the object file.
2120 FIXME: If this makes VALUE zero, we're toast. */
2121 val -= S_GET_VALUE (fixP->fx_addsy);
2126 /* If the fix is relative to a symbol which is not defined, or not
2127 in the same segment as the fix, we cannot resolve it here. */
2128 /* fixP->fx_addsy is NULL if valp contains the entire relocation. */
2129 if (fixP->fx_addsy != NULL
2130 && (!S_IS_DEFINED (fixP->fx_addsy)
2131 || (S_GET_SEGMENT (fixP->fx_addsy) != segment)))
2133 fixP->fx_done = 0;
2134 #ifdef OBJ_ELF
2135 /* For ELF we can just return and let the reloc that will be generated
2136 take care of everything. For COFF we still have to insert 'val'
2137 into the insn since the addend field will be ignored. */
2138 /* return; */
2139 #endif
2141 /* All fixups in the text section must be handled in the linker. */
2142 else if (segment->flags & SEC_CODE)
2143 fixP->fx_done = 0;
2144 else if (!fixP->fx_pcrel && fixP->fx_addsy != NULL)
2145 fixP->fx_done = 0;
2146 else
2147 fixP->fx_done = 1;
2149 switch (fixP->fx_r_type)
2151 case BFD_RELOC_MICROBLAZE_32_LO:
2152 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2153 if (target_big_endian)
2155 buf[2] |= ((val >> 8) & 0xff);
2156 buf[3] |= (val & 0xff);
2158 else
2160 buf[1] |= ((val >> 8) & 0xff);
2161 buf[0] |= (val & 0xff);
2163 break;
2164 case BFD_RELOC_MICROBLAZE_32_ROSDA:
2165 case BFD_RELOC_MICROBLAZE_32_RWSDA:
2166 /* Don't do anything if the symbol is not defined. */
2167 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2169 if (((val & 0xFFFF8000) != 0) && ((val & 0xFFFF8000) != 0xFFFF8000))
2170 as_bad_where (file, fixP->fx_line,
2171 _("pcrel for branch to %s too far (0x%x)"),
2172 symname, (int) val);
2173 if (target_big_endian)
2175 buf[2] |= ((val >> 8) & 0xff);
2176 buf[3] |= (val & 0xff);
2178 else
2180 buf[1] |= ((val >> 8) & 0xff);
2181 buf[0] |= (val & 0xff);
2184 break;
2185 case BFD_RELOC_32:
2186 case BFD_RELOC_RVA:
2187 case BFD_RELOC_32_PCREL:
2188 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2189 /* Don't do anything if the symbol is not defined. */
2190 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2192 if (target_big_endian)
2194 buf[0] |= ((val >> 24) & 0xff);
2195 buf[1] |= ((val >> 16) & 0xff);
2196 buf[2] |= ((val >> 8) & 0xff);
2197 buf[3] |= (val & 0xff);
2199 else
2201 buf[3] |= ((val >> 24) & 0xff);
2202 buf[2] |= ((val >> 16) & 0xff);
2203 buf[1] |= ((val >> 8) & 0xff);
2204 buf[0] |= (val & 0xff);
2207 break;
2208 case BFD_RELOC_64_PCREL:
2209 case BFD_RELOC_64:
2210 case BFD_RELOC_MICROBLAZE_64_TEXTREL:
2211 /* Add an imm instruction. First save the current instruction. */
2212 for (i = 0; i < INST_WORD_SIZE; i++)
2213 buf[i + INST_WORD_SIZE] = buf[i];
2215 /* Generate the imm instruction. */
2216 opcode1
2217 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
2218 if (opcode1 == NULL)
2220 as_bad (_("unknown opcode \"%s\""), "imm");
2221 return;
2224 inst1 = opcode1->bit_sequence;
2225 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2226 inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
2228 buf[0] = INST_BYTE0 (inst1);
2229 buf[1] = INST_BYTE1 (inst1);
2230 buf[2] = INST_BYTE2 (inst1);
2231 buf[3] = INST_BYTE3 (inst1);
2233 /* Add the value only if the symbol is defined. */
2234 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2236 if (target_big_endian)
2238 buf[6] |= ((val >> 8) & 0xff);
2239 buf[7] |= (val & 0xff);
2241 else
2243 buf[5] |= ((val >> 8) & 0xff);
2244 buf[4] |= (val & 0xff);
2247 break;
2249 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2250 case BFD_RELOC_MICROBLAZE_64_TLSGD:
2251 case BFD_RELOC_MICROBLAZE_64_TLSLD:
2252 S_SET_THREAD_LOCAL (fixP->fx_addsy);
2253 /* Fall through. */
2255 case BFD_RELOC_MICROBLAZE_64_GOTPC:
2256 case BFD_RELOC_MICROBLAZE_64_GOT:
2257 case BFD_RELOC_MICROBLAZE_64_PLT:
2258 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2259 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2260 /* Add an imm instruction. First save the current instruction. */
2261 for (i = 0; i < INST_WORD_SIZE; i++)
2262 buf[i + INST_WORD_SIZE] = buf[i];
2264 /* Generate the imm instruction. */
2265 opcode1
2266 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
2267 if (opcode1 == NULL)
2269 as_bad (_("unknown opcode \"%s\""), "imm");
2270 return;
2273 inst1 = opcode1->bit_sequence;
2275 /* We can fixup call to a defined non-global address
2276 within the same section only. */
2277 buf[0] = INST_BYTE0 (inst1);
2278 buf[1] = INST_BYTE1 (inst1);
2279 buf[2] = INST_BYTE2 (inst1);
2280 buf[3] = INST_BYTE3 (inst1);
2281 return;
2283 default:
2284 break;
2287 if (fixP->fx_addsy == NULL)
2289 /* This fixup has been resolved. Create a reloc in case the linker
2290 moves code around due to relaxing. */
2291 if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
2292 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
2293 else if (fixP->fx_r_type == BFD_RELOC_32)
2294 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_32_NONE;
2295 else
2296 fixP->fx_r_type = BFD_RELOC_NONE;
2297 fixP->fx_addsy = section_symbol (absolute_section);
2299 return;
2302 void
2303 md_operand (expressionS * expressionP)
2305 /* Ignore leading hash symbol, if present. */
2306 if (*input_line_pointer == '#')
2308 input_line_pointer ++;
2309 expression (expressionP);
2313 /* Called just before address relaxation, return the length
2314 by which a fragment must grow to reach it's destination. */
2317 md_estimate_size_before_relax (fragS * fragP,
2318 segT segment_type)
2320 sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss");
2321 sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2");
2322 sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata");
2323 sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2");
2325 switch (fragP->fr_subtype)
2327 case INST_PC_OFFSET:
2328 /* Used to be a PC-relative branch. */
2329 if (!fragP->fr_symbol)
2331 /* We know the abs value: Should never happen. */
2332 as_bad (_("Absolute PC-relative value in relaxation code. Assembler error....."));
2333 abort ();
2335 else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
2336 !S_IS_WEAK (fragP->fr_symbol))
2338 fragP->fr_subtype = DEFINED_PC_OFFSET;
2339 /* Don't know now whether we need an imm instruction. */
2340 fragP->fr_var = INST_WORD_SIZE;
2342 else if (S_IS_DEFINED (fragP->fr_symbol)
2343 && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
2345 /* Cannot have a PC-relative branch to a diff segment. */
2346 as_bad (_("PC relative branch to label %s which is not in the instruction space"),
2347 S_GET_NAME (fragP->fr_symbol));
2348 fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2349 fragP->fr_var = INST_WORD_SIZE*2;
2351 else
2353 fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2354 fragP->fr_var = INST_WORD_SIZE*2;
2356 break;
2358 case INST_NO_OFFSET:
2359 case TEXT_OFFSET:
2360 /* Used to be a reference to somewhere which was unknown. */
2361 if (fragP->fr_symbol)
2363 if (fragP->fr_opcode == NULL)
2365 /* Used as an absolute value. */
2366 if (fragP->fr_subtype == INST_NO_OFFSET)
2367 fragP->fr_subtype = DEFINED_ABS_SEGMENT;
2368 /* Variable part does not change. */
2369 fragP->fr_var = INST_WORD_SIZE*2;
2371 else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
2373 /* It is accessed using the small data read only anchor. */
2374 if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
2375 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment)
2376 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment)
2377 || (! S_IS_DEFINED (fragP->fr_symbol)))
2379 fragP->fr_subtype = DEFINED_RO_SEGMENT;
2380 fragP->fr_var = INST_WORD_SIZE;
2382 else
2384 /* Variable not in small data read only segment accessed
2385 using small data read only anchor. */
2386 const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2388 as_bad_where (file, fragP->fr_line,
2389 _("Variable is accessed using small data read "
2390 "only anchor, but it is not in the small data "
2391 "read only section"));
2392 fragP->fr_subtype = DEFINED_RO_SEGMENT;
2393 fragP->fr_var = INST_WORD_SIZE;
2396 else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor))
2398 if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
2399 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment)
2400 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment)
2401 || (!S_IS_DEFINED (fragP->fr_symbol)))
2403 /* It is accessed using the small data read write anchor. */
2404 fragP->fr_subtype = DEFINED_RW_SEGMENT;
2405 fragP->fr_var = INST_WORD_SIZE;
2407 else
2409 const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2411 as_bad_where (file, fragP->fr_line,
2412 _("Variable is accessed using small data read "
2413 "write anchor, but it is not in the small data "
2414 "read write section"));
2415 fragP->fr_subtype = DEFINED_RW_SEGMENT;
2416 fragP->fr_var = INST_WORD_SIZE;
2419 else
2421 as_bad (_("Incorrect fr_opcode value in frag. Internal error....."));
2422 abort ();
2425 else
2427 /* We know the abs value: Should never happen. */
2428 as_bad (_("Absolute value in relaxation code. Assembler error....."));
2429 abort ();
2431 break;
2433 case UNDEFINED_PC_OFFSET:
2434 case LARGE_DEFINED_PC_OFFSET:
2435 case DEFINED_ABS_SEGMENT:
2436 case GOT_OFFSET:
2437 case PLT_OFFSET:
2438 case GOTOFF_OFFSET:
2439 case TEXT_PC_OFFSET:
2440 case TLSGD_OFFSET:
2441 case TLSLD_OFFSET:
2442 case TLSTPREL_OFFSET:
2443 case TLSDTPREL_OFFSET:
2444 fragP->fr_var = INST_WORD_SIZE*2;
2445 break;
2446 case DEFINED_RO_SEGMENT:
2447 case DEFINED_RW_SEGMENT:
2448 case DEFINED_PC_OFFSET:
2449 case TLSDTPMOD_OFFSET:
2450 fragP->fr_var = INST_WORD_SIZE;
2451 break;
2452 default:
2453 abort ();
2456 return fragP->fr_var;
2459 /* Put number into target byte order. */
2461 void
2462 md_number_to_chars (char * ptr, valueT use, int nbytes)
2464 if (target_big_endian)
2465 number_to_chars_bigendian (ptr, use, nbytes);
2466 else
2467 number_to_chars_littleendian (ptr, use, nbytes);
2470 /* Round up a section size to the appropriate boundary. */
2472 valueT
2473 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
2475 return size; /* Byte alignment is fine. */
2479 /* The location from which a PC relative jump should be calculated,
2480 given a PC relative reloc. */
2482 long
2483 md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
2485 #ifdef OBJ_ELF
2486 /* If the symbol is undefined or defined in another section
2487 we leave the add number alone for the linker to fix it later.
2488 Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */
2490 if (fixp->fx_addsy != (symbolS *) NULL
2491 && (!S_IS_DEFINED (fixp->fx_addsy)
2492 || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
2493 return 0;
2494 else
2496 /* The case where we are going to resolve things... */
2497 if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
2498 return fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
2499 else
2500 return fixp->fx_where + fixp->fx_frag->fr_address;
2502 #endif
2506 #define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
2507 #define MAP(SZ,PCREL,TYPE) case F (SZ, PCREL): code = (TYPE); break
2509 arelent *
2510 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
2512 arelent * rel;
2513 bfd_reloc_code_real_type code;
2515 switch (fixp->fx_r_type)
2517 case BFD_RELOC_NONE:
2518 case BFD_RELOC_MICROBLAZE_32_NONE:
2519 case BFD_RELOC_MICROBLAZE_64_NONE:
2520 case BFD_RELOC_32:
2521 case BFD_RELOC_MICROBLAZE_32_LO:
2522 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2523 case BFD_RELOC_RVA:
2524 case BFD_RELOC_64:
2525 case BFD_RELOC_64_PCREL:
2526 case BFD_RELOC_MICROBLAZE_32_ROSDA:
2527 case BFD_RELOC_MICROBLAZE_32_RWSDA:
2528 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2529 case BFD_RELOC_MICROBLAZE_64_GOTPC:
2530 case BFD_RELOC_MICROBLAZE_64_GOT:
2531 case BFD_RELOC_MICROBLAZE_64_PLT:
2532 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2533 case BFD_RELOC_MICROBLAZE_32_GOTOFF:
2534 case BFD_RELOC_MICROBLAZE_64_TLSGD:
2535 case BFD_RELOC_MICROBLAZE_64_TLSLD:
2536 case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
2537 case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
2538 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2539 case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
2540 case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
2541 case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2542 case BFD_RELOC_MICROBLAZE_64_TEXTREL:
2543 code = fixp->fx_r_type;
2544 break;
2546 default:
2547 switch (F (fixp->fx_size, fixp->fx_pcrel))
2549 MAP (1, 0, BFD_RELOC_8);
2550 MAP (2, 0, BFD_RELOC_16);
2551 MAP (4, 0, BFD_RELOC_32);
2552 MAP (1, 1, BFD_RELOC_8_PCREL);
2553 MAP (2, 1, BFD_RELOC_16_PCREL);
2554 MAP (4, 1, BFD_RELOC_32_PCREL);
2555 default:
2556 code = fixp->fx_r_type;
2557 as_bad (_("Can not do %d byte %srelocation"),
2558 fixp->fx_size,
2559 fixp->fx_pcrel ? _("pc-relative ") : "");
2561 break;
2564 rel = XNEW (arelent);
2565 rel->sym_ptr_ptr = XNEW (asymbol *);
2567 if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM)
2568 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
2569 else
2570 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2572 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
2573 /* Always pass the addend along! */
2574 rel->addend = fixp->fx_offset;
2575 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
2577 if (rel->howto == NULL)
2579 as_bad_where (fixp->fx_file, fixp->fx_line,
2580 _("Cannot represent relocation type %s"),
2581 bfd_get_reloc_code_name (code));
2583 /* Set howto to a garbage value so that we can keep going. */
2584 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
2585 gas_assert (rel->howto != NULL);
2587 return rel;
2591 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
2593 switch (c)
2595 case OPTION_EB:
2596 target_big_endian = 1;
2597 break;
2598 case OPTION_EL:
2599 target_big_endian = 0;
2600 break;
2601 default:
2602 return 0;
2604 return 1;
2607 void
2608 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
2610 /* fprintf(stream, _("\
2611 MicroBlaze options:\n\
2612 -noSmall Data in the comm and data sections do not go into the small data section\n")); */
2613 fprintf (stream, _(" MicroBlaze specific assembler options:\n"));
2614 fprintf (stream, " -%-23s%s\n", "mbig-endian", N_("assemble for a big endian cpu"));
2615 fprintf (stream, " -%-23s%s\n", "mlittle-endian", N_("assemble for a little endian cpu"));
2619 /* Create a fixup for a cons expression. If parse_cons_expression_microblaze
2620 found a machine specific op in an expression,
2621 then we create relocs accordingly. */
2623 void
2624 cons_fix_new_microblaze (fragS * frag,
2625 int where,
2626 int size,
2627 expressionS *exp,
2628 bfd_reloc_code_real_type r)
2630 if ((exp->X_op == O_subtract) && (exp->X_add_symbol) &&
2631 (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4)
2632 && (!S_IS_LOCAL (exp->X_op_symbol)))
2633 r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM;
2634 else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva)
2636 exp->X_op = O_symbol;
2637 r = BFD_RELOC_MICROBLAZE_32_GOTOFF;
2639 else
2641 switch (size)
2643 case 1:
2644 r = BFD_RELOC_8;
2645 break;
2646 case 2:
2647 r = BFD_RELOC_16;
2648 break;
2649 case 4:
2650 r = BFD_RELOC_32;
2651 break;
2652 case 8:
2653 r = BFD_RELOC_64;
2654 break;
2655 default:
2656 as_bad (_("unsupported BFD relocation size %u"), size);
2657 r = BFD_RELOC_32;
2658 break;
2661 fix_new_exp (frag, where, size, exp, 0, r);