1 /* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
2 
3    Copyright (C) 2009-2021 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 bool 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 htab_t  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
microblaze_generate_symbol(char * sym)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
microblaze_s_text(int ignore ATTRIBUTE_UNUSED)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
microblaze_s_data(int ignore ATTRIBUTE_UNUSED)149 microblaze_s_data (int ignore ATTRIBUTE_UNUSED)
150 {
151 #ifdef OBJ_ELF
152   obj_elf_change_section (".data", SHT_PROGBITS, 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
microblaze_s_sdata(int ignore ATTRIBUTE_UNUSED)162 microblaze_s_sdata (int ignore ATTRIBUTE_UNUSED)
163 {
164 #ifdef OBJ_ELF
165   obj_elf_change_section (".sdata", SHT_PROGBITS, 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
microblaze_s_lcomm(int xxx ATTRIBUTE_UNUSED)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
microblaze_s_rdata(int localvar)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, 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, SHF_ALLOC,
293 			      0, 0, 0, 0);
294     }
295 #else
296   s_data (ignore);
297 #endif
298 }
299 
300 static void
microblaze_s_bss(int localvar)301 microblaze_s_bss (int localvar)
302 {
303 #ifdef OBJ_ELF
304   if (localvar == 0) /* bss.  */
305     obj_elf_change_section (".bss", SHT_NOBITS, 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, 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
microblaze_s_func(int end_p ATTRIBUTE_UNUSED)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
microblaze_s_weakext(int ignore ATTRIBUTE_UNUSED)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
md_begin(void)412 md_begin (void)
413 {
414   const struct op_code_struct * opcode;
415 
416   opcode_hash_control = str_htab_create ();
417 
418   /* Insert unique names into hash table.  */
419   for (opcode = microblaze_opcodes; opcode->name; opcode ++)
420     str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
421 }
422 
423 /* Try to parse a reg name.  */
424 
425 static char *
parse_reg(char * s,unsigned * reg)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 *
parse_exp(char * s,expressionS * e)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
match_imm(const char * s,int * ilen)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
get_imm_otype(int itype)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 *
parse_imm(char * s,expressionS * e,offsetT min,offsetT max)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 && startswith (s, GOT_SYMBOL_NAME))
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 *
check_got(int * got_type,int * got_len)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 (startswith (atp + 1, "GOTOFF"))
789     {
790       *got_len = 6;
791       *got_type = IMM_GOTOFF;
792     }
793   else if (startswith (atp + 1, "GOT"))
794     {
795       *got_len = 3;
796       *got_type = IMM_GOT;
797     }
798   else if (startswith (atp + 1, "PLT"))
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
parse_cons_expression_microblaze(expressionS * exp,int size)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 bool
check_spl_reg(unsigned * reg)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
tc_microblaze_fix_adjustable(struct fix * fixP)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
md_assemble(char * str)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 *) str_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
1076 	      = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1077 							 "lwi");
1078           else
1079 	    opcode
1080 	      = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1081 							 "swi");
1082           if (opcode == NULL)
1083             {
1084               as_bad (_("unknown opcode \"%s\""), "lwi");
1085               return;
1086             }
1087           inst  = opcode->bit_sequence;
1088           inst |= (reg1 << RD_LOW) & RD_MASK;
1089           inst |= (reg2 << RA_LOW) & RA_MASK;
1090           inst |= (immed << IMM_LOW) & IMM_MASK;
1091 
1092           for (i = 0; i < count - 1; i++)
1093 	    {
1094               output[0] = INST_BYTE0 (inst);
1095               output[1] = INST_BYTE1 (inst);
1096               output[2] = INST_BYTE2 (inst);
1097               output[3] = INST_BYTE3 (inst);
1098               output = frag_more (isize);
1099               immed = immed + 4;
1100               reg1++;
1101               inst = opcode->bit_sequence;
1102               inst |= (reg1 << RD_LOW) & RD_MASK;
1103               inst |= (reg2 << RA_LOW) & RA_MASK;
1104               inst |= (immed << IMM_LOW) & IMM_MASK;
1105             }
1106 	}
1107       else
1108 	{
1109           temp = immed & 0xFFFF8000;
1110           if ((temp != 0) && (temp != 0xFFFF8000))
1111 	    {
1112               /* Needs an immediate inst.  */
1113 	      opcode1
1114 		= (struct op_code_struct *) str_hash_find (opcode_hash_control,
1115 							   "imm");
1116               if (opcode1 == NULL)
1117                 {
1118                   as_bad (_("unknown opcode \"%s\""), "imm");
1119                   return;
1120                 }
1121 
1122               inst1 = opcode1->bit_sequence;
1123               inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
1124               output[0] = INST_BYTE0 (inst1);
1125               output[1] = INST_BYTE1 (inst1);
1126               output[2] = INST_BYTE2 (inst1);
1127               output[3] = INST_BYTE3 (inst1);
1128               output = frag_more (isize);
1129 	    }
1130 	  inst |= (reg1 << RD_LOW) & RD_MASK;
1131 	  inst |= (reg2 << RA_LOW) & RA_MASK;
1132 	  inst |= (immed << IMM_LOW) & IMM_MASK;
1133 	}
1134       break;
1135 
1136     case INST_TYPE_RD_R1_IMM5:
1137       if (strcmp (op_end, ""))
1138         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1139       else
1140 	{
1141           as_fatal (_("Error in statement syntax"));
1142           reg1 = 0;
1143         }
1144       if (strcmp (op_end, ""))
1145         op_end = parse_reg (op_end + 1, &reg2);  /* Get r1.  */
1146       else
1147 	{
1148           as_fatal (_("Error in statement syntax"));
1149           reg2 = 0;
1150         }
1151       if (strcmp (op_end, ""))
1152         op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1153       else
1154         as_fatal (_("Error in statement syntax"));
1155 
1156       /* Check for spl registers.  */
1157       if (check_spl_reg (&reg1))
1158         as_fatal (_("Cannot use special register with this instruction"));
1159       if (check_spl_reg (&reg2))
1160         as_fatal (_("Cannot use special register with this instruction"));
1161 
1162       if (exp.X_op != O_constant)
1163         as_warn (_("Symbol used as immediate for shift instruction"));
1164       else
1165 	{
1166           output = frag_more (isize);
1167           immed = exp.X_add_number;
1168         }
1169 
1170       if (immed != (immed % 32))
1171 	{
1172           as_warn (_("Shift value > 32. using <value %% 32>"));
1173           immed = immed % 32;
1174         }
1175       inst |= (reg1 << RD_LOW) & RD_MASK;
1176       inst |= (reg2 << RA_LOW) & RA_MASK;
1177       inst |= (immed << IMM_LOW) & IMM5_MASK;
1178       break;
1179 
1180     case INST_TYPE_R1_R2:
1181       if (strcmp (op_end, ""))
1182         op_end = parse_reg (op_end + 1, &reg1);  /* Get r1.  */
1183       else
1184 	{
1185           as_fatal (_("Error in statement syntax"));
1186           reg1 = 0;
1187         }
1188       if (strcmp (op_end, ""))
1189         op_end = parse_reg (op_end + 1, &reg2);  /* Get r2.  */
1190       else
1191 	{
1192           as_fatal (_("Error in statement syntax"));
1193           reg2 = 0;
1194         }
1195 
1196       /* Check for spl registers.  */
1197       if (check_spl_reg (& reg1))
1198         as_fatal (_("Cannot use special register with this instruction"));
1199       if (check_spl_reg (& reg2))
1200         as_fatal (_("Cannot use special register with this instruction"));
1201 
1202       inst |= (reg1 << RA_LOW) & RA_MASK;
1203       inst |= (reg2 << RB_LOW) & RB_MASK;
1204       output = frag_more (isize);
1205       break;
1206 
1207     case INST_TYPE_RD_R1:
1208       if (strcmp (op_end, ""))
1209         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1210       else
1211 	{
1212           as_fatal (_("Error in statement syntax"));
1213           reg1 = 0;
1214         }
1215       if (strcmp (op_end, ""))
1216         op_end = parse_reg (op_end + 1, &reg2);  /* Get r1.  */
1217       else
1218 	{
1219           as_fatal (_("Error in statement syntax"));
1220           reg2 =0;
1221         }
1222 
1223       /* Check for spl registers.  */
1224       if (check_spl_reg (&reg1))
1225         as_fatal (_("Cannot use special register with this instruction"));
1226       if (check_spl_reg (&reg2))
1227         as_fatal (_("Cannot use special register with this instruction"));
1228 
1229       inst |= (reg1 << RD_LOW) & RD_MASK;
1230       inst |= (reg2 << RA_LOW) & RA_MASK;
1231       output = frag_more (isize);
1232       break;
1233 
1234     case INST_TYPE_RD_RFSL:
1235       if (strcmp (op_end, ""))
1236         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1237       else
1238 	{
1239           as_fatal (_("Error in statement syntax"));
1240           reg1 = 0;
1241         }
1242       if (strcmp (op_end, ""))
1243         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
1244       else
1245 	{
1246           as_fatal (_("Error in statement syntax"));
1247           immed = 0;
1248         }
1249 
1250       /* Check for spl registers.  */
1251       if (check_spl_reg (&reg1))
1252         as_fatal (_("Cannot use special register with this instruction"));
1253 
1254       inst |= (reg1 << RD_LOW) & RD_MASK;
1255       inst |= (immed << IMM_LOW) & RFSL_MASK;
1256       output = frag_more (isize);
1257       break;
1258 
1259     case INST_TYPE_RD_IMM15:
1260       if (strcmp (op_end, ""))
1261         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1262       else
1263 	{
1264           as_fatal (_("Error in statement syntax"));
1265           reg1 = 0;
1266         }
1267 
1268       if (strcmp (op_end, ""))
1269         op_end = parse_imm (op_end + 1, & exp, MIN_IMM15, MAX_IMM15);
1270       else
1271         as_fatal (_("Error in statement syntax"));
1272 
1273       /* Check for spl registers. */
1274       if (check_spl_reg (&reg1))
1275         as_fatal (_("Cannot use special register with this instruction"));
1276 
1277       if (exp.X_op != O_constant)
1278         as_fatal (_("Symbol used as immediate value for msrset/msrclr instructions"));
1279       else
1280 	{
1281           output = frag_more (isize);
1282           immed = exp.X_add_number;
1283         }
1284       inst |= (reg1 << RD_LOW) & RD_MASK;
1285       inst |= (immed << IMM_LOW) & IMM15_MASK;
1286       break;
1287 
1288     case INST_TYPE_R1_RFSL:
1289       if (strcmp (op_end, ""))
1290         op_end = parse_reg (op_end + 1, &reg1);  /* Get r1.  */
1291       else
1292 	{
1293           as_fatal (_("Error in statement syntax"));
1294           reg1 = 0;
1295         }
1296       if (strcmp (op_end, ""))
1297         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
1298       else
1299 	{
1300           as_fatal (_("Error in statement syntax"));
1301           immed = 0;
1302         }
1303 
1304       /* Check for spl registers.  */
1305       if (check_spl_reg (&reg1))
1306         as_fatal (_("Cannot use special register with this instruction"));
1307 
1308       inst |= (reg1 << RA_LOW) & RA_MASK;
1309       inst |= (immed << IMM_LOW) & RFSL_MASK;
1310       output = frag_more (isize);
1311       break;
1312 
1313     case INST_TYPE_RFSL:
1314       if (strcmp (op_end, ""))
1315         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
1316       else
1317 	{
1318           as_fatal (_("Error in statement syntax"));
1319           immed = 0;
1320         }
1321       inst |= (immed << IMM_LOW) & RFSL_MASK;
1322       output = frag_more (isize);
1323       break;
1324 
1325     case INST_TYPE_R1:
1326       if (strcmp (op_end, ""))
1327         op_end = parse_reg (op_end + 1, &reg1);  /* Get r1.  */
1328       else
1329 	{
1330           as_fatal (_("Error in statement syntax"));
1331           reg1 = 0;
1332         }
1333 
1334       /* Check for spl registers.  */
1335       if (check_spl_reg (&reg1))
1336         as_fatal (_("Cannot use special register with this instruction"));
1337 
1338       inst |= (reg1 << RA_LOW) & RA_MASK;
1339       output = frag_more (isize);
1340       break;
1341 
1342       /* For tuqula insn...:) */
1343     case INST_TYPE_RD:
1344       if (strcmp (op_end, ""))
1345         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1346       else
1347 	{
1348           as_fatal (_("Error in statement syntax"));
1349           reg1 = 0;
1350         }
1351 
1352       /* Check for spl registers.  */
1353       if (check_spl_reg (&reg1))
1354         as_fatal (_("Cannot use special register with this instruction"));
1355 
1356       inst |= (reg1 << RD_LOW) & RD_MASK;
1357       output = frag_more (isize);
1358       break;
1359 
1360     case INST_TYPE_RD_SPECIAL:
1361       if (strcmp (op_end, ""))
1362         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1363       else
1364 	{
1365           as_fatal (_("Error in statement syntax"));
1366           reg1 = 0;
1367         }
1368       if (strcmp (op_end, ""))
1369         op_end = parse_reg (op_end + 1, &reg2);  /* Get r1.  */
1370       else
1371 	{
1372           as_fatal (_("Error in statement syntax"));
1373           reg2 = 0;
1374         }
1375 
1376       if (reg2 == REG_MSR)
1377         immed = opcode->immval_mask | REG_MSR_MASK;
1378       else if (reg2 == REG_PC)
1379         immed = opcode->immval_mask | REG_PC_MASK;
1380       else if (reg2 == REG_EAR)
1381         immed = opcode->immval_mask | REG_EAR_MASK;
1382       else if (reg2 == REG_ESR)
1383         immed = opcode->immval_mask | REG_ESR_MASK;
1384       else if (reg2 == REG_FSR)
1385         immed = opcode->immval_mask | REG_FSR_MASK;
1386       else if (reg2 == REG_BTR)
1387         immed = opcode->immval_mask | REG_BTR_MASK;
1388       else if (reg2 == REG_EDR)
1389         immed = opcode->immval_mask | REG_EDR_MASK;
1390       else if (reg2 == REG_PID)
1391         immed = opcode->immval_mask | REG_PID_MASK;
1392       else if (reg2 == REG_ZPR)
1393         immed = opcode->immval_mask | REG_ZPR_MASK;
1394       else if (reg2 == REG_TLBX)
1395         immed = opcode->immval_mask | REG_TLBX_MASK;
1396       else if (reg2 == REG_TLBLO)
1397         immed = opcode->immval_mask | REG_TLBLO_MASK;
1398       else if (reg2 == REG_TLBHI)
1399         immed = opcode->immval_mask | REG_TLBHI_MASK;
1400       else if (reg2 == REG_SHR)
1401         immed = opcode->immval_mask | REG_SHR_MASK;
1402       else if (reg2 == REG_SLR)
1403         immed = opcode->immval_mask | REG_SLR_MASK;
1404       else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM))
1405 	immed = opcode->immval_mask | REG_PVR_MASK | reg2;
1406       else
1407         as_fatal (_("invalid value for special purpose register"));
1408       inst |= (reg1 << RD_LOW) & RD_MASK;
1409       inst |= (immed << IMM_LOW) & IMM_MASK;
1410       output = frag_more (isize);
1411       break;
1412 
1413     case INST_TYPE_SPECIAL_R1:
1414       if (strcmp (op_end, ""))
1415         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1416       else
1417 	{
1418           as_fatal (_("Error in statement syntax"));
1419           reg1 = 0;
1420         }
1421       if (strcmp (op_end, ""))
1422         op_end = parse_reg (op_end + 1, &reg2);  /* Get r1.  */
1423       else
1424 	{
1425           as_fatal (_("Error in statement syntax"));
1426           reg2 = 0;
1427         }
1428 
1429       if (reg1 == REG_MSR)
1430         immed = opcode->immval_mask | REG_MSR_MASK;
1431       else if (reg1 == REG_PC)
1432         immed = opcode->immval_mask | REG_PC_MASK;
1433       else if (reg1 == REG_EAR)
1434         immed = opcode->immval_mask | REG_EAR_MASK;
1435       else if (reg1 == REG_ESR)
1436         immed = opcode->immval_mask | REG_ESR_MASK;
1437       else if (reg1 == REG_FSR)
1438         immed = opcode->immval_mask | REG_FSR_MASK;
1439       else if (reg1 == REG_BTR)
1440         immed = opcode->immval_mask | REG_BTR_MASK;
1441       else if (reg1 == REG_EDR)
1442         immed = opcode->immval_mask | REG_EDR_MASK;
1443       else if (reg1 == REG_PID)
1444         immed = opcode->immval_mask | REG_PID_MASK;
1445       else if (reg1 == REG_ZPR)
1446         immed = opcode->immval_mask | REG_ZPR_MASK;
1447       else if (reg1 == REG_TLBX)
1448         immed = opcode->immval_mask | REG_TLBX_MASK;
1449       else if (reg1 == REG_TLBLO)
1450         immed = opcode->immval_mask | REG_TLBLO_MASK;
1451       else if (reg1 == REG_TLBHI)
1452         immed = opcode->immval_mask | REG_TLBHI_MASK;
1453       else if (reg1 == REG_TLBSX)
1454         immed = opcode->immval_mask | REG_TLBSX_MASK;
1455       else if (reg1 == REG_SHR)
1456         immed = opcode->immval_mask | REG_SHR_MASK;
1457       else if (reg1 == REG_SLR)
1458         immed = opcode->immval_mask | REG_SLR_MASK;
1459       else
1460         as_fatal (_("invalid value for special purpose register"));
1461       inst |= (reg2 << RA_LOW) & RA_MASK;
1462       inst |= (immed << IMM_LOW) & IMM_MASK;
1463       output = frag_more (isize);
1464       break;
1465 
1466     case INST_TYPE_R1_R2_SPECIAL:
1467       if (strcmp (op_end, ""))
1468         op_end = parse_reg (op_end + 1, &reg1);  /* Get r1.  */
1469       else
1470 	{
1471           as_fatal (_("Error in statement syntax"));
1472           reg1 = 0;
1473         }
1474       if (strcmp (op_end, ""))
1475         op_end = parse_reg (op_end + 1, &reg2);  /* Get r2.  */
1476       else
1477 	{
1478           as_fatal (_("Error in statement syntax"));
1479           reg2 =0;
1480         }
1481 
1482       /* Check for spl registers.  */
1483       if (check_spl_reg (&reg1))
1484         as_fatal (_("Cannot use special register with this instruction"));
1485       if (check_spl_reg (&reg2))
1486         as_fatal (_("Cannot use special register with this instruction"));
1487 
1488       /* insn wic ra, rb => wic ra, ra, rb.  */
1489       inst |= (reg1 << RA_LOW) & RA_MASK;
1490       inst |= (reg2 << RB_LOW) & RB_MASK;
1491 
1492       output = frag_more (isize);
1493       break;
1494 
1495     case INST_TYPE_RD_R2:
1496       if (strcmp (op_end, ""))
1497         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1498       else
1499 	{
1500           as_fatal (_("Error in statement syntax"));
1501           reg1 = 0;
1502         }
1503       if (strcmp (op_end, ""))
1504         op_end = parse_reg (op_end + 1, &reg2);  /* Get r2.  */
1505       else
1506 	{
1507           as_fatal (_("Error in statement syntax"));
1508           reg2 = 0;
1509         }
1510 
1511       /* Check for spl registers.  */
1512       if (check_spl_reg (&reg1))
1513         as_fatal (_("Cannot use special register with this instruction"));
1514       if (check_spl_reg (&reg2))
1515         as_fatal (_("Cannot use special register with this instruction"));
1516 
1517       inst |= (reg1 << RD_LOW) & RD_MASK;
1518       inst |= (reg2 << RB_LOW) & RB_MASK;
1519       output = frag_more (isize);
1520       break;
1521 
1522     case INST_TYPE_R1_IMM:
1523       if (strcmp (op_end, ""))
1524         op_end = parse_reg (op_end + 1, &reg1);  /* Get r1.  */
1525       else
1526 	{
1527           as_fatal (_("Error in statement syntax"));
1528           reg1 = 0;
1529         }
1530       if (strcmp (op_end, ""))
1531         op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1532       else
1533         as_fatal (_("Error in statement syntax"));
1534 
1535       /* Check for spl registers.  */
1536       if (check_spl_reg (&reg1))
1537         as_fatal (_("Cannot use special register with this instruction"));
1538 
1539       if (exp.X_op != O_constant)
1540 	{
1541           char *opc = NULL;
1542           relax_substateT subtype;
1543 
1544 	  if (exp.X_md != 0)
1545 	    subtype = get_imm_otype(exp.X_md);
1546 	  else
1547 	    subtype = opcode->inst_offset_type;
1548 
1549 	  output = frag_var (rs_machine_dependent,
1550 			     isize * 2, /* maxm of 2 words.  */
1551 			     isize,     /* minm of 1 word.  */
1552 			     subtype,   /* PC-relative or not.  */
1553 			     exp.X_add_symbol,
1554 			     exp.X_add_number,
1555 			     opc);
1556 	  immed = 0;
1557 	}
1558       else
1559 	{
1560           output = frag_more (isize);
1561           immed = exp.X_add_number;
1562         }
1563 
1564       temp = immed & 0xFFFF8000;
1565       if ((temp != 0) && (temp != 0xFFFF8000))
1566 	{
1567           /* Needs an immediate inst.  */
1568 	  opcode1
1569 	    = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1570 						       "imm");
1571           if (opcode1 == NULL)
1572             {
1573               as_bad (_("unknown opcode \"%s\""), "imm");
1574 	      return;
1575             }
1576 
1577           inst1 = opcode1->bit_sequence;
1578           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
1579           output[0] = INST_BYTE0 (inst1);
1580           output[1] = INST_BYTE1 (inst1);
1581           output[2] = INST_BYTE2 (inst1);
1582           output[3] = INST_BYTE3 (inst1);
1583           output = frag_more (isize);
1584         }
1585 
1586       inst |= (reg1 << RA_LOW) & RA_MASK;
1587       inst |= (immed << IMM_LOW) & IMM_MASK;
1588       break;
1589 
1590     case INST_TYPE_RD_IMM:
1591       if (strcmp (op_end, ""))
1592         op_end = parse_reg (op_end + 1, &reg1);  /* Get rd.  */
1593       else
1594 	{
1595           as_fatal (_("Error in statement syntax"));
1596           reg1 = 0;
1597         }
1598       if (strcmp (op_end, ""))
1599         op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1600       else
1601         as_fatal (_("Error in statement syntax"));
1602 
1603       /* Check for spl registers.  */
1604       if (check_spl_reg (&reg1))
1605         as_fatal (_("Cannot use special register with this instruction"));
1606 
1607       if (exp.X_op != O_constant)
1608 	{
1609           char *opc = NULL;
1610           relax_substateT subtype;
1611 
1612 	  if (exp.X_md != 0)
1613 	    subtype = get_imm_otype(exp.X_md);
1614 	  else
1615 	    subtype = opcode->inst_offset_type;
1616 
1617           output = frag_var (rs_machine_dependent,
1618 			     isize * 2, /* maxm of 2 words.  */
1619 			     isize,     /* minm of 1 word.  */
1620 			     subtype,   /* PC-relative or not.  */
1621 			     exp.X_add_symbol,
1622 			     exp.X_add_number,
1623 			     opc);
1624           immed = 0;
1625 	}
1626       else
1627 	{
1628           output = frag_more (isize);
1629           immed = exp.X_add_number;
1630         }
1631 
1632       temp = immed & 0xFFFF8000;
1633       if ((temp != 0) && (temp != 0xFFFF8000))
1634 	{
1635           /* Needs an immediate inst.  */
1636           opcode1
1637 	    = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1638 						       "imm");
1639           if (opcode1 == NULL)
1640             {
1641               as_bad (_("unknown opcode \"%s\""), "imm");
1642               return;
1643             }
1644 
1645           inst1 = opcode1->bit_sequence;
1646           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
1647           output[0] = INST_BYTE0 (inst1);
1648           output[1] = INST_BYTE1 (inst1);
1649           output[2] = INST_BYTE2 (inst1);
1650           output[3] = INST_BYTE3 (inst1);
1651           output = frag_more (isize);
1652         }
1653 
1654       inst |= (reg1 << RD_LOW) & RD_MASK;
1655       inst |= (immed << IMM_LOW) & IMM_MASK;
1656       break;
1657 
1658     case INST_TYPE_R2:
1659       if (strcmp (op_end, ""))
1660         op_end = parse_reg (op_end + 1, &reg2);  /* Get r2.  */
1661       else
1662 	{
1663           as_fatal (_("Error in statement syntax"));
1664           reg2 = 0;
1665         }
1666 
1667       /* Check for spl registers.  */
1668       if (check_spl_reg (&reg2))
1669         as_fatal (_("Cannot use special register with this instruction"));
1670 
1671       inst |= (reg2 << RB_LOW) & RB_MASK;
1672       output = frag_more (isize);
1673       break;
1674 
1675     case INST_TYPE_IMM:
1676       if (streq (name, "imm"))
1677         as_fatal (_("An IMM instruction should not be present in the .s file"));
1678 
1679       op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1680 
1681       if (exp.X_op != O_constant)
1682 	{
1683           char *opc = NULL;
1684           relax_substateT subtype;
1685 
1686 	  if (exp.X_md != 0)
1687 	    subtype = get_imm_otype(exp.X_md);
1688 	  else
1689 	    subtype = opcode->inst_offset_type;
1690 
1691           output = frag_var (rs_machine_dependent,
1692 			     isize * 2, /* maxm of 2 words.  */
1693 			     isize,     /* minm of 1 word.  */
1694 			     subtype,   /* PC-relative or not.  */
1695 			     exp.X_add_symbol,
1696 			     exp.X_add_number,
1697 			     opc);
1698           immed = 0;
1699         }
1700       else
1701 	{
1702           output = frag_more (isize);
1703           immed = exp.X_add_number;
1704         }
1705 
1706 
1707       temp = immed & 0xFFFF8000;
1708       if ((temp != 0) && (temp != 0xFFFF8000))
1709 	{
1710           /* Needs an immediate inst.  */
1711           opcode1
1712 	    = (struct op_code_struct *) str_hash_find (opcode_hash_control,
1713 						       "imm");
1714           if (opcode1 == NULL)
1715             {
1716               as_bad (_("unknown opcode \"%s\""), "imm");
1717               return;
1718             }
1719 
1720           inst1 = opcode1->bit_sequence;
1721           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
1722           output[0] = INST_BYTE0 (inst1);
1723           output[1] = INST_BYTE1 (inst1);
1724           output[2] = INST_BYTE2 (inst1);
1725           output[3] = INST_BYTE3 (inst1);
1726           output = frag_more (isize);
1727         }
1728       inst |= (immed << IMM_LOW) & IMM_MASK;
1729       break;
1730 
1731     case INST_TYPE_NONE:
1732       output = frag_more (isize);
1733       break;
1734 
1735     case INST_TYPE_IMM5:
1736       if (strcmp(op_end, ""))
1737         op_end = parse_imm (op_end + 1, & exp, MIN_IMM5, MAX_IMM5);
1738       else
1739         as_fatal(_("Error in statement syntax"));
1740       if (exp.X_op != O_constant) {
1741         as_warn(_("Symbol used as immediate for mbar instruction"));
1742       } else {
1743         output = frag_more (isize);
1744         immed = exp.X_add_number;
1745       }
1746       if (immed != (immed % 32)) {
1747         as_warn(_("Immediate value for mbar > 32. using <value %% 32>"));
1748         immed = immed % 32;
1749       }
1750       inst |= (immed << IMM_MBAR);
1751       break;
1752 
1753     default:
1754       as_fatal (_("unimplemented opcode \"%s\""), name);
1755     }
1756 
1757   /* Drop whitespace after all the operands have been parsed.  */
1758   while (ISSPACE (* op_end))
1759     op_end ++;
1760 
1761   /* Give warning message if the insn has more operands than required.  */
1762   if (strcmp (op_end, opcode->name) && strcmp (op_end, ""))
1763     as_warn (_("ignoring operands: %s "), op_end);
1764 
1765   output[0] = INST_BYTE0 (inst);
1766   output[1] = INST_BYTE1 (inst);
1767   output[2] = INST_BYTE2 (inst);
1768   output[3] = INST_BYTE3 (inst);
1769 
1770 #ifdef OBJ_ELF
1771   dwarf2_emit_insn (4);
1772 #endif
1773 }
1774 
1775 symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)1776 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
1777 {
1778   return NULL;
1779 }
1780 
1781 /* Turn a string in input_line_pointer into a floating point constant of type
1782    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
1783    emitted is stored in *sizeP.  An error message is returned, or NULL on OK.*/
1784 
1785 const char *
md_atof(int type,char * litP,int * sizeP)1786 md_atof (int type, char * litP, int * sizeP)
1787 {
1788   int prec;
1789   LITTLENUM_TYPE words[MAX_LITTLENUMS];
1790   int    i;
1791   char * t;
1792 
1793   switch (type)
1794     {
1795     case 'f':
1796     case 'F':
1797     case 's':
1798     case 'S':
1799       prec = 2;
1800       break;
1801 
1802     case 'd':
1803     case 'D':
1804     case 'r':
1805     case 'R':
1806       prec = 4;
1807       break;
1808 
1809     case 'x':
1810     case 'X':
1811       prec = 6;
1812       break;
1813 
1814     case 'p':
1815     case 'P':
1816       prec = 6;
1817       break;
1818 
1819     default:
1820       *sizeP = 0;
1821       return _("Bad call to MD_NTOF()");
1822     }
1823 
1824   t = atof_ieee (input_line_pointer, type, words);
1825 
1826   if (t)
1827     input_line_pointer = t;
1828 
1829   *sizeP = prec * sizeof (LITTLENUM_TYPE);
1830 
1831   if (! target_big_endian)
1832     {
1833       for (i = prec - 1; i >= 0; i--)
1834         {
1835           md_number_to_chars (litP, (valueT) words[i],
1836                               sizeof (LITTLENUM_TYPE));
1837           litP += sizeof (LITTLENUM_TYPE);
1838         }
1839     }
1840   else
1841     for (i = 0; i < prec; i++)
1842       {
1843         md_number_to_chars (litP, (valueT) words[i],
1844                             sizeof (LITTLENUM_TYPE));
1845         litP += sizeof (LITTLENUM_TYPE);
1846       }
1847 
1848   return NULL;
1849 }
1850 
1851 const char * md_shortopts = "";
1852 
1853 struct option md_longopts[] =
1854 {
1855   {"EB", no_argument, NULL, OPTION_EB},
1856   {"EL", no_argument, NULL, OPTION_EL},
1857   { NULL,          no_argument, NULL, 0}
1858 };
1859 
1860 size_t md_longopts_size = sizeof (md_longopts);
1861 
1862 int md_short_jump_size;
1863 
1864 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)1865 md_create_short_jump (char * ptr ATTRIBUTE_UNUSED,
1866 		      addressT from_Nddr ATTRIBUTE_UNUSED,
1867 		      addressT to_Nddr ATTRIBUTE_UNUSED,
1868 		      fragS * frag ATTRIBUTE_UNUSED,
1869 		      symbolS * to_symbol ATTRIBUTE_UNUSED)
1870 {
1871   as_fatal (_("failed sanity check: short_jump"));
1872 }
1873 
1874 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)1875 md_create_long_jump (char * ptr ATTRIBUTE_UNUSED,
1876 		     addressT from_Nddr ATTRIBUTE_UNUSED,
1877 		     addressT to_Nddr ATTRIBUTE_UNUSED,
1878 		     fragS * frag ATTRIBUTE_UNUSED,
1879 		     symbolS * to_symbol ATTRIBUTE_UNUSED)
1880 {
1881   as_fatal (_("failed sanity check: long_jump"));
1882 }
1883 
1884 /* Called after relaxing, change the frags so they know how big they are.  */
1885 
1886 void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT sec ATTRIBUTE_UNUSED,fragS * fragP)1887 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
1888 	         segT sec ATTRIBUTE_UNUSED,
1889 		 fragS * fragP)
1890 {
1891   fixS *fixP;
1892 
1893   switch (fragP->fr_subtype)
1894     {
1895     case UNDEFINED_PC_OFFSET:
1896       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1897 	       fragP->fr_offset, true, BFD_RELOC_64_PCREL);
1898       fragP->fr_fix += INST_WORD_SIZE * 2;
1899       fragP->fr_var = 0;
1900       break;
1901     case DEFINED_ABS_SEGMENT:
1902       if (fragP->fr_symbol == GOT_symbol)
1903         fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1904 	         fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_64_GOTPC);
1905       else
1906         fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1907 	         fragP->fr_offset, false, BFD_RELOC_64);
1908       fragP->fr_fix += INST_WORD_SIZE * 2;
1909       fragP->fr_var = 0;
1910       break;
1911     case DEFINED_RO_SEGMENT:
1912       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1913 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_32_ROSDA);
1914       fragP->fr_fix += INST_WORD_SIZE;
1915       fragP->fr_var = 0;
1916       break;
1917     case DEFINED_RW_SEGMENT:
1918       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1919 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_32_RWSDA);
1920       fragP->fr_fix += INST_WORD_SIZE;
1921       fragP->fr_var = 0;
1922       break;
1923     case DEFINED_PC_OFFSET:
1924       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1925 	       fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_32_LO_PCREL);
1926       fragP->fr_fix += INST_WORD_SIZE;
1927       fragP->fr_var = 0;
1928       break;
1929     case LARGE_DEFINED_PC_OFFSET:
1930       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1931 	       fragP->fr_offset, true, BFD_RELOC_64_PCREL);
1932       fragP->fr_fix += INST_WORD_SIZE * 2;
1933       fragP->fr_var = 0;
1934       break;
1935     case GOT_OFFSET:
1936       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1937 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_GOT);
1938       fragP->fr_fix += INST_WORD_SIZE * 2;
1939       fragP->fr_var = 0;
1940       break;
1941     case TEXT_OFFSET:
1942       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1943 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TEXTREL);
1944       fragP->fr_fix += INST_WORD_SIZE * 2;
1945       fragP->fr_var = 0;
1946       break;
1947     case TEXT_PC_OFFSET:
1948       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1949 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TEXTPCREL);
1950       fragP->fr_fix += INST_WORD_SIZE * 2;
1951       fragP->fr_var = 0;
1952       break;
1953     case PLT_OFFSET:
1954       fixP = fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1955 	              fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_64_PLT);
1956       /* fixP->fx_plt = 1; */
1957       (void) fixP;
1958       fragP->fr_fix += INST_WORD_SIZE * 2;
1959       fragP->fr_var = 0;
1960       break;
1961     case GOTOFF_OFFSET:
1962       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1963 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_GOTOFF);
1964       fragP->fr_fix += INST_WORD_SIZE * 2;
1965       fragP->fr_var = 0;
1966       break;
1967     case TLSGD_OFFSET:
1968       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1969 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TLSGD);
1970       fragP->fr_fix += INST_WORD_SIZE * 2;
1971       fragP->fr_var = 0;
1972       break;
1973     case TLSLD_OFFSET:
1974       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1975 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TLSLD);
1976       fragP->fr_fix += INST_WORD_SIZE * 2;
1977       fragP->fr_var = 0;
1978       break;
1979     case TLSDTPREL_OFFSET:
1980       fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1981 	       fragP->fr_offset, false, BFD_RELOC_MICROBLAZE_64_TLSDTPREL);
1982       fragP->fr_fix += INST_WORD_SIZE * 2;
1983       fragP->fr_var = 0;
1984       break;
1985 
1986     default:
1987       abort ();
1988     }
1989 }
1990 
1991 /* Applies the desired value to the specified location.
1992    Also sets up addends for 'rela' type relocations.  */
1993 void
md_apply_fix(fixS * fixP,valueT * valp,segT segment)1994 md_apply_fix (fixS *   fixP,
1995 	      valueT * valp,
1996 	      segT     segment)
1997 {
1998   char *       buf  = fixP->fx_where + &fixP->fx_frag->fr_literal[0];
1999   const char *       file = fixP->fx_file ? fixP->fx_file : _("unknown");
2000   const char * symname;
2001   /* Note: use offsetT because it is signed, valueT is unsigned.  */
2002   offsetT      val  = (offsetT) * valp;
2003   int          i;
2004   struct op_code_struct * opcode1;
2005   unsigned long inst1;
2006 
2007   symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
2008 
2009   /* fixP->fx_offset is supposed to be set up correctly for all
2010      symbol relocations.  */
2011   if (fixP->fx_addsy == NULL)
2012     {
2013       if (!fixP->fx_pcrel)
2014         fixP->fx_offset = val; /* Absolute relocation.  */
2015       else
2016         fprintf (stderr, "NULL symbol PC-relative relocation? offset = %08x, val = %08x\n",
2017                  (unsigned int) fixP->fx_offset, (unsigned int) val);
2018     }
2019 
2020   /* If we aren't adjusting this fixup to be against the section
2021      symbol, we need to adjust the value.  */
2022   if (fixP->fx_addsy != NULL)
2023     {
2024       if (S_IS_WEAK (fixP->fx_addsy)
2025 	  || (symbol_used_in_reloc_p (fixP->fx_addsy)
2026 	      && (((bfd_section_flags (S_GET_SEGMENT (fixP->fx_addsy))
2027 		    & SEC_LINK_ONCE) != 0)
2028 		  || startswith (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
2029 				 ".gnu.linkonce"))))
2030 	{
2031 	  val -= S_GET_VALUE (fixP->fx_addsy);
2032 	  if (val != 0 && ! fixP->fx_pcrel)
2033             {
2034               /* In this case, the bfd_install_relocation routine will
2035                  incorrectly add the symbol value back in.  We just want
2036                  the addend to appear in the object file.
2037 	         FIXME: If this makes VALUE zero, we're toast.  */
2038               val -= S_GET_VALUE (fixP->fx_addsy);
2039             }
2040 	}
2041     }
2042 
2043   /* If the fix is relative to a symbol which is not defined, or not
2044      in the same segment as the fix, we cannot resolve it here.  */
2045   /* fixP->fx_addsy is NULL if valp contains the entire relocation.  */
2046   if (fixP->fx_addsy != NULL
2047       && (!S_IS_DEFINED (fixP->fx_addsy)
2048           || (S_GET_SEGMENT (fixP->fx_addsy) != segment)))
2049     {
2050       fixP->fx_done = 0;
2051 #ifdef OBJ_ELF
2052       /* For ELF we can just return and let the reloc that will be generated
2053          take care of everything.  For COFF we still have to insert 'val'
2054          into the insn since the addend field will be ignored.  */
2055       /* return; */
2056 #endif
2057     }
2058   /* All fixups in the text section must be handled in the linker.  */
2059   else if (segment->flags & SEC_CODE)
2060     fixP->fx_done = 0;
2061   else if (!fixP->fx_pcrel && fixP->fx_addsy != NULL)
2062     fixP->fx_done = 0;
2063   else
2064     fixP->fx_done = 1;
2065 
2066   switch (fixP->fx_r_type)
2067     {
2068     case BFD_RELOC_MICROBLAZE_32_LO:
2069     case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2070       if (target_big_endian)
2071 	{
2072 	  buf[2] |= ((val >> 8) & 0xff);
2073 	  buf[3] |= (val & 0xff);
2074 	}
2075       else
2076 	{
2077 	  buf[1] |= ((val >> 8) & 0xff);
2078 	  buf[0] |= (val & 0xff);
2079 	}
2080       break;
2081     case BFD_RELOC_MICROBLAZE_32_ROSDA:
2082     case BFD_RELOC_MICROBLAZE_32_RWSDA:
2083       /* Don't do anything if the symbol is not defined.  */
2084       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2085 	{
2086 	  if (((val & 0xFFFF8000) != 0) && ((val & 0xFFFF8000) != 0xFFFF8000))
2087 	    as_bad_where (file, fixP->fx_line,
2088 			  _("pcrel for branch to %s too far (0x%x)"),
2089 			  symname, (int) val);
2090 	  if (target_big_endian)
2091 	    {
2092 	      buf[2] |= ((val >> 8) & 0xff);
2093 	      buf[3] |= (val & 0xff);
2094 	    }
2095 	  else
2096 	    {
2097 	      buf[1] |= ((val >> 8) & 0xff);
2098 	      buf[0] |= (val & 0xff);
2099 	    }
2100 	}
2101       break;
2102     case BFD_RELOC_32:
2103     case BFD_RELOC_RVA:
2104     case BFD_RELOC_32_PCREL:
2105     case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2106       /* Don't do anything if the symbol is not defined.  */
2107       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2108 	{
2109 	  if (target_big_endian)
2110 	    {
2111 	      buf[0] |= ((val >> 24) & 0xff);
2112 	      buf[1] |= ((val >> 16) & 0xff);
2113 	      buf[2] |= ((val >> 8) & 0xff);
2114 	      buf[3] |= (val & 0xff);
2115 	    }
2116 	  else
2117 	    {
2118 	      buf[3] |= ((val >> 24) & 0xff);
2119 	      buf[2] |= ((val >> 16) & 0xff);
2120 	      buf[1] |= ((val >> 8) & 0xff);
2121 	      buf[0] |= (val & 0xff);
2122 	    }
2123 	}
2124       break;
2125     case BFD_RELOC_64_PCREL:
2126     case BFD_RELOC_64:
2127     case BFD_RELOC_MICROBLAZE_64_TEXTREL:
2128       /* Add an imm instruction.  First save the current instruction.  */
2129       for (i = 0; i < INST_WORD_SIZE; i++)
2130 	buf[i + INST_WORD_SIZE] = buf[i];
2131 
2132       /* Generate the imm instruction.  */
2133       opcode1
2134 	= (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
2135       if (opcode1 == NULL)
2136 	{
2137 	  as_bad (_("unknown opcode \"%s\""), "imm");
2138 	  return;
2139 	}
2140 
2141       inst1 = opcode1->bit_sequence;
2142       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2143 	inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
2144 
2145       buf[0] = INST_BYTE0 (inst1);
2146       buf[1] = INST_BYTE1 (inst1);
2147       buf[2] = INST_BYTE2 (inst1);
2148       buf[3] = INST_BYTE3 (inst1);
2149 
2150       /* Add the value only if the symbol is defined.  */
2151       if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2152 	{
2153 	  if (target_big_endian)
2154 	    {
2155 	      buf[6] |= ((val >> 8) & 0xff);
2156 	      buf[7] |= (val & 0xff);
2157 	    }
2158 	  else
2159 	    {
2160 	      buf[5] |= ((val >> 8) & 0xff);
2161 	      buf[4] |= (val & 0xff);
2162 	    }
2163 	}
2164       break;
2165 
2166     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2167     case BFD_RELOC_MICROBLAZE_64_TLSGD:
2168     case BFD_RELOC_MICROBLAZE_64_TLSLD:
2169       S_SET_THREAD_LOCAL (fixP->fx_addsy);
2170       /* Fall through.  */
2171 
2172     case BFD_RELOC_MICROBLAZE_64_GOTPC:
2173     case BFD_RELOC_MICROBLAZE_64_GOT:
2174     case BFD_RELOC_MICROBLAZE_64_PLT:
2175     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2176     case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2177       /* Add an imm instruction.  First save the current instruction.  */
2178       for (i = 0; i < INST_WORD_SIZE; i++)
2179 	buf[i + INST_WORD_SIZE] = buf[i];
2180 
2181       /* Generate the imm instruction.  */
2182       opcode1
2183 	= (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
2184       if (opcode1 == NULL)
2185 	{
2186 	  as_bad (_("unknown opcode \"%s\""), "imm");
2187 	  return;
2188 	}
2189 
2190       inst1 = opcode1->bit_sequence;
2191 
2192       /* We can fixup call to a defined non-global address
2193 	 within the same section only.  */
2194       buf[0] = INST_BYTE0 (inst1);
2195       buf[1] = INST_BYTE1 (inst1);
2196       buf[2] = INST_BYTE2 (inst1);
2197       buf[3] = INST_BYTE3 (inst1);
2198       return;
2199 
2200     default:
2201       break;
2202     }
2203 
2204   if (fixP->fx_addsy == NULL)
2205     {
2206       /* This fixup has been resolved.  Create a reloc in case the linker
2207 	 moves code around due to relaxing.  */
2208       if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
2209 	fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
2210       else
2211 	fixP->fx_r_type = BFD_RELOC_NONE;
2212       fixP->fx_addsy = section_symbol (absolute_section);
2213     }
2214   return;
2215 }
2216 
2217 void
md_operand(expressionS * expressionP)2218 md_operand (expressionS * expressionP)
2219 {
2220   /* Ignore leading hash symbol, if present.  */
2221   if (*input_line_pointer == '#')
2222     {
2223       input_line_pointer ++;
2224       expression (expressionP);
2225     }
2226 }
2227 
2228 /* Called just before address relaxation, return the length
2229    by which a fragment must grow to reach it's destination.  */
2230 
2231 int
md_estimate_size_before_relax(fragS * fragP,segT segment_type)2232 md_estimate_size_before_relax (fragS * fragP,
2233 			       segT segment_type)
2234 {
2235   sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss");
2236   sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2");
2237   sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata");
2238   sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2");
2239 
2240   switch (fragP->fr_subtype)
2241     {
2242     case INST_PC_OFFSET:
2243       /* Used to be a PC-relative branch.  */
2244       if (!fragP->fr_symbol)
2245         {
2246           /* We know the abs value: Should never happen.  */
2247           as_bad (_("Absolute PC-relative value in relaxation code.  Assembler error....."));
2248           abort ();
2249         }
2250       else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
2251                !S_IS_WEAK (fragP->fr_symbol))
2252         {
2253           fragP->fr_subtype = DEFINED_PC_OFFSET;
2254           /* Don't know now whether we need an imm instruction.  */
2255           fragP->fr_var = INST_WORD_SIZE;
2256         }
2257       else if (S_IS_DEFINED (fragP->fr_symbol)
2258 	       && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
2259         {
2260           /* Cannot have a PC-relative branch to a diff segment.  */
2261           as_bad (_("PC relative branch to label %s which is not in the instruction space"),
2262 		  S_GET_NAME (fragP->fr_symbol));
2263           fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2264           fragP->fr_var = INST_WORD_SIZE*2;
2265         }
2266       else
2267 	{
2268 	  fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2269 	  fragP->fr_var = INST_WORD_SIZE*2;
2270 	}
2271       break;
2272 
2273     case INST_NO_OFFSET:
2274     case TEXT_OFFSET:
2275       /* Used to be a reference to somewhere which was unknown.  */
2276       if (fragP->fr_symbol)
2277         {
2278 	  if (fragP->fr_opcode == NULL)
2279 	    {
2280 	      /* Used as an absolute value.  */
2281 	      if (fragP->fr_subtype == INST_NO_OFFSET)
2282 	        fragP->fr_subtype = DEFINED_ABS_SEGMENT;
2283 	      /* Variable part does not change.  */
2284 	      fragP->fr_var = INST_WORD_SIZE*2;
2285 	    }
2286 	  else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
2287 	    {
2288               /* It is accessed using the small data read only anchor.  */
2289               if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
2290 		  || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment)
2291 		  || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment)
2292 		  || (! S_IS_DEFINED (fragP->fr_symbol)))
2293 		{
2294                   fragP->fr_subtype = DEFINED_RO_SEGMENT;
2295                   fragP->fr_var = INST_WORD_SIZE;
2296                 }
2297 	      else
2298 		{
2299                   /* Variable not in small data read only segment accessed
2300 		     using small data read only anchor.  */
2301                   const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2302 
2303                   as_bad_where (file, fragP->fr_line,
2304                                 _("Variable is accessed using small data read "
2305 				  "only anchor, but it is not in the small data "
2306 			          "read only section"));
2307                   fragP->fr_subtype = DEFINED_RO_SEGMENT;
2308                   fragP->fr_var = INST_WORD_SIZE;
2309                 }
2310             }
2311 	  else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor))
2312 	    {
2313               if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
2314 		  || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment)
2315 		  || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment)
2316 		  || (!S_IS_DEFINED (fragP->fr_symbol)))
2317 	        {
2318                   /* It is accessed using the small data read write anchor.  */
2319                   fragP->fr_subtype = DEFINED_RW_SEGMENT;
2320                   fragP->fr_var = INST_WORD_SIZE;
2321                 }
2322 	      else
2323 		{
2324                   const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2325 
2326                   as_bad_where (file, fragP->fr_line,
2327                                 _("Variable is accessed using small data read "
2328 				  "write anchor, but it is not in the small data "
2329 				  "read write section"));
2330                   fragP->fr_subtype = DEFINED_RW_SEGMENT;
2331                   fragP->fr_var = INST_WORD_SIZE;
2332                 }
2333             }
2334           else
2335 	    {
2336               as_bad (_("Incorrect fr_opcode value in frag.  Internal error....."));
2337               abort ();
2338             }
2339 	}
2340       else
2341 	{
2342 	  /* We know the abs value: Should never happen.  */
2343 	  as_bad (_("Absolute value in relaxation code.  Assembler error....."));
2344 	  abort ();
2345 	}
2346       break;
2347 
2348     case UNDEFINED_PC_OFFSET:
2349     case LARGE_DEFINED_PC_OFFSET:
2350     case DEFINED_ABS_SEGMENT:
2351     case GOT_OFFSET:
2352     case PLT_OFFSET:
2353     case GOTOFF_OFFSET:
2354     case TEXT_PC_OFFSET:
2355     case TLSGD_OFFSET:
2356     case TLSLD_OFFSET:
2357     case TLSTPREL_OFFSET:
2358     case TLSDTPREL_OFFSET:
2359       fragP->fr_var = INST_WORD_SIZE*2;
2360       break;
2361     case DEFINED_RO_SEGMENT:
2362     case DEFINED_RW_SEGMENT:
2363     case DEFINED_PC_OFFSET:
2364     case TLSDTPMOD_OFFSET:
2365       fragP->fr_var = INST_WORD_SIZE;
2366       break;
2367     default:
2368       abort ();
2369     }
2370 
2371   return fragP->fr_var;
2372 }
2373 
2374 /* Put number into target byte order.  */
2375 
2376 void
md_number_to_chars(char * ptr,valueT use,int nbytes)2377 md_number_to_chars (char * ptr, valueT use, int nbytes)
2378 {
2379   if (target_big_endian)
2380     number_to_chars_bigendian (ptr, use, nbytes);
2381   else
2382     number_to_chars_littleendian (ptr, use, nbytes);
2383 }
2384 
2385 /* Round up a section size to the appropriate boundary.  */
2386 
2387 valueT
md_section_align(segT segment ATTRIBUTE_UNUSED,valueT size)2388 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
2389 {
2390   return size;			/* Byte alignment is fine.  */
2391 }
2392 
2393 
2394 /* The location from which a PC relative jump should be calculated,
2395    given a PC relative reloc.  */
2396 
2397 long
md_pcrel_from_section(fixS * fixp,segT sec ATTRIBUTE_UNUSED)2398 md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
2399 {
2400 #ifdef OBJ_ELF
2401   /* If the symbol is undefined or defined in another section
2402      we leave the add number alone for the linker to fix it later.
2403      Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */
2404 
2405   if (fixp->fx_addsy != (symbolS *) NULL
2406       && (!S_IS_DEFINED (fixp->fx_addsy)
2407           || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
2408     return 0;
2409   else
2410     {
2411       /* The case where we are going to resolve things... */
2412       if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
2413         return  fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
2414       else
2415         return  fixp->fx_where + fixp->fx_frag->fr_address;
2416     }
2417 #endif
2418 }
2419 
2420 
2421 #define F(SZ,PCREL)		(((SZ) << 1) + (PCREL))
2422 #define MAP(SZ,PCREL,TYPE)	case F (SZ, PCREL): code = (TYPE); break
2423 
2424 arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixp)2425 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
2426 {
2427   arelent * rel;
2428   bfd_reloc_code_real_type code;
2429 
2430   switch (fixp->fx_r_type)
2431     {
2432     case BFD_RELOC_NONE:
2433     case BFD_RELOC_MICROBLAZE_64_NONE:
2434     case BFD_RELOC_32:
2435     case BFD_RELOC_MICROBLAZE_32_LO:
2436     case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2437     case BFD_RELOC_RVA:
2438     case BFD_RELOC_64:
2439     case BFD_RELOC_64_PCREL:
2440     case BFD_RELOC_MICROBLAZE_32_ROSDA:
2441     case BFD_RELOC_MICROBLAZE_32_RWSDA:
2442     case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2443     case BFD_RELOC_MICROBLAZE_64_GOTPC:
2444     case BFD_RELOC_MICROBLAZE_64_GOT:
2445     case BFD_RELOC_MICROBLAZE_64_PLT:
2446     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2447     case BFD_RELOC_MICROBLAZE_32_GOTOFF:
2448     case BFD_RELOC_MICROBLAZE_64_TLSGD:
2449     case BFD_RELOC_MICROBLAZE_64_TLSLD:
2450     case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
2451     case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
2452     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2453     case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
2454     case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
2455     case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2456     case BFD_RELOC_MICROBLAZE_64_TEXTREL:
2457       code = fixp->fx_r_type;
2458       break;
2459 
2460     default:
2461       switch (F (fixp->fx_size, fixp->fx_pcrel))
2462         {
2463           MAP (1, 0, BFD_RELOC_8);
2464           MAP (2, 0, BFD_RELOC_16);
2465           MAP (4, 0, BFD_RELOC_32);
2466           MAP (1, 1, BFD_RELOC_8_PCREL);
2467           MAP (2, 1, BFD_RELOC_16_PCREL);
2468           MAP (4, 1, BFD_RELOC_32_PCREL);
2469         default:
2470           code = fixp->fx_r_type;
2471           as_bad (_("Can not do %d byte %srelocation"),
2472                   fixp->fx_size,
2473                   fixp->fx_pcrel ? _("pc-relative ") : "");
2474         }
2475       break;
2476     }
2477 
2478   rel = XNEW (arelent);
2479   rel->sym_ptr_ptr = XNEW (asymbol *);
2480 
2481   if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM)
2482     *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
2483   else
2484     *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2485 
2486   rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
2487   /* Always pass the addend along!  */
2488   rel->addend = fixp->fx_offset;
2489   rel->howto = bfd_reloc_type_lookup (stdoutput, code);
2490 
2491   if (rel->howto == NULL)
2492     {
2493       as_bad_where (fixp->fx_file, fixp->fx_line,
2494                     _("Cannot represent relocation type %s"),
2495                     bfd_get_reloc_code_name (code));
2496 
2497       /* Set howto to a garbage value so that we can keep going.  */
2498       rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
2499       gas_assert (rel->howto != NULL);
2500     }
2501   return rel;
2502 }
2503 
2504 int
md_parse_option(int c,const char * arg ATTRIBUTE_UNUSED)2505 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
2506 {
2507   switch (c)
2508     {
2509     case OPTION_EB:
2510       target_big_endian = 1;
2511       break;
2512     case OPTION_EL:
2513       target_big_endian = 0;
2514       break;
2515     default:
2516       return 0;
2517     }
2518   return 1;
2519 }
2520 
2521 void
md_show_usage(FILE * stream ATTRIBUTE_UNUSED)2522 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
2523 {
2524   /*  fprintf(stream, _("\
2525       MicroBlaze options:\n\
2526       -noSmall         Data in the comm and data sections do not go into the small data section\n")); */
2527 }
2528 
2529 
2530 /* Create a fixup for a cons expression.  If parse_cons_expression_microblaze
2531    found a machine specific op in an expression,
2532    then we create relocs accordingly.  */
2533 
2534 void
cons_fix_new_microblaze(fragS * frag,int where,int size,expressionS * exp,bfd_reloc_code_real_type r)2535 cons_fix_new_microblaze (fragS * frag,
2536 			 int where,
2537 			 int size,
2538 			 expressionS *exp,
2539 			 bfd_reloc_code_real_type r)
2540 {
2541   if ((exp->X_op == O_subtract) && (exp->X_add_symbol) &&
2542       (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4)
2543       && (!S_IS_LOCAL (exp->X_op_symbol)))
2544     r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM;
2545   else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva)
2546     {
2547       exp->X_op = O_symbol;
2548       r = BFD_RELOC_MICROBLAZE_32_GOTOFF;
2549     }
2550   else
2551     {
2552       switch (size)
2553         {
2554         case 1:
2555           r = BFD_RELOC_8;
2556           break;
2557         case 2:
2558           r = BFD_RELOC_16;
2559           break;
2560         case 4:
2561           r = BFD_RELOC_32;
2562           break;
2563         case 8:
2564           r = BFD_RELOC_64;
2565           break;
2566         default:
2567           as_bad (_("unsupported BFD relocation size %u"), size);
2568           r = BFD_RELOC_32;
2569           break;
2570         }
2571     }
2572   fix_new_exp (frag, where, size, exp, 0, r);
2573 }
2574