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