2012-01-06 Tristan Gingold <gingold@adacore.com>
[binutils.git] / gas / config / tc-epiphany.c
blob6cc7d66a07ef44991be2593ca1c5dc3a99bb281d
1 /* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY
2 Copyright 2009, 2011 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"
31 #include "libbfd.h"
33 /* Structure to hold all of the different components describing
34 an individual instruction. */
35 typedef struct
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];
53 epiphany_insn;
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";
61 /* Flag to detect when switching to code section where insn alignment is
62 implied. */
63 static bfd_boolean force_code_align = FALSE;
65 static void
66 epiphany_elf_section_rtn (int i)
68 obj_elf_section (i);
70 if (force_code_align)
72 /* The s_align_ptwo function expects that we are just after a .align
73 directive and it will either try and read the align value or stop
74 if end of line so we must fake it out so it thinks we are at the
75 end of the line. */
76 char *old_input_line_pointer = input_line_pointer;
78 input_line_pointer = "\n";
79 s_align_ptwo (1);
80 force_code_align = FALSE;
82 /* Restore. */
83 input_line_pointer = old_input_line_pointer;
87 static void
88 epiphany_elf_section_text (int i)
90 char *old_input_line_pointer;
92 obj_elf_text (i);
94 /* The s_align_ptwo function expects that we are just after a .align
95 directive and it will either try and read the align value or stop if
96 end of line so we must fake it out so it thinks we are at the end of
97 the line. */
98 old_input_line_pointer = input_line_pointer;
99 input_line_pointer = "\n";
100 s_align_ptwo (1);
101 force_code_align = FALSE;
102 /* Restore. */
103 input_line_pointer = old_input_line_pointer;
106 /* The target specific pseudo-ops which we support. */
107 const pseudo_typeS md_pseudo_table[] =
109 { "text", epiphany_elf_section_text, 0 },
110 { "sect", epiphany_elf_section_rtn, 0 },
111 /* .word should be 32 bits. */
112 { "word", cons, 4 },
113 { "cpu", s_ignore, 0 },
114 { "thumb_func", s_ignore, 0 },
115 { "code", s_ignore, 0 },
116 { NULL, NULL, 0 }
121 enum options
123 OPTION_CPU_EPIPHANY = OPTION_MD_BASE,
124 OPTION_CPU_EPIPHANY16
127 struct option md_longopts[] =
129 { "mepiphany ", no_argument, NULL, OPTION_CPU_EPIPHANY },
130 { "mepiphany16", no_argument, NULL, OPTION_CPU_EPIPHANY16 },
131 { NULL, no_argument, NULL, 0 },
134 size_t md_longopts_size = sizeof (md_longopts);
136 const char * md_shortopts = "";
139 md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
141 return 0; /* No target-specific options. */
144 void
145 md_show_usage (FILE * stream)
147 fprintf (stream, _("EPIPHANY specific command line options:\n"));
151 void
152 md_begin (void)
154 /* Initialize the `cgen' interface. */
156 /* Set the machine number and endian. */
157 gas_cgen_cpu_desc = epiphany_cgen_cpu_open (CGEN_CPU_OPEN_MACHS,
158 bfd_mach_epiphany32,
159 CGEN_CPU_OPEN_ENDIAN,
160 CGEN_ENDIAN_LITTLE,
161 CGEN_CPU_OPEN_END);
162 epiphany_cgen_init_asm (gas_cgen_cpu_desc);
164 /* This is a callback from cgen to gas to parse operands. */
165 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
167 /* Set the machine type. */
168 bfd_default_set_arch_mach (stdoutput, bfd_arch_epiphany, bfd_mach_epiphany32);
171 valueT
172 md_section_align (segT segment, valueT size)
174 int align = bfd_get_section_alignment (stdoutput, segment);
176 return ((size + (1 << align) - 1) & (-1 << align));
180 /* Functions concerning relocs. */
182 long
183 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
185 abort ();
188 /* Write a value out to the object file, using the appropriate endianness. */
190 void
191 md_number_to_chars (char * buf, valueT val, int n)
193 number_to_chars_littleendian (buf, val, n);
197 epiphany_elf_section_flags (int flags,
198 int attr ATTRIBUTE_UNUSED,
199 int type ATTRIBUTE_UNUSED)
201 /* This is used to detect when the section changes to an executable section.
202 This function is called by the elf section processing. When we note an
203 executable section specifier we set an internal flag to denote when
204 word alignment should be forced. */
205 if (flags & SEC_CODE)
206 force_code_align = TRUE;
208 return flags;
211 /* Non-zero if we are generating PIC code. */
212 int pic_code;
214 /* Epiphany er_flags. */
215 static int epiphany_flags = 0;
217 /* Relocations against symbols are done in two
218 parts, with a HI relocation and a LO relocation. Each relocation
219 has only 16 bits of space to store an addend. This means that in
220 order for the linker to handle carries correctly, it must be able
221 to locate both the HI and the LO relocation. This means that the
222 relocations must appear in order in the relocation table.
224 In order to implement this, we keep track of each unmatched HI
225 relocation. We then sort them so that they immediately precede the
226 corresponding LO relocation. */
228 struct epiphany_hi_fixup
230 /* Next HI fixup. */
231 struct epiphany_hi_fixup *next;
233 /* This fixup. */
234 fixS *fixp;
236 /* The section this fixup is in. */
237 segT seg;
241 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
242 static symbolS * GOT_symbol;
244 static inline bfd_boolean
245 epiphany_PIC_related_p (symbolS *sym)
247 expressionS *exp;
249 if (! sym)
250 return FALSE;
252 if (sym == GOT_symbol)
253 return TRUE;
255 exp = symbol_get_value_expression (sym);
257 return (exp->X_op == O_PIC_reloc
258 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM24
259 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM8
260 || epiphany_PIC_related_p (exp->X_add_symbol)
261 || epiphany_PIC_related_p (exp->X_op_symbol));
264 /* Perform target dependent relocations that are done at compile time.
265 There aren't very many of these. */
267 void
268 epiphany_apply_fix (fixS *fixP, valueT *valP, segT seg)
270 if (fixP->fx_addsy == (symbolS *) NULL)
271 fixP->fx_done = 1;
273 if (((int) fixP->fx_r_type < (int) BFD_RELOC_UNUSED)
274 && fixP->fx_done)
276 /* Install EPIPHANY-dependent relocations HERE because nobody else
277 will. */
278 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
279 unsigned char *insn = (unsigned char *)where;
280 valueT value = * valP;
282 switch (fixP->fx_r_type)
284 default:
285 break;
287 case BFD_RELOC_NONE:
288 return;
290 case BFD_RELOC_EPIPHANY_SIMM11:
291 where[0] = where[0] | ((value & 1) << 7);
292 where[1] = where[1] | ((value & 6) >> 1);
293 where[2] = (value >> 3) & 0xff;
294 return;
296 case BFD_RELOC_EPIPHANY_IMM11:
297 where[0] = where[0] | ((value & 1) << 7);
298 where[1] = where[1] | ((value & 6) >> 1);
299 where[2] = (value >> 3) & 0xff;
300 return;
302 case BFD_RELOC_EPIPHANY_SIMM8:
303 md_number_to_chars (where+1, value>>1, 1);
304 return;
306 case BFD_RELOC_EPIPHANY_SIMM24:
307 md_number_to_chars (where+1, value>>1, 3);
308 return;
310 case BFD_RELOC_EPIPHANY_HIGH:
311 value >>= 16;
312 /* fall thru */
313 case BFD_RELOC_EPIPHANY_LOW:
314 value = (((value & 0xff) << 5) | insn[0])
315 | (insn[1] << 8)
316 | ((value & 0xff00) << 12)
317 | (insn[2] << 16);
318 md_number_to_chars (where, value, 3);
319 return;
323 /* Just do the default if we can't special case. */
324 return gas_cgen_md_apply_fix (fixP, valP, seg);
328 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
329 of an rs_align_code fragment. 0x01a2 is 16-bit pattern for a "nop". */
331 static const unsigned char nop_pattern[] = { 0xa2, 0x01 };
333 void
334 epiphany_handle_align (fragS *fragp)
336 int bytes, fix;
337 char *p;
339 if (fragp->fr_type != rs_align_code)
340 return;
342 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
343 p = fragp->fr_literal + fragp->fr_fix;
344 fix = 0;
346 if (bytes & 1)
348 fix = 1;
349 *p++ = 0;
350 bytes--;
353 if (bytes & 2)
355 memcpy (p, nop_pattern, 2);
356 p += 2;
357 bytes -= 2;
358 fix += 2;
360 fragp->fr_fix += fix;
363 /* Read a comma separated incrementing list of register names
364 and form a bit mask of upto 15 registers 0..14. */
366 static const char *
367 parse_reglist (const char * s, int * mask)
369 int regmask = 0;
371 while (*s)
373 long value;
375 while (*s == ' ')
376 ++s;
378 /* Parse a list with "," or "}" as limiters. */
379 const char *errmsg
380 = cgen_parse_keyword (gas_cgen_cpu_desc, &s,
381 &epiphany_cgen_opval_gr_names, &value);
382 if (errmsg)
383 return errmsg;
385 if (value > 15)
386 return _("register number too large for push/pop");
388 regmask |= 1 << value;
389 if (regmask < *mask)
390 return _("register is out of order");
391 *mask |= regmask;
393 while (*s==' ')
394 ++s;
396 if (*s == '}')
397 return NULL;
398 else if (*s++ == ',')
399 continue;
400 else
401 return _("bad register list");
404 return _("malformed reglist in push/pop");
408 void
409 md_assemble (char *str)
411 epiphany_insn insn;
412 char *errmsg = 0;
413 const char * pperr = 0;
414 int regmask=0, push=0, pop=0;
416 memset (&insn, 0, sizeof (insn));
418 /* Special-case push/pop instruction macros. */
419 if (0 == strncmp (str, "push {", 6))
421 char * s = str + 6;
422 push = 1;
423 pperr = parse_reglist (s, &regmask);
425 else if (0 == strncmp (str, "pop {", 5))
427 char * s = str + 5;
428 pop = 1;
429 pperr = parse_reglist (s, &regmask);
432 if (pperr)
434 as_bad ("%s", pperr);
435 return;
438 if (push && regmask)
440 char buff[20];
441 int i,p ATTRIBUTE_UNUSED;
443 md_assemble ("mov r15,4");
444 md_assemble ("sub sp,sp,r15");
446 for (i = 0, p = 1; i <= 15; ++i, regmask >>= 1)
448 if (regmask == 1)
449 sprintf (buff, "str r%d,[sp]", i); /* Last one. */
450 else if (regmask & 1)
451 sprintf (buff, "str r%d,[sp],-r15", i);
452 else
453 continue;
454 md_assemble (buff);
456 return;
458 else if (pop && regmask)
460 char buff[20];
461 int i,p;
463 md_assemble ("mov r15,4");
465 for (i = 15, p = 1 << 15; i >= 0; --i, p >>= 1)
466 if (regmask & p)
468 sprintf (buff, "ldr r%d,[sp],+r15", i);
469 md_assemble (buff);
471 return;
474 /* Initialize GAS's cgen interface for a new instruction. */
475 gas_cgen_init_parse ();
477 insn.insn = epiphany_cgen_assemble_insn
478 (gas_cgen_cpu_desc, str, &insn.fields, insn.buffer, & errmsg);
480 if (!insn.insn)
482 as_bad ("%s", errmsg);
483 return;
486 if (CGEN_INSN_BITSIZE (insn.insn) == 32)
488 /* Doesn't really matter what we pass for RELAX_P here. */
489 gas_cgen_finish_insn (insn.insn, insn.buffer,
490 CGEN_FIELDS_BITSIZE (&insn.fields), 1, NULL);
492 else
494 if (CGEN_INSN_BITSIZE (insn.insn) != 16)
495 abort ();
497 insn.orig_insn = insn.insn;
499 gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
500 CGEN_FIELDS_BITSIZE (&insn.fields),
501 1 /* relax_p */, NULL);
504 /* Checks for behavioral restrictions on LD/ST instructions. */
505 #define DISPMOD _("destination register modified by displacement-post-modified address")
506 #define LDSTODD _("ldrd/strd requires even:odd register pair")
508 /* Helper macros for spliting apart instruction fields. */
509 #define ADDR_POST_MODIFIED(i) (((i) >> 25) & 0x1)
510 #define ADDR_SIZE(i) (((i) >> 5) & 3)
511 #define ADDR_LOADSTORE(i) (((i) >> 4) & 0x1)
513 switch (insn.buffer[0] & 0xf)
515 /* Post-modify registers cannot be destinations. */
516 case OP4_LDSTR16P:
518 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD)
519 if (insn.fields.f_rd == insn.fields.f_rn /* Postmodify dest. */
520 || (insn.fields.f_rd+1 == insn.fields.f_rn
521 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
523 as_bad ("%s", DISPMOD);
524 return;
526 if ((insn.fields.f_rd & 1) /* Odd-numbered register... */
527 && insn.fields.f_wordsize == OPW_DOUBLE) /* ...and 64 bit transfer. */
529 as_bad ("%s", LDSTODD);
530 return;
532 break;
535 case OP4_LDSTRP:
537 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD) /* A load. */
538 if (insn.fields.f_rd6 == insn.fields.f_rn6 /* Postmodify dest. */
539 /* Check for regpair postindexed. */
540 || (insn.fields.f_rd6 + 1 == insn.fields.f_rn6
541 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
543 as_bad ("%s", DISPMOD);
544 return;
546 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
547 /* Lsb of RD odd and 64 bit transfer. */
549 as_bad ("%s", LDSTODD);
550 return;
552 break;
555 case OP4_LDSTR16X:
556 case OP4_LDSTR16D:
558 /* Check for unaligned load/store double. */
559 if ((insn.fields.f_rd & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
560 /* Lsb of RD odd and 64 bit transfer. */
562 as_bad ("%s", LDSTODD);
563 return;
565 break;
568 case OP4_LDSTRD:
570 /* Check for load to post-modified register. */
571 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD /* A load. */
572 && ADDR_POST_MODIFIED (insn.buffer[0]) == PMOD_POST /* Post-mod. */
573 && (insn.fields.f_rd6 == insn.fields.f_rn6
574 || (insn.fields.f_rd6+1 == insn.fields.f_rn6
575 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)))
577 as_bad ("%s", DISPMOD);
578 return;
581 /* fall-thru. */
583 case OP4_LDSTRX:
585 /* Check for unaligned load/store double. */
586 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
588 as_bad ("%s", LDSTODD);
589 return;
591 break;
594 default:
595 break;
599 /* The syntax in the manual says constants begin with '#'.
600 We just ignore it. */
602 void
603 md_operand (expressionS *expressionP)
605 if (*input_line_pointer == '#')
607 input_line_pointer++;
608 expression (expressionP);
612 symbolS *
613 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
615 return NULL;
618 /* Interface to relax_segment. */
620 /* FIXME: Build table by hand, get it working, then machine generate. */
622 const relax_typeS md_relax_table[] =
624 /* The fields are:
625 1) most positive reach of this state,
626 2) most negative reach of this state,
627 3) how many bytes this mode will add to the size of the current frag
628 4) which index into the table to try if we can't fit into this one. */
630 /* The first entry must be unused because an `rlx_more' value of zero ends
631 each list. */
632 {1, 1, 0, EPIPHANY_RELAX_NONE},
633 {0, 0, 0, EPIPHANY_RELAX_NONE}, /* Also a dummy entry to indicate we need to expand codes. */
635 /* The displacement used by GAS is from the end of the 2 byte insn,
636 so we subtract 2 from the following. */
637 /* 16 bit insn, 8 bit disp -> +127 words, -128 words. */
638 {0x00000100 - 1 - 2, -0x00000100 - 2, 0, EPIPHANY_RELAX_BRANCH_LONG },
639 /* 32 bit insn, 24 bit disp -> 25 bit range. */
640 {0x01000000 - 1 - 2, -0x01000000 - 2, 2, EPIPHANY_RELAX_NONE },
642 /* addi/subi 3 bits -4..+3. */
643 { 3, -4,0, EPIPHANY_RELAX_ARITH_SIMM11 },
644 /* addi/subi 11 bits. */
645 { 1023, -1024,2, EPIPHANY_RELAX_NONE },
647 /* mov r,imm8. */
648 { 255, 0,0, EPIPHANY_RELAX_MOV_IMM16 },
649 /* mov r,imm16. */
650 { 65535, 0,2, EPIPHANY_RELAX_NONE },
652 /* ld/st rd,[rn,imm3]. */
653 { 7, 0,0, EPIPHANY_RELAX_LDST_IMM11},
654 /* ld/st rd,[rn,imm11]. */
655 { 2047, 0,2, EPIPHANY_RELAX_NONE }
659 static const EPIPHANY_RELAX_TYPES relax_insn[] =
661 EPIPHANY_RELAX_BRANCH_SHORT, /* OP4_BRANCH16 */
662 EPIPHANY_RELAX_NONE, /* OP4_LDSTR16X */
663 EPIPHANY_RELAX_NONE, /* OP4_FLOW16 */
664 EPIPHANY_RELAX_ARITH_SIMM3, /* OP4_IMM16 - special */
665 EPIPHANY_RELAX_LDST_IMM3, /* OP4_LDSTR16D */
666 EPIPHANY_RELAX_NONE, /* OP4_LDSTR126P */
667 EPIPHANY_RELAX_NONE, /* OP4_LSHIFT16 */
668 EPIPHANY_RELAX_NONE, /* OP4_DSP16 */
669 EPIPHANY_RELAX_BRANCH_LONG, /* OP4_BRANCH */
670 EPIPHANY_RELAX_NONE, /* OP4_LDSTRX */
671 EPIPHANY_RELAX_NONE, /* OP4_ALU16 */
672 EPIPHANY_RELAX_ARITH_SIMM11, /* OP4_IMM32 - special */
673 EPIPHANY_RELAX_LDST_IMM11, /* OP4_LDSTRD */
674 EPIPHANY_RELAX_NONE, /* OP4_LDSTRP */
675 EPIPHANY_RELAX_NONE, /* OP4_ASHIFT16 */
676 EPIPHANY_RELAX_NONE /* OP4_MISC */
679 long
680 epiphany_relax_frag (segT segment, fragS *fragP, long stretch)
682 /* Address of branch insn. */
683 long address ATTRIBUTE_UNUSED = fragP->fr_address + fragP->fr_fix - 2;
684 long growth = 0;
686 if (fragP->fr_subtype == EPIPHANY_RELAX_NEED_RELAXING)
688 EPIPHANY_RELAX_TYPES subtype = relax_insn [*fragP->fr_opcode & 0xf];
690 /* Special cases add/sub vs mov immediates. */
691 if (subtype == EPIPHANY_RELAX_ARITH_SIMM3)
693 if ((*fragP->fr_opcode & 0x10) == 0)
694 subtype = EPIPHANY_RELAX_MOV_IMM8;
696 else if (subtype == EPIPHANY_RELAX_ARITH_SIMM11)
698 if ((*fragP->fr_opcode & 0x10) == 0)
699 subtype = EPIPHANY_RELAX_MOV_IMM16;
702 /* Remember refinements for the future. */
703 fragP->fr_subtype = subtype;
706 growth = relax_frag (segment, fragP, stretch);
708 return growth;
711 /* Return an initial guess of the length by which a fragment must grow to
712 hold a branch to reach its destination.
713 Also updates fr_type/fr_subtype as necessary.
715 Called just before doing relaxation.
716 Any symbol that is now undefined will not become defined.
717 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
718 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
719 Although it may not be explicit in the frag, pretend fr_var starts
720 with a 0 value. */
723 md_estimate_size_before_relax (fragS *fragP, segT segment)
725 /* The only thing we have to handle here are symbols outside of the
726 current segment. They may be undefined or in a different segment in
727 which case linker scripts may place them anywhere.
728 However, we can't finish the fragment here and emit the reloc as insn
729 alignment requirements may move the insn about. */
730 if (S_GET_SEGMENT (fragP->fr_symbol) != segment
731 || S_IS_EXTERNAL (fragP->fr_symbol)
732 || S_IS_WEAK (fragP->fr_symbol))
734 /* The symbol is undefined in this segment. Change the
735 relaxation subtype to the max allowable and leave all further
736 handling to md_convert_frag. */
738 EPIPHANY_RELAX_TYPES subtype;
739 /* We haven't relaxed this at all, so the relaxation type may be
740 completely wrong. Set the subtype correctly. */
741 epiphany_relax_frag (segment, fragP, 0);
742 subtype = fragP->fr_subtype;
744 switch (subtype)
746 case EPIPHANY_RELAX_LDST_IMM3:
747 subtype = EPIPHANY_RELAX_LDST_IMM11;
748 break;
749 case EPIPHANY_RELAX_BRANCH_SHORT:
750 subtype = EPIPHANY_RELAX_BRANCH_LONG;
751 break;
752 case EPIPHANY_RELAX_MOV_IMM8:
753 subtype = EPIPHANY_RELAX_MOV_IMM16;
754 break;
755 case EPIPHANY_RELAX_ARITH_SIMM3:
756 subtype = EPIPHANY_RELAX_ARITH_SIMM11;
757 break;
759 default:
760 break;
763 fragP->fr_subtype = subtype;
766 const CGEN_INSN *insn;
767 int i;
769 /* Update the recorded insn. */
771 for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
773 if ((strcmp (CGEN_INSN_MNEMONIC (insn),
774 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
775 == 0)
776 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
777 break;
780 if (i == 4)
781 abort ();
783 fragP->fr_cgen.insn = insn;
787 return md_relax_table[fragP->fr_subtype].rlx_length;
790 /* *FRAGP has been relaxed to its final size, and now needs to have
791 the bytes inside it modified to conform to the new size.
793 Called after relaxation is finished.
794 fragP->fr_type == rs_machine_dependent.
795 fragP->fr_subtype is the subtype of what the address relaxed to. */
797 void
798 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
799 segT sec,
800 fragS *fragP)
802 char *opcode;
803 char *displacement;
804 int target_address;
805 int opcode_address;
806 int extension;
807 int addend;
808 int opindx = -1;
810 opcode = fragP->fr_opcode;
812 /* Address opcode resides at in file space. */
813 opcode_address = fragP->fr_address + fragP->fr_fix - 2;
814 extension = 0;
815 displacement = &opcode[1];
817 /* Set up any addend necessary for branches. */
818 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
819 || S_IS_EXTERNAL (fragP->fr_symbol)
820 || S_IS_WEAK (fragP->fr_symbol))
822 /* Symbol must be resolved by linker. */
823 if (fragP->fr_offset & 1)
824 as_warn (_("Addend to unresolved symbol not on word boundary."));
825 addend = 0;
827 else
829 /* Address we want to reach in file space. */
830 target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
831 addend = (target_address - (opcode_address & -2));
834 /* Do all the housekeeping for frag conversions. */
835 switch (fragP->fr_subtype)
837 case EPIPHANY_RELAX_ARITH_SIMM11:
838 *opcode |= OP4_IMM32;
839 displacement = &opcode[0];
840 extension += 3;
842 addend
843 = (((addend & 0x7) << 7)
844 | opcode[0]
845 | ((addend & 0x7f8) << 13)
846 | (opcode[1] << 8)
847 | (opcode[2] << 16));
849 opindx = EPIPHANY_OPERAND_SIMM11;
850 break;
852 case EPIPHANY_RELAX_BRANCH_LONG:
853 /* Branches differ only in low nibble of instruction being 8 not 0.
854 24 bit displacement goes to bytes 1..3 . */
855 *opcode |= OP4_BRANCH;
856 extension += 2;
858 addend >>= 1; /* Convert to word offset. */
859 opindx = EPIPHANY_OPERAND_SIMM24;
860 break;
862 case EPIPHANY_RELAX_MOV_IMM16:
863 *opcode |= OP4_IMM32;
864 extension += 3;
866 addend
867 = (((addend & 0xff00) << 12)
868 | (opcode[2] << 16)
869 | ((addend & 0x00ff) << 5)
870 | (opcode[1] << 8)
871 | opcode[0]);
872 displacement = &opcode[0];
873 opindx = EPIPHANY_OPERAND_IMM16;
874 break;
876 case EPIPHANY_RELAX_LDST_IMM11:
877 *opcode |= OP4_LDSTRD;
878 displacement = &opcode[0];
879 extension += 3;
881 if (addend < 0)
882 /* Convert twos-complement address value to sign-magnitude. */
883 addend = (-addend & 0x7ff) | 0x800;
885 addend
886 = (((addend & 0x7) << 5)
887 | opcode[0]
888 | ((addend & 0xff8) << 13)
889 | (opcode[1] << 8)
890 | (opcode[2] << 16));
892 opindx = EPIPHANY_OPERAND_DISP11;
893 break;
895 case EPIPHANY_RELAX_ARITH_SIMM3:
896 addend = ((addend & 7) << 5) | opcode[0];
897 opindx = EPIPHANY_OPERAND_SIMM3;
898 break;
900 case EPIPHANY_RELAX_LDST_IMM3:
901 addend = ((addend & 7) << 5) | opcode[0];
902 opindx = EPIPHANY_OPERAND_DISP3;
904 case EPIPHANY_RELAX_BRANCH_SHORT:
905 addend >>= 1; /* Convert to a word offset. */
906 displacement = & opcode[1];
907 opindx = EPIPHANY_OPERAND_SIMM8;
908 break;
910 case EPIPHANY_RELAX_MOV_IMM8:
911 addend
912 = (((addend & 0xff) << 5)
913 | opcode[0]
914 | (opcode[1] << 8));
915 opindx = EPIPHANY_OPERAND_IMM8;
916 break;
918 case EPIPHANY_RELAX_NONE:
919 case EPIPHANY_RELAX_NEED_RELAXING:
920 default: /* Anything else? */
921 as_bad ("unrecognized fragment subtype");
922 break;
925 /* Create a relocation for symbols that must be resolved by the linker.
926 Otherwise output the completed insn. */
928 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
929 || S_IS_EXTERNAL (fragP->fr_symbol)
930 || S_IS_WEAK (fragP->fr_symbol))
932 fixS *fixP;
933 const CGEN_OPERAND *operand
934 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx);
935 bfd_reloc_code_real_type reloc_type;
937 gas_assert (fragP->fr_cgen.insn != 0);
939 reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL);
941 fixP = gas_cgen_record_fixup (fragP,
942 /* Offset of insn in frag. */
943 (opcode - fragP->fr_literal),
944 fragP->fr_cgen.insn,
945 CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8,
946 operand,
947 reloc_type,
948 fragP->fr_symbol, fragP->fr_offset);
949 fixP->fx_r_type = fixP->fx_cgen.opinfo;
952 md_number_to_chars (displacement, (valueT) addend, extension + 1);
954 fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added. */
958 /* Functions concerning relocs. */
960 /* The location from which a PC relative jump should be calculated,
961 given a PC relative reloc. */
963 long
964 md_pcrel_from_section (fixS *fixP, segT sec)
966 if (fixP->fx_addsy != (symbolS *) NULL
967 && (!S_IS_DEFINED (fixP->fx_addsy)
968 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
969 || S_IS_EXTERNAL (fixP->fx_addsy)
970 || S_IS_WEAK (fixP->fx_addsy)))
971 return 0;
973 return fixP->fx_frag->fr_address + fixP->fx_where;
976 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
977 Returns BFD_RELOC_NONE if no reloc type can be found.
978 *FIXP may be modified if desired. */
980 bfd_reloc_code_real_type
981 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
982 const CGEN_OPERAND *operand,
983 fixS *fixP ATTRIBUTE_UNUSED)
985 switch (operand->type)
987 case EPIPHANY_OPERAND_SIMM11:
988 return BFD_RELOC_EPIPHANY_SIMM11;
989 case EPIPHANY_OPERAND_DISP11:
990 return BFD_RELOC_EPIPHANY_IMM11;
992 case EPIPHANY_OPERAND_SIMM8:
993 return BFD_RELOC_EPIPHANY_SIMM8;
994 case EPIPHANY_OPERAND_SIMM24:
995 return BFD_RELOC_EPIPHANY_SIMM24;
997 case EPIPHANY_OPERAND_IMM8:
998 return BFD_RELOC_EPIPHANY_IMM8;
1000 case EPIPHANY_OPERAND_IMM16:
1001 if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn)))
1002 return BFD_RELOC_EPIPHANY_HIGH;
1003 else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn)))
1004 return BFD_RELOC_EPIPHANY_LOW;
1005 else
1006 as_bad ("unknown imm16 operand");
1007 /* fall-thru */
1009 default:
1010 break;
1012 return BFD_RELOC_NONE;
1016 /* Turn a string in input_line_pointer into a floating point constant
1017 of type TYPE, and store the appropriate bytes in *LITP. The number
1018 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1019 returned, or NULL on OK. */
1021 /* Equal to MAX_PRECISION in atof-ieee.c. */
1022 #define MAX_LITTLENUMS 6
1024 char *
1025 md_atof (int type, char *litP, int *sizeP)
1027 return ieee_md_atof (type, litP, sizeP, FALSE);
1030 /* Return true if can adjust the reloc to be relative to its section
1031 (such as .data) instead of relative to some symbol. */
1033 bfd_boolean
1034 epiphany_fix_adjustable (fixS *fixP)
1036 bfd_reloc_code_real_type reloc_type;
1038 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1040 const CGEN_INSN *insn = fixP->fx_cgen.insn;
1041 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1042 const CGEN_OPERAND *operand =
1043 cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindex);
1045 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1047 else
1048 reloc_type = fixP->fx_r_type;
1050 if (fixP->fx_addsy == NULL)
1051 return TRUE;
1053 /* Prevent all adjustments to global symbols. */
1054 if (S_IS_EXTERNAL (fixP->fx_addsy))
1055 return FALSE;
1057 if (S_IS_WEAK (fixP->fx_addsy))
1058 return FALSE;
1060 if (pic_code
1061 && (reloc_type == BFD_RELOC_EPIPHANY_SIMM24
1062 || reloc_type == BFD_RELOC_EPIPHANY_SIMM8
1063 || reloc_type == BFD_RELOC_EPIPHANY_HIGH
1064 || reloc_type == BFD_RELOC_EPIPHANY_LOW))
1065 return FALSE;
1067 /* Since we don't use partial_inplace, we must not reduce symbols in
1068 mergable sections to their section symbol. */
1069 if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
1070 return FALSE;
1072 return TRUE;
1075 void
1076 epiphany_elf_final_processing (void)
1078 elf_elfheader (stdoutput)->e_flags |= epiphany_flags;
1082 epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED)
1084 LITTLENUM_TYPE words[2];
1086 switch (opinfo)
1088 case BFD_RELOC_EPIPHANY_LOW:
1089 case BFD_RELOC_EPIPHANY_HIGH:
1090 break;
1091 default:
1092 return opinfo;
1095 /* Doing a %LOW or %HIGH. */
1096 switch (exp->X_op)
1098 default:
1099 return opinfo;
1100 case O_big: /* Bignum. */
1101 if (exp->X_add_number > 0) /* Integer value too large. */
1102 return opinfo;
1105 /* Convert to SP number. */
1106 gen_to_words (words, 2, 8L);
1107 exp->X_add_number = words[1] | (words[0] << 16);
1108 exp->X_op = O_constant;
1109 return opinfo;