1 /* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY
2 Copyright (C) 2009-2016 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"
33 /* Structure to hold all of the different components describing
34 an individual instruction. */
37 const CGEN_INSN
* insn
;
38 const CGEN_INSN
* orig_insn
;
41 CGEN_INSN_INT buffer
[1];
42 #define INSN_VALUE(buf) (*(buf))
44 unsigned char buffer
[CGEN_MAX_INSN_SIZE
];
45 #define INSN_VALUE(buf) (buf)
50 fixS
* fixups
[GAS_CGEN_MAX_FIXUPS
];
51 int indices
[MAX_OPERAND_INSTANCES
];
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
63 static bfd_boolean force_code_align
= FALSE
;
66 epiphany_elf_section_rtn (int i
)
72 do_align (1, NULL
, 0, 0);
73 force_code_align
= FALSE
;
78 epiphany_elf_section_text (int i
)
82 do_align (1, NULL
, 0, 0);
83 force_code_align
= FALSE
;
86 /* The target specific pseudo-ops which we support. */
87 const pseudo_typeS md_pseudo_table
[] =
89 { "text", epiphany_elf_section_text
, 0 },
90 { "sect", epiphany_elf_section_rtn
, 0 },
91 /* .word should be 32 bits. */
93 { "cpu", s_ignore
, 0 },
94 { "thumb_func", s_ignore
, 0 },
95 { "code", s_ignore
, 0 },
103 OPTION_CPU_EPIPHANY
= OPTION_MD_BASE
,
104 OPTION_CPU_EPIPHANY16
107 struct option md_longopts
[] =
109 { "mepiphany ", no_argument
, NULL
, OPTION_CPU_EPIPHANY
},
110 { "mepiphany16", no_argument
, NULL
, OPTION_CPU_EPIPHANY16
},
111 { NULL
, no_argument
, NULL
, 0 },
114 size_t md_longopts_size
= sizeof (md_longopts
);
116 const char * md_shortopts
= "";
119 md_parse_option (int c ATTRIBUTE_UNUSED
, const char * arg ATTRIBUTE_UNUSED
)
121 return 0; /* No target-specific options. */
125 md_show_usage (FILE * stream
)
127 fprintf (stream
, _("EPIPHANY specific command line options:\n"));
134 /* Initialize the `cgen' interface. */
136 /* Set the machine number and endian. */
137 gas_cgen_cpu_desc
= epiphany_cgen_cpu_open (CGEN_CPU_OPEN_MACHS
,
139 CGEN_CPU_OPEN_ENDIAN
,
142 epiphany_cgen_init_asm (gas_cgen_cpu_desc
);
144 /* This is a callback from cgen to gas to parse operands. */
145 cgen_set_parse_operand_fn (gas_cgen_cpu_desc
, gas_cgen_parse_operand
);
147 /* Set the machine type. */
148 bfd_default_set_arch_mach (stdoutput
, bfd_arch_epiphany
, bfd_mach_epiphany32
);
152 md_section_align (segT segment
, valueT size
)
154 int align
= bfd_get_section_alignment (stdoutput
, segment
);
156 return ((size
+ (1 << align
) - 1) & -(1 << align
));
160 /* Functions concerning relocs. */
163 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
168 /* Write a value out to the object file, using the appropriate endianness. */
171 md_number_to_chars (char * buf
, valueT val
, int n
)
173 number_to_chars_littleendian (buf
, val
, n
);
177 epiphany_elf_section_flags (int flags
,
178 int attr ATTRIBUTE_UNUSED
,
179 int type ATTRIBUTE_UNUSED
)
181 /* This is used to detect when the section changes to an executable section.
182 This function is called by the elf section processing. When we note an
183 executable section specifier we set an internal flag to denote when
184 word alignment should be forced. */
185 if (flags
& SEC_CODE
)
186 force_code_align
= TRUE
;
191 /* Non-zero if we are generating PIC code. */
194 /* Epiphany er_flags. */
195 static int epiphany_flags
= 0;
197 /* Relocations against symbols are done in two
198 parts, with a HI relocation and a LO relocation. Each relocation
199 has only 16 bits of space to store an addend. This means that in
200 order for the linker to handle carries correctly, it must be able
201 to locate both the HI and the LO relocation. This means that the
202 relocations must appear in order in the relocation table.
204 In order to implement this, we keep track of each unmatched HI
205 relocation. We then sort them so that they immediately precede the
206 corresponding LO relocation. */
208 struct epiphany_hi_fixup
211 struct epiphany_hi_fixup
*next
;
216 /* The section this fixup is in. */
221 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
222 static symbolS
* GOT_symbol
;
224 static inline bfd_boolean
225 epiphany_PIC_related_p (symbolS
*sym
)
232 if (sym
== GOT_symbol
)
235 exp
= symbol_get_value_expression (sym
);
237 return (exp
->X_op
== O_PIC_reloc
238 || exp
->X_md
== BFD_RELOC_EPIPHANY_SIMM24
239 || exp
->X_md
== BFD_RELOC_EPIPHANY_SIMM8
240 || epiphany_PIC_related_p (exp
->X_add_symbol
)
241 || epiphany_PIC_related_p (exp
->X_op_symbol
));
244 /* Perform target dependent relocations that are done at compile time.
245 There aren't very many of these. */
248 epiphany_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg
)
250 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
253 if (((int) fixP
->fx_r_type
< (int) BFD_RELOC_UNUSED
)
256 /* Install EPIPHANY-dependent relocations HERE because nobody else
258 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
259 unsigned char *insn
= (unsigned char *)where
;
260 valueT value
= * valP
;
262 switch (fixP
->fx_r_type
)
270 case BFD_RELOC_EPIPHANY_SIMM11
:
271 where
[0] = where
[0] | ((value
& 1) << 7);
272 where
[1] = where
[1] | ((value
& 6) >> 1);
273 where
[2] = (value
>> 3) & 0xff;
276 case BFD_RELOC_EPIPHANY_IMM11
:
277 where
[0] = where
[0] | ((value
& 1) << 7);
278 where
[1] = where
[1] | ((value
& 6) >> 1);
279 where
[2] = (value
>> 3) & 0xff;
282 case BFD_RELOC_EPIPHANY_SIMM8
:
283 md_number_to_chars (where
+1, value
>>1, 1);
286 case BFD_RELOC_EPIPHANY_SIMM24
:
287 md_number_to_chars (where
+1, value
>>1, 3);
290 case BFD_RELOC_EPIPHANY_HIGH
:
293 case BFD_RELOC_EPIPHANY_LOW
:
294 value
= (((value
& 0xff) << 5) | insn
[0])
296 | ((value
& 0xff00) << 12)
298 md_number_to_chars (where
, value
, 3);
303 /* Just do the default if we can't special case. */
304 return gas_cgen_md_apply_fix (fixP
, valP
, seg
);
308 /* This is called from HANDLE_ALIGN in write.c. Fill in the contents
309 of an rs_align_code fragment. 0x01a2 is 16-bit pattern for a "nop". */
311 static const unsigned char nop_pattern
[] = { 0xa2, 0x01 };
314 epiphany_handle_align (fragS
*fragp
)
319 if (fragp
->fr_type
!= rs_align_code
)
322 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
323 p
= fragp
->fr_literal
+ fragp
->fr_fix
;
335 memcpy (p
, nop_pattern
, 2);
340 fragp
->fr_fix
+= fix
;
343 /* Read a comma separated incrementing list of register names
344 and form a bit mask of upto 15 registers 0..14. */
347 parse_reglist (const char * s
, int * mask
)
358 /* Parse a list with "," or "}" as limiters. */
360 = cgen_parse_keyword (gas_cgen_cpu_desc
, &s
,
361 &epiphany_cgen_opval_gr_names
, &value
);
366 return _("register number too large for push/pop");
368 regmask
|= 1 << value
;
370 return _("register is out of order");
378 else if (*s
++ == ',')
381 return _("bad register list");
384 return _("malformed reglist in push/pop");
388 /* Assemble an instruction, push and pop pseudo instructions should have
389 already been expanded. */
392 epiphany_assemble (const char *str
)
397 memset (&insn
, 0, sizeof (insn
));
399 /* Initialize GAS's cgen interface for a new instruction. */
400 gas_cgen_init_parse ();
402 insn
.insn
= epiphany_cgen_assemble_insn
403 (gas_cgen_cpu_desc
, str
, &insn
.fields
, insn
.buffer
, & errmsg
);
407 as_bad ("%s", errmsg
);
411 if (CGEN_INSN_BITSIZE (insn
.insn
) == 32)
413 /* Doesn't really matter what we pass for RELAX_P here. */
414 gas_cgen_finish_insn (insn
.insn
, insn
.buffer
,
415 CGEN_FIELDS_BITSIZE (&insn
.fields
), 1, NULL
);
419 if (CGEN_INSN_BITSIZE (insn
.insn
) != 16)
422 insn
.orig_insn
= insn
.insn
;
424 gas_cgen_finish_insn (insn
.orig_insn
, insn
.buffer
,
425 CGEN_FIELDS_BITSIZE (&insn
.fields
),
426 1 /* relax_p */, NULL
);
429 /* Checks for behavioral restrictions on LD/ST instructions. */
430 #define DISPMOD _("destination register modified by displacement-post-modified address")
431 #define LDSTODD _("ldrd/strd requires even:odd register pair")
433 /* Helper macros for spliting apart instruction fields. */
434 #define ADDR_POST_MODIFIED(i) (((i) >> 25) & 0x1)
435 #define ADDR_SIZE(i) (((i) >> 5) & 3)
436 #define ADDR_LOADSTORE(i) (((i) >> 4) & 0x1)
438 switch (insn
.buffer
[0] & 0xf)
440 /* Post-modify registers cannot be destinations. */
443 if (ADDR_LOADSTORE (insn
.buffer
[0]) == OP_LOAD
)
444 if (insn
.fields
.f_rd
== insn
.fields
.f_rn
/* Postmodify dest. */
445 || (insn
.fields
.f_rd
+1 == insn
.fields
.f_rn
446 && ADDR_SIZE (insn
.buffer
[0]) == OPW_DOUBLE
))
448 as_bad ("%s", DISPMOD
);
451 if ((insn
.fields
.f_rd
& 1) /* Odd-numbered register... */
452 && insn
.fields
.f_wordsize
== OPW_DOUBLE
) /* ...and 64 bit transfer. */
454 as_bad ("%s", LDSTODD
);
462 if (ADDR_LOADSTORE (insn
.buffer
[0]) == OP_LOAD
) /* A load. */
463 if (insn
.fields
.f_rd6
== insn
.fields
.f_rn6
/* Postmodify dest. */
464 /* Check for regpair postindexed. */
465 || (insn
.fields
.f_rd6
+ 1 == insn
.fields
.f_rn6
466 && ADDR_SIZE (insn
.buffer
[0]) == OPW_DOUBLE
))
468 as_bad ("%s", DISPMOD
);
471 if ((insn
.fields
.f_rd6
& 1) && ADDR_SIZE (insn
.buffer
[0]) == OPW_DOUBLE
)
472 /* Lsb of RD odd and 64 bit transfer. */
474 as_bad ("%s", LDSTODD
);
483 /* Check for unaligned load/store double. */
484 if ((insn
.fields
.f_rd
& 1) && ADDR_SIZE (insn
.buffer
[0]) == OPW_DOUBLE
)
485 /* Lsb of RD odd and 64 bit transfer. */
487 as_bad ("%s", LDSTODD
);
495 /* Check for load to post-modified register. */
496 if (ADDR_LOADSTORE (insn
.buffer
[0]) == OP_LOAD
/* A load. */
497 && ADDR_POST_MODIFIED (insn
.buffer
[0]) == PMOD_POST
/* Post-mod. */
498 && (insn
.fields
.f_rd6
== insn
.fields
.f_rn6
499 || (insn
.fields
.f_rd6
+1 == insn
.fields
.f_rn6
500 && ADDR_SIZE (insn
.buffer
[0]) == OPW_DOUBLE
)))
502 as_bad ("%s", DISPMOD
);
510 /* Check for unaligned load/store double. */
511 if ((insn
.fields
.f_rd6
& 1) && ADDR_SIZE (insn
.buffer
[0]) == OPW_DOUBLE
)
513 as_bad ("%s", LDSTODD
);
525 md_assemble (char *str
)
527 const char * pperr
= 0;
528 int regmask
=0, push
=0, pop
=0;
530 /* Special-case push/pop instruction macros. */
531 if (0 == strncmp (str
, "push {", 6))
535 pperr
= parse_reglist (s
, ®mask
);
537 else if (0 == strncmp (str
, "pop {", 5))
541 pperr
= parse_reglist (s
, ®mask
);
546 as_bad ("%s", pperr
);
553 int i
,p ATTRIBUTE_UNUSED
;
555 epiphany_assemble ("mov r15,4");
556 epiphany_assemble ("sub sp,sp,r15");
558 for (i
= 0, p
= 1; i
<= 15; ++i
, regmask
>>= 1)
561 sprintf (buff
, "str r%d,[sp]", i
); /* Last one. */
562 else if (regmask
& 1)
563 sprintf (buff
, "str r%d,[sp],-r15", i
);
566 epiphany_assemble (buff
);
570 else if (pop
&& regmask
)
575 epiphany_assemble ("mov r15,4");
577 for (i
= 15, p
= 1 << 15; i
>= 0; --i
, p
>>= 1)
580 sprintf (buff
, "ldr r%d,[sp],+r15", i
);
581 epiphany_assemble (buff
);
586 epiphany_assemble (str
);
589 /* The syntax in the manual says constants begin with '#'.
590 We just ignore it. */
593 md_operand (expressionS
*expressionP
)
595 if (*input_line_pointer
== '#')
597 input_line_pointer
++;
598 expression (expressionP
);
603 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
608 /* Interface to relax_segment. */
610 /* FIXME: Build table by hand, get it working, then machine generate. */
612 const relax_typeS md_relax_table
[] =
615 1) most positive reach of this state,
616 2) most negative reach of this state,
617 3) how many bytes this mode will add to the size of the current frag
618 4) which index into the table to try if we can't fit into this one. */
620 /* The first entry must be unused because an `rlx_more' value of zero ends
622 {1, 1, 0, EPIPHANY_RELAX_NONE
},
623 {0, 0, 0, EPIPHANY_RELAX_NONE
}, /* Also a dummy entry to indicate we need to expand codes. */
625 /* The displacement used by GAS is from the end of the 2 byte insn,
626 so we subtract 2 from the following. */
627 /* 16 bit insn, 8 bit disp -> +127 words, -128 words. */
628 {0x00000100 - 1 - 2, -0x00000100 - 2, 0, EPIPHANY_RELAX_BRANCH_LONG
},
629 /* 32 bit insn, 24 bit disp -> 25 bit range. */
630 {0x01000000 - 1 - 2, -0x01000000 - 2, 2, EPIPHANY_RELAX_NONE
},
632 /* addi/subi 3 bits -4..+3. */
633 { 3, -4,0, EPIPHANY_RELAX_ARITH_SIMM11
},
634 /* addi/subi 11 bits. */
635 { 1023, -1024,2, EPIPHANY_RELAX_NONE
},
638 { 255, 0,0, EPIPHANY_RELAX_MOV_IMM16
},
640 { 65535, 0,2, EPIPHANY_RELAX_NONE
},
642 /* ld/st rd,[rn,imm3]. */
643 { 7, 0,0, EPIPHANY_RELAX_LDST_IMM11
},
644 /* ld/st rd,[rn,imm11]. */
645 { 2047, 0,2, EPIPHANY_RELAX_NONE
}
649 static const EPIPHANY_RELAX_TYPES relax_insn
[] =
651 EPIPHANY_RELAX_BRANCH_SHORT
, /* OP4_BRANCH16 */
652 EPIPHANY_RELAX_NONE
, /* OP4_LDSTR16X */
653 EPIPHANY_RELAX_NONE
, /* OP4_FLOW16 */
654 EPIPHANY_RELAX_ARITH_SIMM3
, /* OP4_IMM16 - special */
655 EPIPHANY_RELAX_LDST_IMM3
, /* OP4_LDSTR16D */
656 EPIPHANY_RELAX_NONE
, /* OP4_LDSTR126P */
657 EPIPHANY_RELAX_NONE
, /* OP4_LSHIFT16 */
658 EPIPHANY_RELAX_NONE
, /* OP4_DSP16 */
659 EPIPHANY_RELAX_BRANCH_LONG
, /* OP4_BRANCH */
660 EPIPHANY_RELAX_NONE
, /* OP4_LDSTRX */
661 EPIPHANY_RELAX_NONE
, /* OP4_ALU16 */
662 EPIPHANY_RELAX_ARITH_SIMM11
, /* OP4_IMM32 - special */
663 EPIPHANY_RELAX_LDST_IMM11
, /* OP4_LDSTRD */
664 EPIPHANY_RELAX_NONE
, /* OP4_LDSTRP */
665 EPIPHANY_RELAX_NONE
, /* OP4_ASHIFT16 */
666 EPIPHANY_RELAX_NONE
/* OP4_MISC */
670 epiphany_relax_frag (segT segment
, fragS
*fragP
, long stretch
)
672 /* Address of branch insn. */
673 long address ATTRIBUTE_UNUSED
= fragP
->fr_address
+ fragP
->fr_fix
- 2;
676 if (fragP
->fr_subtype
== EPIPHANY_RELAX_NEED_RELAXING
)
678 EPIPHANY_RELAX_TYPES subtype
= relax_insn
[*fragP
->fr_opcode
& 0xf];
680 /* Special cases add/sub vs mov immediates. */
681 if (subtype
== EPIPHANY_RELAX_ARITH_SIMM3
)
683 if ((*fragP
->fr_opcode
& 0x10) == 0)
684 subtype
= EPIPHANY_RELAX_MOV_IMM8
;
686 else if (subtype
== EPIPHANY_RELAX_ARITH_SIMM11
)
688 if ((*fragP
->fr_opcode
& 0x10) == 0)
689 subtype
= EPIPHANY_RELAX_MOV_IMM16
;
692 /* Remember refinements for the future. */
693 fragP
->fr_subtype
= subtype
;
696 growth
= relax_frag (segment
, fragP
, stretch
);
701 /* Return an initial guess of the length by which a fragment must grow to
702 hold a branch to reach its destination.
703 Also updates fr_type/fr_subtype as necessary.
705 Called just before doing relaxation.
706 Any symbol that is now undefined will not become defined.
707 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
708 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
709 Although it may not be explicit in the frag, pretend fr_var starts
713 md_estimate_size_before_relax (fragS
*fragP
, segT segment
)
715 /* The only thing we have to handle here are symbols outside of the
716 current segment. They may be undefined or in a different segment in
717 which case linker scripts may place them anywhere.
718 However, we can't finish the fragment here and emit the reloc as insn
719 alignment requirements may move the insn about. */
720 if (S_GET_SEGMENT (fragP
->fr_symbol
) != segment
721 || S_IS_EXTERNAL (fragP
->fr_symbol
)
722 || S_IS_WEAK (fragP
->fr_symbol
))
724 /* The symbol is undefined in this segment. Change the
725 relaxation subtype to the max allowable and leave all further
726 handling to md_convert_frag. */
728 EPIPHANY_RELAX_TYPES subtype
;
729 /* We haven't relaxed this at all, so the relaxation type may be
730 completely wrong. Set the subtype correctly. */
731 epiphany_relax_frag (segment
, fragP
, 0);
732 subtype
= fragP
->fr_subtype
;
736 case EPIPHANY_RELAX_LDST_IMM3
:
737 subtype
= EPIPHANY_RELAX_LDST_IMM11
;
739 case EPIPHANY_RELAX_BRANCH_SHORT
:
740 subtype
= EPIPHANY_RELAX_BRANCH_LONG
;
742 case EPIPHANY_RELAX_MOV_IMM8
:
743 subtype
= EPIPHANY_RELAX_MOV_IMM16
;
745 case EPIPHANY_RELAX_ARITH_SIMM3
:
746 subtype
= EPIPHANY_RELAX_ARITH_SIMM11
;
753 fragP
->fr_subtype
= subtype
;
756 const CGEN_INSN
*insn
;
759 /* Update the recorded insn. */
761 for (i
= 0, insn
= fragP
->fr_cgen
.insn
; i
< 4; i
++, insn
++)
763 if ((strcmp (CGEN_INSN_MNEMONIC (insn
),
764 CGEN_INSN_MNEMONIC (fragP
->fr_cgen
.insn
))
766 && CGEN_INSN_ATTR_VALUE (insn
, CGEN_INSN_RELAXED
))
773 fragP
->fr_cgen
.insn
= insn
;
777 return md_relax_table
[fragP
->fr_subtype
].rlx_length
;
780 /* *FRAGP has been relaxed to its final size, and now needs to have
781 the bytes inside it modified to conform to the new size.
783 Called after relaxation is finished.
784 fragP->fr_type == rs_machine_dependent.
785 fragP->fr_subtype is the subtype of what the address relaxed to. */
788 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
800 opcode
= fragP
->fr_opcode
;
802 /* Address opcode resides at in file space. */
803 opcode_address
= fragP
->fr_address
+ fragP
->fr_fix
- 2;
805 displacement
= &opcode
[1];
807 /* Set up any addend necessary for branches. */
808 if (S_GET_SEGMENT (fragP
->fr_symbol
) != sec
809 || S_IS_EXTERNAL (fragP
->fr_symbol
)
810 || S_IS_WEAK (fragP
->fr_symbol
))
812 /* Symbol must be resolved by linker. */
813 if (fragP
->fr_offset
& 1)
814 as_warn (_("Addend to unresolved symbol not on word boundary."));
819 /* Address we want to reach in file space. */
820 target_address
= S_GET_VALUE (fragP
->fr_symbol
) + fragP
->fr_offset
;
821 addend
= (target_address
- (opcode_address
& -2));
824 /* Do all the housekeeping for frag conversions. */
825 switch (fragP
->fr_subtype
)
827 case EPIPHANY_RELAX_ARITH_SIMM11
:
828 *opcode
|= OP4_IMM32
;
829 displacement
= &opcode
[0];
833 = (((addend
& 0x7) << 7)
835 | ((addend
& 0x7f8) << 13)
837 | (opcode
[2] << 16));
839 opindx
= EPIPHANY_OPERAND_SIMM11
;
842 case EPIPHANY_RELAX_BRANCH_LONG
:
843 /* Branches differ only in low nibble of instruction being 8 not 0.
844 24 bit displacement goes to bytes 1..3 . */
845 *opcode
|= OP4_BRANCH
;
848 addend
>>= 1; /* Convert to word offset. */
849 opindx
= EPIPHANY_OPERAND_SIMM24
;
852 case EPIPHANY_RELAX_MOV_IMM16
:
853 *opcode
|= OP4_IMM32
;
857 = (((addend
& 0xff00) << 12)
859 | ((addend
& 0x00ff) << 5)
862 displacement
= &opcode
[0];
863 opindx
= EPIPHANY_OPERAND_IMM16
;
866 case EPIPHANY_RELAX_LDST_IMM11
:
867 *opcode
|= OP4_LDSTRD
;
868 displacement
= &opcode
[0];
872 /* Convert twos-complement address value to sign-magnitude. */
873 addend
= (-addend
& 0x7ff) | 0x800;
876 = (((addend
& 0x7) << 5)
878 | ((addend
& 0xff8) << 13)
880 | (opcode
[2] << 16));
882 opindx
= EPIPHANY_OPERAND_DISP11
;
885 case EPIPHANY_RELAX_ARITH_SIMM3
:
886 addend
= ((addend
& 7) << 5) | opcode
[0];
887 opindx
= EPIPHANY_OPERAND_SIMM3
;
890 case EPIPHANY_RELAX_LDST_IMM3
:
891 addend
= ((addend
& 7) << 5) | opcode
[0];
892 opindx
= EPIPHANY_OPERAND_DISP3
;
895 case EPIPHANY_RELAX_BRANCH_SHORT
:
896 addend
>>= 1; /* Convert to a word offset. */
897 displacement
= & opcode
[1];
898 opindx
= EPIPHANY_OPERAND_SIMM8
;
901 case EPIPHANY_RELAX_MOV_IMM8
:
903 = (((addend
& 0xff) << 5)
906 opindx
= EPIPHANY_OPERAND_IMM8
;
909 case EPIPHANY_RELAX_NONE
:
910 case EPIPHANY_RELAX_NEED_RELAXING
:
911 default: /* Anything else? */
912 as_bad ("unrecognized fragment subtype");
916 /* Create a relocation for symbols that must be resolved by the linker.
917 Otherwise output the completed insn. */
919 if (S_GET_SEGMENT (fragP
->fr_symbol
) != sec
920 || S_IS_EXTERNAL (fragP
->fr_symbol
)
921 || S_IS_WEAK (fragP
->fr_symbol
))
924 const CGEN_OPERAND
*operand
925 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc
, opindx
);
926 bfd_reloc_code_real_type reloc_type
;
928 gas_assert (fragP
->fr_cgen
.insn
!= 0);
930 reloc_type
= md_cgen_lookup_reloc (fragP
->fr_cgen
.insn
, operand
, NULL
);
932 fixP
= gas_cgen_record_fixup (fragP
,
933 /* Offset of insn in frag. */
934 (opcode
- fragP
->fr_literal
),
936 CGEN_INSN_BITSIZE (fragP
->fr_cgen
.insn
) / 8,
939 fragP
->fr_symbol
, fragP
->fr_offset
);
940 fixP
->fx_r_type
= fixP
->fx_cgen
.opinfo
;
943 md_number_to_chars (displacement
, (valueT
) addend
, extension
+ 1);
945 fragP
->fr_fix
+= (extension
& -2); /* 0,2 or 4 bytes added. */
949 /* Functions concerning relocs. */
951 /* The location from which a PC relative jump should be calculated,
952 given a PC relative reloc. */
955 md_pcrel_from_section (fixS
*fixP
, segT sec
)
957 if (fixP
->fx_addsy
!= (symbolS
*) NULL
958 && (!S_IS_DEFINED (fixP
->fx_addsy
)
959 || (S_GET_SEGMENT (fixP
->fx_addsy
) != sec
)
960 || S_IS_EXTERNAL (fixP
->fx_addsy
)
961 || S_IS_WEAK (fixP
->fx_addsy
)))
964 return fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
967 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
968 Returns BFD_RELOC_NONE if no reloc type can be found.
969 *FIXP may be modified if desired. */
971 bfd_reloc_code_real_type
972 md_cgen_lookup_reloc (const CGEN_INSN
*insn ATTRIBUTE_UNUSED
,
973 const CGEN_OPERAND
*operand
,
974 fixS
*fixP ATTRIBUTE_UNUSED
)
976 switch (operand
->type
)
978 case EPIPHANY_OPERAND_SIMM11
:
979 return BFD_RELOC_EPIPHANY_SIMM11
;
980 case EPIPHANY_OPERAND_DISP11
:
981 return BFD_RELOC_EPIPHANY_IMM11
;
983 case EPIPHANY_OPERAND_SIMM8
:
984 return BFD_RELOC_EPIPHANY_SIMM8
;
985 case EPIPHANY_OPERAND_SIMM24
:
986 return BFD_RELOC_EPIPHANY_SIMM24
;
988 case EPIPHANY_OPERAND_IMM8
:
989 return BFD_RELOC_EPIPHANY_IMM8
;
991 case EPIPHANY_OPERAND_IMM16
:
992 if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn
)))
993 return BFD_RELOC_EPIPHANY_HIGH
;
994 else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn
)))
995 return BFD_RELOC_EPIPHANY_LOW
;
997 as_bad ("unknown imm16 operand");
1003 return BFD_RELOC_NONE
;
1007 /* Turn a string in input_line_pointer into a floating point constant
1008 of type TYPE, and store the appropriate bytes in *LITP. The number
1009 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1010 returned, or NULL on OK. */
1012 /* Equal to MAX_PRECISION in atof-ieee.c. */
1013 #define MAX_LITTLENUMS 6
1016 md_atof (int type
, char *litP
, int *sizeP
)
1018 return ieee_md_atof (type
, litP
, sizeP
, FALSE
);
1021 /* Return true if can adjust the reloc to be relative to its section
1022 (such as .data) instead of relative to some symbol. */
1025 epiphany_fix_adjustable (fixS
*fixP
)
1027 bfd_reloc_code_real_type reloc_type
;
1029 if ((int) fixP
->fx_r_type
>= (int) BFD_RELOC_UNUSED
)
1031 const CGEN_INSN
*insn
= fixP
->fx_cgen
.insn
;
1032 int opindex
= (int) fixP
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
1033 const CGEN_OPERAND
*operand
=
1034 cgen_operand_lookup_by_num (gas_cgen_cpu_desc
, opindex
);
1036 reloc_type
= md_cgen_lookup_reloc (insn
, operand
, fixP
);
1039 reloc_type
= fixP
->fx_r_type
;
1041 if (fixP
->fx_addsy
== NULL
)
1044 /* Prevent all adjustments to global symbols. */
1045 if (S_IS_EXTERNAL (fixP
->fx_addsy
))
1048 if (S_IS_WEAK (fixP
->fx_addsy
))
1052 && (reloc_type
== BFD_RELOC_EPIPHANY_SIMM24
1053 || reloc_type
== BFD_RELOC_EPIPHANY_SIMM8
1054 || reloc_type
== BFD_RELOC_EPIPHANY_HIGH
1055 || reloc_type
== BFD_RELOC_EPIPHANY_LOW
))
1058 /* Since we don't use partial_inplace, we must not reduce symbols in
1059 mergable sections to their section symbol. */
1060 if ((S_GET_SEGMENT (fixP
->fx_addsy
)->flags
& SEC_MERGE
) != 0)
1067 epiphany_elf_final_processing (void)
1069 elf_elfheader (stdoutput
)->e_flags
|= epiphany_flags
;
1073 epiphany_cgen_parse_fix_exp (int opinfo
, expressionS
*exp ATTRIBUTE_UNUSED
)
1075 LITTLENUM_TYPE words
[2];
1079 case BFD_RELOC_EPIPHANY_LOW
:
1080 case BFD_RELOC_EPIPHANY_HIGH
:
1086 /* Doing a %LOW or %HIGH. */
1091 case O_big
: /* Bignum. */
1092 if (exp
->X_add_number
> 0) /* Integer value too large. */
1096 /* Convert to SP number. */
1097 gen_to_words (words
, 2, 8L);
1098 exp
->X_add_number
= words
[1] | (words
[0] << 16);
1099 exp
->X_op
= O_constant
;