1/* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
2
3   Copyright (C) 2009-2020 Free Software Foundation, Inc.
4
5   This file is part of GAS, the GNU Assembler.
6
7   GAS is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3, or (at your option)
10   any later version.
11
12   GAS is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with GAS; see the file COPYING.  If not, write to the Free
19   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20   02110-1301, USA.  */
21
22#include "as.h"
23#include <stdio.h>
24#include "bfd.h"
25#include "subsegs.h"
26#define DEFINE_TABLE
27#include "../opcodes/microblaze-opc.h"
28#include "../opcodes/microblaze-opcm.h"
29#include "safe-ctype.h"
30#include <string.h>
31#include <dwarf2dbg.h>
32#include "aout/stab_gnu.h"
33
34#ifndef streq
35#define streq(a,b) (strcmp (a, b) == 0)
36#endif
37
38#define OPTION_EB (OPTION_MD_BASE + 0)
39#define OPTION_EL (OPTION_MD_BASE + 1)
40
41void microblaze_generate_symbol (char *sym);
42static bfd_boolean check_spl_reg (unsigned *);
43
44/* Several places in this file insert raw instructions into the
45   object. They should generate the instruction
46   and then use these four macros to crack the instruction value into
47   the appropriate byte values.  */
48#define	INST_BYTE0(x)  (target_big_endian ? (((x) >> 24) & 0xFF) : ((x) & 0xFF))
49#define	INST_BYTE1(x)  (target_big_endian ? (((x) >> 16) & 0xFF) : (((x) >> 8) & 0xFF))
50#define	INST_BYTE2(x)  (target_big_endian ? (((x) >> 8) & 0xFF) : (((x) >> 16) & 0xFF))
51#define	INST_BYTE3(x)  (target_big_endian ? ((x) & 0xFF) : (((x) >> 24) & 0xFF))
52
53/* This array holds the chars that always start a comment.  If the
54   pre-processor is disabled, these aren't very useful.  */
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  struct op_code_struct * opcode;
415
416  opcode_hash_control = str_htab_create ();
417
418  /* Insert unique names into hash table.  */
419  for (opcode = 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 && ! strncmp (s, GOT_SYMBOL_NAME, 20))
744    {
745      GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
746    }
747
748  if (e->X_op == O_absent)
749    ; /* An error message has already been emitted.  */
750  else if ((e->X_op != O_constant && e->X_op != O_symbol) )
751    as_fatal (_("operand must be a constant or a label"));
752  else if (e->X_op == O_constant)
753    {
754      /* Special case: sign extend negative 32-bit values to offsetT size.  */
755      if ((e->X_add_number >> 31) == 1)
756	e->X_add_number |= -((addressT) (1U << 31));
757
758      if (e->X_add_number < min || e->X_add_number > max)
759	{
760	  as_fatal (_("operand must be absolute in range %lx..%lx, not %lx"),
761		    (long) min, (long) max, (long) e->X_add_number);
762	}
763    }
764
765  if (atp)
766    {
767      *atp = '@'; /* restore back (needed?)  */
768      if (new_pointer >= atp)
769        new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */
770    }
771  return new_pointer;
772}
773
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 (strncmp (atp + 1, "GOTOFF", 5) == 0)
789    {
790      *got_len = 6;
791      *got_type = IMM_GOTOFF;
792    }
793  else if (strncmp (atp + 1, "GOT", 3) == 0)
794    {
795      *got_len = 3;
796      *got_type = IMM_GOT;
797    }
798  else if (strncmp (atp + 1, "PLT", 3) == 0)
799    {
800      *got_len = 3;
801      *got_type = IMM_PLT;
802    }
803  else
804    return NULL;
805
806  if (!GOT_symbol)
807    GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
808
809  first = atp - input_line_pointer;
810
811  past_got = atp + *got_len + 1;
812  for (new_pointer = past_got; !is_end_of_line[(unsigned char) *new_pointer++];)
813    ;
814  second = new_pointer - past_got;
815  /* One extra byte for ' ' and one for NUL.  */
816  tmpbuf = XNEWVEC (char, first + second + 2);
817  memcpy (tmpbuf, input_line_pointer, first);
818  tmpbuf[first] = ' '; /* @GOTOFF is replaced with a single space.  */
819  memcpy (tmpbuf + first + 1, past_got, second);
820  tmpbuf[first + second + 1] = '\0';
821
822  return tmpbuf;
823}
824
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 bfd_boolean
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, 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		  || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
2029			       ".gnu.linkonce",
2030			       sizeof (".gnu.linkonce") - 1))))
2031	{
2032	  val -= S_GET_VALUE (fixP->fx_addsy);
2033	  if (val != 0 && ! fixP->fx_pcrel)
2034            {
2035              /* In this case, the bfd_install_relocation routine will
2036                 incorrectly add the symbol value back in.  We just want
2037                 the addend to appear in the object file.
2038	         FIXME: If this makes VALUE zero, we're toast.  */
2039              val -= S_GET_VALUE (fixP->fx_addsy);
2040            }
2041	}
2042    }
2043
2044  /* If the fix is relative to a symbol which is not defined, or not
2045     in the same segment as the fix, we cannot resolve it here.  */
2046  /* fixP->fx_addsy is NULL if valp contains the entire relocation.  */
2047  if (fixP->fx_addsy != NULL
2048      && (!S_IS_DEFINED (fixP->fx_addsy)
2049          || (S_GET_SEGMENT (fixP->fx_addsy) != segment)))
2050    {
2051      fixP->fx_done = 0;
2052#ifdef OBJ_ELF
2053      /* For ELF we can just return and let the reloc that will be generated
2054         take care of everything.  For COFF we still have to insert 'val'
2055         into the insn since the addend field will be ignored.  */
2056      /* return; */
2057#endif
2058    }
2059  /* All fixups in the text section must be handled in the linker.  */
2060  else if (segment->flags & SEC_CODE)
2061    fixP->fx_done = 0;
2062  else if (!fixP->fx_pcrel && fixP->fx_addsy != NULL)
2063    fixP->fx_done = 0;
2064  else
2065    fixP->fx_done = 1;
2066
2067  switch (fixP->fx_r_type)
2068    {
2069    case BFD_RELOC_MICROBLAZE_32_LO:
2070    case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2071      if (target_big_endian)
2072	{
2073	  buf[2] |= ((val >> 8) & 0xff);
2074	  buf[3] |= (val & 0xff);
2075	}
2076      else
2077	{
2078	  buf[1] |= ((val >> 8) & 0xff);
2079	  buf[0] |= (val & 0xff);
2080	}
2081      break;
2082    case BFD_RELOC_MICROBLAZE_32_ROSDA:
2083    case BFD_RELOC_MICROBLAZE_32_RWSDA:
2084      /* Don't do anything if the symbol is not defined.  */
2085      if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2086	{
2087	  if (((val & 0xFFFF8000) != 0) && ((val & 0xFFFF8000) != 0xFFFF8000))
2088	    as_bad_where (file, fixP->fx_line,
2089			  _("pcrel for branch to %s too far (0x%x)"),
2090			  symname, (int) val);
2091	  if (target_big_endian)
2092	    {
2093	      buf[2] |= ((val >> 8) & 0xff);
2094	      buf[3] |= (val & 0xff);
2095	    }
2096	  else
2097	    {
2098	      buf[1] |= ((val >> 8) & 0xff);
2099	      buf[0] |= (val & 0xff);
2100	    }
2101	}
2102      break;
2103    case BFD_RELOC_32:
2104    case BFD_RELOC_RVA:
2105    case BFD_RELOC_32_PCREL:
2106    case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2107      /* Don't do anything if the symbol is not defined.  */
2108      if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2109	{
2110	  if (target_big_endian)
2111	    {
2112	      buf[0] |= ((val >> 24) & 0xff);
2113	      buf[1] |= ((val >> 16) & 0xff);
2114	      buf[2] |= ((val >> 8) & 0xff);
2115	      buf[3] |= (val & 0xff);
2116	    }
2117	  else
2118	    {
2119	      buf[3] |= ((val >> 24) & 0xff);
2120	      buf[2] |= ((val >> 16) & 0xff);
2121	      buf[1] |= ((val >> 8) & 0xff);
2122	      buf[0] |= (val & 0xff);
2123	    }
2124	}
2125      break;
2126    case BFD_RELOC_64_PCREL:
2127    case BFD_RELOC_64:
2128    case BFD_RELOC_MICROBLAZE_64_TEXTREL:
2129      /* Add an imm instruction.  First save the current instruction.  */
2130      for (i = 0; i < INST_WORD_SIZE; i++)
2131	buf[i + INST_WORD_SIZE] = buf[i];
2132
2133      /* Generate the imm instruction.  */
2134      opcode1
2135	= (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
2136      if (opcode1 == NULL)
2137	{
2138	  as_bad (_("unknown opcode \"%s\""), "imm");
2139	  return;
2140	}
2141
2142      inst1 = opcode1->bit_sequence;
2143      if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2144	inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
2145
2146      buf[0] = INST_BYTE0 (inst1);
2147      buf[1] = INST_BYTE1 (inst1);
2148      buf[2] = INST_BYTE2 (inst1);
2149      buf[3] = INST_BYTE3 (inst1);
2150
2151      /* Add the value only if the symbol is defined.  */
2152      if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2153	{
2154	  if (target_big_endian)
2155	    {
2156	      buf[6] |= ((val >> 8) & 0xff);
2157	      buf[7] |= (val & 0xff);
2158	    }
2159	  else
2160	    {
2161	      buf[5] |= ((val >> 8) & 0xff);
2162	      buf[4] |= (val & 0xff);
2163	    }
2164	}
2165      break;
2166
2167    case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2168    case BFD_RELOC_MICROBLAZE_64_TLSGD:
2169    case BFD_RELOC_MICROBLAZE_64_TLSLD:
2170      S_SET_THREAD_LOCAL (fixP->fx_addsy);
2171      /* Fall through.  */
2172
2173    case BFD_RELOC_MICROBLAZE_64_GOTPC:
2174    case BFD_RELOC_MICROBLAZE_64_GOT:
2175    case BFD_RELOC_MICROBLAZE_64_PLT:
2176    case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2177    case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2178      /* Add an imm instruction.  First save the current instruction.  */
2179      for (i = 0; i < INST_WORD_SIZE; i++)
2180	buf[i + INST_WORD_SIZE] = buf[i];
2181
2182      /* Generate the imm instruction.  */
2183      opcode1
2184	= (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
2185      if (opcode1 == NULL)
2186	{
2187	  as_bad (_("unknown opcode \"%s\""), "imm");
2188	  return;
2189	}
2190
2191      inst1 = opcode1->bit_sequence;
2192
2193      /* We can fixup call to a defined non-global address
2194	 within the same section only.  */
2195      buf[0] = INST_BYTE0 (inst1);
2196      buf[1] = INST_BYTE1 (inst1);
2197      buf[2] = INST_BYTE2 (inst1);
2198      buf[3] = INST_BYTE3 (inst1);
2199      return;
2200
2201    default:
2202      break;
2203    }
2204
2205  if (fixP->fx_addsy == NULL)
2206    {
2207      /* This fixup has been resolved.  Create a reloc in case the linker
2208	 moves code around due to relaxing.  */
2209      if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
2210	fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
2211      else
2212	fixP->fx_r_type = BFD_RELOC_NONE;
2213      fixP->fx_addsy = section_symbol (absolute_section);
2214    }
2215  return;
2216}
2217
2218void
2219md_operand (expressionS * expressionP)
2220{
2221  /* Ignore leading hash symbol, if present.  */
2222  if (*input_line_pointer == '#')
2223    {
2224      input_line_pointer ++;
2225      expression (expressionP);
2226    }
2227}
2228
2229/* Called just before address relaxation, return the length
2230   by which a fragment must grow to reach it's destination.  */
2231
2232int
2233md_estimate_size_before_relax (fragS * fragP,
2234			       segT segment_type)
2235{
2236  sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss");
2237  sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2");
2238  sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata");
2239  sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2");
2240
2241  switch (fragP->fr_subtype)
2242    {
2243    case INST_PC_OFFSET:
2244      /* Used to be a PC-relative branch.  */
2245      if (!fragP->fr_symbol)
2246        {
2247          /* We know the abs value: Should never happen.  */
2248          as_bad (_("Absolute PC-relative value in relaxation code.  Assembler error....."));
2249          abort ();
2250        }
2251      else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
2252               !S_IS_WEAK (fragP->fr_symbol))
2253        {
2254          fragP->fr_subtype = DEFINED_PC_OFFSET;
2255          /* Don't know now whether we need an imm instruction.  */
2256          fragP->fr_var = INST_WORD_SIZE;
2257        }
2258      else if (S_IS_DEFINED (fragP->fr_symbol)
2259	       && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
2260        {
2261          /* Cannot have a PC-relative branch to a diff segment.  */
2262          as_bad (_("PC relative branch to label %s which is not in the instruction space"),
2263		  S_GET_NAME (fragP->fr_symbol));
2264          fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2265          fragP->fr_var = INST_WORD_SIZE*2;
2266        }
2267      else
2268	{
2269	  fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2270	  fragP->fr_var = INST_WORD_SIZE*2;
2271	}
2272      break;
2273
2274    case INST_NO_OFFSET:
2275    case TEXT_OFFSET:
2276      /* Used to be a reference to somewhere which was unknown.  */
2277      if (fragP->fr_symbol)
2278        {
2279	  if (fragP->fr_opcode == NULL)
2280	    {
2281	      /* Used as an absolute value.  */
2282	      if (fragP->fr_subtype == INST_NO_OFFSET)
2283	        fragP->fr_subtype = DEFINED_ABS_SEGMENT;
2284	      /* Variable part does not change.  */
2285	      fragP->fr_var = INST_WORD_SIZE*2;
2286	    }
2287	  else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
2288	    {
2289              /* It is accessed using the small data read only anchor.  */
2290              if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
2291		  || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment)
2292		  || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment)
2293		  || (! S_IS_DEFINED (fragP->fr_symbol)))
2294		{
2295                  fragP->fr_subtype = DEFINED_RO_SEGMENT;
2296                  fragP->fr_var = INST_WORD_SIZE;
2297                }
2298	      else
2299		{
2300                  /* Variable not in small data read only segment accessed
2301		     using small data read only anchor.  */
2302                  const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2303
2304                  as_bad_where (file, fragP->fr_line,
2305                                _("Variable is accessed using small data read "
2306				  "only anchor, but it is not in the small data "
2307			          "read only section"));
2308                  fragP->fr_subtype = DEFINED_RO_SEGMENT;
2309                  fragP->fr_var = INST_WORD_SIZE;
2310                }
2311            }
2312	  else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor))
2313	    {
2314              if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
2315		  || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment)
2316		  || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment)
2317		  || (!S_IS_DEFINED (fragP->fr_symbol)))
2318	        {
2319                  /* It is accessed using the small data read write anchor.  */
2320                  fragP->fr_subtype = DEFINED_RW_SEGMENT;
2321                  fragP->fr_var = INST_WORD_SIZE;
2322                }
2323	      else
2324		{
2325                  const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2326
2327                  as_bad_where (file, fragP->fr_line,
2328                                _("Variable is accessed using small data read "
2329				  "write anchor, but it is not in the small data "
2330				  "read write section"));
2331                  fragP->fr_subtype = DEFINED_RW_SEGMENT;
2332                  fragP->fr_var = INST_WORD_SIZE;
2333                }
2334            }
2335          else
2336	    {
2337              as_bad (_("Incorrect fr_opcode value in frag.  Internal error....."));
2338              abort ();
2339            }
2340	}
2341      else
2342	{
2343	  /* We know the abs value: Should never happen.  */
2344	  as_bad (_("Absolute value in relaxation code.  Assembler error....."));
2345	  abort ();
2346	}
2347      break;
2348
2349    case UNDEFINED_PC_OFFSET:
2350    case LARGE_DEFINED_PC_OFFSET:
2351    case DEFINED_ABS_SEGMENT:
2352    case GOT_OFFSET:
2353    case PLT_OFFSET:
2354    case GOTOFF_OFFSET:
2355    case TEXT_PC_OFFSET:
2356    case TLSGD_OFFSET:
2357    case TLSLD_OFFSET:
2358    case TLSTPREL_OFFSET:
2359    case TLSDTPREL_OFFSET:
2360      fragP->fr_var = INST_WORD_SIZE*2;
2361      break;
2362    case DEFINED_RO_SEGMENT:
2363    case DEFINED_RW_SEGMENT:
2364    case DEFINED_PC_OFFSET:
2365    case TLSDTPMOD_OFFSET:
2366      fragP->fr_var = INST_WORD_SIZE;
2367      break;
2368    default:
2369      abort ();
2370    }
2371
2372  return fragP->fr_var;
2373}
2374
2375/* Put number into target byte order.  */
2376
2377void
2378md_number_to_chars (char * ptr, valueT use, int nbytes)
2379{
2380  if (target_big_endian)
2381    number_to_chars_bigendian (ptr, use, nbytes);
2382  else
2383    number_to_chars_littleendian (ptr, use, nbytes);
2384}
2385
2386/* Round up a section size to the appropriate boundary.  */
2387
2388valueT
2389md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
2390{
2391  return size;			/* Byte alignment is fine.  */
2392}
2393
2394
2395/* The location from which a PC relative jump should be calculated,
2396   given a PC relative reloc.  */
2397
2398long
2399md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
2400{
2401#ifdef OBJ_ELF
2402  /* If the symbol is undefined or defined in another section
2403     we leave the add number alone for the linker to fix it later.
2404     Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */
2405
2406  if (fixp->fx_addsy != (symbolS *) NULL
2407      && (!S_IS_DEFINED (fixp->fx_addsy)
2408          || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
2409    return 0;
2410  else
2411    {
2412      /* The case where we are going to resolve things... */
2413      if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
2414        return  fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
2415      else
2416        return  fixp->fx_where + fixp->fx_frag->fr_address;
2417    }
2418#endif
2419}
2420
2421
2422#define F(SZ,PCREL)		(((SZ) << 1) + (PCREL))
2423#define MAP(SZ,PCREL,TYPE)	case F (SZ, PCREL): code = (TYPE); break
2424
2425arelent *
2426tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
2427{
2428  arelent * rel;
2429  bfd_reloc_code_real_type code;
2430
2431  switch (fixp->fx_r_type)
2432    {
2433    case BFD_RELOC_NONE:
2434    case BFD_RELOC_MICROBLAZE_64_NONE:
2435    case BFD_RELOC_32:
2436    case BFD_RELOC_MICROBLAZE_32_LO:
2437    case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2438    case BFD_RELOC_RVA:
2439    case BFD_RELOC_64:
2440    case BFD_RELOC_64_PCREL:
2441    case BFD_RELOC_MICROBLAZE_32_ROSDA:
2442    case BFD_RELOC_MICROBLAZE_32_RWSDA:
2443    case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2444    case BFD_RELOC_MICROBLAZE_64_GOTPC:
2445    case BFD_RELOC_MICROBLAZE_64_GOT:
2446    case BFD_RELOC_MICROBLAZE_64_PLT:
2447    case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2448    case BFD_RELOC_MICROBLAZE_32_GOTOFF:
2449    case BFD_RELOC_MICROBLAZE_64_TLSGD:
2450    case BFD_RELOC_MICROBLAZE_64_TLSLD:
2451    case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
2452    case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
2453    case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2454    case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
2455    case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
2456    case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
2457    case BFD_RELOC_MICROBLAZE_64_TEXTREL:
2458      code = fixp->fx_r_type;
2459      break;
2460
2461    default:
2462      switch (F (fixp->fx_size, fixp->fx_pcrel))
2463        {
2464          MAP (1, 0, BFD_RELOC_8);
2465          MAP (2, 0, BFD_RELOC_16);
2466          MAP (4, 0, BFD_RELOC_32);
2467          MAP (1, 1, BFD_RELOC_8_PCREL);
2468          MAP (2, 1, BFD_RELOC_16_PCREL);
2469          MAP (4, 1, BFD_RELOC_32_PCREL);
2470        default:
2471          code = fixp->fx_r_type;
2472          as_bad (_("Can not do %d byte %srelocation"),
2473                  fixp->fx_size,
2474                  fixp->fx_pcrel ? _("pc-relative ") : "");
2475        }
2476      break;
2477    }
2478
2479  rel = XNEW (arelent);
2480  rel->sym_ptr_ptr = XNEW (asymbol *);
2481
2482  if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM)
2483    *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
2484  else
2485    *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2486
2487  rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
2488  /* Always pass the addend along!  */
2489  rel->addend = fixp->fx_offset;
2490  rel->howto = bfd_reloc_type_lookup (stdoutput, code);
2491
2492  if (rel->howto == NULL)
2493    {
2494      as_bad_where (fixp->fx_file, fixp->fx_line,
2495                    _("Cannot represent relocation type %s"),
2496                    bfd_get_reloc_code_name (code));
2497
2498      /* Set howto to a garbage value so that we can keep going.  */
2499      rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
2500      gas_assert (rel->howto != NULL);
2501    }
2502  return rel;
2503}
2504
2505int
2506md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
2507{
2508  switch (c)
2509    {
2510    case OPTION_EB:
2511      target_big_endian = 1;
2512      break;
2513    case OPTION_EL:
2514      target_big_endian = 0;
2515      break;
2516    default:
2517      return 0;
2518    }
2519  return 1;
2520}
2521
2522void
2523md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
2524{
2525  /*  fprintf(stream, _("\
2526      MicroBlaze options:\n\
2527      -noSmall         Data in the comm and data sections do not go into the small data section\n")); */
2528}
2529
2530
2531/* Create a fixup for a cons expression.  If parse_cons_expression_microblaze
2532   found a machine specific op in an expression,
2533   then we create relocs accordingly.  */
2534
2535void
2536cons_fix_new_microblaze (fragS * frag,
2537			 int where,
2538			 int size,
2539			 expressionS *exp,
2540			 bfd_reloc_code_real_type r)
2541{
2542  if ((exp->X_op == O_subtract) && (exp->X_add_symbol) &&
2543      (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4)
2544      && (!S_IS_LOCAL (exp->X_op_symbol)))
2545    r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM;
2546  else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva)
2547    {
2548      exp->X_op = O_symbol;
2549      r = BFD_RELOC_MICROBLAZE_32_GOTOFF;
2550    }
2551  else
2552    {
2553      switch (size)
2554        {
2555        case 1:
2556          r = BFD_RELOC_8;
2557          break;
2558        case 2:
2559          r = BFD_RELOC_16;
2560          break;
2561        case 4:
2562          r = BFD_RELOC_32;
2563          break;
2564        case 8:
2565          r = BFD_RELOC_64;
2566          break;
2567        default:
2568          as_bad (_("unsupported BFD relocation size %u"), size);
2569          r = BFD_RELOC_32;
2570          break;
2571        }
2572    }
2573  fix_new_exp (frag, where, size, exp, 0, r);
2574}
2575