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
);
149 literal_prefix_dollar_hex
= TRUE
;
153 md_section_align (segT segment
, valueT size
)
155 int align
= bfd_get_section_alignment (stdoutput
, segment
);
157 return ((size
+ (1 << align
) - 1) & -(1 << align
));
161 /* Functions concerning relocs. */
164 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
169 /* Write a value out to the object file, using the appropriate endianness. */
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
;
192 /* Non-zero if we are generating 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
212 struct epiphany_hi_fixup
*next
;
217 /* The section this fixup is in. */
222 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
223 static symbolS
* GOT_symbol
;
225 static inline bfd_boolean
226 epiphany_PIC_related_p (symbolS
*sym
)
233 if (sym
== GOT_symbol
)
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. */
249 epiphany_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg
)
251 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
254 if (((int) fixP
->fx_r_type
< (int) BFD_RELOC_UNUSED
)
257 /* Install EPIPHANY-dependent relocations HERE because nobody else
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
)
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;
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;
283 case BFD_RELOC_EPIPHANY_SIMM8
:
284 md_number_to_chars (where
+1, value
>>1, 1);
287 case BFD_RELOC_EPIPHANY_SIMM24
:
288 md_number_to_chars (where
+1, value
>>1, 3);
291 case BFD_RELOC_EPIPHANY_HIGH
:
294 case BFD_RELOC_EPIPHANY_LOW
:
295 value
= (((value
& 0xff) << 5) | insn
[0])
297 | ((value
& 0xff00) << 12)
299 md_number_to_chars (where
, value
, 3);
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 };
315 epiphany_handle_align (fragS
*fragp
)
320 if (fragp
->fr_type
!= rs_align_code
)
323 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
324 p
= fragp
->fr_literal
+ fragp
->fr_fix
;
336 memcpy (p
, nop_pattern
, 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. */
348 parse_reglist (const char * s
, int * mask
)
359 /* Parse a list with "," or "}" as limiters. */
361 = cgen_parse_keyword (gas_cgen_cpu_desc
, &s
,
362 &epiphany_cgen_opval_gr_names
, &value
);
367 return _("register number too large for push/pop");
369 regmask
|= 1 << value
;
371 return _("register is out of order");
379 else if (*s
++ == ',')
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. */
393 epiphany_assemble (const char *str
)
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
);
408 as_bad ("%s", errmsg
);
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
);
420 if (CGEN_INSN_BITSIZE (insn
.insn
) != 16)
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. */
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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 (0 == strncmp (str
, "push {", 6))
536 pperr
= parse_reglist (s
, ®mask
);
538 else if (0 == strncmp (str
, "pop {", 5))
542 pperr
= parse_reglist (s
, ®mask
);
547 as_bad ("%s", pperr
);
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)
562 sprintf (buff
, "str r%d,[sp]", i
); /* Last one. */
563 else if (regmask
& 1)
564 sprintf (buff
, "str r%d,[sp],-r15", i
);
567 epiphany_assemble (buff
);
571 else if (pop
&& regmask
)
576 epiphany_assemble ("mov r15,4");
578 for (i
= 15, p
= 1 << 15; i
>= 0; --i
, p
>>= 1)
581 sprintf (buff
, "ldr r%d,[sp],+r15", i
);
582 epiphany_assemble (buff
);
587 epiphany_assemble (str
);
590 /* The syntax in the manual says constants begin with '#'.
591 We just ignore it. */
594 md_operand (expressionS
*expressionP
)
596 if (*input_line_pointer
== '#')
598 input_line_pointer
++;
599 expression (expressionP
);
604 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
609 /* Interface to relax_segment. */
611 /* FIXME: Build table by hand, get it working, then machine generate. */
613 const relax_typeS md_relax_table
[] =
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
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
},
639 { 255, 0,0, EPIPHANY_RELAX_MOV_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 */
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;
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
);
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
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 /* We haven't relaxed this at all, so the relaxation type may be
731 completely wrong. Set the subtype correctly. */
732 epiphany_relax_frag (segment
, fragP
, 0);
733 subtype
= fragP
->fr_subtype
;
737 case EPIPHANY_RELAX_LDST_IMM3
:
738 subtype
= EPIPHANY_RELAX_LDST_IMM11
;
740 case EPIPHANY_RELAX_BRANCH_SHORT
:
741 subtype
= EPIPHANY_RELAX_BRANCH_LONG
;
743 case EPIPHANY_RELAX_MOV_IMM8
:
744 subtype
= EPIPHANY_RELAX_MOV_IMM16
;
746 case EPIPHANY_RELAX_ARITH_SIMM3
:
747 subtype
= EPIPHANY_RELAX_ARITH_SIMM11
;
754 fragP
->fr_subtype
= subtype
;
757 const CGEN_INSN
*insn
;
760 /* Update the recorded insn. */
762 for (i
= 0, insn
= fragP
->fr_cgen
.insn
; i
< 4; i
++, insn
++)
764 if ((strcmp (CGEN_INSN_MNEMONIC (insn
),
765 CGEN_INSN_MNEMONIC (fragP
->fr_cgen
.insn
))
767 && CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_RELAXED
))
774 fragP
->fr_cgen
.insn
= insn
;
778 return md_relax_table
[fragP
->fr_subtype
].rlx_length
;
781 /* *FRAGP has been relaxed to its final size, and now needs to have
782 the bytes inside it modified to conform to the new size.
784 Called after relaxation is finished.
785 fragP->fr_type == rs_machine_dependent.
786 fragP->fr_subtype is the subtype of what the address relaxed to. */
789 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
801 opcode
= fragP
->fr_opcode
;
803 /* Address opcode resides at in file space. */
804 opcode_address
= fragP
->fr_address
+ fragP
->fr_fix
- 2;
806 displacement
= &opcode
[1];
808 /* Set up any addend necessary for branches. */
809 if (S_GET_SEGMENT (fragP
->fr_symbol
) != sec
810 || S_IS_EXTERNAL (fragP
->fr_symbol
)
811 || S_IS_WEAK (fragP
->fr_symbol
))
813 /* Symbol must be resolved by linker. */
814 if (fragP
->fr_offset
& 1)
815 as_warn (_("Addend to unresolved symbol not on word boundary."));
820 /* Address we want to reach in file space. */
821 target_address
= S_GET_VALUE (fragP
->fr_symbol
) + fragP
->fr_offset
;
822 addend
= (target_address
- (opcode_address
& -2));
825 /* Do all the housekeeping for frag conversions. */
826 switch (fragP
->fr_subtype
)
828 case EPIPHANY_RELAX_ARITH_SIMM11
:
829 *opcode
|= OP4_IMM32
;
830 displacement
= &opcode
[0];
834 = (((addend
& 0x7) << 7)
836 | ((addend
& 0x7f8) << 13)
838 | (opcode
[2] << 16));
840 opindx
= EPIPHANY_OPERAND_SIMM11
;
843 case EPIPHANY_RELAX_BRANCH_LONG
:
844 /* Branches differ only in low nibble of instruction being 8 not 0.
845 24 bit displacement goes to bytes 1..3 . */
846 *opcode
|= OP4_BRANCH
;
849 addend
>>= 1; /* Convert to word offset. */
850 opindx
= EPIPHANY_OPERAND_SIMM24
;
853 case EPIPHANY_RELAX_MOV_IMM16
:
854 *opcode
|= OP4_IMM32
;
858 = (((addend
& 0xff00) << 12)
860 | ((addend
& 0x00ff) << 5)
863 displacement
= &opcode
[0];
864 opindx
= EPIPHANY_OPERAND_IMM16
;
867 case EPIPHANY_RELAX_LDST_IMM11
:
868 *opcode
|= OP4_LDSTRD
;
869 displacement
= &opcode
[0];
873 /* Convert twos-complement address value to sign-magnitude. */
874 addend
= (-addend
& 0x7ff) | 0x800;
877 = (((addend
& 0x7) << 5)
879 | ((addend
& 0xff8) << 13)
881 | (opcode
[2] << 16));
883 opindx
= EPIPHANY_OPERAND_DISP11
;
886 case EPIPHANY_RELAX_ARITH_SIMM3
:
887 addend
= ((addend
& 7) << 5) | opcode
[0];
888 opindx
= EPIPHANY_OPERAND_SIMM3
;
891 case EPIPHANY_RELAX_LDST_IMM3
:
892 addend
= ((addend
& 7) << 5) | opcode
[0];
893 opindx
= EPIPHANY_OPERAND_DISP3
;
896 case EPIPHANY_RELAX_BRANCH_SHORT
:
897 addend
>>= 1; /* Convert to a word offset. */
898 displacement
= & opcode
[1];
899 opindx
= EPIPHANY_OPERAND_SIMM8
;
902 case EPIPHANY_RELAX_MOV_IMM8
:
904 = (((addend
& 0xff) << 5)
907 opindx
= EPIPHANY_OPERAND_IMM8
;
910 case EPIPHANY_RELAX_NONE
:
911 case EPIPHANY_RELAX_NEED_RELAXING
:
912 default: /* Anything else? */
913 as_bad ("unrecognized fragment subtype");
917 /* Create a relocation for symbols that must be resolved by the linker.
918 Otherwise output the completed insn. */
920 if (S_GET_SEGMENT (fragP
->fr_symbol
) != sec
921 || S_IS_EXTERNAL (fragP
->fr_symbol
)
922 || S_IS_WEAK (fragP
->fr_symbol
))
925 const CGEN_OPERAND
*operand
926 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc
, opindx
);
927 bfd_reloc_code_real_type reloc_type
;
929 gas_assert (fragP
->fr_cgen
.insn
!= 0);
931 reloc_type
= md_cgen_lookup_reloc (fragP
->fr_cgen
.insn
, operand
, NULL
);
933 fixP
= gas_cgen_record_fixup (fragP
,
934 /* Offset of insn in frag. */
935 (opcode
- fragP
->fr_literal
),
937 CGEN_INSN_BITSIZE (fragP
->fr_cgen
.insn
) / 8,
940 fragP
->fr_symbol
, fragP
->fr_offset
);
941 fixP
->fx_r_type
= fixP
->fx_cgen
.opinfo
;
944 md_number_to_chars (displacement
, (valueT
) addend
, extension
+ 1);
946 fragP
->fr_fix
+= (extension
& -2); /* 0,2 or 4 bytes added. */
950 /* Functions concerning relocs. */
952 /* The location from which a PC relative jump should be calculated,
953 given a PC relative reloc. */
956 md_pcrel_from_section (fixS
*fixP
, segT sec
)
958 if (fixP
->fx_addsy
!= (symbolS
*) NULL
959 && (!S_IS_DEFINED (fixP
->fx_addsy
)
960 || (S_GET_SEGMENT (fixP
->fx_addsy
) != sec
)
961 || S_IS_EXTERNAL (fixP
->fx_addsy
)
962 || S_IS_WEAK (fixP
->fx_addsy
)))
965 return fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
968 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
969 Returns BFD_RELOC_NONE if no reloc type can be found.
970 *FIXP may be modified if desired. */
972 bfd_reloc_code_real_type
973 md_cgen_lookup_reloc (const CGEN_INSN
*insn ATTRIBUTE_UNUSED
,
974 const CGEN_OPERAND
*operand
,
975 fixS
*fixP ATTRIBUTE_UNUSED
)
977 switch (operand
->type
)
979 case EPIPHANY_OPERAND_SIMM11
:
980 return BFD_RELOC_EPIPHANY_SIMM11
;
981 case EPIPHANY_OPERAND_DISP11
:
982 return BFD_RELOC_EPIPHANY_IMM11
;
984 case EPIPHANY_OPERAND_SIMM8
:
985 return BFD_RELOC_EPIPHANY_SIMM8
;
986 case EPIPHANY_OPERAND_SIMM24
:
987 return BFD_RELOC_EPIPHANY_SIMM24
;
989 case EPIPHANY_OPERAND_IMM8
:
990 return BFD_RELOC_EPIPHANY_IMM8
;
992 case EPIPHANY_OPERAND_IMM16
:
993 if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn
)))
994 return BFD_RELOC_EPIPHANY_HIGH
;
995 else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn
)))
996 return BFD_RELOC_EPIPHANY_LOW
;
998 as_bad ("unknown imm16 operand");
1004 return BFD_RELOC_NONE
;
1008 /* Turn a string in input_line_pointer into a floating point constant
1009 of type TYPE, and store the appropriate bytes in *LITP. The number
1010 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1011 returned, or NULL on OK. */
1014 md_atof (int type
, char *litP
, int *sizeP
)
1016 return ieee_md_atof (type
, litP
, sizeP
, FALSE
);
1019 /* Return true if can adjust the reloc to be relative to its section
1020 (such as .data) instead of relative to some symbol. */
1023 epiphany_fix_adjustable (fixS
*fixP
)
1025 bfd_reloc_code_real_type reloc_type
;
1027 if ((int) fixP
->fx_r_type
>= (int) BFD_RELOC_UNUSED
)
1029 const CGEN_INSN
*insn
= fixP
->fx_cgen
.insn
;
1030 int opindex
= (int) fixP
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1031 const CGEN_OPERAND
*operand
=
1032 cgen_operand_lookup_by_num (gas_cgen_cpu_desc
, opindex
);
1034 reloc_type
= md_cgen_lookup_reloc (insn
, operand
, fixP
);
1037 reloc_type
= fixP
->fx_r_type
;
1039 if (fixP
->fx_addsy
== NULL
)
1042 /* Prevent all adjustments to global symbols. */
1043 if (S_IS_EXTERNAL (fixP
->fx_addsy
))
1046 if (S_IS_WEAK (fixP
->fx_addsy
))
1050 && (reloc_type
== BFD_RELOC_EPIPHANY_SIMM24
1051 || reloc_type
== BFD_RELOC_EPIPHANY_SIMM8
1052 || reloc_type
== BFD_RELOC_EPIPHANY_HIGH
1053 || reloc_type
== BFD_RELOC_EPIPHANY_LOW
))
1056 /* Since we don't use partial_inplace, we must not reduce symbols in
1057 mergeable sections to their section symbol. */
1058 if ((S_GET_SEGMENT (fixP
->fx_addsy
)->flags
& SEC_MERGE
) != 0)
1065 epiphany_elf_final_processing (void)
1067 elf_elfheader (stdoutput
)->e_flags
|= epiphany_flags
;
1071 epiphany_cgen_parse_fix_exp (int opinfo
, expressionS
*exp ATTRIBUTE_UNUSED
)
1073 LITTLENUM_TYPE words
[2];
1077 case BFD_RELOC_EPIPHANY_LOW
:
1078 case BFD_RELOC_EPIPHANY_HIGH
:
1084 /* Doing a %LOW or %HIGH. */
1089 case O_big
: /* Bignum. */
1090 if (exp
->X_add_number
> 0) /* Integer value too large. */
1094 /* Convert to SP number. */
1095 gen_to_words (words
, 2, 8L);
1096 exp
->X_add_number
= words
[1] | (words
[0] << 16);
1097 exp
->X_op
= O_constant
;