[PATCH 5/57][Arm][GAS] Add support for MVE instructions: vmull{b,t}
[binutils-gdb.git] / gas / config / tc-epiphany.c
blobca24520ffefc76f6e425e25c9bd8e014ab2cb30f
1 /* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY
2 Copyright (C) 2009-2019 Free Software Foundation, Inc.
3 Contributed by Embecosm on behalf of Adapteva, Inc.
5 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
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"
32 /* Structure to hold all of the different components describing
33 an individual instruction. */
34 typedef struct
36 const CGEN_INSN * insn;
37 const CGEN_INSN * orig_insn;
38 CGEN_FIELDS fields;
39 #if CGEN_INT_INSN_P
40 CGEN_INSN_INT buffer [1];
41 #define INSN_VALUE(buf) (*(buf))
42 #else
43 unsigned char buffer [CGEN_MAX_INSN_SIZE];
44 #define INSN_VALUE(buf) (buf)
45 #endif
46 char * addr;
47 fragS * frag;
48 int num_fixups;
49 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
50 int indices [MAX_OPERAND_INSTANCES];
52 epiphany_insn;
54 const char comment_chars[] = ";";
55 const char line_comment_chars[] = "#";
56 const char line_separator_chars[] = "`";
57 const char EXP_CHARS[] = "eE";
58 const char FLT_CHARS[] = "fFdD";
60 /* Flag to detect when switching to code section where insn alignment is
61 implied. */
62 static bfd_boolean force_code_align = FALSE;
64 static void
65 epiphany_elf_section_rtn (int i)
67 obj_elf_section (i);
69 if (force_code_align)
71 do_align (1, NULL, 0, 0);
72 force_code_align = FALSE;
76 static void
77 epiphany_elf_section_text (int i)
79 obj_elf_text (i);
81 do_align (1, NULL, 0, 0);
82 force_code_align = FALSE;
85 /* The target specific pseudo-ops which we support. */
86 const pseudo_typeS md_pseudo_table[] =
88 { "text", epiphany_elf_section_text, 0 },
89 { "sect", epiphany_elf_section_rtn, 0 },
90 /* .word should be 32 bits. */
91 { "word", cons, 4 },
92 { "cpu", s_ignore, 0 },
93 { "thumb_func", s_ignore, 0 },
94 { "code", s_ignore, 0 },
95 { NULL, NULL, 0 }
100 enum options
102 OPTION_CPU_EPIPHANY = OPTION_MD_BASE,
103 OPTION_CPU_EPIPHANY16
106 struct option md_longopts[] =
108 { "mepiphany ", no_argument, NULL, OPTION_CPU_EPIPHANY },
109 { "mepiphany16", no_argument, NULL, OPTION_CPU_EPIPHANY16 },
110 { NULL, no_argument, NULL, 0 },
113 size_t md_longopts_size = sizeof (md_longopts);
115 const char * md_shortopts = "";
118 md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg ATTRIBUTE_UNUSED)
120 return 0; /* No target-specific options. */
123 void
124 md_show_usage (FILE * stream)
126 fprintf (stream, _("EPIPHANY specific command line options:\n"));
130 void
131 md_begin (void)
133 /* Initialize the `cgen' interface. */
135 /* Set the machine number and endian. */
136 gas_cgen_cpu_desc = epiphany_cgen_cpu_open (CGEN_CPU_OPEN_MACHS,
137 bfd_mach_epiphany32,
138 CGEN_CPU_OPEN_ENDIAN,
139 CGEN_ENDIAN_LITTLE,
140 CGEN_CPU_OPEN_END);
141 epiphany_cgen_init_asm (gas_cgen_cpu_desc);
143 /* This is a callback from cgen to gas to parse operands. */
144 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
146 /* Set the machine type. */
147 bfd_default_set_arch_mach (stdoutput, bfd_arch_epiphany, bfd_mach_epiphany32);
150 valueT
151 md_section_align (segT segment, valueT size)
153 int align = bfd_get_section_alignment (stdoutput, segment);
155 return ((size + (1 << align) - 1) & -(1 << align));
159 /* Functions concerning relocs. */
161 long
162 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
164 abort ();
167 /* Write a value out to the object file, using the appropriate endianness. */
169 void
170 md_number_to_chars (char * buf, valueT val, int n)
172 number_to_chars_littleendian (buf, val, n);
176 epiphany_elf_section_flags (int flags,
177 int attr ATTRIBUTE_UNUSED,
178 int type ATTRIBUTE_UNUSED)
180 /* This is used to detect when the section changes to an executable section.
181 This function is called by the elf section processing. When we note an
182 executable section specifier we set an internal flag to denote when
183 word alignment should be forced. */
184 if (flags & SEC_CODE)
185 force_code_align = TRUE;
187 return flags;
190 /* Non-zero if we are generating PIC code. */
191 int pic_code;
193 /* Epiphany er_flags. */
194 static int epiphany_flags = 0;
196 /* Relocations against symbols are done in two
197 parts, with a HI relocation and a LO relocation. Each relocation
198 has only 16 bits of space to store an addend. This means that in
199 order for the linker to handle carries correctly, it must be able
200 to locate both the HI and the LO relocation. This means that the
201 relocations must appear in order in the relocation table.
203 In order to implement this, we keep track of each unmatched HI
204 relocation. We then sort them so that they immediately precede the
205 corresponding LO relocation. */
207 struct epiphany_hi_fixup
209 /* Next HI fixup. */
210 struct epiphany_hi_fixup *next;
212 /* This fixup. */
213 fixS *fixp;
215 /* The section this fixup is in. */
216 segT seg;
220 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
221 static symbolS * GOT_symbol;
223 static inline bfd_boolean
224 epiphany_PIC_related_p (symbolS *sym)
226 expressionS *exp;
228 if (! sym)
229 return FALSE;
231 if (sym == GOT_symbol)
232 return TRUE;
234 exp = symbol_get_value_expression (sym);
236 return (exp->X_op == O_PIC_reloc
237 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM24
238 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM8
239 || epiphany_PIC_related_p (exp->X_add_symbol)
240 || epiphany_PIC_related_p (exp->X_op_symbol));
243 /* Perform target dependent relocations that are done at compile time.
244 There aren't very many of these. */
246 void
247 epiphany_apply_fix (fixS *fixP, valueT *valP, segT seg)
249 if (fixP->fx_addsy == (symbolS *) NULL)
250 fixP->fx_done = 1;
252 if (((int) fixP->fx_r_type < (int) BFD_RELOC_UNUSED)
253 && fixP->fx_done)
255 /* Install EPIPHANY-dependent relocations HERE because nobody else
256 will. */
257 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
258 unsigned char *insn = (unsigned char *)where;
259 valueT value = * valP;
261 switch (fixP->fx_r_type)
263 default:
264 break;
266 case BFD_RELOC_NONE:
267 return;
269 case BFD_RELOC_EPIPHANY_SIMM11:
270 where[0] = where[0] | ((value & 1) << 7);
271 where[1] = where[1] | ((value & 6) >> 1);
272 where[2] = (value >> 3) & 0xff;
273 return;
275 case BFD_RELOC_EPIPHANY_IMM11:
276 where[0] = where[0] | ((value & 1) << 7);
277 where[1] = where[1] | ((value & 6) >> 1);
278 where[2] = (value >> 3) & 0xff;
279 return;
281 case BFD_RELOC_EPIPHANY_SIMM8:
282 md_number_to_chars (where+1, value>>1, 1);
283 return;
285 case BFD_RELOC_EPIPHANY_SIMM24:
286 md_number_to_chars (where+1, value>>1, 3);
287 return;
289 case BFD_RELOC_EPIPHANY_HIGH:
290 value >>= 16;
291 /* fallthru */
292 case BFD_RELOC_EPIPHANY_LOW:
293 value = (((value & 0xff) << 5) | insn[0])
294 | (insn[1] << 8)
295 | ((value & 0xff00) << 12)
296 | (insn[2] << 16);
297 md_number_to_chars (where, value, 3);
298 return;
302 /* Just do the default if we can't special case. */
303 return gas_cgen_md_apply_fix (fixP, valP, seg);
307 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
308 of an rs_align_code fragment. 0x01a2 is 16-bit pattern for a "nop". */
310 static const unsigned char nop_pattern[] = { 0xa2, 0x01 };
312 void
313 epiphany_handle_align (fragS *fragp)
315 int bytes, fix;
316 char *p;
318 if (fragp->fr_type != rs_align_code)
319 return;
321 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
322 p = fragp->fr_literal + fragp->fr_fix;
323 fix = 0;
325 if (bytes & 1)
327 fix = 1;
328 *p++ = 0;
329 bytes--;
332 if (bytes & 2)
334 memcpy (p, nop_pattern, 2);
335 p += 2;
336 bytes -= 2;
337 fix += 2;
339 fragp->fr_fix += fix;
342 /* Read a comma separated incrementing list of register names
343 and form a bit mask of up to 15 registers 0..14. */
345 static const char *
346 parse_reglist (const char * s, int * mask)
348 int regmask = 0;
350 while (*s)
352 long value;
354 while (*s == ' ')
355 ++s;
357 /* Parse a list with "," or "}" as limiters. */
358 const char *errmsg
359 = cgen_parse_keyword (gas_cgen_cpu_desc, &s,
360 &epiphany_cgen_opval_gr_names, &value);
361 if (errmsg)
362 return errmsg;
364 if (value > 15)
365 return _("register number too large for push/pop");
367 regmask |= 1 << value;
368 if (regmask < *mask)
369 return _("register is out of order");
370 *mask |= regmask;
372 while (*s==' ')
373 ++s;
375 if (*s == '}')
376 return NULL;
377 else if (*s++ == ',')
378 continue;
379 else
380 return _("bad register list");
383 return _("malformed reglist in push/pop");
387 /* Assemble an instruction, push and pop pseudo instructions should have
388 already been expanded. */
390 static void
391 epiphany_assemble (const char *str)
393 epiphany_insn insn;
394 char *errmsg = 0;
396 memset (&insn, 0, sizeof (insn));
398 /* Initialize GAS's cgen interface for a new instruction. */
399 gas_cgen_init_parse ();
401 insn.insn = epiphany_cgen_assemble_insn
402 (gas_cgen_cpu_desc, str, &insn.fields, insn.buffer, & errmsg);
404 if (!insn.insn)
406 as_bad ("%s", errmsg);
407 return;
410 if (CGEN_INSN_BITSIZE (insn.insn) == 32)
412 /* Doesn't really matter what we pass for RELAX_P here. */
413 gas_cgen_finish_insn (insn.insn, insn.buffer,
414 CGEN_FIELDS_BITSIZE (&insn.fields), 1, NULL);
416 else
418 if (CGEN_INSN_BITSIZE (insn.insn) != 16)
419 abort ();
421 insn.orig_insn = insn.insn;
423 gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
424 CGEN_FIELDS_BITSIZE (&insn.fields),
425 1 /* relax_p */, NULL);
428 /* Checks for behavioral restrictions on LD/ST instructions. */
429 #define DISPMOD _("destination register modified by displacement-post-modified address")
430 #define LDSTODD _("ldrd/strd requires even:odd register pair")
432 /* Helper macros for splitting apart instruction fields. */
433 #define ADDR_POST_MODIFIED(i) (((i) >> 25) & 0x1)
434 #define ADDR_SIZE(i) (((i) >> 5) & 3)
435 #define ADDR_LOADSTORE(i) (((i) >> 4) & 0x1)
437 switch (insn.buffer[0] & 0xf)
439 /* Post-modify registers cannot be destinations. */
440 case OP4_LDSTR16P:
442 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD)
443 if (insn.fields.f_rd == insn.fields.f_rn /* Postmodify dest. */
444 || (insn.fields.f_rd+1 == insn.fields.f_rn
445 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
447 as_bad ("%s", DISPMOD);
448 return;
450 if ((insn.fields.f_rd & 1) /* Odd-numbered register... */
451 && insn.fields.f_wordsize == OPW_DOUBLE) /* ...and 64 bit transfer. */
453 as_bad ("%s", LDSTODD);
454 return;
456 break;
459 case OP4_LDSTRP:
461 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD) /* A load. */
462 if (insn.fields.f_rd6 == insn.fields.f_rn6 /* Postmodify dest. */
463 /* Check for regpair postindexed. */
464 || (insn.fields.f_rd6 + 1 == insn.fields.f_rn6
465 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
467 as_bad ("%s", DISPMOD);
468 return;
470 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
471 /* Lsb of RD odd and 64 bit transfer. */
473 as_bad ("%s", LDSTODD);
474 return;
476 break;
479 case OP4_LDSTR16X:
480 case OP4_LDSTR16D:
482 /* Check for unaligned load/store double. */
483 if ((insn.fields.f_rd & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
484 /* Lsb of RD odd and 64 bit transfer. */
486 as_bad ("%s", LDSTODD);
487 return;
489 break;
492 case OP4_LDSTRD:
494 /* Check for load to post-modified register. */
495 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD /* A load. */
496 && ADDR_POST_MODIFIED (insn.buffer[0]) == PMOD_POST /* Post-mod. */
497 && (insn.fields.f_rd6 == insn.fields.f_rn6
498 || (insn.fields.f_rd6+1 == insn.fields.f_rn6
499 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)))
501 as_bad ("%s", DISPMOD);
502 return;
505 /* fallthru */
507 case OP4_LDSTRX:
509 /* Check for unaligned load/store double. */
510 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
512 as_bad ("%s", LDSTODD);
513 return;
515 break;
518 default:
519 break;
523 void
524 md_assemble (char *str)
526 const char * pperr = 0;
527 int regmask=0, push=0, pop=0;
529 /* Special-case push/pop instruction macros. */
530 if (0 == strncmp (str, "push {", 6))
532 char * s = str + 6;
533 push = 1;
534 pperr = parse_reglist (s, &regmask);
536 else if (0 == strncmp (str, "pop {", 5))
538 char * s = str + 5;
539 pop = 1;
540 pperr = parse_reglist (s, &regmask);
543 if (pperr)
545 as_bad ("%s", pperr);
546 return;
549 if (push && regmask)
551 char buff[20];
552 int i,p ATTRIBUTE_UNUSED;
554 epiphany_assemble ("mov r15,4");
555 epiphany_assemble ("sub sp,sp,r15");
557 for (i = 0, p = 1; i <= 15; ++i, regmask >>= 1)
559 if (regmask == 1)
560 sprintf (buff, "str r%d,[sp]", i); /* Last one. */
561 else if (regmask & 1)
562 sprintf (buff, "str r%d,[sp],-r15", i);
563 else
564 continue;
565 epiphany_assemble (buff);
567 return;
569 else if (pop && regmask)
571 char buff[20];
572 int i,p;
574 epiphany_assemble ("mov r15,4");
576 for (i = 15, p = 1 << 15; i >= 0; --i, p >>= 1)
577 if (regmask & p)
579 sprintf (buff, "ldr r%d,[sp],+r15", i);
580 epiphany_assemble (buff);
582 return;
585 epiphany_assemble (str);
588 /* The syntax in the manual says constants begin with '#'.
589 We just ignore it. */
591 void
592 md_operand (expressionS *expressionP)
594 if (*input_line_pointer == '#')
596 input_line_pointer++;
597 expression (expressionP);
601 symbolS *
602 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
604 return NULL;
607 /* Interface to relax_segment. */
609 /* FIXME: Build table by hand, get it working, then machine generate. */
611 const relax_typeS md_relax_table[] =
613 /* The fields are:
614 1) most positive reach of this state,
615 2) most negative reach of this state,
616 3) how many bytes this mode will add to the size of the current frag
617 4) which index into the table to try if we can't fit into this one. */
619 /* The first entry must be unused because an `rlx_more' value of zero ends
620 each list. */
621 {1, 1, 0, EPIPHANY_RELAX_NONE},
622 {0, 0, 0, EPIPHANY_RELAX_NONE}, /* Also a dummy entry to indicate we need to expand codes. */
624 /* The displacement used by GAS is from the end of the 2 byte insn,
625 so we subtract 2 from the following. */
626 /* 16 bit insn, 8 bit disp -> +127 words, -128 words. */
627 {0x00000100 - 1 - 2, -0x00000100 - 2, 0, EPIPHANY_RELAX_BRANCH_LONG },
628 /* 32 bit insn, 24 bit disp -> 25 bit range. */
629 {0x01000000 - 1 - 2, -0x01000000 - 2, 2, EPIPHANY_RELAX_NONE },
631 /* addi/subi 3 bits -4..+3. */
632 { 3, -4,0, EPIPHANY_RELAX_ARITH_SIMM11 },
633 /* addi/subi 11 bits. */
634 { 1023, -1024,2, EPIPHANY_RELAX_NONE },
636 /* mov r,imm8. */
637 { 255, 0,0, EPIPHANY_RELAX_MOV_IMM16 },
638 /* mov r,imm16. */
639 { 65535, 0,2, EPIPHANY_RELAX_NONE },
641 /* ld/st rd,[rn,imm3]. */
642 { 7, 0,0, EPIPHANY_RELAX_LDST_IMM11},
643 /* ld/st rd,[rn,imm11]. */
644 { 2047, 0,2, EPIPHANY_RELAX_NONE }
648 static const EPIPHANY_RELAX_TYPES relax_insn[] =
650 EPIPHANY_RELAX_BRANCH_SHORT, /* OP4_BRANCH16 */
651 EPIPHANY_RELAX_NONE, /* OP4_LDSTR16X */
652 EPIPHANY_RELAX_NONE, /* OP4_FLOW16 */
653 EPIPHANY_RELAX_ARITH_SIMM3, /* OP4_IMM16 - special */
654 EPIPHANY_RELAX_LDST_IMM3, /* OP4_LDSTR16D */
655 EPIPHANY_RELAX_NONE, /* OP4_LDSTR126P */
656 EPIPHANY_RELAX_NONE, /* OP4_LSHIFT16 */
657 EPIPHANY_RELAX_NONE, /* OP4_DSP16 */
658 EPIPHANY_RELAX_BRANCH_LONG, /* OP4_BRANCH */
659 EPIPHANY_RELAX_NONE, /* OP4_LDSTRX */
660 EPIPHANY_RELAX_NONE, /* OP4_ALU16 */
661 EPIPHANY_RELAX_ARITH_SIMM11, /* OP4_IMM32 - special */
662 EPIPHANY_RELAX_LDST_IMM11, /* OP4_LDSTRD */
663 EPIPHANY_RELAX_NONE, /* OP4_LDSTRP */
664 EPIPHANY_RELAX_NONE, /* OP4_ASHIFT16 */
665 EPIPHANY_RELAX_NONE /* OP4_MISC */
668 long
669 epiphany_relax_frag (segT segment, fragS *fragP, long stretch)
671 /* Address of branch insn. */
672 long address ATTRIBUTE_UNUSED = fragP->fr_address + fragP->fr_fix - 2;
673 long growth = 0;
675 if (fragP->fr_subtype == EPIPHANY_RELAX_NEED_RELAXING)
677 EPIPHANY_RELAX_TYPES subtype = relax_insn [*fragP->fr_opcode & 0xf];
679 /* Special cases add/sub vs mov immediates. */
680 if (subtype == EPIPHANY_RELAX_ARITH_SIMM3)
682 if ((*fragP->fr_opcode & 0x10) == 0)
683 subtype = EPIPHANY_RELAX_MOV_IMM8;
685 else if (subtype == EPIPHANY_RELAX_ARITH_SIMM11)
687 if ((*fragP->fr_opcode & 0x10) == 0)
688 subtype = EPIPHANY_RELAX_MOV_IMM16;
691 /* Remember refinements for the future. */
692 fragP->fr_subtype = subtype;
695 growth = relax_frag (segment, fragP, stretch);
697 return growth;
700 /* Return an initial guess of the length by which a fragment must grow to
701 hold a branch to reach its destination.
702 Also updates fr_type/fr_subtype as necessary.
704 Called just before doing relaxation.
705 Any symbol that is now undefined will not become defined.
706 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
707 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
708 Although it may not be explicit in the frag, pretend fr_var starts
709 with a 0 value. */
712 md_estimate_size_before_relax (fragS *fragP, segT segment)
714 /* The only thing we have to handle here are symbols outside of the
715 current segment. They may be undefined or in a different segment in
716 which case linker scripts may place them anywhere.
717 However, we can't finish the fragment here and emit the reloc as insn
718 alignment requirements may move the insn about. */
719 if (S_GET_SEGMENT (fragP->fr_symbol) != segment
720 || S_IS_EXTERNAL (fragP->fr_symbol)
721 || S_IS_WEAK (fragP->fr_symbol))
723 /* The symbol is undefined in this segment. Change the
724 relaxation subtype to the max allowable and leave all further
725 handling to md_convert_frag. */
727 EPIPHANY_RELAX_TYPES subtype;
728 /* We haven't relaxed this at all, so the relaxation type may be
729 completely wrong. Set the subtype correctly. */
730 epiphany_relax_frag (segment, fragP, 0);
731 subtype = fragP->fr_subtype;
733 switch (subtype)
735 case EPIPHANY_RELAX_LDST_IMM3:
736 subtype = EPIPHANY_RELAX_LDST_IMM11;
737 break;
738 case EPIPHANY_RELAX_BRANCH_SHORT:
739 subtype = EPIPHANY_RELAX_BRANCH_LONG;
740 break;
741 case EPIPHANY_RELAX_MOV_IMM8:
742 subtype = EPIPHANY_RELAX_MOV_IMM16;
743 break;
744 case EPIPHANY_RELAX_ARITH_SIMM3:
745 subtype = EPIPHANY_RELAX_ARITH_SIMM11;
746 break;
748 default:
749 break;
752 fragP->fr_subtype = subtype;
755 const CGEN_INSN *insn;
756 int i;
758 /* Update the recorded insn. */
760 for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
762 if ((strcmp (CGEN_INSN_MNEMONIC (insn),
763 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
764 == 0)
765 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
766 break;
769 if (i == 4)
770 abort ();
772 fragP->fr_cgen.insn = insn;
776 return md_relax_table[fragP->fr_subtype].rlx_length;
779 /* *FRAGP has been relaxed to its final size, and now needs to have
780 the bytes inside it modified to conform to the new size.
782 Called after relaxation is finished.
783 fragP->fr_type == rs_machine_dependent.
784 fragP->fr_subtype is the subtype of what the address relaxed to. */
786 void
787 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
788 segT sec,
789 fragS *fragP)
791 char *opcode;
792 char *displacement;
793 int target_address;
794 int opcode_address;
795 int extension;
796 int addend;
797 int opindx = -1;
799 opcode = fragP->fr_opcode;
801 /* Address opcode resides at in file space. */
802 opcode_address = fragP->fr_address + fragP->fr_fix - 2;
803 extension = 0;
804 displacement = &opcode[1];
806 /* Set up any addend necessary for branches. */
807 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
808 || S_IS_EXTERNAL (fragP->fr_symbol)
809 || S_IS_WEAK (fragP->fr_symbol))
811 /* Symbol must be resolved by linker. */
812 if (fragP->fr_offset & 1)
813 as_warn (_("Addend to unresolved symbol not on word boundary."));
814 addend = 0;
816 else
818 /* Address we want to reach in file space. */
819 target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
820 addend = (target_address - (opcode_address & -2));
823 /* Do all the housekeeping for frag conversions. */
824 switch (fragP->fr_subtype)
826 case EPIPHANY_RELAX_ARITH_SIMM11:
827 *opcode |= OP4_IMM32;
828 displacement = &opcode[0];
829 extension += 3;
831 addend
832 = (((addend & 0x7) << 7)
833 | opcode[0]
834 | ((addend & 0x7f8) << 13)
835 | (opcode[1] << 8)
836 | (opcode[2] << 16));
838 opindx = EPIPHANY_OPERAND_SIMM11;
839 break;
841 case EPIPHANY_RELAX_BRANCH_LONG:
842 /* Branches differ only in low nibble of instruction being 8 not 0.
843 24 bit displacement goes to bytes 1..3 . */
844 *opcode |= OP4_BRANCH;
845 extension += 2;
847 addend >>= 1; /* Convert to word offset. */
848 opindx = EPIPHANY_OPERAND_SIMM24;
849 break;
851 case EPIPHANY_RELAX_MOV_IMM16:
852 *opcode |= OP4_IMM32;
853 extension += 3;
855 addend
856 = (((addend & 0xff00) << 12)
857 | (opcode[2] << 16)
858 | ((addend & 0x00ff) << 5)
859 | (opcode[1] << 8)
860 | opcode[0]);
861 displacement = &opcode[0];
862 opindx = EPIPHANY_OPERAND_IMM16;
863 break;
865 case EPIPHANY_RELAX_LDST_IMM11:
866 *opcode |= OP4_LDSTRD;
867 displacement = &opcode[0];
868 extension += 3;
870 if (addend < 0)
871 /* Convert twos-complement address value to sign-magnitude. */
872 addend = (-addend & 0x7ff) | 0x800;
874 addend
875 = (((addend & 0x7) << 5)
876 | opcode[0]
877 | ((addend & 0xff8) << 13)
878 | (opcode[1] << 8)
879 | (opcode[2] << 16));
881 opindx = EPIPHANY_OPERAND_DISP11;
882 break;
884 case EPIPHANY_RELAX_ARITH_SIMM3:
885 addend = ((addend & 7) << 5) | opcode[0];
886 opindx = EPIPHANY_OPERAND_SIMM3;
887 break;
889 case EPIPHANY_RELAX_LDST_IMM3:
890 addend = ((addend & 7) << 5) | opcode[0];
891 opindx = EPIPHANY_OPERAND_DISP3;
892 break;
894 case EPIPHANY_RELAX_BRANCH_SHORT:
895 addend >>= 1; /* Convert to a word offset. */
896 displacement = & opcode[1];
897 opindx = EPIPHANY_OPERAND_SIMM8;
898 break;
900 case EPIPHANY_RELAX_MOV_IMM8:
901 addend
902 = (((addend & 0xff) << 5)
903 | opcode[0]
904 | (opcode[1] << 8));
905 opindx = EPIPHANY_OPERAND_IMM8;
906 break;
908 case EPIPHANY_RELAX_NONE:
909 case EPIPHANY_RELAX_NEED_RELAXING:
910 default: /* Anything else? */
911 as_bad ("unrecognized fragment subtype");
912 break;
915 /* Create a relocation for symbols that must be resolved by the linker.
916 Otherwise output the completed insn. */
918 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
919 || S_IS_EXTERNAL (fragP->fr_symbol)
920 || S_IS_WEAK (fragP->fr_symbol))
922 fixS *fixP;
923 const CGEN_OPERAND *operand
924 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx);
925 bfd_reloc_code_real_type reloc_type;
927 gas_assert (fragP->fr_cgen.insn != 0);
929 reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL);
931 fixP = gas_cgen_record_fixup (fragP,
932 /* Offset of insn in frag. */
933 (opcode - fragP->fr_literal),
934 fragP->fr_cgen.insn,
935 CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8,
936 operand,
937 reloc_type,
938 fragP->fr_symbol, fragP->fr_offset);
939 fixP->fx_r_type = fixP->fx_cgen.opinfo;
942 md_number_to_chars (displacement, (valueT) addend, extension + 1);
944 fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added. */
948 /* Functions concerning relocs. */
950 /* The location from which a PC relative jump should be calculated,
951 given a PC relative reloc. */
953 long
954 md_pcrel_from_section (fixS *fixP, segT sec)
956 if (fixP->fx_addsy != (symbolS *) NULL
957 && (!S_IS_DEFINED (fixP->fx_addsy)
958 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
959 || S_IS_EXTERNAL (fixP->fx_addsy)
960 || S_IS_WEAK (fixP->fx_addsy)))
961 return 0;
963 return fixP->fx_frag->fr_address + fixP->fx_where;
966 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
967 Returns BFD_RELOC_NONE if no reloc type can be found.
968 *FIXP may be modified if desired. */
970 bfd_reloc_code_real_type
971 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
972 const CGEN_OPERAND *operand,
973 fixS *fixP ATTRIBUTE_UNUSED)
975 switch (operand->type)
977 case EPIPHANY_OPERAND_SIMM11:
978 return BFD_RELOC_EPIPHANY_SIMM11;
979 case EPIPHANY_OPERAND_DISP11:
980 return BFD_RELOC_EPIPHANY_IMM11;
982 case EPIPHANY_OPERAND_SIMM8:
983 return BFD_RELOC_EPIPHANY_SIMM8;
984 case EPIPHANY_OPERAND_SIMM24:
985 return BFD_RELOC_EPIPHANY_SIMM24;
987 case EPIPHANY_OPERAND_IMM8:
988 return BFD_RELOC_EPIPHANY_IMM8;
990 case EPIPHANY_OPERAND_IMM16:
991 if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn)))
992 return BFD_RELOC_EPIPHANY_HIGH;
993 else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn)))
994 return BFD_RELOC_EPIPHANY_LOW;
995 else
996 as_bad ("unknown imm16 operand");
997 /* fallthru */
999 default:
1000 break;
1002 return BFD_RELOC_NONE;
1006 /* Turn a string in input_line_pointer into a floating point constant
1007 of type TYPE, and store the appropriate bytes in *LITP. The number
1008 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1009 returned, or NULL on OK. */
1011 const char *
1012 md_atof (int type, char *litP, int *sizeP)
1014 return ieee_md_atof (type, litP, sizeP, FALSE);
1017 /* Return true if can adjust the reloc to be relative to its section
1018 (such as .data) instead of relative to some symbol. */
1020 bfd_boolean
1021 epiphany_fix_adjustable (fixS *fixP)
1023 bfd_reloc_code_real_type reloc_type;
1025 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1027 const CGEN_INSN *insn = fixP->fx_cgen.insn;
1028 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1029 const CGEN_OPERAND *operand =
1030 cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindex);
1032 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1034 else
1035 reloc_type = fixP->fx_r_type;
1037 if (fixP->fx_addsy == NULL)
1038 return TRUE;
1040 /* Prevent all adjustments to global symbols. */
1041 if (S_IS_EXTERNAL (fixP->fx_addsy))
1042 return FALSE;
1044 if (S_IS_WEAK (fixP->fx_addsy))
1045 return FALSE;
1047 if (pic_code
1048 && (reloc_type == BFD_RELOC_EPIPHANY_SIMM24
1049 || reloc_type == BFD_RELOC_EPIPHANY_SIMM8
1050 || reloc_type == BFD_RELOC_EPIPHANY_HIGH
1051 || reloc_type == BFD_RELOC_EPIPHANY_LOW))
1052 return FALSE;
1054 /* Since we don't use partial_inplace, we must not reduce symbols in
1055 mergeable sections to their section symbol. */
1056 if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
1057 return FALSE;
1059 return TRUE;
1062 void
1063 epiphany_elf_final_processing (void)
1065 elf_elfheader (stdoutput)->e_flags |= epiphany_flags;
1069 epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED)
1071 LITTLENUM_TYPE words[2];
1073 switch (opinfo)
1075 case BFD_RELOC_EPIPHANY_LOW:
1076 case BFD_RELOC_EPIPHANY_HIGH:
1077 break;
1078 default:
1079 return opinfo;
1082 /* Doing a %LOW or %HIGH. */
1083 switch (exp->X_op)
1085 default:
1086 return opinfo;
1087 case O_big: /* Bignum. */
1088 if (exp->X_add_number > 0) /* Integer value too large. */
1089 return opinfo;
1092 /* Convert to SP number. */
1093 gen_to_words (words, 2, 8L);
1094 exp->X_add_number = words[1] | (words[0] << 16);
1095 exp->X_op = O_constant;
1096 return opinfo;