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)
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 bool 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 const 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 const 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_section_alignment (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
;
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 (startswith (str
, "push {"))
536 pperr
= parse_reglist (s
, ®mask
);
538 else if (startswith (str
, "pop {"))
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 const CGEN_INSN
*insn
;
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
;
739 case EPIPHANY_RELAX_LDST_IMM3
:
740 subtype
= EPIPHANY_RELAX_LDST_IMM11
;
742 case EPIPHANY_RELAX_BRANCH_SHORT
:
743 subtype
= EPIPHANY_RELAX_BRANCH_LONG
;
745 case EPIPHANY_RELAX_MOV_IMM8
:
746 subtype
= EPIPHANY_RELAX_MOV_IMM16
;
748 case EPIPHANY_RELAX_ARITH_SIMM3
:
749 subtype
= EPIPHANY_RELAX_ARITH_SIMM11
;
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
))
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. */
794 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
806 opcode
= fragP
->fr_opcode
;
808 /* Address opcode resides at in file space. */
809 opcode_address
= fragP
->fr_address
+ fragP
->fr_fix
- 2;
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."));
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];
839 = (((addend
& 0x7) << 7)
841 | ((addend
& 0x7f8) << 13)
843 | (opcode
[2] << 16));
845 opindx
= EPIPHANY_OPERAND_SIMM11
;
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
;
854 addend
>>= 1; /* Convert to word offset. */
855 opindx
= EPIPHANY_OPERAND_SIMM24
;
858 case EPIPHANY_RELAX_MOV_IMM16
:
859 *opcode
|= OP4_IMM32
;
863 = (((addend
& 0xff00) << 12)
865 | ((addend
& 0x00ff) << 5)
868 displacement
= &opcode
[0];
869 opindx
= EPIPHANY_OPERAND_IMM16
;
872 case EPIPHANY_RELAX_LDST_IMM11
:
873 *opcode
|= OP4_LDSTRD
;
874 displacement
= &opcode
[0];
878 /* Convert twos-complement address value to sign-magnitude. */
879 addend
= (-addend
& 0x7ff) | 0x800;
882 = (((addend
& 0x7) << 5)
884 | ((addend
& 0xff8) << 13)
886 | (opcode
[2] << 16));
888 opindx
= EPIPHANY_OPERAND_DISP11
;
891 case EPIPHANY_RELAX_ARITH_SIMM3
:
892 addend
= ((addend
& 7) << 5) | opcode
[0];
893 opindx
= EPIPHANY_OPERAND_SIMM3
;
896 case EPIPHANY_RELAX_LDST_IMM3
:
897 addend
= ((addend
& 7) << 5) | opcode
[0];
898 opindx
= EPIPHANY_OPERAND_DISP3
;
901 case EPIPHANY_RELAX_BRANCH_SHORT
:
902 addend
>>= 1; /* Convert to a word offset. */
903 displacement
= & opcode
[1];
904 opindx
= EPIPHANY_OPERAND_SIMM8
;
907 case EPIPHANY_RELAX_MOV_IMM8
:
909 = (((addend
& 0xff) << 5)
912 opindx
= EPIPHANY_OPERAND_IMM8
;
915 case EPIPHANY_RELAX_NONE
:
916 case EPIPHANY_RELAX_NEED_RELAXING
:
917 default: /* Anything else? */
918 as_bad ("unrecognized fragment subtype");
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
))
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
),
942 CGEN_INSN_BITSIZE (fragP
->fr_cgen
.insn
) / 8,
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. */
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
)))
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
;
1003 as_bad ("unknown imm16 operand");
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. */
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. */
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
);
1042 reloc_type
= fixP
->fx_r_type
;
1044 if (fixP
->fx_addsy
== NULL
)
1047 /* Prevent all adjustments to global symbols. */
1048 if (S_IS_EXTERNAL (fixP
->fx_addsy
))
1051 if (S_IS_WEAK (fixP
->fx_addsy
))
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
))
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)
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];
1082 case BFD_RELOC_EPIPHANY_LOW
:
1083 case BFD_RELOC_EPIPHANY_HIGH
:
1089 /* Doing a %LOW or %HIGH. */
1094 case O_big
: /* Bignum. */
1095 if (exp
->X_add_number
> 0) /* Integer value too large. */
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
;