1 /* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY
2    Copyright (C) 2009-2016 Free Software Foundation, Inc.
3    Contributed by Embecosm on behalf of Adapteva, 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
19    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20    Boston, MA 02110-1301, USA.  */
21 
22 #include "as.h"
23 #include "subsegs.h"
24 #include "symcat.h"
25 #include "opcodes/epiphany-desc.h"
26 #include "opcodes/epiphany-opc.h"
27 #include "cgen.h"
28 #include "elf/common.h"
29 #include "elf/epiphany.h"
30 #include "dwarf2dbg.h"
31 #include "libbfd.h"
32 
33 /* Structure to hold all of the different components describing
34    an individual instruction.  */
35 typedef struct
36 {
37   const CGEN_INSN *	insn;
38   const CGEN_INSN *	orig_insn;
39   CGEN_FIELDS		fields;
40 #if CGEN_INT_INSN_P
41   CGEN_INSN_INT         buffer [1];
42 #define INSN_VALUE(buf) (*(buf))
43 #else
44   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
45 #define INSN_VALUE(buf) (buf)
46 #endif
47   char *		addr;
48   fragS *		frag;
49   int                   num_fixups;
50   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
51   int                   indices [MAX_OPERAND_INSTANCES];
52 }
53 epiphany_insn;
54 
55 const char comment_chars[]        = ";";
56 const char line_comment_chars[]   = "#";
57 const char line_separator_chars[] = "`";
58 const char EXP_CHARS[]            = "eE";
59 const char FLT_CHARS[]            = "fFdD";
60 
61 /* Flag to detect when switching to code section where insn alignment is
62    implied.  */
63 static bfd_boolean force_code_align = FALSE;
64 
65 static void
epiphany_elf_section_rtn(int i)66 epiphany_elf_section_rtn (int i)
67 {
68   obj_elf_section (i);
69 
70   if (force_code_align)
71     {
72       do_align (1, NULL, 0, 0);
73       force_code_align = FALSE;
74     }
75 }
76 
77 static void
epiphany_elf_section_text(int i)78 epiphany_elf_section_text (int i)
79 {
80   obj_elf_text (i);
81 
82   do_align (1, NULL, 0, 0);
83   force_code_align = FALSE;
84 }
85 
86 /* The target specific pseudo-ops which we support.  */
87 const pseudo_typeS md_pseudo_table[] =
88 {
89     { "text",   epiphany_elf_section_text,  0 },
90     { "sect",   epiphany_elf_section_rtn,   0 },
91     /* .word should be 32 bits.  */
92     { "word",       cons, 4 },
93     { "cpu",        s_ignore,         0 },
94     { "thumb_func", s_ignore,         0 },
95     { "code",       s_ignore,         0 },
96     { NULL,         NULL,             0 }
97 };
98 
99 
100 
101 enum options
102 {
103   OPTION_CPU_EPIPHANY = OPTION_MD_BASE,
104   OPTION_CPU_EPIPHANY16
105 };
106 
107 struct option md_longopts[] =
108 {
109   { "mepiphany ",  no_argument, NULL, OPTION_CPU_EPIPHANY },
110   { "mepiphany16", no_argument, NULL, OPTION_CPU_EPIPHANY16 },
111   { NULL,          no_argument, NULL, 0 },
112 };
113 
114 size_t md_longopts_size = sizeof (md_longopts);
115 
116 const char * md_shortopts = "";
117 
118 int
md_parse_option(int c ATTRIBUTE_UNUSED,const char * arg ATTRIBUTE_UNUSED)119 md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg ATTRIBUTE_UNUSED)
120 {
121   return 0;	/* No target-specific options.  */
122 }
123 
124 void
md_show_usage(FILE * stream)125 md_show_usage (FILE * stream)
126 {
127   fprintf (stream, _("EPIPHANY specific command line options:\n"));
128 }
129 
130 
131 void
md_begin(void)132 md_begin (void)
133 {
134   /* Initialize the `cgen' interface.  */
135 
136   /* Set the machine number and endian.  */
137   gas_cgen_cpu_desc = epiphany_cgen_cpu_open (CGEN_CPU_OPEN_MACHS,
138 					   bfd_mach_epiphany32,
139 					   CGEN_CPU_OPEN_ENDIAN,
140 					   CGEN_ENDIAN_LITTLE,
141 					   CGEN_CPU_OPEN_END);
142   epiphany_cgen_init_asm (gas_cgen_cpu_desc);
143 
144   /* This is a callback from cgen to gas to parse operands.  */
145   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
146 
147   /* Set the machine type.  */
148   bfd_default_set_arch_mach (stdoutput, bfd_arch_epiphany, bfd_mach_epiphany32);
149 }
150 
151 valueT
md_section_align(segT segment,valueT size)152 md_section_align (segT segment, valueT size)
153 {
154   int align = bfd_get_section_alignment (stdoutput, segment);
155 
156   return ((size + (1 << align) - 1) & -(1 << align));
157 }
158 
159 
160 /* Functions concerning relocs.  */
161 
162 long
md_pcrel_from(fixS * fixP ATTRIBUTE_UNUSED)163 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
164 {
165   abort ();
166 }
167 
168 /* Write a value out to the object file, using the appropriate endianness.  */
169 
170 void
md_number_to_chars(char * buf,valueT val,int n)171 md_number_to_chars (char * buf, valueT val, int n)
172 {
173   number_to_chars_littleendian (buf, val, n);
174 }
175 
176 int
epiphany_elf_section_flags(int flags,int attr ATTRIBUTE_UNUSED,int type ATTRIBUTE_UNUSED)177 epiphany_elf_section_flags (int flags,
178 			    int attr ATTRIBUTE_UNUSED,
179 			    int type ATTRIBUTE_UNUSED)
180 {
181   /* This is used to detect when the section changes to an executable section.
182      This function is called by the elf section processing.  When we note an
183      executable section specifier we set an internal flag to denote when
184      word alignment should be forced.  */
185   if (flags & SEC_CODE)
186     force_code_align = TRUE;
187 
188   return flags;
189 }
190 
191 /* Non-zero if we are generating PIC code.  */
192 int pic_code;
193 
194 /* Epiphany er_flags.  */
195 static int epiphany_flags = 0;
196 
197 /* Relocations against symbols are done in two
198    parts, with a HI relocation and a LO relocation.  Each relocation
199    has only 16 bits of space to store an addend.  This means that in
200    order for the linker to handle carries correctly, it must be able
201    to locate both the HI and the LO relocation.  This means that the
202    relocations must appear in order in the relocation table.
203 
204    In order to implement this, we keep track of each unmatched HI
205    relocation.  We then sort them so that they immediately precede the
206    corresponding LO relocation.  */
207 
208 struct epiphany_hi_fixup
209 {
210   /* Next HI fixup.  */
211   struct epiphany_hi_fixup *next;
212 
213   /* This fixup.  */
214   fixS *fixp;
215 
216   /* The section this fixup is in.  */
217   segT seg;
218 };
219 
220 
221 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
222 static symbolS * GOT_symbol;
223 
224 static inline bfd_boolean
epiphany_PIC_related_p(symbolS * sym)225 epiphany_PIC_related_p (symbolS *sym)
226 {
227   expressionS *exp;
228 
229   if (! sym)
230     return FALSE;
231 
232   if (sym == GOT_symbol)
233     return TRUE;
234 
235   exp = symbol_get_value_expression (sym);
236 
237   return (exp->X_op == O_PIC_reloc
238 	  || exp->X_md == BFD_RELOC_EPIPHANY_SIMM24
239 	  || exp->X_md == BFD_RELOC_EPIPHANY_SIMM8
240 	  || epiphany_PIC_related_p (exp->X_add_symbol)
241 	  || epiphany_PIC_related_p (exp->X_op_symbol));
242 }
243 
244 /* Perform target dependent relocations that are done at compile time.
245    There aren't very many of these.  */
246 
247 void
epiphany_apply_fix(fixS * fixP,valueT * valP,segT seg)248 epiphany_apply_fix (fixS *fixP, valueT *valP, segT seg)
249 {
250   if (fixP->fx_addsy == (symbolS *) NULL)
251     fixP->fx_done = 1;
252 
253   if (((int) fixP->fx_r_type < (int) BFD_RELOC_UNUSED)
254       && fixP->fx_done)
255     {
256       /* Install EPIPHANY-dependent relocations HERE because nobody else
257 	 will.  */
258       char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
259       unsigned char *insn = (unsigned char *)where;
260       valueT value = * valP;
261 
262       switch (fixP->fx_r_type)
263 	{
264 	default:
265 	  break;
266 
267 	case BFD_RELOC_NONE:
268 	  return;
269 
270 	case BFD_RELOC_EPIPHANY_SIMM11:
271 	  where[0] = where[0] | ((value & 1) << 7);
272 	  where[1] = where[1] | ((value & 6) >> 1);
273 	  where[2] = (value >> 3) & 0xff;
274 	  return;
275 
276 	case BFD_RELOC_EPIPHANY_IMM11:
277 	  where[0] = where[0] | ((value & 1) << 7);
278 	  where[1] = where[1] | ((value & 6) >> 1);
279 	  where[2] = (value >> 3) & 0xff;
280 	  return;
281 
282 	case BFD_RELOC_EPIPHANY_SIMM8:
283 	  md_number_to_chars (where+1, value>>1, 1);
284 	  return;
285 
286 	case BFD_RELOC_EPIPHANY_SIMM24:
287 	  md_number_to_chars (where+1, value>>1, 3);
288 	  return;
289 
290 	case BFD_RELOC_EPIPHANY_HIGH:
291 	  value >>= 16;
292 	  /* fall thru */
293 	case BFD_RELOC_EPIPHANY_LOW:
294 	  value = (((value & 0xff) << 5) | insn[0])
295 	    | (insn[1] << 8)
296 	    | ((value & 0xff00) << 12)
297 	    | (insn[2] << 16);
298 	  md_number_to_chars (where, value, 3);
299 	  return;
300 	}
301     }
302 
303   /* Just do the default if we can't special case.  */
304   return gas_cgen_md_apply_fix (fixP, valP, seg);
305 }
306 
307 
308 /* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
309    of an rs_align_code fragment.  0x01a2 is 16-bit pattern for a "nop".  */
310 
311 static const unsigned char nop_pattern[] = { 0xa2, 0x01 };
312 
313 void
epiphany_handle_align(fragS * fragp)314 epiphany_handle_align (fragS *fragp)
315 {
316   int bytes, fix;
317   char *p;
318 
319   if (fragp->fr_type != rs_align_code)
320     return;
321 
322   bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
323   p = fragp->fr_literal + fragp->fr_fix;
324   fix = 0;
325 
326   if (bytes & 1)
327     {
328       fix = 1;
329       *p++ = 0;
330       bytes--;
331     }
332 
333   if (bytes & 2)
334     {
335       memcpy (p, nop_pattern, 2);
336       p += 2;
337       bytes -= 2;
338       fix += 2;
339     }
340   fragp->fr_fix += fix;
341 }
342 
343 /* Read a comma separated incrementing list of register names
344    and form a bit mask of upto 15 registers 0..14.  */
345 
346 static const char *
parse_reglist(const char * s,int * mask)347 parse_reglist (const char * s, int * mask)
348 {
349   int regmask = 0;
350 
351   while (*s)
352     {
353       long value;
354 
355       while (*s == ' ')
356 	++s;
357 
358       /* Parse a list with "," or "}" as limiters.  */
359       const char *errmsg
360 	= cgen_parse_keyword (gas_cgen_cpu_desc, &s,
361 			      &epiphany_cgen_opval_gr_names, &value);
362       if (errmsg)
363 	return errmsg;
364 
365       if (value > 15)
366 	return _("register number too large for push/pop");
367 
368       regmask |= 1 << value;
369       if (regmask < *mask)
370 	return _("register is out of order");
371       *mask |= regmask;
372 
373       while (*s==' ')
374 	++s;
375 
376       if (*s == '}')
377 	return NULL;
378       else if (*s++ == ',')
379 	continue;
380       else
381 	return _("bad register list");
382     }
383 
384   return _("malformed reglist in push/pop");
385 }
386 
387 
388 /* Assemble an instruction,  push and pop pseudo instructions should have
389    already been expanded.  */
390 
391 static void
epiphany_assemble(const char * str)392 epiphany_assemble (const char *str)
393     {
394   epiphany_insn insn;
395   char *errmsg = 0;
396 
397   memset (&insn, 0, sizeof (insn));
398 
399   /* Initialize GAS's cgen interface for a new instruction.  */
400   gas_cgen_init_parse ();
401 
402   insn.insn = epiphany_cgen_assemble_insn
403     (gas_cgen_cpu_desc, str, &insn.fields, insn.buffer, & errmsg);
404 
405   if (!insn.insn)
406     {
407       as_bad ("%s", errmsg);
408       return;
409     }
410 
411   if (CGEN_INSN_BITSIZE (insn.insn) == 32)
412     {
413       /* Doesn't really matter what we pass for RELAX_P here.  */
414       gas_cgen_finish_insn (insn.insn, insn.buffer,
415 			    CGEN_FIELDS_BITSIZE (&insn.fields), 1, NULL);
416     }
417   else
418     {
419       if (CGEN_INSN_BITSIZE (insn.insn) != 16)
420 	abort ();
421 
422       insn.orig_insn = insn.insn;
423 
424       gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
425 			    CGEN_FIELDS_BITSIZE (&insn.fields),
426 			    1 /* relax_p  */, NULL);
427     }
428 
429   /* Checks for behavioral restrictions on LD/ST instructions.  */
430 #define DISPMOD _("destination register modified by displacement-post-modified address")
431 #define LDSTODD _("ldrd/strd requires even:odd register pair")
432 
433   /* Helper macros for spliting apart instruction fields.  */
434 #define ADDR_POST_MODIFIED(i) (((i) >> 25) & 0x1)
435 #define ADDR_SIZE(i)          (((i) >>  5) &   3)
436 #define ADDR_LOADSTORE(i)     (((i) >>  4) & 0x1)
437 
438   switch (insn.buffer[0] & 0xf)
439     {
440       /* Post-modify registers cannot be destinations.  */
441     case OP4_LDSTR16P:
442       {
443 	if (ADDR_LOADSTORE (insn.buffer[0]) ==  OP_LOAD)
444 	  if (insn.fields.f_rd == insn.fields.f_rn /* Postmodify dest.  */
445 	      || (insn.fields.f_rd+1 == insn.fields.f_rn
446 		  && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
447 	    {
448 	      as_bad ("%s", DISPMOD);
449 	      return;
450 	    }
451 	if ((insn.fields.f_rd & 1) /* Odd-numbered register...  */
452 	    && insn.fields.f_wordsize == OPW_DOUBLE) /* ...and 64 bit transfer.  */
453 	  {
454 	    as_bad ("%s", LDSTODD);
455 	    return;
456 	  }
457 	break;
458       }
459 
460     case OP4_LDSTRP:
461       {
462 	if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD) /* A load.  */
463 	  if (insn.fields.f_rd6 == insn.fields.f_rn6 /* Postmodify dest.  */
464 	      /* Check for regpair postindexed.  */
465 	      || (insn.fields.f_rd6 + 1 == insn.fields.f_rn6
466 		  && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
467 	    {
468 	      as_bad ("%s", DISPMOD);
469 	      return;
470 	    }
471 	if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
472 	  /* Lsb of RD odd and 64 bit transfer.  */
473 	  {
474 	    as_bad ("%s", LDSTODD);
475 	    return;
476 	  }
477 	break;
478       }
479 
480     case OP4_LDSTR16X:
481     case OP4_LDSTR16D:
482       {
483 	/* Check for unaligned load/store double.  */
484 	if ((insn.fields.f_rd & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
485 	  /* Lsb of RD odd and 64 bit transfer.  */
486 	  {
487 	    as_bad ("%s", LDSTODD);
488 	    return;
489 	  }
490 	break;
491       }
492 
493     case OP4_LDSTRD:
494       {
495 	/* Check for load to post-modified register.  */
496 	if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD /* A load.  */
497 	    && ADDR_POST_MODIFIED (insn.buffer[0]) == PMOD_POST /* Post-mod.  */
498 	    && (insn.fields.f_rd6 == insn.fields.f_rn6
499 		|| (insn.fields.f_rd6+1 == insn.fields.f_rn6
500 		    && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)))
501 	  {
502 	    as_bad ("%s", DISPMOD);
503 	    return;
504 	  }
505       }
506       /* fall-thru.  */
507 
508     case OP4_LDSTRX:
509       {
510 	/* Check for unaligned load/store double.  */
511 	if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
512 	  {
513 	    as_bad ("%s", LDSTODD);
514 	    return;
515 	  }
516 	break;
517       }
518 
519     default:
520       break;
521     }
522 }
523 
524 void
md_assemble(char * str)525 md_assemble (char *str)
526 {
527   const char * pperr = 0;
528   int regmask=0, push=0, pop=0;
529 
530   /* Special-case push/pop instruction macros.  */
531   if (0 == strncmp (str, "push {", 6))
532     {
533       char * s = str + 6;
534       push = 1;
535       pperr = parse_reglist (s, &regmask);
536     }
537   else if (0 == strncmp (str, "pop {", 5))
538     {
539       char * s = str + 5;
540       pop = 1;
541       pperr = parse_reglist (s, &regmask);
542     }
543 
544   if (pperr)
545     {
546       as_bad ("%s", pperr);
547       return;
548     }
549 
550   if (push && regmask)
551     {
552       char buff[20];
553       int i,p ATTRIBUTE_UNUSED;
554 
555       epiphany_assemble ("mov r15,4");
556       epiphany_assemble ("sub sp,sp,r15");
557 
558       for (i = 0, p = 1; i <= 15; ++i, regmask >>= 1)
559 	{
560 	  if (regmask == 1)
561 	    sprintf (buff, "str r%d,[sp]", i); /* Last one.  */
562 	  else if (regmask & 1)
563 	    sprintf (buff, "str r%d,[sp],-r15", i);
564 	  else
565 	    continue;
566 	  epiphany_assemble (buff);
567 	}
568       return;
569     }
570   else if (pop && regmask)
571     {
572       char buff[20];
573       int i,p;
574 
575       epiphany_assemble ("mov r15,4");
576 
577       for (i = 15, p = 1 << 15; i >= 0; --i, p >>= 1)
578 	if (regmask & p)
579 	  {
580 	    sprintf (buff, "ldr r%d,[sp],+r15", i);
581 	    epiphany_assemble (buff);
582 	  }
583       return;
584     }
585 
586   epiphany_assemble (str);
587 }
588 
589 /* The syntax in the manual says constants begin with '#'.
590    We just ignore it.  */
591 
592 void
md_operand(expressionS * expressionP)593 md_operand (expressionS *expressionP)
594 {
595   if (*input_line_pointer == '#')
596     {
597       input_line_pointer++;
598       expression (expressionP);
599     }
600 }
601 
602 symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)603 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
604 {
605   return NULL;
606 }
607 
608 /* Interface to relax_segment.  */
609 
610 /* FIXME: Build table by hand, get it working, then machine generate.  */
611 
612 const relax_typeS md_relax_table[] =
613 {
614   /* The fields are:
615      1) most positive reach of this state,
616      2) most negative reach of this state,
617      3) how many bytes this mode will add to the size of the current frag
618      4) which index into the table to try if we can't fit into this one.  */
619 
620   /* The first entry must be unused because an `rlx_more' value of zero ends
621      each list.  */
622   {1, 1, 0, EPIPHANY_RELAX_NONE},
623   {0, 0, 0, EPIPHANY_RELAX_NONE},    /* Also a dummy entry to indicate we need to expand codes.  */
624 
625   /* The displacement used by GAS is from the end of the 2 byte insn,
626      so we subtract 2 from the following.  */
627   /* 16 bit insn, 8 bit disp -> +127 words, -128 words.  */
628   {0x00000100 - 1 - 2, -0x00000100 - 2, 0, EPIPHANY_RELAX_BRANCH_LONG },
629   /* 32 bit insn, 24 bit disp -> 25 bit range.  */
630   {0x01000000 - 1 - 2, -0x01000000 - 2, 2, EPIPHANY_RELAX_NONE },
631 
632   /* addi/subi 3 bits -4..+3.  */
633   {    3,           -4,0, EPIPHANY_RELAX_ARITH_SIMM11 },
634   /* addi/subi 11 bits.  */
635   {  1023,       -1024,2, EPIPHANY_RELAX_NONE },
636 
637   /* mov r,imm8.  */
638   {   255,           0,0, EPIPHANY_RELAX_MOV_IMM16 },
639   /* mov r,imm16. */
640   { 65535,           0,2, EPIPHANY_RELAX_NONE },
641 
642   /* ld/st rd,[rn,imm3].  */
643   {     7,           0,0, EPIPHANY_RELAX_LDST_IMM11},
644   /* ld/st rd,[rn,imm11].  */
645   {  2047,           0,2, EPIPHANY_RELAX_NONE }
646 
647 };
648 
649 static const EPIPHANY_RELAX_TYPES relax_insn[] =
650 {
651   EPIPHANY_RELAX_BRANCH_SHORT,	/* OP4_BRANCH16 */
652   EPIPHANY_RELAX_NONE,		/* OP4_LDSTR16X */
653   EPIPHANY_RELAX_NONE,		/* OP4_FLOW16 */
654   EPIPHANY_RELAX_ARITH_SIMM3,	/* OP4_IMM16 - special */
655   EPIPHANY_RELAX_LDST_IMM3,	/* OP4_LDSTR16D */
656   EPIPHANY_RELAX_NONE,		/* OP4_LDSTR126P */
657   EPIPHANY_RELAX_NONE,		/* OP4_LSHIFT16 */
658   EPIPHANY_RELAX_NONE,		/* OP4_DSP16 */
659   EPIPHANY_RELAX_BRANCH_LONG,	/* OP4_BRANCH */
660   EPIPHANY_RELAX_NONE,		/* OP4_LDSTRX */
661   EPIPHANY_RELAX_NONE,		/* OP4_ALU16 */
662   EPIPHANY_RELAX_ARITH_SIMM11,	/* OP4_IMM32 - special */
663   EPIPHANY_RELAX_LDST_IMM11,	/* OP4_LDSTRD */
664   EPIPHANY_RELAX_NONE,		/* OP4_LDSTRP */
665   EPIPHANY_RELAX_NONE,		/* OP4_ASHIFT16 */
666   EPIPHANY_RELAX_NONE		/* OP4_MISC */
667 };
668 
669 long
epiphany_relax_frag(segT segment,fragS * fragP,long stretch)670 epiphany_relax_frag (segT segment, fragS *fragP, long stretch)
671 {
672   /* Address of branch insn.  */
673   long address ATTRIBUTE_UNUSED = fragP->fr_address + fragP->fr_fix - 2;
674   long growth = 0;
675 
676   if (fragP->fr_subtype == EPIPHANY_RELAX_NEED_RELAXING)
677     {
678       EPIPHANY_RELAX_TYPES subtype = relax_insn [*fragP->fr_opcode & 0xf];
679 
680       /* Special cases add/sub vs mov immediates.  */
681       if (subtype == EPIPHANY_RELAX_ARITH_SIMM3)
682 	{
683 	  if ((*fragP->fr_opcode & 0x10) == 0)
684 	    subtype = EPIPHANY_RELAX_MOV_IMM8;
685 	}
686       else if (subtype == EPIPHANY_RELAX_ARITH_SIMM11)
687 	{
688 	  if ((*fragP->fr_opcode & 0x10) == 0)
689 	    subtype = EPIPHANY_RELAX_MOV_IMM16;
690 	}
691 
692       /* Remember refinements for the future.  */
693       fragP->fr_subtype = subtype;
694     }
695 
696   growth = relax_frag (segment, fragP, stretch);
697 
698   return growth;
699 }
700 
701 /* Return an initial guess of the length by which a fragment must grow to
702    hold a branch to reach its destination.
703    Also updates fr_type/fr_subtype as necessary.
704 
705    Called just before doing relaxation.
706    Any symbol that is now undefined will not become defined.
707    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
708    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
709    Although it may not be explicit in the frag, pretend fr_var starts
710    with a 0 value.  */
711 
712 int
md_estimate_size_before_relax(fragS * fragP,segT segment)713 md_estimate_size_before_relax (fragS *fragP, segT segment)
714 {
715   /* The only thing we have to handle here are symbols outside of the
716      current segment.  They may be undefined or in a different segment in
717      which case linker scripts may place them anywhere.
718      However, we can't finish the fragment here and emit the reloc as insn
719      alignment requirements may move the insn about.  */
720   if (S_GET_SEGMENT (fragP->fr_symbol) != segment
721       || S_IS_EXTERNAL (fragP->fr_symbol)
722       || S_IS_WEAK (fragP->fr_symbol))
723     {
724       /* The symbol is undefined in this segment.  Change the
725 	 relaxation subtype to the max allowable and leave all further
726 	 handling to md_convert_frag.  */
727 
728       EPIPHANY_RELAX_TYPES subtype;
729       /* We haven't relaxed this at all, so the relaxation type may be
730 	 completely wrong.  Set the subtype correctly.  */
731       epiphany_relax_frag (segment, fragP, 0);
732       subtype = fragP->fr_subtype;
733 
734       switch (subtype)
735 	{
736 	case EPIPHANY_RELAX_LDST_IMM3:
737 	  subtype = EPIPHANY_RELAX_LDST_IMM11;
738 	  break;
739 	case EPIPHANY_RELAX_BRANCH_SHORT:
740 	  subtype = EPIPHANY_RELAX_BRANCH_LONG;
741 	  break;
742 	case EPIPHANY_RELAX_MOV_IMM8:
743 	  subtype = EPIPHANY_RELAX_MOV_IMM16;
744 	  break;
745 	case EPIPHANY_RELAX_ARITH_SIMM3:
746 	  subtype = EPIPHANY_RELAX_ARITH_SIMM11;
747 	  break;
748 
749 	default:
750 	  break;
751 	}
752 
753       fragP->fr_subtype = subtype;
754 
755       {
756 	const CGEN_INSN *insn;
757 	int i;
758 
759 	/* Update the recorded insn.  */
760 
761 	for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
762 	  {
763 	    if ((strcmp (CGEN_INSN_MNEMONIC (insn),
764 			 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
765 		 == 0)
766 		&& CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
767 	      break;
768 	  }
769 
770 	if (i == 4)
771 	  abort ();
772 
773 	fragP->fr_cgen.insn = insn;
774       }
775     }
776 
777   return md_relax_table[fragP->fr_subtype].rlx_length;
778 }
779 
780 /* *FRAGP has been relaxed to its final size, and now needs to have
781    the bytes inside it modified to conform to the new size.
782 
783    Called after relaxation is finished.
784    fragP->fr_type == rs_machine_dependent.
785    fragP->fr_subtype is the subtype of what the address relaxed to.  */
786 
787 void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT sec,fragS * fragP)788 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
789 		 segT sec,
790 		 fragS *fragP)
791 {
792   char *opcode;
793   char *displacement;
794   int target_address;
795   int opcode_address;
796   int extension;
797   int addend;
798   int opindx = -1;
799 
800   opcode = fragP->fr_opcode;
801 
802   /* Address opcode resides at in file space.  */
803   opcode_address = fragP->fr_address + fragP->fr_fix - 2;
804   extension = 0;
805   displacement = &opcode[1];
806 
807   /* Set up any addend necessary for branches.  */
808   if (S_GET_SEGMENT (fragP->fr_symbol) != sec
809       || S_IS_EXTERNAL (fragP->fr_symbol)
810       || S_IS_WEAK (fragP->fr_symbol))
811     {
812       /* Symbol must be resolved by linker.  */
813       if (fragP->fr_offset & 1)
814 	as_warn (_("Addend to unresolved symbol not on word boundary."));
815       addend = 0;
816     }
817   else
818     {
819       /* Address we want to reach in file space.  */
820       target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
821       addend = (target_address - (opcode_address & -2));
822     }
823 
824   /* Do all the housekeeping for frag conversions. */
825   switch (fragP->fr_subtype)
826     {
827     case EPIPHANY_RELAX_ARITH_SIMM11:
828       *opcode |= OP4_IMM32;
829       displacement = &opcode[0];
830       extension += 3;
831 
832       addend
833 	= (((addend & 0x7) << 7)
834 	   | opcode[0]
835 	   | ((addend & 0x7f8) << 13)
836 	   | (opcode[1] << 8)
837 	   | (opcode[2] << 16));
838 
839       opindx = EPIPHANY_OPERAND_SIMM11;
840       break;
841 
842     case EPIPHANY_RELAX_BRANCH_LONG:
843       /* Branches differ only in low nibble of instruction being 8 not 0.
844 	 24 bit displacement goes to bytes 1..3 .  */
845       *opcode |= OP4_BRANCH;
846       extension += 2;
847 
848       addend >>= 1;		/* Convert to word offset.  */
849       opindx = EPIPHANY_OPERAND_SIMM24;
850       break;
851 
852     case EPIPHANY_RELAX_MOV_IMM16:
853       *opcode |=  OP4_IMM32;
854       extension += 3;
855 
856       addend
857 	= (((addend & 0xff00) << 12)
858 	   | (opcode[2] << 16)
859 	   | ((addend & 0x00ff) << 5)
860 	   | (opcode[1] << 8)
861 	   | opcode[0]);
862       displacement = &opcode[0];
863       opindx = EPIPHANY_OPERAND_IMM16;
864       break;
865 
866     case EPIPHANY_RELAX_LDST_IMM11:
867       *opcode |= OP4_LDSTRD;
868       displacement = &opcode[0];
869       extension += 3;
870 
871       if (addend < 0)
872 	/* Convert twos-complement address value to sign-magnitude.  */
873 	addend = (-addend & 0x7ff) | 0x800;
874 
875       addend
876 	= (((addend & 0x7) << 5)
877 	   | opcode[0]
878 	   | ((addend & 0xff8) << 13)
879 	   | (opcode[1] << 8)
880 	   | (opcode[2] << 16));
881 
882       opindx = EPIPHANY_OPERAND_DISP11;
883       break;
884 
885     case EPIPHANY_RELAX_ARITH_SIMM3:
886       addend = ((addend & 7) << 5) | opcode[0];
887       opindx = EPIPHANY_OPERAND_SIMM3;
888       break;
889 
890     case EPIPHANY_RELAX_LDST_IMM3:
891       addend = ((addend & 7) << 5) | opcode[0];
892       opindx = EPIPHANY_OPERAND_DISP3;
893       break;
894 
895     case EPIPHANY_RELAX_BRANCH_SHORT:
896       addend >>= 1;		/* Convert to a word offset.  */
897       displacement = & opcode[1];
898       opindx = EPIPHANY_OPERAND_SIMM8;
899       break;
900 
901     case EPIPHANY_RELAX_MOV_IMM8:
902       addend
903 	= (((addend & 0xff) << 5)
904 	   | opcode[0]
905 	   | (opcode[1] << 8));
906       opindx = EPIPHANY_OPERAND_IMM8;
907       break;
908 
909     case EPIPHANY_RELAX_NONE:
910     case EPIPHANY_RELAX_NEED_RELAXING:
911     default:			/* Anything else?  */
912       as_bad ("unrecognized fragment subtype");
913       break;
914     }
915 
916   /* Create a relocation for symbols that must be resolved by the linker.
917      Otherwise output the completed insn.  */
918 
919   if (S_GET_SEGMENT (fragP->fr_symbol) != sec
920       || S_IS_EXTERNAL (fragP->fr_symbol)
921       || S_IS_WEAK (fragP->fr_symbol))
922     {
923       fixS *fixP;
924       const CGEN_OPERAND *operand
925 	= cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx);
926       bfd_reloc_code_real_type reloc_type;
927 
928       gas_assert (fragP->fr_cgen.insn != 0);
929 
930       reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL);
931 
932       fixP = gas_cgen_record_fixup (fragP,
933 				    /* Offset of insn in frag.  */
934 				    (opcode - fragP->fr_literal),
935 				    fragP->fr_cgen.insn,
936 				    CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8,
937 				    operand,
938 				    reloc_type,
939 				    fragP->fr_symbol, fragP->fr_offset);
940       fixP->fx_r_type = fixP->fx_cgen.opinfo;
941     }
942 
943   md_number_to_chars (displacement, (valueT) addend, extension + 1);
944 
945   fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added.  */
946 }
947 
948 
949 /* Functions concerning relocs.  */
950 
951 /* The location from which a PC relative jump should be calculated,
952    given a PC relative reloc.  */
953 
954 long
md_pcrel_from_section(fixS * fixP,segT sec)955 md_pcrel_from_section (fixS *fixP, segT sec)
956 {
957   if (fixP->fx_addsy != (symbolS *) NULL
958       && (!S_IS_DEFINED (fixP->fx_addsy)
959 	  || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
960 	  || S_IS_EXTERNAL (fixP->fx_addsy)
961 	  || S_IS_WEAK (fixP->fx_addsy)))
962     return 0;
963 
964   return fixP->fx_frag->fr_address + fixP->fx_where;
965 }
966 
967 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
968    Returns BFD_RELOC_NONE if no reloc type can be found.
969    *FIXP may be modified if desired.  */
970 
971 bfd_reloc_code_real_type
md_cgen_lookup_reloc(const CGEN_INSN * insn ATTRIBUTE_UNUSED,const CGEN_OPERAND * operand,fixS * fixP ATTRIBUTE_UNUSED)972 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
973 		      const CGEN_OPERAND *operand,
974 		      fixS *fixP ATTRIBUTE_UNUSED)
975 {
976   switch (operand->type)
977     {
978     case EPIPHANY_OPERAND_SIMM11:
979       return BFD_RELOC_EPIPHANY_SIMM11;
980     case EPIPHANY_OPERAND_DISP11:
981       return BFD_RELOC_EPIPHANY_IMM11;
982 
983     case EPIPHANY_OPERAND_SIMM8:
984       return BFD_RELOC_EPIPHANY_SIMM8;
985     case EPIPHANY_OPERAND_SIMM24:
986       return BFD_RELOC_EPIPHANY_SIMM24;
987 
988     case EPIPHANY_OPERAND_IMM8:
989       return BFD_RELOC_EPIPHANY_IMM8;
990 
991     case EPIPHANY_OPERAND_IMM16:
992       if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn)))
993 	return BFD_RELOC_EPIPHANY_HIGH;
994       else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn)))
995 	return BFD_RELOC_EPIPHANY_LOW;
996       else
997 	as_bad ("unknown imm16 operand");
998       /* fall-thru */
999 
1000     default:
1001       break;
1002     }
1003   return BFD_RELOC_NONE;
1004 }
1005 
1006 
1007 /* Turn a string in input_line_pointer into a floating point constant
1008    of type TYPE, and store the appropriate bytes in *LITP.  The number
1009    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
1010    returned, or NULL on OK.  */
1011 
1012 /* Equal to MAX_PRECISION in atof-ieee.c.  */
1013 #define MAX_LITTLENUMS 6
1014 
1015 const char *
md_atof(int type,char * litP,int * sizeP)1016 md_atof (int type, char *litP, int *sizeP)
1017 {
1018   return ieee_md_atof (type, litP, sizeP, FALSE);
1019 }
1020 
1021 /* Return true if can adjust the reloc to be relative to its section
1022    (such as .data) instead of relative to some symbol.  */
1023 
1024 bfd_boolean
epiphany_fix_adjustable(fixS * fixP)1025 epiphany_fix_adjustable (fixS *fixP)
1026 {
1027  bfd_reloc_code_real_type reloc_type;
1028 
1029   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1030     {
1031       const CGEN_INSN *insn = fixP->fx_cgen.insn;
1032       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1033       const CGEN_OPERAND *operand =
1034 	cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindex);
1035 
1036       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1037     }
1038   else
1039     reloc_type = fixP->fx_r_type;
1040 
1041   if (fixP->fx_addsy == NULL)
1042     return TRUE;
1043 
1044   /* Prevent all adjustments to global symbols.  */
1045   if (S_IS_EXTERNAL (fixP->fx_addsy))
1046     return FALSE;
1047 
1048   if (S_IS_WEAK (fixP->fx_addsy))
1049     return FALSE;
1050 
1051   if (pic_code
1052       && (reloc_type == BFD_RELOC_EPIPHANY_SIMM24
1053 	  || reloc_type == BFD_RELOC_EPIPHANY_SIMM8
1054 	  || reloc_type == BFD_RELOC_EPIPHANY_HIGH
1055 	  || reloc_type == BFD_RELOC_EPIPHANY_LOW))
1056     return FALSE;
1057 
1058   /* Since we don't use partial_inplace, we must not reduce symbols in
1059      mergable sections to their section symbol.  */
1060   if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
1061     return FALSE;
1062 
1063   return TRUE;
1064 }
1065 
1066 void
epiphany_elf_final_processing(void)1067 epiphany_elf_final_processing (void)
1068 {
1069   elf_elfheader (stdoutput)->e_flags |= epiphany_flags;
1070 }
1071 
1072 int
epiphany_cgen_parse_fix_exp(int opinfo,expressionS * exp ATTRIBUTE_UNUSED)1073 epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED)
1074 {
1075   LITTLENUM_TYPE words[2];
1076 
1077   switch (opinfo)
1078     {
1079     case BFD_RELOC_EPIPHANY_LOW:
1080     case BFD_RELOC_EPIPHANY_HIGH:
1081       break;
1082     default:
1083       return opinfo;
1084     }
1085 
1086   /* Doing a %LOW or %HIGH.  */
1087   switch (exp->X_op)
1088     {
1089     default:
1090       return opinfo;
1091     case O_big:				/* Bignum.  */
1092       if (exp->X_add_number > 0)	/* Integer value too large.  */
1093 	return opinfo;
1094     }
1095 
1096   /* Convert to SP number.  */
1097   gen_to_words (words, 2, 8L);
1098   exp->X_add_number = words[1] | (words[0] << 16);
1099   exp->X_op = O_constant;
1100   return opinfo;
1101 }
1102