Update year range in copyright notice of binutils files
[binutils-gdb.git] / gas / config / tc-epiphany.c
blobfd6728cc6170ed131e9de3d404ad6e752f62d8d1
1 /* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY
2 Copyright (C) 2009-2024 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 bool 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);
149 literal_prefix_dollar_hex = true;
152 valueT
153 md_section_align (segT segment, valueT size)
155 int align = bfd_section_alignment (segment);
157 return ((size + (1 << align) - 1) & -(1 << align));
161 /* Functions concerning relocs. */
163 long
164 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
166 abort ();
169 /* Write a value out to the object file, using the appropriate endianness. */
171 void
172 md_number_to_chars (char * buf, valueT val, int n)
174 number_to_chars_littleendian (buf, val, n);
178 epiphany_elf_section_flags (int flags,
179 int attr ATTRIBUTE_UNUSED,
180 int type ATTRIBUTE_UNUSED)
182 /* This is used to detect when the section changes to an executable section.
183 This function is called by the elf section processing. When we note an
184 executable section specifier we set an internal flag to denote when
185 word alignment should be forced. */
186 if (flags & SEC_CODE)
187 force_code_align = true;
189 return flags;
192 /* Non-zero if we are generating PIC code. */
193 int pic_code;
195 /* Epiphany er_flags. */
196 static int epiphany_flags = 0;
198 /* Relocations against symbols are done in two
199 parts, with a HI relocation and a LO relocation. Each relocation
200 has only 16 bits of space to store an addend. This means that in
201 order for the linker to handle carries correctly, it must be able
202 to locate both the HI and the LO relocation. This means that the
203 relocations must appear in order in the relocation table.
205 In order to implement this, we keep track of each unmatched HI
206 relocation. We then sort them so that they immediately precede the
207 corresponding LO relocation. */
209 struct epiphany_hi_fixup
211 /* Next HI fixup. */
212 struct epiphany_hi_fixup *next;
214 /* This fixup. */
215 fixS *fixp;
217 /* The section this fixup is in. */
218 segT seg;
222 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
223 static symbolS * GOT_symbol;
225 static inline bool
226 epiphany_PIC_related_p (symbolS *sym)
228 expressionS *exp;
230 if (! sym)
231 return false;
233 if (sym == GOT_symbol)
234 return true;
236 exp = symbol_get_value_expression (sym);
238 return (exp->X_op == O_PIC_reloc
239 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM24
240 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM8
241 || epiphany_PIC_related_p (exp->X_add_symbol)
242 || epiphany_PIC_related_p (exp->X_op_symbol));
245 /* Perform target dependent relocations that are done at compile time.
246 There aren't very many of these. */
248 void
249 epiphany_apply_fix (fixS *fixP, valueT *valP, segT seg)
251 if (fixP->fx_addsy == (symbolS *) NULL)
252 fixP->fx_done = 1;
254 if (((int) fixP->fx_r_type < (int) BFD_RELOC_UNUSED)
255 && fixP->fx_done)
257 /* Install EPIPHANY-dependent relocations HERE because nobody else
258 will. */
259 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
260 unsigned char *insn = (unsigned char *)where;
261 valueT value = * valP;
263 switch (fixP->fx_r_type)
265 default:
266 break;
268 case BFD_RELOC_NONE:
269 return;
271 case BFD_RELOC_EPIPHANY_SIMM11:
272 where[0] = where[0] | ((value & 1) << 7);
273 where[1] = where[1] | ((value & 6) >> 1);
274 where[2] = (value >> 3) & 0xff;
275 return;
277 case BFD_RELOC_EPIPHANY_IMM11:
278 where[0] = where[0] | ((value & 1) << 7);
279 where[1] = where[1] | ((value & 6) >> 1);
280 where[2] = (value >> 3) & 0xff;
281 return;
283 case BFD_RELOC_EPIPHANY_SIMM8:
284 md_number_to_chars (where+1, value>>1, 1);
285 return;
287 case BFD_RELOC_EPIPHANY_SIMM24:
288 md_number_to_chars (where+1, value>>1, 3);
289 return;
291 case BFD_RELOC_EPIPHANY_HIGH:
292 value >>= 16;
293 /* fallthru */
294 case BFD_RELOC_EPIPHANY_LOW:
295 value = (((value & 0xff) << 5) | insn[0])
296 | (insn[1] << 8)
297 | ((value & 0xff00) << 12)
298 | (insn[2] << 16);
299 md_number_to_chars (where, value, 3);
300 return;
304 /* Just do the default if we can't special case. */
305 return gas_cgen_md_apply_fix (fixP, valP, seg);
309 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
310 of an rs_align_code fragment. 0x01a2 is 16-bit pattern for a "nop". */
312 static const unsigned char nop_pattern[] = { 0xa2, 0x01 };
314 void
315 epiphany_handle_align (fragS *fragp)
317 int bytes, fix;
318 char *p;
320 if (fragp->fr_type != rs_align_code)
321 return;
323 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
324 p = fragp->fr_literal + fragp->fr_fix;
325 fix = 0;
327 if (bytes & 1)
329 fix = 1;
330 *p++ = 0;
331 bytes--;
334 if (bytes & 2)
336 memcpy (p, nop_pattern, 2);
337 p += 2;
338 bytes -= 2;
339 fix += 2;
341 fragp->fr_fix += fix;
344 /* Read a comma separated incrementing list of register names
345 and form a bit mask of up to 15 registers 0..14. */
347 static const char *
348 parse_reglist (const char * s, int * mask)
350 int regmask = 0;
352 while (*s)
354 long value;
356 while (*s == ' ')
357 ++s;
359 /* Parse a list with "," or "}" as limiters. */
360 const char *errmsg
361 = cgen_parse_keyword (gas_cgen_cpu_desc, &s,
362 &epiphany_cgen_opval_gr_names, &value);
363 if (errmsg)
364 return errmsg;
366 if (value > 15)
367 return _("register number too large for push/pop");
369 regmask |= 1 << value;
370 if (regmask < *mask)
371 return _("register is out of order");
372 *mask |= regmask;
374 while (*s==' ')
375 ++s;
377 if (*s == '}')
378 return NULL;
379 else if (*s++ == ',')
380 continue;
381 else
382 return _("bad register list");
385 return _("malformed reglist in push/pop");
389 /* Assemble an instruction, push and pop pseudo instructions should have
390 already been expanded. */
392 static void
393 epiphany_assemble (const char *str)
395 epiphany_insn insn;
396 char *errmsg = 0;
398 memset (&insn, 0, sizeof (insn));
400 /* Initialize GAS's cgen interface for a new instruction. */
401 gas_cgen_init_parse ();
403 insn.insn = epiphany_cgen_assemble_insn
404 (gas_cgen_cpu_desc, str, &insn.fields, insn.buffer, & errmsg);
406 if (!insn.insn)
408 as_bad ("%s", errmsg);
409 return;
412 if (CGEN_INSN_BITSIZE (insn.insn) == 32)
414 /* Doesn't really matter what we pass for RELAX_P here. */
415 gas_cgen_finish_insn (insn.insn, insn.buffer,
416 CGEN_FIELDS_BITSIZE (&insn.fields), 1, NULL);
418 else
420 if (CGEN_INSN_BITSIZE (insn.insn) != 16)
421 abort ();
423 insn.orig_insn = insn.insn;
425 gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
426 CGEN_FIELDS_BITSIZE (&insn.fields),
427 1 /* relax_p */, NULL);
430 /* Checks for behavioral restrictions on LD/ST instructions. */
431 #define DISPMOD _("destination register modified by displacement-post-modified address")
432 #define LDSTODD _("ldrd/strd requires even:odd register pair")
434 /* Helper macros for splitting apart instruction fields. */
435 #define ADDR_POST_MODIFIED(i) (((i) >> 25) & 0x1)
436 #define ADDR_SIZE(i) (((i) >> 5) & 3)
437 #define ADDR_LOADSTORE(i) (((i) >> 4) & 0x1)
439 switch (insn.buffer[0] & 0xf)
441 /* Post-modify registers cannot be destinations. */
442 case OP4_LDSTR16P:
444 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD)
445 if (insn.fields.f_rd == insn.fields.f_rn /* Postmodify dest. */
446 || (insn.fields.f_rd+1 == insn.fields.f_rn
447 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
449 as_bad ("%s", DISPMOD);
450 return;
452 if ((insn.fields.f_rd & 1) /* Odd-numbered register... */
453 && insn.fields.f_wordsize == OPW_DOUBLE) /* ...and 64 bit transfer. */
455 as_bad ("%s", LDSTODD);
456 return;
458 break;
461 case OP4_LDSTRP:
463 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD) /* A load. */
464 if (insn.fields.f_rd6 == insn.fields.f_rn6 /* Postmodify dest. */
465 /* Check for regpair postindexed. */
466 || (insn.fields.f_rd6 + 1 == insn.fields.f_rn6
467 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
469 as_bad ("%s", DISPMOD);
470 return;
472 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
473 /* Lsb of RD odd and 64 bit transfer. */
475 as_bad ("%s", LDSTODD);
476 return;
478 break;
481 case OP4_LDSTR16X:
482 case OP4_LDSTR16D:
484 /* Check for unaligned load/store double. */
485 if ((insn.fields.f_rd & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
486 /* Lsb of RD odd and 64 bit transfer. */
488 as_bad ("%s", LDSTODD);
489 return;
491 break;
494 case OP4_LDSTRD:
496 /* Check for load to post-modified register. */
497 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD /* A load. */
498 && ADDR_POST_MODIFIED (insn.buffer[0]) == PMOD_POST /* Post-mod. */
499 && (insn.fields.f_rd6 == insn.fields.f_rn6
500 || (insn.fields.f_rd6+1 == insn.fields.f_rn6
501 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)))
503 as_bad ("%s", DISPMOD);
504 return;
507 /* fallthru */
509 case OP4_LDSTRX:
511 /* Check for unaligned load/store double. */
512 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
514 as_bad ("%s", LDSTODD);
515 return;
517 break;
520 default:
521 break;
525 void
526 md_assemble (char *str)
528 const char * pperr = 0;
529 int regmask=0, push=0, pop=0;
531 /* Special-case push/pop instruction macros. */
532 if (startswith (str, "push {"))
534 char * s = str + 6;
535 push = 1;
536 pperr = parse_reglist (s, &regmask);
538 else if (startswith (str, "pop {"))
540 char * s = str + 5;
541 pop = 1;
542 pperr = parse_reglist (s, &regmask);
545 if (pperr)
547 as_bad ("%s", pperr);
548 return;
551 if (push && regmask)
553 char buff[32];
554 int i,p ATTRIBUTE_UNUSED;
556 epiphany_assemble ("mov r15,4");
557 epiphany_assemble ("sub sp,sp,r15");
559 for (i = 0, p = 1; i <= 15; ++i, regmask >>= 1)
561 if (regmask == 1)
562 sprintf (buff, "str r%d,[sp]", i); /* Last one. */
563 else if (regmask & 1)
564 sprintf (buff, "str r%d,[sp],-r15", i);
565 else
566 continue;
567 epiphany_assemble (buff);
569 return;
571 else if (pop && regmask)
573 char buff[32];
574 int i,p;
576 epiphany_assemble ("mov r15,4");
578 for (i = 15, p = 1 << 15; i >= 0; --i, p >>= 1)
579 if (regmask & p)
581 sprintf (buff, "ldr r%d,[sp],+r15", i);
582 epiphany_assemble (buff);
584 return;
587 epiphany_assemble (str);
590 /* The syntax in the manual says constants begin with '#'.
591 We just ignore it. */
593 void
594 md_operand (expressionS *expressionP)
596 if (*input_line_pointer == '#')
598 input_line_pointer++;
599 expression (expressionP);
603 symbolS *
604 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
606 return NULL;
609 /* Interface to relax_segment. */
611 /* FIXME: Build table by hand, get it working, then machine generate. */
613 const relax_typeS md_relax_table[] =
615 /* The fields are:
616 1) most positive reach of this state,
617 2) most negative reach of this state,
618 3) how many bytes this mode will add to the size of the current frag
619 4) which index into the table to try if we can't fit into this one. */
621 /* The first entry must be unused because an `rlx_more' value of zero ends
622 each list. */
623 {1, 1, 0, EPIPHANY_RELAX_NONE},
624 {0, 0, 0, EPIPHANY_RELAX_NONE}, /* Also a dummy entry to indicate we need to expand codes. */
626 /* The displacement used by GAS is from the end of the 2 byte insn,
627 so we subtract 2 from the following. */
628 /* 16 bit insn, 8 bit disp -> +127 words, -128 words. */
629 {0x00000100 - 1 - 2, -0x00000100 - 2, 0, EPIPHANY_RELAX_BRANCH_LONG },
630 /* 32 bit insn, 24 bit disp -> 25 bit range. */
631 {0x01000000 - 1 - 2, -0x01000000 - 2, 2, EPIPHANY_RELAX_NONE },
633 /* addi/subi 3 bits -4..+3. */
634 { 3, -4,0, EPIPHANY_RELAX_ARITH_SIMM11 },
635 /* addi/subi 11 bits. */
636 { 1023, -1024,2, EPIPHANY_RELAX_NONE },
638 /* mov r,imm8. */
639 { 255, 0,0, EPIPHANY_RELAX_MOV_IMM16 },
640 /* mov r,imm16. */
641 { 65535, 0,2, EPIPHANY_RELAX_NONE },
643 /* ld/st rd,[rn,imm3]. */
644 { 7, 0,0, EPIPHANY_RELAX_LDST_IMM11},
645 /* ld/st rd,[rn,imm11]. */
646 { 2047, 0,2, EPIPHANY_RELAX_NONE }
650 static const EPIPHANY_RELAX_TYPES relax_insn[] =
652 EPIPHANY_RELAX_BRANCH_SHORT, /* OP4_BRANCH16 */
653 EPIPHANY_RELAX_NONE, /* OP4_LDSTR16X */
654 EPIPHANY_RELAX_NONE, /* OP4_FLOW16 */
655 EPIPHANY_RELAX_ARITH_SIMM3, /* OP4_IMM16 - special */
656 EPIPHANY_RELAX_LDST_IMM3, /* OP4_LDSTR16D */
657 EPIPHANY_RELAX_NONE, /* OP4_LDSTR126P */
658 EPIPHANY_RELAX_NONE, /* OP4_LSHIFT16 */
659 EPIPHANY_RELAX_NONE, /* OP4_DSP16 */
660 EPIPHANY_RELAX_BRANCH_LONG, /* OP4_BRANCH */
661 EPIPHANY_RELAX_NONE, /* OP4_LDSTRX */
662 EPIPHANY_RELAX_NONE, /* OP4_ALU16 */
663 EPIPHANY_RELAX_ARITH_SIMM11, /* OP4_IMM32 - special */
664 EPIPHANY_RELAX_LDST_IMM11, /* OP4_LDSTRD */
665 EPIPHANY_RELAX_NONE, /* OP4_LDSTRP */
666 EPIPHANY_RELAX_NONE, /* OP4_ASHIFT16 */
667 EPIPHANY_RELAX_NONE /* OP4_MISC */
670 long
671 epiphany_relax_frag (segT segment, fragS *fragP, long stretch)
673 /* Address of branch insn. */
674 long address ATTRIBUTE_UNUSED = fragP->fr_address + fragP->fr_fix - 2;
675 long growth = 0;
677 if (fragP->fr_subtype == EPIPHANY_RELAX_NEED_RELAXING)
679 EPIPHANY_RELAX_TYPES subtype = relax_insn [*fragP->fr_opcode & 0xf];
681 /* Special cases add/sub vs mov immediates. */
682 if (subtype == EPIPHANY_RELAX_ARITH_SIMM3)
684 if ((*fragP->fr_opcode & 0x10) == 0)
685 subtype = EPIPHANY_RELAX_MOV_IMM8;
687 else if (subtype == EPIPHANY_RELAX_ARITH_SIMM11)
689 if ((*fragP->fr_opcode & 0x10) == 0)
690 subtype = EPIPHANY_RELAX_MOV_IMM16;
693 /* Remember refinements for the future. */
694 fragP->fr_subtype = subtype;
697 growth = relax_frag (segment, fragP, stretch);
699 return growth;
702 /* Return an initial guess of the length by which a fragment must grow to
703 hold a branch to reach its destination.
704 Also updates fr_type/fr_subtype as necessary.
706 Called just before doing relaxation.
707 Any symbol that is now undefined will not become defined.
708 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
709 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
710 Although it may not be explicit in the frag, pretend fr_var starts
711 with a 0 value. */
714 md_estimate_size_before_relax (fragS *fragP, segT segment)
716 /* The only thing we have to handle here are symbols outside of the
717 current segment. They may be undefined or in a different segment in
718 which case linker scripts may place them anywhere.
719 However, we can't finish the fragment here and emit the reloc as insn
720 alignment requirements may move the insn about. */
721 if (S_GET_SEGMENT (fragP->fr_symbol) != segment
722 || S_IS_EXTERNAL (fragP->fr_symbol)
723 || S_IS_WEAK (fragP->fr_symbol))
725 /* The symbol is undefined in this segment. Change the
726 relaxation subtype to the max allowable and leave all further
727 handling to md_convert_frag. */
729 EPIPHANY_RELAX_TYPES subtype;
730 const CGEN_INSN *insn;
731 int i;
732 /* We haven't relaxed this at all, so the relaxation type may be
733 completely wrong. Set the subtype correctly. */
734 epiphany_relax_frag (segment, fragP, 0);
735 subtype = fragP->fr_subtype;
737 switch (subtype)
739 case EPIPHANY_RELAX_LDST_IMM3:
740 subtype = EPIPHANY_RELAX_LDST_IMM11;
741 break;
742 case EPIPHANY_RELAX_BRANCH_SHORT:
743 subtype = EPIPHANY_RELAX_BRANCH_LONG;
744 break;
745 case EPIPHANY_RELAX_MOV_IMM8:
746 subtype = EPIPHANY_RELAX_MOV_IMM16;
747 break;
748 case EPIPHANY_RELAX_ARITH_SIMM3:
749 subtype = EPIPHANY_RELAX_ARITH_SIMM11;
750 break;
752 default:
753 break;
756 fragP->fr_subtype = subtype;
758 /* Update the recorded insn. */
759 for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
761 if (strcmp (CGEN_INSN_MNEMONIC (insn),
762 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn)) == 0
763 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
764 break;
767 if (i == 4)
768 abort ();
770 /* When changing from a 2-byte to 4-byte insn, don't leave
771 opcode bytes uninitialised. */
772 if (CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) < CGEN_INSN_BITSIZE (insn))
774 gas_assert (CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) == 16);
775 gas_assert (CGEN_INSN_BITSIZE (insn) == 32);
776 fragP->fr_opcode[2] = 0;
777 fragP->fr_opcode[3] = 0;
780 fragP->fr_cgen.insn = insn;
783 return md_relax_table[fragP->fr_subtype].rlx_length;
786 /* *FRAGP has been relaxed to its final size, and now needs to have
787 the bytes inside it modified to conform to the new size.
789 Called after relaxation is finished.
790 fragP->fr_type == rs_machine_dependent.
791 fragP->fr_subtype is the subtype of what the address relaxed to. */
793 void
794 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
795 segT sec,
796 fragS *fragP)
798 char *opcode;
799 char *displacement;
800 int target_address;
801 int opcode_address;
802 int extension;
803 int addend;
804 int opindx = -1;
806 opcode = fragP->fr_opcode;
808 /* Address opcode resides at in file space. */
809 opcode_address = fragP->fr_address + fragP->fr_fix - 2;
810 extension = 0;
811 displacement = &opcode[1];
813 /* Set up any addend necessary for branches. */
814 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
815 || S_IS_EXTERNAL (fragP->fr_symbol)
816 || S_IS_WEAK (fragP->fr_symbol))
818 /* Symbol must be resolved by linker. */
819 if (fragP->fr_offset & 1)
820 as_warn (_("Addend to unresolved symbol not on word boundary."));
821 addend = 0;
823 else
825 /* Address we want to reach in file space. */
826 target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
827 addend = (target_address - (opcode_address & -2));
830 /* Do all the housekeeping for frag conversions. */
831 switch (fragP->fr_subtype)
833 case EPIPHANY_RELAX_ARITH_SIMM11:
834 *opcode |= OP4_IMM32;
835 displacement = &opcode[0];
836 extension += 3;
838 addend
839 = (((addend & 0x7) << 7)
840 | opcode[0]
841 | ((addend & 0x7f8) << 13)
842 | (opcode[1] << 8)
843 | (opcode[2] << 16));
845 opindx = EPIPHANY_OPERAND_SIMM11;
846 break;
848 case EPIPHANY_RELAX_BRANCH_LONG:
849 /* Branches differ only in low nibble of instruction being 8 not 0.
850 24 bit displacement goes to bytes 1..3 . */
851 *opcode |= OP4_BRANCH;
852 extension += 2;
854 addend >>= 1; /* Convert to word offset. */
855 opindx = EPIPHANY_OPERAND_SIMM24;
856 break;
858 case EPIPHANY_RELAX_MOV_IMM16:
859 *opcode |= OP4_IMM32;
860 extension += 3;
862 addend
863 = (((addend & 0xff00) << 12)
864 | (opcode[2] << 16)
865 | ((addend & 0x00ff) << 5)
866 | (opcode[1] << 8)
867 | opcode[0]);
868 displacement = &opcode[0];
869 opindx = EPIPHANY_OPERAND_IMM16;
870 break;
872 case EPIPHANY_RELAX_LDST_IMM11:
873 *opcode |= OP4_LDSTRD;
874 displacement = &opcode[0];
875 extension += 3;
877 if (addend < 0)
878 /* Convert twos-complement address value to sign-magnitude. */
879 addend = (-addend & 0x7ff) | 0x800;
881 addend
882 = (((addend & 0x7) << 5)
883 | opcode[0]
884 | ((addend & 0xff8) << 13)
885 | (opcode[1] << 8)
886 | (opcode[2] << 16));
888 opindx = EPIPHANY_OPERAND_DISP11;
889 break;
891 case EPIPHANY_RELAX_ARITH_SIMM3:
892 addend = ((addend & 7) << 5) | opcode[0];
893 opindx = EPIPHANY_OPERAND_SIMM3;
894 break;
896 case EPIPHANY_RELAX_LDST_IMM3:
897 addend = ((addend & 7) << 5) | opcode[0];
898 opindx = EPIPHANY_OPERAND_DISP3;
899 break;
901 case EPIPHANY_RELAX_BRANCH_SHORT:
902 addend >>= 1; /* Convert to a word offset. */
903 displacement = & opcode[1];
904 opindx = EPIPHANY_OPERAND_SIMM8;
905 break;
907 case EPIPHANY_RELAX_MOV_IMM8:
908 addend
909 = (((addend & 0xff) << 5)
910 | opcode[0]
911 | (opcode[1] << 8));
912 opindx = EPIPHANY_OPERAND_IMM8;
913 break;
915 case EPIPHANY_RELAX_NONE:
916 case EPIPHANY_RELAX_NEED_RELAXING:
917 default: /* Anything else? */
918 as_bad ("unrecognized fragment subtype");
919 break;
922 /* Create a relocation for symbols that must be resolved by the linker.
923 Otherwise output the completed insn. */
925 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
926 || S_IS_EXTERNAL (fragP->fr_symbol)
927 || S_IS_WEAK (fragP->fr_symbol))
929 fixS *fixP;
930 const CGEN_OPERAND *operand
931 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx);
932 bfd_reloc_code_real_type reloc_type;
934 gas_assert (fragP->fr_cgen.insn != 0);
936 reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL);
938 fixP = gas_cgen_record_fixup (fragP,
939 /* Offset of insn in frag. */
940 (opcode - fragP->fr_literal),
941 fragP->fr_cgen.insn,
942 CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8,
943 operand,
944 reloc_type,
945 fragP->fr_symbol, fragP->fr_offset);
946 fixP->fx_r_type = fixP->fx_cgen.opinfo;
949 md_number_to_chars (displacement, (valueT) addend, extension + 1);
951 fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added. */
955 /* Functions concerning relocs. */
957 /* The location from which a PC relative jump should be calculated,
958 given a PC relative reloc. */
960 long
961 md_pcrel_from_section (fixS *fixP, segT sec)
963 if (fixP->fx_addsy != (symbolS *) NULL
964 && (!S_IS_DEFINED (fixP->fx_addsy)
965 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
966 || S_IS_EXTERNAL (fixP->fx_addsy)
967 || S_IS_WEAK (fixP->fx_addsy)))
968 return 0;
970 return fixP->fx_frag->fr_address + fixP->fx_where;
973 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
974 Returns BFD_RELOC_NONE if no reloc type can be found.
975 *FIXP may be modified if desired. */
977 bfd_reloc_code_real_type
978 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
979 const CGEN_OPERAND *operand,
980 fixS *fixP ATTRIBUTE_UNUSED)
982 switch (operand->type)
984 case EPIPHANY_OPERAND_SIMM11:
985 return BFD_RELOC_EPIPHANY_SIMM11;
986 case EPIPHANY_OPERAND_DISP11:
987 return BFD_RELOC_EPIPHANY_IMM11;
989 case EPIPHANY_OPERAND_SIMM8:
990 return BFD_RELOC_EPIPHANY_SIMM8;
991 case EPIPHANY_OPERAND_SIMM24:
992 return BFD_RELOC_EPIPHANY_SIMM24;
994 case EPIPHANY_OPERAND_IMM8:
995 return BFD_RELOC_EPIPHANY_IMM8;
997 case EPIPHANY_OPERAND_IMM16:
998 if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn)))
999 return BFD_RELOC_EPIPHANY_HIGH;
1000 else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn)))
1001 return BFD_RELOC_EPIPHANY_LOW;
1002 else
1003 as_bad ("unknown imm16 operand");
1004 /* fallthru */
1006 default:
1007 break;
1009 return BFD_RELOC_NONE;
1013 /* Turn a string in input_line_pointer into a floating point constant
1014 of type TYPE, and store the appropriate bytes in *LITP. The number
1015 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1016 returned, or NULL on OK. */
1018 const char *
1019 md_atof (int type, char *litP, int *sizeP)
1021 return ieee_md_atof (type, litP, sizeP, false);
1024 /* Return true if can adjust the reloc to be relative to its section
1025 (such as .data) instead of relative to some symbol. */
1027 bool
1028 epiphany_fix_adjustable (fixS *fixP)
1030 bfd_reloc_code_real_type reloc_type;
1032 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1034 const CGEN_INSN *insn = fixP->fx_cgen.insn;
1035 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1036 const CGEN_OPERAND *operand =
1037 cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindex);
1039 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1041 else
1042 reloc_type = fixP->fx_r_type;
1044 if (fixP->fx_addsy == NULL)
1045 return true;
1047 /* Prevent all adjustments to global symbols. */
1048 if (S_IS_EXTERNAL (fixP->fx_addsy))
1049 return false;
1051 if (S_IS_WEAK (fixP->fx_addsy))
1052 return false;
1054 if (pic_code
1055 && (reloc_type == BFD_RELOC_EPIPHANY_SIMM24
1056 || reloc_type == BFD_RELOC_EPIPHANY_SIMM8
1057 || reloc_type == BFD_RELOC_EPIPHANY_HIGH
1058 || reloc_type == BFD_RELOC_EPIPHANY_LOW))
1059 return false;
1061 /* Since we don't use partial_inplace, we must not reduce symbols in
1062 mergeable sections to their section symbol. */
1063 if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
1064 return false;
1066 return true;
1069 void
1070 epiphany_elf_final_processing (void)
1072 elf_elfheader (stdoutput)->e_flags |= epiphany_flags;
1076 epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED)
1078 LITTLENUM_TYPE words[2];
1080 switch (opinfo)
1082 case BFD_RELOC_EPIPHANY_LOW:
1083 case BFD_RELOC_EPIPHANY_HIGH:
1084 break;
1085 default:
1086 return opinfo;
1089 /* Doing a %LOW or %HIGH. */
1090 switch (exp->X_op)
1092 default:
1093 return opinfo;
1094 case O_big: /* Bignum. */
1095 if (exp->X_add_number > 0) /* Integer value too large. */
1096 return opinfo;
1099 /* Convert to SP number. */
1100 gen_to_words (words, 2, 8L);
1101 exp->X_add_number = words[1] | (words[0] << 16);
1102 exp->X_op = O_constant;
1103 return opinfo;