1/* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
2
3   Copyright (C) 2009-2022 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
41void microblaze_generate_symbol (char *sym);
42static 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.  */
55const char comment_chars[] = "#";
56
57const char line_separator_chars[] = ";";
58
59/* This array holds the chars that only start a comment at the beginning of
60   a line.  */
61const char line_comment_chars[] = "#";
62
63const int md_reloc_size = 8; /* Size of relocation record.  */
64
65/* Chars that can be used to separate mant
66   from exp in floating point numbers.  */
67const char EXP_CHARS[] = "eE";
68
69/* Chars that mean this number is a floating point constant
70   As in 0f12.456
71   or    0d1.2345e12.  */
72const char FLT_CHARS[] = "rRsSfFdDxXpP";
73
74/* INST_PC_OFFSET and INST_NO_OFFSET are 0 and 1.  */
75#define UNDEFINED_PC_OFFSET  2
76#define DEFINED_ABS_SEGMENT  3
77#define DEFINED_PC_OFFSET    4
78#define DEFINED_RO_SEGMENT   5
79#define DEFINED_RW_SEGMENT   6
80#define LARGE_DEFINED_PC_OFFSET 7
81#define GOT_OFFSET           8
82#define PLT_OFFSET           9
83#define GOTOFF_OFFSET        10
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.  */
94const relax_typeS md_relax_table[] =
95{
96  {          1,          1,                0, 0 },  /*  0: Unused.  */
97  {          1,          1,                0, 0 },  /*  1: Unused.  */
98  {          1,          1,                0, 0 },  /*  2: Unused.  */
99  {          1,          1,                0, 0 },  /*  3: Unused.  */
100  {      32767,   -32768, INST_WORD_SIZE, LARGE_DEFINED_PC_OFFSET }, /* 4: DEFINED_PC_OFFSET.  */
101  {    1,     1,       0, 0 },                      /*  5: Unused.  */
102  {    1,     1,       0, 0 },                      /*  6: Unused.  */
103  { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 },  /*  7: LARGE_DEFINED_PC_OFFSET.  */
104  { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 },  /*  8: GOT_OFFSET.  */
105  { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 },  /*  9: PLT_OFFSET.  */
106  { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 },  /* 10: GOTOFF_OFFSET.  */
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
117static htab_t  opcode_hash_control;	/* Opcode mnemonics.  */
118
119static segT sbss_segment = 0; 	/* Small bss section.  */
120static segT sbss2_segment = 0; 	/* Section not used.  */
121static segT sdata_segment = 0; 	/* Small data section.  */
122static segT sdata2_segment = 0; /* Small read-only section.  */
123static segT rodata_segment = 0; /* read-only section.  */
124
125/* Generate a symbol for stabs information.  */
126
127void
128microblaze_generate_symbol (char *sym)
129{
130#define MICROBLAZE_FAKE_LABEL_NAME "XL0\001"
131  static int microblaze_label_count;
132  sprintf (sym, "%sL%d", MICROBLAZE_FAKE_LABEL_NAME, microblaze_label_count);
133  ++microblaze_label_count;
134}
135
136/* Handle the section changing pseudo-ops. */
137
138static void
139microblaze_s_text (int ignore ATTRIBUTE_UNUSED)
140{
141#ifdef OBJ_ELF
142  obj_elf_text (ignore);
143#else
144  s_text (ignore);
145#endif
146}
147
148static void
149microblaze_s_data (int ignore ATTRIBUTE_UNUSED)
150{
151#ifdef OBJ_ELF
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
161static void
162microblaze_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
174static void
175microblaze_s_lcomm (int xxx ATTRIBUTE_UNUSED)
176{
177  char *name;
178  char c;
179  char *p;
180  offsetT size;
181  symbolS *symbolP;
182  offsetT align;
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
277static void
278microblaze_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
300static void
301microblaze_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
324static void
325microblaze_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
334static void
335microblaze_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.  */
385const pseudo_typeS md_pseudo_table[] =
386{
387  {"lcomm", microblaze_s_lcomm, 1},
388  {"data", microblaze_s_data, 0},
389  {"data8", cons, 1},      /* Same as byte.  */
390  {"data16", cons, 2},     /* Same as hword.  */
391  {"data32", cons, 4},     /* Same as word.  */
392  {"ent", s_func, 0}, /* Treat ent as function entry point.  */
393  {"end", microblaze_s_func, 1}, /* Treat end as function end point.  */
394  {"gpword", s_rva, 4}, /* gpword label => store resolved label address in data section.  */
395  {"weakext", microblaze_s_weakext, 0},
396  {"rodata", microblaze_s_rdata, 0},
397  {"sdata2", microblaze_s_rdata, 1},
398  {"sdata", microblaze_s_sdata, 0},
399  {"bss", microblaze_s_bss, 0},
400  {"sbss", microblaze_s_bss, 1},
401  {"text", microblaze_s_text, 0},
402  {"word", cons, 4},
403  {"frame", s_ignore, 0},
404  {"mask", s_ignore, 0}, /* Emitted by gcc.  */
405  {NULL, NULL, 0}
406};
407
408/* This function is called once, at assembler startup time.  This should
409   set up all the tables, etc that the MD part of the assembler needs.  */
410
411void
412md_begin (void)
413{
414  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
425static char *
426parse_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
597static char *
598parse_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
635struct 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  */
643static struct imm_type imm_types[] = {
644	{ "NONE", IMM_NONE , 0 },
645	{ "GOTOFF", IMM_GOTOFF , GOTOFF_OFFSET },
646	{ "GOT", IMM_GOT , GOT_OFFSET },
647	{ "PLT", IMM_PLT , PLT_OFFSET },
648	{ "TLSGD", IMM_TLSGD , TLSGD_OFFSET },
649	{ "TLSLDM", IMM_TLSLD, TLSLD_OFFSET },
650	{ "TLSDTPMOD", IMM_TLSDTPMOD, TLSDTPMOD_OFFSET },
651	{ "TLSDTPREL", IMM_TLSDTPREL, TLSDTPREL_OFFSET },
652	{ "TLSTPREL", IMM_TLSTPREL, TLSTPREL_OFFSET },
653	{ "TXTREL", IMM_TXTREL, TEXT_OFFSET },
654	{ "TXTPCREL", IMM_TXTPCREL, TEXT_PC_OFFSET }
655};
656
657static int
658match_imm (const char *s, int *ilen)
659{
660  int i;
661  int slen;
662
663  /* Check for matching suffix */
664  for (i = 1; i < IMM_MAX; i++)
665    {
666      slen = strlen (imm_types[i].isuffix);
667
668      if (strncmp (imm_types[i].isuffix, s, slen) == 0)
669        {
670          *ilen = slen;
671          return imm_types[i].itype;
672        }
673    } /* for */
674  *ilen = 0;
675  return 0;
676}
677
678static int
679get_imm_otype (int itype)
680{
681  int i, otype;
682
683  otype = 0;
684  /* Check for matching itype */
685  for (i = 1; i < IMM_MAX; i++)
686    {
687      if (imm_types[i].itype == itype)
688        {
689          otype = imm_types[i].otype;
690          break;
691        }
692    }
693  return otype;
694}
695
696static symbolS * GOT_symbol;
697
698#define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_"
699
700static char *
701parse_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
774static char *
775check_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
825extern bfd_reloc_code_real_type
826parse_cons_expression_microblaze (expressionS *exp, int size)
827{
828  if (size == 4)
829    {
830      /* Handle @GOTOFF et.al.  */
831      char *save, *gotfree_copy;
832      int got_len, got_type;
833
834      save = input_line_pointer;
835      gotfree_copy = check_got (& got_type, & got_len);
836      if (gotfree_copy)
837        input_line_pointer = gotfree_copy;
838
839      expression (exp);
840
841      if (gotfree_copy)
842	{
843          exp->X_md = got_type;
844          input_line_pointer = save + (input_line_pointer - gotfree_copy)
845	    + got_len;
846          free (gotfree_copy);
847        }
848    }
849  else
850    expression (exp);
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
858static const char * str_microblaze_ro_anchor = "RO";
859static const char * str_microblaze_rw_anchor = "RW";
860
861static bool
862check_spl_reg (unsigned * reg)
863{
864  if ((*reg == REG_MSR)   || (*reg == REG_PC)
865      || (*reg == REG_EAR)   || (*reg == REG_ESR)
866      || (*reg == REG_FSR)   || (*reg == REG_BTR) || (*reg == REG_EDR)
867      || (*reg == REG_PID)   || (*reg == REG_ZPR)
868      || (*reg == REG_TLBX)  || (*reg == REG_TLBLO)
869      || (*reg == REG_TLBHI) || (*reg == REG_TLBSX)
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
882int
883tc_microblaze_fix_adjustable (struct fix *fixP)
884{
885  if (GOT_symbol && fixP->fx_subsy == GOT_symbol)
886    return 0;
887
888  if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF
889      || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF
890      || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT
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
904void
905md_assemble (char * str)
906{
907  char * op_start;
908  char * op_end;
909  struct op_code_struct * opcode, *opcode1;
910  char * output = NULL;
911  int nlen = 0;
912  int i;
913  unsigned long inst, inst1;
914  unsigned reg1;
915  unsigned reg2;
916  unsigned reg3;
917  unsigned isize;
918  unsigned int immed = 0, 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
1775symbolS *
1776md_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
1785const char *
1786md_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
1851const char * md_shortopts = "";
1852
1853struct 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
1860size_t md_longopts_size = sizeof (md_longopts);
1861
1862int md_short_jump_size;
1863
1864void
1865md_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
1874void
1875md_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
1886void
1887md_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.  */
1993void
1994md_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
2217void
2218md_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
2231int
2232md_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
2376void
2377md_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
2387valueT
2388md_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
2397long
2398md_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
2424arelent *
2425tc_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
2504int
2505md_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
2521void
2522md_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
2534void
2535cons_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