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)
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. */
25 #include "opcodes/epiphany-desc.h"
26 #include "opcodes/epiphany-opc.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. */
36 const CGEN_INSN
* insn
;
37 const CGEN_INSN
* orig_insn
;
40 CGEN_INSN_INT buffer
[1];
41 #define INSN_VALUE(buf) (*(buf))
43 unsigned char buffer
[CGEN_MAX_INSN_SIZE
];
44 #define INSN_VALUE(buf) (buf)
49 fixS
* fixups
[GAS_CGEN_MAX_FIXUPS
];
50 int indices
[MAX_OPERAND_INSTANCES
];
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
62 static bfd_boolean force_code_align
= FALSE
;
65 epiphany_elf_section_rtn (int i
)
71 do_align (1, NULL
, 0, 0);
72 force_code_align
= FALSE
;
77 epiphany_elf_section_text (int 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. */
92 { "cpu", s_ignore
, 0 },
93 { "thumb_func", s_ignore
, 0 },
94 { "code", s_ignore
, 0 },
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. */
124 md_show_usage (FILE * stream
)
126 fprintf (stream
, _("EPIPHANY specific command line options:\n"));
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
,
138 CGEN_CPU_OPEN_ENDIAN
,
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
);
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. */
162 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
167 /* Write a value out to the object file, using the appropriate endianness. */
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
;
190 /* Non-zero if we are generating 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
210 struct epiphany_hi_fixup
*next
;
215 /* The section this fixup is in. */
220 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
221 static symbolS
* GOT_symbol
;
223 static inline bfd_boolean
224 epiphany_PIC_related_p (symbolS
*sym
)
231 if (sym
== GOT_symbol
)
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. */
247 epiphany_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg
)
249 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
252 if (((int) fixP
->fx_r_type
< (int) BFD_RELOC_UNUSED
)
255 /* Install EPIPHANY-dependent relocations HERE because nobody else
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
)
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;
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;
281 case BFD_RELOC_EPIPHANY_SIMM8
:
282 md_number_to_chars (where
+1, value
>>1, 1);
285 case BFD_RELOC_EPIPHANY_SIMM24
:
286 md_number_to_chars (where
+1, value
>>1, 3);
289 case BFD_RELOC_EPIPHANY_HIGH
:
292 case BFD_RELOC_EPIPHANY_LOW
:
293 value
= (((value
& 0xff) << 5) | insn
[0])
295 | ((value
& 0xff00) << 12)
297 md_number_to_chars (where
, value
, 3);
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 };
313 epiphany_handle_align (fragS
*fragp
)
318 if (fragp
->fr_type
!= rs_align_code
)
321 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
322 p
= fragp
->fr_literal
+ fragp
->fr_fix
;
334 memcpy (p
, nop_pattern
, 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. */
346 parse_reglist (const char * s
, int * mask
)
357 /* Parse a list with "," or "}" as limiters. */
359 = cgen_parse_keyword (gas_cgen_cpu_desc
, &s
,
360 &epiphany_cgen_opval_gr_names
, &value
);
365 return _("register number too large for push/pop");
367 regmask
|= 1 << value
;
369 return _("register is out of order");
377 else if (*s
++ == ',')
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. */
391 epiphany_assemble (const char *str
)
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
);
406 as_bad ("%s", errmsg
);
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
);
418 if (CGEN_INSN_BITSIZE (insn
.insn
) != 16)
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. */
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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))
534 pperr
= parse_reglist (s
, ®mask
);
536 else if (0 == strncmp (str
, "pop {", 5))
540 pperr
= parse_reglist (s
, ®mask
);
545 as_bad ("%s", pperr
);
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)
560 sprintf (buff
, "str r%d,[sp]", i
); /* Last one. */
561 else if (regmask
& 1)
562 sprintf (buff
, "str r%d,[sp],-r15", i
);
565 epiphany_assemble (buff
);
569 else if (pop
&& regmask
)
574 epiphany_assemble ("mov r15,4");
576 for (i
= 15, p
= 1 << 15; i
>= 0; --i
, p
>>= 1)
579 sprintf (buff
, "ldr r%d,[sp],+r15", i
);
580 epiphany_assemble (buff
);
585 epiphany_assemble (str
);
588 /* The syntax in the manual says constants begin with '#'.
589 We just ignore it. */
592 md_operand (expressionS
*expressionP
)
594 if (*input_line_pointer
== '#')
596 input_line_pointer
++;
597 expression (expressionP
);
602 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
607 /* Interface to relax_segment. */
609 /* FIXME: Build table by hand, get it working, then machine generate. */
611 const relax_typeS md_relax_table
[] =
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
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
},
637 { 255, 0,0, EPIPHANY_RELAX_MOV_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 */
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;
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
);
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
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
;
735 case EPIPHANY_RELAX_LDST_IMM3
:
736 subtype
= EPIPHANY_RELAX_LDST_IMM11
;
738 case EPIPHANY_RELAX_BRANCH_SHORT
:
739 subtype
= EPIPHANY_RELAX_BRANCH_LONG
;
741 case EPIPHANY_RELAX_MOV_IMM8
:
742 subtype
= EPIPHANY_RELAX_MOV_IMM16
;
744 case EPIPHANY_RELAX_ARITH_SIMM3
:
745 subtype
= EPIPHANY_RELAX_ARITH_SIMM11
;
752 fragP
->fr_subtype
= subtype
;
755 const CGEN_INSN
*insn
;
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
))
765 && CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_RELAXED
))
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. */
787 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
799 opcode
= fragP
->fr_opcode
;
801 /* Address opcode resides at in file space. */
802 opcode_address
= fragP
->fr_address
+ fragP
->fr_fix
- 2;
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."));
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];
832 = (((addend
& 0x7) << 7)
834 | ((addend
& 0x7f8) << 13)
836 | (opcode
[2] << 16));
838 opindx
= EPIPHANY_OPERAND_SIMM11
;
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
;
847 addend
>>= 1; /* Convert to word offset. */
848 opindx
= EPIPHANY_OPERAND_SIMM24
;
851 case EPIPHANY_RELAX_MOV_IMM16
:
852 *opcode
|= OP4_IMM32
;
856 = (((addend
& 0xff00) << 12)
858 | ((addend
& 0x00ff) << 5)
861 displacement
= &opcode
[0];
862 opindx
= EPIPHANY_OPERAND_IMM16
;
865 case EPIPHANY_RELAX_LDST_IMM11
:
866 *opcode
|= OP4_LDSTRD
;
867 displacement
= &opcode
[0];
871 /* Convert twos-complement address value to sign-magnitude. */
872 addend
= (-addend
& 0x7ff) | 0x800;
875 = (((addend
& 0x7) << 5)
877 | ((addend
& 0xff8) << 13)
879 | (opcode
[2] << 16));
881 opindx
= EPIPHANY_OPERAND_DISP11
;
884 case EPIPHANY_RELAX_ARITH_SIMM3
:
885 addend
= ((addend
& 7) << 5) | opcode
[0];
886 opindx
= EPIPHANY_OPERAND_SIMM3
;
889 case EPIPHANY_RELAX_LDST_IMM3
:
890 addend
= ((addend
& 7) << 5) | opcode
[0];
891 opindx
= EPIPHANY_OPERAND_DISP3
;
894 case EPIPHANY_RELAX_BRANCH_SHORT
:
895 addend
>>= 1; /* Convert to a word offset. */
896 displacement
= & opcode
[1];
897 opindx
= EPIPHANY_OPERAND_SIMM8
;
900 case EPIPHANY_RELAX_MOV_IMM8
:
902 = (((addend
& 0xff) << 5)
905 opindx
= EPIPHANY_OPERAND_IMM8
;
908 case EPIPHANY_RELAX_NONE
:
909 case EPIPHANY_RELAX_NEED_RELAXING
:
910 default: /* Anything else? */
911 as_bad ("unrecognized fragment subtype");
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
))
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
),
935 CGEN_INSN_BITSIZE (fragP
->fr_cgen
.insn
) / 8,
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. */
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
)))
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
;
996 as_bad ("unknown imm16 operand");
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. */
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. */
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
);
1035 reloc_type
= fixP
->fx_r_type
;
1037 if (fixP
->fx_addsy
== NULL
)
1040 /* Prevent all adjustments to global symbols. */
1041 if (S_IS_EXTERNAL (fixP
->fx_addsy
))
1044 if (S_IS_WEAK (fixP
->fx_addsy
))
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
))
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)
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];
1075 case BFD_RELOC_EPIPHANY_LOW
:
1076 case BFD_RELOC_EPIPHANY_HIGH
:
1082 /* Doing a %LOW or %HIGH. */
1087 case O_big
: /* Bignum. */
1088 if (exp
->X_add_number
> 0) /* Integer value too large. */
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
;