xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/tc-microblaze.c (revision 154bfe8e089c1a0a4e9ed8414f08d3da90949162)
1 /* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
2 
3    Copyright (C) 2009-2020 Free Software Foundation, Inc.
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 
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"
33 
34 #ifndef streq
35 #define streq(a,b) (strcmp (a, b) == 0)
36 #endif
37 
38 #define OPTION_EB (OPTION_MD_BASE + 0)
39 #define OPTION_EL (OPTION_MD_BASE + 1)
40 
41 void microblaze_generate_symbol (char *sym);
42 static 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.  */
55 const char comment_chars[] = "#";
56 
57 const char line_separator_chars[] = ";";
58 
59 /* This array holds the chars that only start a comment at the beginning of
60    a line.  */
61 const char line_comment_chars[] = "#";
62 
63 const 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.  */
67 const 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.  */
72 const 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
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
92 
93 /* Initialize the relax table.  */
94 const 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.  */
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.  */
115 };
116 
117 static struct hash_control * opcode_hash_control;	/* Opcode mnemonics.  */
118 
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.  */
124 
125 /* Generate a symbol for stabs information.  */
126 
127 void
128 microblaze_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 
138 static void
139 microblaze_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 
148 static void
149 microblaze_s_data (int ignore ATTRIBUTE_UNUSED)
150 {
151 #ifdef OBJ_ELF
152   obj_elf_change_section (".data", SHT_PROGBITS, 0, SHF_ALLOC+SHF_WRITE,
153 			  0, 0, 0, 0);
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 
161 static void
162 microblaze_s_sdata (int ignore ATTRIBUTE_UNUSED)
163 {
164 #ifdef OBJ_ELF
165   obj_elf_change_section (".sdata", SHT_PROGBITS, 0, SHF_ALLOC+SHF_WRITE,
166 			  0, 0, 0, 0);
167 #else
168   s_data (ignore);
169 #endif
170 }
171 
172 /* Pseudo op to make file scope bss items.  */
173 
174 static void
175 microblaze_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;
183   char *pfrag;
184   int align2;
185   segT current_seg = now_seg;
186   subsegT current_subseg = now_subseg;
187 
188   c = get_symbol_name (&name);
189 
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 != ',')
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.  */
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 
277 static void
278 microblaze_s_rdata (int localvar)
279 {
280 #ifdef OBJ_ELF
281   if (localvar == 0)
282     {
283       /* rodata.  */
284       obj_elf_change_section (".rodata", SHT_PROGBITS, 0, SHF_ALLOC,
285 			      0, 0, 0, 0);
286       if (rodata_segment == 0)
287 	rodata_segment = subseg_new (".rodata", 0);
288     }
289   else
290     {
291       /* 1 .sdata2.  */
292       obj_elf_change_section (".sdata2", SHT_PROGBITS, 0, SHF_ALLOC,
293 			      0, 0, 0, 0);
294     }
295 #else
296   s_data (ignore);
297 #endif
298 }
299 
300 static void
301 microblaze_s_bss (int localvar)
302 {
303 #ifdef OBJ_ELF
304   if (localvar == 0) /* bss.  */
305     obj_elf_change_section (".bss", SHT_NOBITS, 0, SHF_ALLOC+SHF_WRITE,
306 			    0, 0, 0, 0);
307   else if (localvar == 1)
308     {
309       /* sbss.  */
310       obj_elf_change_section (".sbss", SHT_NOBITS, 0, SHF_ALLOC+SHF_WRITE,
311 			      0, 0, 0, 0);
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 
324 static void
325 microblaze_s_func (int end_p ATTRIBUTE_UNUSED)
326 {
327   char *name;
328   restore_line_pointer (get_symbol_name (&name));
329   s_func (1);
330 }
331 
332 /* Handle the .weakext pseudo-op as defined in Kane and Heinrich.  */
333 
334 static void
335 microblaze_s_weakext (int ignore ATTRIBUTE_UNUSED)
336 {
337   char *name;
338   int c;
339   symbolS *symbolP;
340   expressionS exp;
341 
342   c = get_symbol_name (&name);
343   symbolP = symbol_find_or_make (name);
344   S_SET_WEAK (symbolP);
345   (void) restore_line_pointer (c);
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.  */
385 const 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 
411 void
412 md_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 
425 static char *
426 parse_reg (char * s, unsigned * reg)
427 {
428   unsigned tmpreg = 0;
429 
430   /* Strip leading whitespace.  */
431   while (ISSPACE (* s))
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     {
503       if (ISDIGIT (s[4]) && ISDIGIT (s[5]))
504         {
505           tmpreg = (s[4]-'0')*10 + s[5] - '0';
506           s += 6;
507         }
508 
509       else if (ISDIGIT (s[4]))
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     {
532       if (ISDIGIT (s[4]) && ISDIGIT (s[5]))
533         {
534           tmpreg = (s[4] - '0') * 10 + s[5] - '0';
535           s += 6;
536         }
537       else if (ISDIGIT (s[4]))
538         {
539           tmpreg = s[4] - '0';
540           s += 5;
541         }
542       else
543 	as_bad (_("register expected, but saw '%.6s'"), s);
544 
545       if ((int) tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM)
546         *reg = tmpreg;
547       else
548 	{
549           as_bad (_("Invalid register number at '%.6s'"), s);
550           *reg = 0;
551 	}
552       return s;
553     }
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     }
565   else
566     {
567       if (TOLOWER (s[0]) == 'r')
568         {
569           if (ISDIGIT (s[1]) && ISDIGIT (s[2]))
570             {
571               tmpreg = (s[1] - '0') * 10 + s[2] - '0';
572               s += 3;
573             }
574           else if (ISDIGIT (s[1]))
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 
597 static char *
598 parse_exp (char *s, expressionS *e)
599 {
600   char *save;
601   char *new_pointer;
602 
603   /* Skip whitespace.  */
604   while (ISSPACE (* s))
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 
615   new_pointer = input_line_pointer;
616   input_line_pointer = save;
617 
618   return new_pointer;
619 }
620 
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
634 
635 struct imm_type {
636 	const char *isuffix;	 /* Suffix String */
637 	int itype;       /* Suffix Type */
638 	int otype;       /* Offset Type */
639 };
640 
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 }
655 };
656 
657 static int
658 match_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 
678 static int
679 get_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 }
695 
696 static symbolS * GOT_symbol;
697 
698 #define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_"
699 
700 static char *
701 parse_imm (char * s, expressionS * e, offsetT min, offsetT max)
702 {
703   char *new_pointer;
704   char *atp;
705   int itype, ilen;
706 
707   ilen = 0;
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     {
716       itype = match_imm (atp + 1, &ilen);
717       if (itype != 0)
718         {
719           *atp = 0;
720           e->X_md = itype;
721         }
722       else
723         {
724           atp = NULL;
725           e->X_md = 0;
726           ilen = 0;
727         }
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 
741   new_pointer = parse_exp (s, e);
742 
743   if (!GOT_symbol && ! strncmp (s, GOT_SYMBOL_NAME, 20))
744     {
745       GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
746     }
747 
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)
753     {
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));
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 	}
763     }
764 
765   if (atp)
766     {
767       *atp = '@'; /* restore back (needed?)  */
768       if (new_pointer >= atp)
769         new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */
770     }
771   return new_pointer;
772 }
773 
774 static char *
775 check_got (int * got_type, int * got_len)
776 {
777   char *new_pointer;
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;
812   for (new_pointer = past_got; !is_end_of_line[(unsigned char) *new_pointer++];)
813     ;
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';
821 
822   return tmpbuf;
823 }
824 
825 extern bfd_reloc_code_real_type
826 parse_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);
851   return BFD_RELOC_NONE;
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 
858 static const char * str_microblaze_ro_anchor = "RO";
859 static const char * str_microblaze_rw_anchor = "RW";
860 
861 static bfd_boolean
862 check_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)
870       || (*reg == REG_SHR)   || (*reg == REG_SLR)
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 
882 int
883 tc_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
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;
900 
901   return 1;
902 }
903 
904 void
905 md_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;
918   unsigned int immed, temp;
919   expressionS exp;
920   char name[20];
921 
922   /* Drop leading whitespace.  */
923   while (ISSPACE (* str))
924     str ++;
925 
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++)
930     {
931       name[nlen] = op_start[nlen];
932       nlen++;
933       if (nlen == sizeof (name) - 1)
934 	break;
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 
1030       if (exp.X_op != O_constant || exp.X_md == IMM_TXTPCREL)
1031 	{
1032           const char *opc;
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;
1046 	  if (exp.X_md != 0)
1047 	    subtype = get_imm_otype(exp.X_md);
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,
1057 			     (char *) opc);
1058 	  immed = 0;
1059         }
1060       else
1061 	{
1062           output = frag_more (isize);
1063           immed = exp.X_add_number;
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;
1086           inst |= (immed << IMM_LOW) & IMM_MASK;
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);
1095               immed = immed + 4;
1096               reg1++;
1097               inst = opcode->bit_sequence;
1098               inst |= (reg1 << RD_LOW) & RD_MASK;
1099               inst |= (reg2 << RA_LOW) & RA_MASK;
1100               inst |= (immed << IMM_LOW) & IMM_MASK;
1101             }
1102 	}
1103       else
1104 	{
1105           temp = immed & 0xFFFF8000;
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;
1117               inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
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;
1126 	  inst |= (immed << IMM_LOW) & IMM_MASK;
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);
1161           immed = exp.X_add_number;
1162         }
1163 
1164       if (immed != (immed % 32))
1165 	{
1166           as_warn (_("Shift value > 32. using <value %% 32>"));
1167           immed = immed % 32;
1168         }
1169       inst |= (reg1 << RD_LOW) & RD_MASK;
1170       inst |= (reg2 << RA_LOW) & RA_MASK;
1171       inst |= (immed << IMM_LOW) & IMM5_MASK;
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, ""))
1237         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
1238       else
1239 	{
1240           as_fatal (_("Error in statement syntax"));
1241           immed = 0;
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;
1249       inst |= (immed << IMM_LOW) & RFSL_MASK;
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);
1276           immed = exp.X_add_number;
1277         }
1278       inst |= (reg1 << RD_LOW) & RD_MASK;
1279       inst |= (immed << IMM_LOW) & IMM15_MASK;
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, ""))
1291         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
1292       else
1293 	{
1294           as_fatal (_("Error in statement syntax"));
1295           immed = 0;
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;
1303       inst |= (immed << IMM_LOW) & RFSL_MASK;
1304       output = frag_more (isize);
1305       break;
1306 
1307     case INST_TYPE_RFSL:
1308       if (strcmp (op_end, ""))
1309         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
1310       else
1311 	{
1312           as_fatal (_("Error in statement syntax"));
1313           immed = 0;
1314         }
1315       inst |= (immed << IMM_LOW) & RFSL_MASK;
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)
1371         immed = opcode->immval_mask | REG_MSR_MASK;
1372       else if (reg2 == REG_PC)
1373         immed = opcode->immval_mask | REG_PC_MASK;
1374       else if (reg2 == REG_EAR)
1375         immed = opcode->immval_mask | REG_EAR_MASK;
1376       else if (reg2 == REG_ESR)
1377         immed = opcode->immval_mask | REG_ESR_MASK;
1378       else if (reg2 == REG_FSR)
1379         immed = opcode->immval_mask | REG_FSR_MASK;
1380       else if (reg2 == REG_BTR)
1381         immed = opcode->immval_mask | REG_BTR_MASK;
1382       else if (reg2 == REG_EDR)
1383         immed = opcode->immval_mask | REG_EDR_MASK;
1384       else if (reg2 == REG_PID)
1385         immed = opcode->immval_mask | REG_PID_MASK;
1386       else if (reg2 == REG_ZPR)
1387         immed = opcode->immval_mask | REG_ZPR_MASK;
1388       else if (reg2 == REG_TLBX)
1389         immed = opcode->immval_mask | REG_TLBX_MASK;
1390       else if (reg2 == REG_TLBLO)
1391         immed = opcode->immval_mask | REG_TLBLO_MASK;
1392       else if (reg2 == REG_TLBHI)
1393         immed = opcode->immval_mask | REG_TLBHI_MASK;
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;
1398       else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM))
1399 	immed = opcode->immval_mask | REG_PVR_MASK | reg2;
1400       else
1401         as_fatal (_("invalid value for special purpose register"));
1402       inst |= (reg1 << RD_LOW) & RD_MASK;
1403       inst |= (immed << IMM_LOW) & IMM_MASK;
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)
1424         immed = opcode->immval_mask | REG_MSR_MASK;
1425       else if (reg1 == REG_PC)
1426         immed = opcode->immval_mask | REG_PC_MASK;
1427       else if (reg1 == REG_EAR)
1428         immed = opcode->immval_mask | REG_EAR_MASK;
1429       else if (reg1 == REG_ESR)
1430         immed = opcode->immval_mask | REG_ESR_MASK;
1431       else if (reg1 == REG_FSR)
1432         immed = opcode->immval_mask | REG_FSR_MASK;
1433       else if (reg1 == REG_BTR)
1434         immed = opcode->immval_mask | REG_BTR_MASK;
1435       else if (reg1 == REG_EDR)
1436         immed = opcode->immval_mask | REG_EDR_MASK;
1437       else if (reg1 == REG_PID)
1438         immed = opcode->immval_mask | REG_PID_MASK;
1439       else if (reg1 == REG_ZPR)
1440         immed = opcode->immval_mask | REG_ZPR_MASK;
1441       else if (reg1 == REG_TLBX)
1442         immed = opcode->immval_mask | REG_TLBX_MASK;
1443       else if (reg1 == REG_TLBLO)
1444         immed = opcode->immval_mask | REG_TLBLO_MASK;
1445       else if (reg1 == REG_TLBHI)
1446         immed = opcode->immval_mask | REG_TLBHI_MASK;
1447       else if (reg1 == REG_TLBSX)
1448         immed = opcode->immval_mask | REG_TLBSX_MASK;
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;
1453       else
1454         as_fatal (_("invalid value for special purpose register"));
1455       inst |= (reg2 << RA_LOW) & RA_MASK;
1456       inst |= (immed << IMM_LOW) & IMM_MASK;
1457       output = frag_more (isize);
1458       break;
1459 
1460     case INST_TYPE_R1_R2_SPECIAL:
1461       if (strcmp (op_end, ""))
1462         op_end = parse_reg (op_end + 1, &reg1);  /* Get r1.  */
1463       else
1464 	{
1465           as_fatal (_("Error in statement syntax"));
1466           reg1 = 0;
1467         }
1468       if (strcmp (op_end, ""))
1469         op_end = parse_reg (op_end + 1, &reg2);  /* Get r2.  */
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.  */
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 
1538 	  if (exp.X_md != 0)
1539 	    subtype = get_imm_otype(exp.X_md);
1540 	  else
1541 	    subtype = opcode->inst_offset_type;
1542 
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);
1550 	  immed = 0;
1551 	}
1552       else
1553 	{
1554           output = frag_more (isize);
1555           immed = exp.X_add_number;
1556         }
1557 
1558       temp = immed & 0xFFFF8000;
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;
1570           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
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;
1579       inst |= (immed << IMM_LOW) & IMM_MASK;
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 
1604 	  if (exp.X_md != 0)
1605 	    subtype = get_imm_otype(exp.X_md);
1606 	  else
1607 	    subtype = opcode->inst_offset_type;
1608 
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);
1616           immed = 0;
1617 	}
1618       else
1619 	{
1620           output = frag_more (isize);
1621           immed = exp.X_add_number;
1622         }
1623 
1624       temp = immed & 0xFFFF8000;
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;
1636           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
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;
1645       inst |= (immed << IMM_LOW) & IMM_MASK;
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 
1676 	  if (exp.X_md != 0)
1677 	    subtype = get_imm_otype(exp.X_md);
1678 	  else
1679 	    subtype = opcode->inst_offset_type;
1680 
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);
1688           immed = 0;
1689         }
1690       else
1691 	{
1692           output = frag_more (isize);
1693           immed = exp.X_add_number;
1694         }
1695 
1696 
1697       temp = immed & 0xFFFF8000;
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;
1709           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
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         }
1716       inst |= (immed << IMM_LOW) & IMM_MASK;
1717       break;
1718 
1719     case INST_TYPE_NONE:
1720       output = frag_more (isize);
1721       break;
1722 
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 
1741     default:
1742       as_fatal (_("unimplemented opcode \"%s\""), name);
1743     }
1744 
1745   /* Drop whitespace after all the operands have been parsed.  */
1746   while (ISSPACE (* op_end))
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 
1763 symbolS *
1764 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
1765 {
1766   return NULL;
1767 }
1768 
1769 /* Turn a string in input_line_pointer into a floating point constant of type
1770    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
1771    emitted is stored in *sizeP.  An error message is returned, or NULL on OK.*/
1772 
1773 const char *
1774 md_atof (int type, char * litP, int * sizeP)
1775 {
1776   int prec;
1777   LITTLENUM_TYPE words[MAX_LITTLENUMS];
1778   int    i;
1779   char * t;
1780 
1781   switch (type)
1782     {
1783     case 'f':
1784     case 'F':
1785     case 's':
1786     case 'S':
1787       prec = 2;
1788       break;
1789 
1790     case 'd':
1791     case 'D':
1792     case 'r':
1793     case 'R':
1794       prec = 4;
1795       break;
1796 
1797     case 'x':
1798     case 'X':
1799       prec = 6;
1800       break;
1801 
1802     case 'p':
1803     case 'P':
1804       prec = 6;
1805       break;
1806 
1807     default:
1808       *sizeP = 0;
1809       return _("Bad call to MD_NTOF()");
1810     }
1811 
1812   t = atof_ieee (input_line_pointer, type, words);
1813 
1814   if (t)
1815     input_line_pointer = t;
1816 
1817   *sizeP = prec * sizeof (LITTLENUM_TYPE);
1818 
1819   if (! target_big_endian)
1820     {
1821       for (i = prec - 1; i >= 0; i--)
1822         {
1823           md_number_to_chars (litP, (valueT) words[i],
1824                               sizeof (LITTLENUM_TYPE));
1825           litP += sizeof (LITTLENUM_TYPE);
1826         }
1827     }
1828   else
1829     for (i = 0; i < prec; i++)
1830       {
1831         md_number_to_chars (litP, (valueT) words[i],
1832                             sizeof (LITTLENUM_TYPE));
1833         litP += sizeof (LITTLENUM_TYPE);
1834       }
1835 
1836   return NULL;
1837 }
1838 
1839 const char * md_shortopts = "";
1840 
1841 struct option md_longopts[] =
1842 {
1843   {"EB", no_argument, NULL, OPTION_EB},
1844   {"EL", no_argument, NULL, OPTION_EL},
1845   { NULL,          no_argument, NULL, 0}
1846 };
1847 
1848 size_t md_longopts_size = sizeof (md_longopts);
1849 
1850 int md_short_jump_size;
1851 
1852 void
1853 md_create_short_jump (char * ptr ATTRIBUTE_UNUSED,
1854 		      addressT from_Nddr ATTRIBUTE_UNUSED,
1855 		      addressT to_Nddr ATTRIBUTE_UNUSED,
1856 		      fragS * frag ATTRIBUTE_UNUSED,
1857 		      symbolS * to_symbol ATTRIBUTE_UNUSED)
1858 {
1859   as_fatal (_("failed sanity check: short_jump"));
1860 }
1861 
1862 void
1863 md_create_long_jump (char * ptr ATTRIBUTE_UNUSED,
1864 		     addressT from_Nddr ATTRIBUTE_UNUSED,
1865 		     addressT to_Nddr ATTRIBUTE_UNUSED,
1866 		     fragS * frag ATTRIBUTE_UNUSED,
1867 		     symbolS * to_symbol ATTRIBUTE_UNUSED)
1868 {
1869   as_fatal (_("failed sanity check: long_jump"));
1870 }
1871 
1872 /* Called after relaxing, change the frags so they know how big they are.  */
1873 
1874 void
1875 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
1876 	         segT sec ATTRIBUTE_UNUSED,
1877 		 fragS * fragP)
1878 {
1879   fixS *fixP;
1880 
1881   switch (fragP->fr_subtype)
1882     {
1883     case UNDEFINED_PC_OFFSET:
1884       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1885 	       fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL);
1886       fragP->fr_fix += INST_WORD_SIZE * 2;
1887       fragP->fr_var = 0;
1888       break;
1889     case DEFINED_ABS_SEGMENT:
1890       if (fragP->fr_symbol == GOT_symbol)
1891         fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1892 	         fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GOTPC);
1893       else
1894         fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1895 	         fragP->fr_offset, FALSE, BFD_RELOC_64);
1896       fragP->fr_fix += INST_WORD_SIZE * 2;
1897       fragP->fr_var = 0;
1898       break;
1899     case DEFINED_RO_SEGMENT:
1900       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1901 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_ROSDA);
1902       fragP->fr_fix += INST_WORD_SIZE;
1903       fragP->fr_var = 0;
1904       break;
1905     case DEFINED_RW_SEGMENT:
1906       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1907 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_RWSDA);
1908       fragP->fr_fix += INST_WORD_SIZE;
1909       fragP->fr_var = 0;
1910       break;
1911     case DEFINED_PC_OFFSET:
1912       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1913 	       fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_32_LO_PCREL);
1914       fragP->fr_fix += INST_WORD_SIZE;
1915       fragP->fr_var = 0;
1916       break;
1917     case LARGE_DEFINED_PC_OFFSET:
1918       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1919 	       fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL);
1920       fragP->fr_fix += INST_WORD_SIZE * 2;
1921       fragP->fr_var = 0;
1922       break;
1923     case GOT_OFFSET:
1924       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1925 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOT);
1926       fragP->fr_fix += INST_WORD_SIZE * 2;
1927       fragP->fr_var = 0;
1928       break;
1929     case TEXT_OFFSET:
1930       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1931 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TEXTREL);
1932       fragP->fr_fix += INST_WORD_SIZE * 2;
1933       fragP->fr_var = 0;
1934       break;
1935     case TEXT_PC_OFFSET:
1936       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1937 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TEXTPCREL);
1938       fragP->fr_fix += INST_WORD_SIZE * 2;
1939       fragP->fr_var = 0;
1940       break;
1941     case PLT_OFFSET:
1942       fixP = fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1943 	              fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_PLT);
1944       /* fixP->fx_plt = 1; */
1945       (void) fixP;
1946       fragP->fr_fix += INST_WORD_SIZE * 2;
1947       fragP->fr_var = 0;
1948       break;
1949     case GOTOFF_OFFSET:
1950       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1951 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOTOFF);
1952       fragP->fr_fix += INST_WORD_SIZE * 2;
1953       fragP->fr_var = 0;
1954       break;
1955     case TLSGD_OFFSET:
1956       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1957 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSGD);
1958       fragP->fr_fix += INST_WORD_SIZE * 2;
1959       fragP->fr_var = 0;
1960       break;
1961     case TLSLD_OFFSET:
1962       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1963 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSLD);
1964       fragP->fr_fix += INST_WORD_SIZE * 2;
1965       fragP->fr_var = 0;
1966       break;
1967     case TLSDTPREL_OFFSET:
1968       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1969 	       fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSDTPREL);
1970       fragP->fr_fix += INST_WORD_SIZE * 2;
1971       fragP->fr_var = 0;
1972       break;
1973 
1974     default:
1975       abort ();
1976     }
1977 }
1978 
1979 /* Applies the desired value to the specified location.
1980    Also sets up addends for 'rela' type relocations.  */
1981 void
1982 md_apply_fix (fixS *   fixP,
1983 	      valueT * valp,
1984 	      segT     segment)
1985 {
1986   char *       buf  = fixP->fx_where + fixP->fx_frag->fr_literal;
1987   const char *       file = fixP->fx_file ? fixP->fx_file : _("unknown");
1988   const char * symname;
1989   /* Note: use offsetT because it is signed, valueT is unsigned.  */
1990   offsetT      val  = (offsetT) * valp;
1991   int          i;
1992   struct op_code_struct * opcode1;
1993   unsigned long inst1;
1994 
1995   symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
1996 
1997   /* fixP->fx_offset is supposed to be set up correctly for all
1998      symbol relocations.  */
1999   if (fixP->fx_addsy == NULL)
2000     {
2001       if (!fixP->fx_pcrel)
2002         fixP->fx_offset = val; /* Absolute relocation.  */
2003       else
2004         fprintf (stderr, "NULL symbol PC-relative relocation? offset = %08x, val = %08x\n",
2005                  (unsigned int) fixP->fx_offset, (unsigned int) val);
2006     }
2007 
2008   /* If we aren't adjusting this fixup to be against the section
2009      symbol, we need to adjust the value.  */
2010   if (fixP->fx_addsy != NULL)
2011     {
2012       if (S_IS_WEAK (fixP->fx_addsy)
2013 	  || (symbol_used_in_reloc_p (fixP->fx_addsy)
2014 	      && (((bfd_section_flags (S_GET_SEGMENT (fixP->fx_addsy))
2015 		    & SEC_LINK_ONCE) != 0)
2016 		  || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
2017 			       ".gnu.linkonce",
2018 			       sizeof (".gnu.linkonce") - 1))))
2019 	{
2020 	  val -= S_GET_VALUE (fixP->fx_addsy);
2021 	  if (val != 0 && ! fixP->fx_pcrel)
2022             {
2023               /* In this case, the bfd_install_relocation routine will
2024                  incorrectly add the symbol value back in.  We just want
2025                  the addend to appear in the object file.
2026 	         FIXME: If this makes VALUE zero, we're toast.  */
2027               val -= S_GET_VALUE (fixP->fx_addsy);
2028             }
2029 	}
2030     }
2031 
2032   /* If the fix is relative to a symbol which is not defined, or not
2033      in the same segment as the fix, we cannot resolve it here.  */
2034   /* fixP->fx_addsy is NULL if valp contains the entire relocation.  */
2035   if (fixP->fx_addsy != NULL
2036       && (!S_IS_DEFINED (fixP->fx_addsy)
2037           || (S_GET_SEGMENT (fixP->fx_addsy) != segment)))
2038     {
2039       fixP->fx_done = 0;
2040 #ifdef OBJ_ELF
2041       /* For ELF we can just return and let the reloc that will be generated
2042          take care of everything.  For COFF we still have to insert 'val'
2043          into the insn since the addend field will be ignored.  */
2044       /* return; */
2045 #endif
2046     }
2047   /* All fixups in the text section must be handled in the linker.  */
2048   else if (segment->flags & SEC_CODE)
2049     fixP->fx_done = 0;
2050   else if (!fixP->fx_pcrel && fixP->fx_addsy != NULL)
2051     fixP->fx_done = 0;
2052   else
2053     fixP->fx_done = 1;
2054 
2055   switch (fixP->fx_r_type)
2056     {
2057     case BFD_RELOC_MICROBLAZE_32_LO:
2058     case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2059       if (target_big_endian)
2060 	{
2061 	  buf[2] |= ((val >> 8) & 0xff);
2062 	  buf[3] |= (val & 0xff);
2063 	}
2064       else
2065 	{
2066 	  buf[1] |= ((val >> 8) & 0xff);
2067 	  buf[0] |= (val & 0xff);
2068 	}
2069       break;
2070     case BFD_RELOC_MICROBLAZE_32_ROSDA:
2071     case BFD_RELOC_MICROBLAZE_32_RWSDA:
2072       /* Don't do anything if the symbol is not defined.  */
2073       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2074 	{
2075 	  if (((val & 0xFFFF8000) != 0) && ((val & 0xFFFF8000) != 0xFFFF8000))
2076 	    as_bad_where (file, fixP->fx_line,
2077 			  _("pcrel for branch to %s too far (0x%x)"),
2078 			  symname, (int) val);
2079 	  if (target_big_endian)
2080 	    {
2081 	      buf[2] |= ((val >> 8) & 0xff);
2082 	      buf[3] |= (val & 0xff);
2083 	    }
2084 	  else
2085 	    {
2086 	      buf[1] |= ((val >> 8) & 0xff);
2087 	      buf[0] |= (val & 0xff);
2088 	    }
2089 	}
2090       break;
2091     case BFD_RELOC_32:
2092     case BFD_RELOC_RVA:
2093     case BFD_RELOC_32_PCREL:
2094     case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2095       /* Don't do anything if the symbol is not defined.  */
2096       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2097 	{
2098 	  if (target_big_endian)
2099 	    {
2100 	      buf[0] |= ((val >> 24) & 0xff);
2101 	      buf[1] |= ((val >> 16) & 0xff);
2102 	      buf[2] |= ((val >> 8) & 0xff);
2103 	      buf[3] |= (val & 0xff);
2104 	    }
2105 	  else
2106 	    {
2107 	      buf[3] |= ((val >> 24) & 0xff);
2108 	      buf[2] |= ((val >> 16) & 0xff);
2109 	      buf[1] |= ((val >> 8) & 0xff);
2110 	      buf[0] |= (val & 0xff);
2111 	    }
2112 	}
2113       break;
2114     case BFD_RELOC_64_PCREL:
2115     case BFD_RELOC_64:
2116     case BFD_RELOC_MICROBLAZE_64_TEXTREL:
2117       /* Add an imm instruction.  First save the current instruction.  */
2118       for (i = 0; i < INST_WORD_SIZE; i++)
2119 	buf[i + INST_WORD_SIZE] = buf[i];
2120 
2121       /* Generate the imm instruction.  */
2122       opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
2123       if (opcode1 == NULL)
2124 	{
2125 	  as_bad (_("unknown opcode \"%s\""), "imm");
2126 	  return;
2127 	}
2128 
2129       inst1 = opcode1->bit_sequence;
2130       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2131 	inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
2132 
2133       buf[0] = INST_BYTE0 (inst1);
2134       buf[1] = INST_BYTE1 (inst1);
2135       buf[2] = INST_BYTE2 (inst1);
2136       buf[3] = INST_BYTE3 (inst1);
2137 
2138       /* Add the value only if the symbol is defined.  */
2139       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2140 	{
2141 	  if (target_big_endian)
2142 	    {
2143 	      buf[6] |= ((val >> 8) & 0xff);
2144 	      buf[7] |= (val & 0xff);
2145 	    }
2146 	  else
2147 	    {
2148 	      buf[5] |= ((val >> 8) & 0xff);
2149 	      buf[4] |= (val & 0xff);
2150 	    }
2151 	}
2152       break;
2153 
2154     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2155     case BFD_RELOC_MICROBLAZE_64_TLSGD:
2156     case BFD_RELOC_MICROBLAZE_64_TLSLD:
2157       S_SET_THREAD_LOCAL (fixP->fx_addsy);
2158       /* Fall through.  */
2159 
2160     case BFD_RELOC_MICROBLAZE_64_GOTPC:
2161     case BFD_RELOC_MICROBLAZE_64_GOT:
2162     case BFD_RELOC_MICROBLAZE_64_PLT:
2163     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2164     case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2165       /* Add an imm instruction.  First save the current instruction.  */
2166       for (i = 0; i < INST_WORD_SIZE; i++)
2167 	buf[i + INST_WORD_SIZE] = buf[i];
2168 
2169       /* Generate the imm instruction.  */
2170       opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
2171       if (opcode1 == NULL)
2172 	{
2173 	  as_bad (_("unknown opcode \"%s\""), "imm");
2174 	  return;
2175 	}
2176 
2177       inst1 = opcode1->bit_sequence;
2178 
2179       /* We can fixup call to a defined non-global address
2180 	 within the same section only.  */
2181       buf[0] = INST_BYTE0 (inst1);
2182       buf[1] = INST_BYTE1 (inst1);
2183       buf[2] = INST_BYTE2 (inst1);
2184       buf[3] = INST_BYTE3 (inst1);
2185       return;
2186 
2187     default:
2188       break;
2189     }
2190 
2191   if (fixP->fx_addsy == NULL)
2192     {
2193       /* This fixup has been resolved.  Create a reloc in case the linker
2194 	 moves code around due to relaxing.  */
2195       if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
2196 	fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
2197       else
2198 	fixP->fx_r_type = BFD_RELOC_NONE;
2199       fixP->fx_addsy = section_symbol (absolute_section);
2200     }
2201   return;
2202 }
2203 
2204 void
2205 md_operand (expressionS * expressionP)
2206 {
2207   /* Ignore leading hash symbol, if present.  */
2208   if (*input_line_pointer == '#')
2209     {
2210       input_line_pointer ++;
2211       expression (expressionP);
2212     }
2213 }
2214 
2215 /* Called just before address relaxation, return the length
2216    by which a fragment must grow to reach it's destination.  */
2217 
2218 int
2219 md_estimate_size_before_relax (fragS * fragP,
2220 			       segT segment_type)
2221 {
2222   sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss");
2223   sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2");
2224   sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata");
2225   sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2");
2226 
2227   switch (fragP->fr_subtype)
2228     {
2229     case INST_PC_OFFSET:
2230       /* Used to be a PC-relative branch.  */
2231       if (!fragP->fr_symbol)
2232         {
2233           /* We know the abs value: Should never happen.  */
2234           as_bad (_("Absolute PC-relative value in relaxation code.  Assembler error....."));
2235           abort ();
2236         }
2237       else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
2238                !S_IS_WEAK (fragP->fr_symbol))
2239         {
2240           fragP->fr_subtype = DEFINED_PC_OFFSET;
2241           /* Don't know now whether we need an imm instruction.  */
2242           fragP->fr_var = INST_WORD_SIZE;
2243         }
2244       else if (S_IS_DEFINED (fragP->fr_symbol)
2245 	       && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
2246         {
2247           /* Cannot have a PC-relative branch to a diff segment.  */
2248           as_bad (_("PC relative branch to label %s which is not in the instruction space"),
2249 		  S_GET_NAME (fragP->fr_symbol));
2250           fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2251           fragP->fr_var = INST_WORD_SIZE*2;
2252         }
2253       else
2254 	{
2255 	  fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2256 	  fragP->fr_var = INST_WORD_SIZE*2;
2257 	}
2258       break;
2259 
2260     case INST_NO_OFFSET:
2261     case TEXT_OFFSET:
2262       /* Used to be a reference to somewhere which was unknown.  */
2263       if (fragP->fr_symbol)
2264         {
2265 	  if (fragP->fr_opcode == NULL)
2266 	    {
2267 	      /* Used as an absolute value.  */
2268 	      if (fragP->fr_subtype == INST_NO_OFFSET)
2269 	        fragP->fr_subtype = DEFINED_ABS_SEGMENT;
2270 	      /* Variable part does not change.  */
2271 	      fragP->fr_var = INST_WORD_SIZE*2;
2272 	    }
2273 	  else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
2274 	    {
2275               /* It is accessed using the small data read only anchor.  */
2276               if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
2277 		  || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment)
2278 		  || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment)
2279 		  || (! S_IS_DEFINED (fragP->fr_symbol)))
2280 		{
2281                   fragP->fr_subtype = DEFINED_RO_SEGMENT;
2282                   fragP->fr_var = INST_WORD_SIZE;
2283                 }
2284 	      else
2285 		{
2286                   /* Variable not in small data read only segment accessed
2287 		     using small data read only anchor.  */
2288                   const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2289 
2290                   as_bad_where (file, fragP->fr_line,
2291                                 _("Variable is accessed using small data read "
2292 				  "only anchor, but it is not in the small data "
2293 			          "read only section"));
2294                   fragP->fr_subtype = DEFINED_RO_SEGMENT;
2295                   fragP->fr_var = INST_WORD_SIZE;
2296                 }
2297             }
2298 	  else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor))
2299 	    {
2300               if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
2301 		  || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment)
2302 		  || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment)
2303 		  || (!S_IS_DEFINED (fragP->fr_symbol)))
2304 	        {
2305                   /* It is accessed using the small data read write anchor.  */
2306                   fragP->fr_subtype = DEFINED_RW_SEGMENT;
2307                   fragP->fr_var = INST_WORD_SIZE;
2308                 }
2309 	      else
2310 		{
2311                   const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2312 
2313                   as_bad_where (file, fragP->fr_line,
2314                                 _("Variable is accessed using small data read "
2315 				  "write anchor, but it is not in the small data "
2316 				  "read write section"));
2317                   fragP->fr_subtype = DEFINED_RW_SEGMENT;
2318                   fragP->fr_var = INST_WORD_SIZE;
2319                 }
2320             }
2321           else
2322 	    {
2323               as_bad (_("Incorrect fr_opcode value in frag.  Internal error....."));
2324               abort ();
2325             }
2326 	}
2327       else
2328 	{
2329 	  /* We know the abs value: Should never happen.  */
2330 	  as_bad (_("Absolute value in relaxation code.  Assembler error....."));
2331 	  abort ();
2332 	}
2333       break;
2334 
2335     case UNDEFINED_PC_OFFSET:
2336     case LARGE_DEFINED_PC_OFFSET:
2337     case DEFINED_ABS_SEGMENT:
2338     case GOT_OFFSET:
2339     case PLT_OFFSET:
2340     case GOTOFF_OFFSET:
2341     case TEXT_PC_OFFSET:
2342     case TLSGD_OFFSET:
2343     case TLSLD_OFFSET:
2344     case TLSTPREL_OFFSET:
2345     case TLSDTPREL_OFFSET:
2346       fragP->fr_var = INST_WORD_SIZE*2;
2347       break;
2348     case DEFINED_RO_SEGMENT:
2349     case DEFINED_RW_SEGMENT:
2350     case DEFINED_PC_OFFSET:
2351     case TLSDTPMOD_OFFSET:
2352       fragP->fr_var = INST_WORD_SIZE;
2353       break;
2354     default:
2355       abort ();
2356     }
2357 
2358   return fragP->fr_var;
2359 }
2360 
2361 /* Put number into target byte order.  */
2362 
2363 void
2364 md_number_to_chars (char * ptr, valueT use, int nbytes)
2365 {
2366   if (target_big_endian)
2367     number_to_chars_bigendian (ptr, use, nbytes);
2368   else
2369     number_to_chars_littleendian (ptr, use, nbytes);
2370 }
2371 
2372 /* Round up a section size to the appropriate boundary.  */
2373 
2374 valueT
2375 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
2376 {
2377   return size;			/* Byte alignment is fine.  */
2378 }
2379 
2380 
2381 /* The location from which a PC relative jump should be calculated,
2382    given a PC relative reloc.  */
2383 
2384 long
2385 md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
2386 {
2387 #ifdef OBJ_ELF
2388   /* If the symbol is undefined or defined in another section
2389      we leave the add number alone for the linker to fix it later.
2390      Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */
2391 
2392   if (fixp->fx_addsy != (symbolS *) NULL
2393       && (!S_IS_DEFINED (fixp->fx_addsy)
2394           || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
2395     return 0;
2396   else
2397     {
2398       /* The case where we are going to resolve things... */
2399       if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
2400         return  fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
2401       else
2402         return  fixp->fx_where + fixp->fx_frag->fr_address;
2403     }
2404 #endif
2405 }
2406 
2407 
2408 #define F(SZ,PCREL)		(((SZ) << 1) + (PCREL))
2409 #define MAP(SZ,PCREL,TYPE)	case F (SZ, PCREL): code = (TYPE); break
2410 
2411 arelent *
2412 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
2413 {
2414   arelent * rel;
2415   bfd_reloc_code_real_type code;
2416 
2417   switch (fixp->fx_r_type)
2418     {
2419     case BFD_RELOC_NONE:
2420     case BFD_RELOC_MICROBLAZE_64_NONE:
2421     case BFD_RELOC_32:
2422     case BFD_RELOC_MICROBLAZE_32_LO:
2423     case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2424     case BFD_RELOC_RVA:
2425     case BFD_RELOC_64:
2426     case BFD_RELOC_64_PCREL:
2427     case BFD_RELOC_MICROBLAZE_32_ROSDA:
2428     case BFD_RELOC_MICROBLAZE_32_RWSDA:
2429     case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2430     case BFD_RELOC_MICROBLAZE_64_GOTPC:
2431     case BFD_RELOC_MICROBLAZE_64_GOT:
2432     case BFD_RELOC_MICROBLAZE_64_PLT:
2433     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2434     case BFD_RELOC_MICROBLAZE_32_GOTOFF:
2435     case BFD_RELOC_MICROBLAZE_64_TLSGD:
2436     case BFD_RELOC_MICROBLAZE_64_TLSLD:
2437     case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
2438     case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
2439     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2440     case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
2441     case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
2442     case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2443     case BFD_RELOC_MICROBLAZE_64_TEXTREL:
2444       code = fixp->fx_r_type;
2445       break;
2446 
2447     default:
2448       switch (F (fixp->fx_size, fixp->fx_pcrel))
2449         {
2450           MAP (1, 0, BFD_RELOC_8);
2451           MAP (2, 0, BFD_RELOC_16);
2452           MAP (4, 0, BFD_RELOC_32);
2453           MAP (1, 1, BFD_RELOC_8_PCREL);
2454           MAP (2, 1, BFD_RELOC_16_PCREL);
2455           MAP (4, 1, BFD_RELOC_32_PCREL);
2456         default:
2457           code = fixp->fx_r_type;
2458           as_bad (_("Can not do %d byte %srelocation"),
2459                   fixp->fx_size,
2460                   fixp->fx_pcrel ? _("pc-relative ") : "");
2461         }
2462       break;
2463     }
2464 
2465   rel = XNEW (arelent);
2466   rel->sym_ptr_ptr = XNEW (asymbol *);
2467 
2468   if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM)
2469     *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
2470   else
2471     *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2472 
2473   rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
2474   /* Always pass the addend along!  */
2475   rel->addend = fixp->fx_offset;
2476   rel->howto = bfd_reloc_type_lookup (stdoutput, code);
2477 
2478   if (rel->howto == NULL)
2479     {
2480       as_bad_where (fixp->fx_file, fixp->fx_line,
2481                     _("Cannot represent relocation type %s"),
2482                     bfd_get_reloc_code_name (code));
2483 
2484       /* Set howto to a garbage value so that we can keep going.  */
2485       rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
2486       gas_assert (rel->howto != NULL);
2487     }
2488   return rel;
2489 }
2490 
2491 int
2492 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
2493 {
2494   switch (c)
2495     {
2496     case OPTION_EB:
2497       target_big_endian = 1;
2498       break;
2499     case OPTION_EL:
2500       target_big_endian = 0;
2501       break;
2502     default:
2503       return 0;
2504     }
2505   return 1;
2506 }
2507 
2508 void
2509 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
2510 {
2511   /*  fprintf(stream, _("\
2512       MicroBlaze options:\n\
2513       -noSmall         Data in the comm and data sections do not go into the small data section\n")); */
2514 }
2515 
2516 
2517 /* Create a fixup for a cons expression.  If parse_cons_expression_microblaze
2518    found a machine specific op in an expression,
2519    then we create relocs accordingly.  */
2520 
2521 void
2522 cons_fix_new_microblaze (fragS * frag,
2523 			 int where,
2524 			 int size,
2525 			 expressionS *exp,
2526 			 bfd_reloc_code_real_type r)
2527 {
2528   if ((exp->X_op == O_subtract) && (exp->X_add_symbol) &&
2529       (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4)
2530       && (!S_IS_LOCAL (exp->X_op_symbol)))
2531     r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM;
2532   else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva)
2533     {
2534       exp->X_op = O_symbol;
2535       r = BFD_RELOC_MICROBLAZE_32_GOTOFF;
2536     }
2537   else
2538     {
2539       switch (size)
2540         {
2541         case 1:
2542           r = BFD_RELOC_8;
2543           break;
2544         case 2:
2545           r = BFD_RELOC_16;
2546           break;
2547         case 4:
2548           r = BFD_RELOC_32;
2549           break;
2550         case 8:
2551           r = BFD_RELOC_64;
2552           break;
2553         default:
2554           as_bad (_("unsupported BFD relocation size %u"), size);
2555           r = BFD_RELOC_32;
2556           break;
2557         }
2558     }
2559   fix_new_exp (frag, where, size, exp, 0, r);
2560 }
2561