callfuncs.exp: avoid spurious register differences in sparc64 targets.
[deliverable/binutils-gdb.git] / gas / config / tc-epiphany.c
CommitLineData
cfb8c092 1/* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY
b90efa5b 2 Copyright (C) 2009-2015 Free Software Foundation, Inc.
cfb8c092
NC
3 Contributed by Embecosm on behalf of Adapteva, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
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.
16
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. */
21
22#include "as.h"
23#include "subsegs.h"
24#include "symcat.h"
25#include "opcodes/epiphany-desc.h"
26#include "opcodes/epiphany-opc.h"
27#include "cgen.h"
28#include "elf/common.h"
29#include "elf/epiphany.h"
30#include "dwarf2dbg.h"
31#include "libbfd.h"
32
33/* Structure to hold all of the different components describing
34 an individual instruction. */
35typedef struct
36{
37 const CGEN_INSN * insn;
38 const CGEN_INSN * orig_insn;
39 CGEN_FIELDS fields;
40#if CGEN_INT_INSN_P
41 CGEN_INSN_INT buffer [1];
42#define INSN_VALUE(buf) (*(buf))
43#else
44 unsigned char buffer [CGEN_MAX_INSN_SIZE];
45#define INSN_VALUE(buf) (buf)
46#endif
47 char * addr;
48 fragS * frag;
49 int num_fixups;
50 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
51 int indices [MAX_OPERAND_INSTANCES];
52}
53epiphany_insn;
54
55const char comment_chars[] = ";";
56const char line_comment_chars[] = "#";
57const char line_separator_chars[] = "`";
58const char EXP_CHARS[] = "eE";
59const char FLT_CHARS[] = "fFdD";
60
61/* Flag to detect when switching to code section where insn alignment is
62 implied. */
63static bfd_boolean force_code_align = FALSE;
64
65static void
66epiphany_elf_section_rtn (int i)
67{
68 obj_elf_section (i);
69
70 if (force_code_align)
71 {
72 /* The s_align_ptwo function expects that we are just after a .align
73 directive and it will either try and read the align value or stop
74 if end of line so we must fake it out so it thinks we are at the
75 end of the line. */
76 char *old_input_line_pointer = input_line_pointer;
77
78 input_line_pointer = "\n";
79 s_align_ptwo (1);
80 force_code_align = FALSE;
81
82 /* Restore. */
83 input_line_pointer = old_input_line_pointer;
84 }
85}
86
87static void
88epiphany_elf_section_text (int i)
89{
90 char *old_input_line_pointer;
91
92 obj_elf_text (i);
93
94 /* The s_align_ptwo function expects that we are just after a .align
95 directive and it will either try and read the align value or stop if
96 end of line so we must fake it out so it thinks we are at the end of
97 the line. */
98 old_input_line_pointer = input_line_pointer;
99 input_line_pointer = "\n";
100 s_align_ptwo (1);
101 force_code_align = FALSE;
102 /* Restore. */
103 input_line_pointer = old_input_line_pointer;
104}
105
106/* The target specific pseudo-ops which we support. */
107const pseudo_typeS md_pseudo_table[] =
108{
109 { "text", epiphany_elf_section_text, 0 },
110 { "sect", epiphany_elf_section_rtn, 0 },
111 /* .word should be 32 bits. */
112 { "word", cons, 4 },
113 { "cpu", s_ignore, 0 },
114 { "thumb_func", s_ignore, 0 },
115 { "code", s_ignore, 0 },
116 { NULL, NULL, 0 }
117};
118
119\f
120
121enum options
122{
123 OPTION_CPU_EPIPHANY = OPTION_MD_BASE,
124 OPTION_CPU_EPIPHANY16
125};
126
127struct option md_longopts[] =
128{
129 { "mepiphany ", no_argument, NULL, OPTION_CPU_EPIPHANY },
130 { "mepiphany16", no_argument, NULL, OPTION_CPU_EPIPHANY16 },
131 { NULL, no_argument, NULL, 0 },
132};
133
134size_t md_longopts_size = sizeof (md_longopts);
135
136const char * md_shortopts = "";
137
138int
139md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
140{
141 return 0; /* No target-specific options. */
142}
143
144void
145md_show_usage (FILE * stream)
146{
147 fprintf (stream, _("EPIPHANY specific command line options:\n"));
148}
149
150\f
151void
152md_begin (void)
153{
154 /* Initialize the `cgen' interface. */
155
156 /* Set the machine number and endian. */
157 gas_cgen_cpu_desc = epiphany_cgen_cpu_open (CGEN_CPU_OPEN_MACHS,
158 bfd_mach_epiphany32,
159 CGEN_CPU_OPEN_ENDIAN,
160 CGEN_ENDIAN_LITTLE,
161 CGEN_CPU_OPEN_END);
162 epiphany_cgen_init_asm (gas_cgen_cpu_desc);
163
164 /* This is a callback from cgen to gas to parse operands. */
165 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
166
167 /* Set the machine type. */
168 bfd_default_set_arch_mach (stdoutput, bfd_arch_epiphany, bfd_mach_epiphany32);
169}
170
171valueT
172md_section_align (segT segment, valueT size)
173{
174 int align = bfd_get_section_alignment (stdoutput, segment);
175
8d3842cd 176 return ((size + (1 << align) - 1) & -(1 << align));
cfb8c092
NC
177}
178
179\f
180/* Functions concerning relocs. */
181
182long
183md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
184{
185 abort ();
186}
187
188/* Write a value out to the object file, using the appropriate endianness. */
189
190void
191md_number_to_chars (char * buf, valueT val, int n)
192{
193 number_to_chars_littleendian (buf, val, n);
194}
195
196int
197epiphany_elf_section_flags (int flags,
198 int attr ATTRIBUTE_UNUSED,
199 int type ATTRIBUTE_UNUSED)
200{
201 /* This is used to detect when the section changes to an executable section.
202 This function is called by the elf section processing. When we note an
203 executable section specifier we set an internal flag to denote when
204 word alignment should be forced. */
205 if (flags & SEC_CODE)
206 force_code_align = TRUE;
207
208 return flags;
209}
210
211/* Non-zero if we are generating PIC code. */
212int pic_code;
213
214/* Epiphany er_flags. */
215static int epiphany_flags = 0;
216
217/* Relocations against symbols are done in two
218 parts, with a HI relocation and a LO relocation. Each relocation
219 has only 16 bits of space to store an addend. This means that in
220 order for the linker to handle carries correctly, it must be able
221 to locate both the HI and the LO relocation. This means that the
222 relocations must appear in order in the relocation table.
223
224 In order to implement this, we keep track of each unmatched HI
225 relocation. We then sort them so that they immediately precede the
226 corresponding LO relocation. */
227
228struct epiphany_hi_fixup
229{
230 /* Next HI fixup. */
231 struct epiphany_hi_fixup *next;
232
233 /* This fixup. */
234 fixS *fixp;
235
236 /* The section this fixup is in. */
237 segT seg;
238};
239
240\f
241#define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
242static symbolS * GOT_symbol;
243
244static inline bfd_boolean
245epiphany_PIC_related_p (symbolS *sym)
246{
247 expressionS *exp;
248
249 if (! sym)
250 return FALSE;
251
252 if (sym == GOT_symbol)
253 return TRUE;
254
255 exp = symbol_get_value_expression (sym);
256
257 return (exp->X_op == O_PIC_reloc
258 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM24
259 || exp->X_md == BFD_RELOC_EPIPHANY_SIMM8
260 || epiphany_PIC_related_p (exp->X_add_symbol)
261 || epiphany_PIC_related_p (exp->X_op_symbol));
262}
263
264/* Perform target dependent relocations that are done at compile time.
265 There aren't very many of these. */
266
267void
268epiphany_apply_fix (fixS *fixP, valueT *valP, segT seg)
269{
270 if (fixP->fx_addsy == (symbolS *) NULL)
271 fixP->fx_done = 1;
272
273 if (((int) fixP->fx_r_type < (int) BFD_RELOC_UNUSED)
274 && fixP->fx_done)
275 {
276 /* Install EPIPHANY-dependent relocations HERE because nobody else
277 will. */
278 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
279 unsigned char *insn = (unsigned char *)where;
280 valueT value = * valP;
281
282 switch (fixP->fx_r_type)
283 {
284 default:
285 break;
286
287 case BFD_RELOC_NONE:
288 return;
289
290 case BFD_RELOC_EPIPHANY_SIMM11:
291 where[0] = where[0] | ((value & 1) << 7);
292 where[1] = where[1] | ((value & 6) >> 1);
293 where[2] = (value >> 3) & 0xff;
294 return;
295
296 case BFD_RELOC_EPIPHANY_IMM11:
297 where[0] = where[0] | ((value & 1) << 7);
298 where[1] = where[1] | ((value & 6) >> 1);
299 where[2] = (value >> 3) & 0xff;
300 return;
301
302 case BFD_RELOC_EPIPHANY_SIMM8:
303 md_number_to_chars (where+1, value>>1, 1);
304 return;
305
306 case BFD_RELOC_EPIPHANY_SIMM24:
307 md_number_to_chars (where+1, value>>1, 3);
308 return;
309
310 case BFD_RELOC_EPIPHANY_HIGH:
311 value >>= 16;
312 /* fall thru */
313 case BFD_RELOC_EPIPHANY_LOW:
314 value = (((value & 0xff) << 5) | insn[0])
315 | (insn[1] << 8)
316 | ((value & 0xff00) << 12)
317 | (insn[2] << 16);
318 md_number_to_chars (where, value, 3);
319 return;
320 }
321 }
322
323 /* Just do the default if we can't special case. */
324 return gas_cgen_md_apply_fix (fixP, valP, seg);
325}
326
327
328/* This is called from HANDLE_ALIGN in write.c. Fill in the contents
329 of an rs_align_code fragment. 0x01a2 is 16-bit pattern for a "nop". */
330
331static const unsigned char nop_pattern[] = { 0xa2, 0x01 };
332
333void
334epiphany_handle_align (fragS *fragp)
335{
336 int bytes, fix;
337 char *p;
338
339 if (fragp->fr_type != rs_align_code)
340 return;
341
342 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
343 p = fragp->fr_literal + fragp->fr_fix;
344 fix = 0;
345
346 if (bytes & 1)
347 {
348 fix = 1;
349 *p++ = 0;
350 bytes--;
351 }
352
353 if (bytes & 2)
354 {
355 memcpy (p, nop_pattern, 2);
356 p += 2;
357 bytes -= 2;
358 fix += 2;
359 }
360 fragp->fr_fix += fix;
361}
362\f
363/* Read a comma separated incrementing list of register names
364 and form a bit mask of upto 15 registers 0..14. */
365
366static const char *
367parse_reglist (const char * s, int * mask)
368{
369 int regmask = 0;
370
371 while (*s)
372 {
373 long value;
374
375 while (*s == ' ')
376 ++s;
377
378 /* Parse a list with "," or "}" as limiters. */
379 const char *errmsg
380 = cgen_parse_keyword (gas_cgen_cpu_desc, &s,
381 &epiphany_cgen_opval_gr_names, &value);
382 if (errmsg)
383 return errmsg;
384
385 if (value > 15)
386 return _("register number too large for push/pop");
387
388 regmask |= 1 << value;
389 if (regmask < *mask)
390 return _("register is out of order");
391 *mask |= regmask;
392
393 while (*s==' ')
394 ++s;
395
396 if (*s == '}')
397 return NULL;
398 else if (*s++ == ',')
399 continue;
400 else
401 return _("bad register list");
402 }
403
404 return _("malformed reglist in push/pop");
405}
406
407\f
408void
409md_assemble (char *str)
410{
411 epiphany_insn insn;
412 char *errmsg = 0;
413 const char * pperr = 0;
414 int regmask=0, push=0, pop=0;
415
416 memset (&insn, 0, sizeof (insn));
417
418 /* Special-case push/pop instruction macros. */
419 if (0 == strncmp (str, "push {", 6))
420 {
421 char * s = str + 6;
422 push = 1;
423 pperr = parse_reglist (s, &regmask);
424 }
425 else if (0 == strncmp (str, "pop {", 5))
426 {
427 char * s = str + 5;
428 pop = 1;
429 pperr = parse_reglist (s, &regmask);
430 }
431
432 if (pperr)
433 {
434 as_bad ("%s", pperr);
435 return;
436 }
437
438 if (push && regmask)
439 {
440 char buff[20];
441 int i,p ATTRIBUTE_UNUSED;
442
443 md_assemble ("mov r15,4");
444 md_assemble ("sub sp,sp,r15");
445
446 for (i = 0, p = 1; i <= 15; ++i, regmask >>= 1)
447 {
448 if (regmask == 1)
449 sprintf (buff, "str r%d,[sp]", i); /* Last one. */
450 else if (regmask & 1)
451 sprintf (buff, "str r%d,[sp],-r15", i);
452 else
453 continue;
454 md_assemble (buff);
455 }
456 return;
457 }
458 else if (pop && regmask)
459 {
460 char buff[20];
461 int i,p;
462
463 md_assemble ("mov r15,4");
464
465 for (i = 15, p = 1 << 15; i >= 0; --i, p >>= 1)
466 if (regmask & p)
467 {
468 sprintf (buff, "ldr r%d,[sp],+r15", i);
469 md_assemble (buff);
470 }
471 return;
472 }
473
474 /* Initialize GAS's cgen interface for a new instruction. */
475 gas_cgen_init_parse ();
476
477 insn.insn = epiphany_cgen_assemble_insn
478 (gas_cgen_cpu_desc, str, &insn.fields, insn.buffer, & errmsg);
479
480 if (!insn.insn)
481 {
482 as_bad ("%s", errmsg);
483 return;
484 }
485
486 if (CGEN_INSN_BITSIZE (insn.insn) == 32)
487 {
488 /* Doesn't really matter what we pass for RELAX_P here. */
489 gas_cgen_finish_insn (insn.insn, insn.buffer,
490 CGEN_FIELDS_BITSIZE (&insn.fields), 1, NULL);
491 }
492 else
493 {
494 if (CGEN_INSN_BITSIZE (insn.insn) != 16)
495 abort ();
496
497 insn.orig_insn = insn.insn;
498
499 gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
500 CGEN_FIELDS_BITSIZE (&insn.fields),
501 1 /* relax_p */, NULL);
502 }
503
504 /* Checks for behavioral restrictions on LD/ST instructions. */
505#define DISPMOD _("destination register modified by displacement-post-modified address")
506#define LDSTODD _("ldrd/strd requires even:odd register pair")
507
508 /* Helper macros for spliting apart instruction fields. */
509#define ADDR_POST_MODIFIED(i) (((i) >> 25) & 0x1)
510#define ADDR_SIZE(i) (((i) >> 5) & 3)
511#define ADDR_LOADSTORE(i) (((i) >> 4) & 0x1)
512
513 switch (insn.buffer[0] & 0xf)
514 {
515 /* Post-modify registers cannot be destinations. */
516 case OP4_LDSTR16P:
517 {
518 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD)
519 if (insn.fields.f_rd == insn.fields.f_rn /* Postmodify dest. */
520 || (insn.fields.f_rd+1 == insn.fields.f_rn
521 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
522 {
523 as_bad ("%s", DISPMOD);
524 return;
525 }
526 if ((insn.fields.f_rd & 1) /* Odd-numbered register... */
527 && insn.fields.f_wordsize == OPW_DOUBLE) /* ...and 64 bit transfer. */
528 {
529 as_bad ("%s", LDSTODD);
530 return;
531 }
532 break;
533 }
534
535 case OP4_LDSTRP:
536 {
537 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD) /* A load. */
538 if (insn.fields.f_rd6 == insn.fields.f_rn6 /* Postmodify dest. */
539 /* Check for regpair postindexed. */
540 || (insn.fields.f_rd6 + 1 == insn.fields.f_rn6
541 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE))
542 {
543 as_bad ("%s", DISPMOD);
544 return;
545 }
546 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
547 /* Lsb of RD odd and 64 bit transfer. */
548 {
549 as_bad ("%s", LDSTODD);
550 return;
551 }
552 break;
553 }
554
555 case OP4_LDSTR16X:
556 case OP4_LDSTR16D:
557 {
558 /* Check for unaligned load/store double. */
559 if ((insn.fields.f_rd & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
560 /* Lsb of RD odd and 64 bit transfer. */
561 {
562 as_bad ("%s", LDSTODD);
563 return;
564 }
565 break;
566 }
567
568 case OP4_LDSTRD:
569 {
570 /* Check for load to post-modified register. */
571 if (ADDR_LOADSTORE (insn.buffer[0]) == OP_LOAD /* A load. */
572 && ADDR_POST_MODIFIED (insn.buffer[0]) == PMOD_POST /* Post-mod. */
573 && (insn.fields.f_rd6 == insn.fields.f_rn6
574 || (insn.fields.f_rd6+1 == insn.fields.f_rn6
575 && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)))
576 {
577 as_bad ("%s", DISPMOD);
578 return;
579 }
580 }
581 /* fall-thru. */
582
583 case OP4_LDSTRX:
584 {
585 /* Check for unaligned load/store double. */
586 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
587 {
588 as_bad ("%s", LDSTODD);
589 return;
590 }
591 break;
592 }
593
594 default:
595 break;
596 }
597}
598
599/* The syntax in the manual says constants begin with '#'.
600 We just ignore it. */
601
602void
603md_operand (expressionS *expressionP)
604{
605 if (*input_line_pointer == '#')
606 {
607 input_line_pointer++;
608 expression (expressionP);
609 }
610}
611
612symbolS *
613md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
614{
615 return NULL;
616}
617\f
618/* Interface to relax_segment. */
619
620/* FIXME: Build table by hand, get it working, then machine generate. */
621
622const relax_typeS md_relax_table[] =
623{
624 /* The fields are:
625 1) most positive reach of this state,
626 2) most negative reach of this state,
627 3) how many bytes this mode will add to the size of the current frag
628 4) which index into the table to try if we can't fit into this one. */
629
630 /* The first entry must be unused because an `rlx_more' value of zero ends
631 each list. */
632 {1, 1, 0, EPIPHANY_RELAX_NONE},
633 {0, 0, 0, EPIPHANY_RELAX_NONE}, /* Also a dummy entry to indicate we need to expand codes. */
634
635 /* The displacement used by GAS is from the end of the 2 byte insn,
636 so we subtract 2 from the following. */
637 /* 16 bit insn, 8 bit disp -> +127 words, -128 words. */
638 {0x00000100 - 1 - 2, -0x00000100 - 2, 0, EPIPHANY_RELAX_BRANCH_LONG },
639 /* 32 bit insn, 24 bit disp -> 25 bit range. */
640 {0x01000000 - 1 - 2, -0x01000000 - 2, 2, EPIPHANY_RELAX_NONE },
641
642 /* addi/subi 3 bits -4..+3. */
643 { 3, -4,0, EPIPHANY_RELAX_ARITH_SIMM11 },
644 /* addi/subi 11 bits. */
645 { 1023, -1024,2, EPIPHANY_RELAX_NONE },
646
647 /* mov r,imm8. */
648 { 255, 0,0, EPIPHANY_RELAX_MOV_IMM16 },
649 /* mov r,imm16. */
650 { 65535, 0,2, EPIPHANY_RELAX_NONE },
651
652 /* ld/st rd,[rn,imm3]. */
653 { 7, 0,0, EPIPHANY_RELAX_LDST_IMM11},
654 /* ld/st rd,[rn,imm11]. */
655 { 2047, 0,2, EPIPHANY_RELAX_NONE }
656
657};
658
659static const EPIPHANY_RELAX_TYPES relax_insn[] =
660{
661 EPIPHANY_RELAX_BRANCH_SHORT, /* OP4_BRANCH16 */
662 EPIPHANY_RELAX_NONE, /* OP4_LDSTR16X */
663 EPIPHANY_RELAX_NONE, /* OP4_FLOW16 */
664 EPIPHANY_RELAX_ARITH_SIMM3, /* OP4_IMM16 - special */
665 EPIPHANY_RELAX_LDST_IMM3, /* OP4_LDSTR16D */
666 EPIPHANY_RELAX_NONE, /* OP4_LDSTR126P */
667 EPIPHANY_RELAX_NONE, /* OP4_LSHIFT16 */
668 EPIPHANY_RELAX_NONE, /* OP4_DSP16 */
669 EPIPHANY_RELAX_BRANCH_LONG, /* OP4_BRANCH */
670 EPIPHANY_RELAX_NONE, /* OP4_LDSTRX */
671 EPIPHANY_RELAX_NONE, /* OP4_ALU16 */
672 EPIPHANY_RELAX_ARITH_SIMM11, /* OP4_IMM32 - special */
673 EPIPHANY_RELAX_LDST_IMM11, /* OP4_LDSTRD */
674 EPIPHANY_RELAX_NONE, /* OP4_LDSTRP */
675 EPIPHANY_RELAX_NONE, /* OP4_ASHIFT16 */
676 EPIPHANY_RELAX_NONE /* OP4_MISC */
677};
678
679long
680epiphany_relax_frag (segT segment, fragS *fragP, long stretch)
681{
682 /* Address of branch insn. */
683 long address ATTRIBUTE_UNUSED = fragP->fr_address + fragP->fr_fix - 2;
684 long growth = 0;
685
686 if (fragP->fr_subtype == EPIPHANY_RELAX_NEED_RELAXING)
687 {
688 EPIPHANY_RELAX_TYPES subtype = relax_insn [*fragP->fr_opcode & 0xf];
689
690 /* Special cases add/sub vs mov immediates. */
691 if (subtype == EPIPHANY_RELAX_ARITH_SIMM3)
692 {
693 if ((*fragP->fr_opcode & 0x10) == 0)
694 subtype = EPIPHANY_RELAX_MOV_IMM8;
695 }
696 else if (subtype == EPIPHANY_RELAX_ARITH_SIMM11)
697 {
698 if ((*fragP->fr_opcode & 0x10) == 0)
699 subtype = EPIPHANY_RELAX_MOV_IMM16;
700 }
701
702 /* Remember refinements for the future. */
703 fragP->fr_subtype = subtype;
704 }
705
706 growth = relax_frag (segment, fragP, stretch);
707
708 return growth;
709}
710
711/* Return an initial guess of the length by which a fragment must grow to
712 hold a branch to reach its destination.
713 Also updates fr_type/fr_subtype as necessary.
714
715 Called just before doing relaxation.
716 Any symbol that is now undefined will not become defined.
717 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
718 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
719 Although it may not be explicit in the frag, pretend fr_var starts
720 with a 0 value. */
721
722int
723md_estimate_size_before_relax (fragS *fragP, segT segment)
724{
725 /* The only thing we have to handle here are symbols outside of the
726 current segment. They may be undefined or in a different segment in
727 which case linker scripts may place them anywhere.
728 However, we can't finish the fragment here and emit the reloc as insn
729 alignment requirements may move the insn about. */
730 if (S_GET_SEGMENT (fragP->fr_symbol) != segment
731 || S_IS_EXTERNAL (fragP->fr_symbol)
732 || S_IS_WEAK (fragP->fr_symbol))
733 {
734 /* The symbol is undefined in this segment. Change the
735 relaxation subtype to the max allowable and leave all further
736 handling to md_convert_frag. */
737
738 EPIPHANY_RELAX_TYPES subtype;
739 /* We haven't relaxed this at all, so the relaxation type may be
740 completely wrong. Set the subtype correctly. */
741 epiphany_relax_frag (segment, fragP, 0);
742 subtype = fragP->fr_subtype;
743
744 switch (subtype)
745 {
746 case EPIPHANY_RELAX_LDST_IMM3:
747 subtype = EPIPHANY_RELAX_LDST_IMM11;
748 break;
749 case EPIPHANY_RELAX_BRANCH_SHORT:
750 subtype = EPIPHANY_RELAX_BRANCH_LONG;
751 break;
752 case EPIPHANY_RELAX_MOV_IMM8:
753 subtype = EPIPHANY_RELAX_MOV_IMM16;
754 break;
755 case EPIPHANY_RELAX_ARITH_SIMM3:
756 subtype = EPIPHANY_RELAX_ARITH_SIMM11;
757 break;
758
759 default:
760 break;
761 }
762
763 fragP->fr_subtype = subtype;
764
765 {
766 const CGEN_INSN *insn;
767 int i;
768
769 /* Update the recorded insn. */
770
771 for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
772 {
773 if ((strcmp (CGEN_INSN_MNEMONIC (insn),
774 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
775 == 0)
776 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
777 break;
778 }
779
780 if (i == 4)
781 abort ();
782
783 fragP->fr_cgen.insn = insn;
784 }
785 }
786
787 return md_relax_table[fragP->fr_subtype].rlx_length;
788}
789
790/* *FRAGP has been relaxed to its final size, and now needs to have
791 the bytes inside it modified to conform to the new size.
792
793 Called after relaxation is finished.
794 fragP->fr_type == rs_machine_dependent.
795 fragP->fr_subtype is the subtype of what the address relaxed to. */
796
797void
798md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
799 segT sec,
800 fragS *fragP)
801{
802 char *opcode;
803 char *displacement;
804 int target_address;
805 int opcode_address;
806 int extension;
807 int addend;
808 int opindx = -1;
809
810 opcode = fragP->fr_opcode;
811
812 /* Address opcode resides at in file space. */
813 opcode_address = fragP->fr_address + fragP->fr_fix - 2;
814 extension = 0;
815 displacement = &opcode[1];
816
817 /* Set up any addend necessary for branches. */
818 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
819 || S_IS_EXTERNAL (fragP->fr_symbol)
820 || S_IS_WEAK (fragP->fr_symbol))
821 {
822 /* Symbol must be resolved by linker. */
823 if (fragP->fr_offset & 1)
824 as_warn (_("Addend to unresolved symbol not on word boundary."));
825 addend = 0;
826 }
827 else
828 {
829 /* Address we want to reach in file space. */
830 target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
831 addend = (target_address - (opcode_address & -2));
832 }
833
834 /* Do all the housekeeping for frag conversions. */
835 switch (fragP->fr_subtype)
836 {
837 case EPIPHANY_RELAX_ARITH_SIMM11:
838 *opcode |= OP4_IMM32;
839 displacement = &opcode[0];
840 extension += 3;
841
842 addend
843 = (((addend & 0x7) << 7)
844 | opcode[0]
845 | ((addend & 0x7f8) << 13)
846 | (opcode[1] << 8)
847 | (opcode[2] << 16));
848
849 opindx = EPIPHANY_OPERAND_SIMM11;
850 break;
851
852 case EPIPHANY_RELAX_BRANCH_LONG:
853 /* Branches differ only in low nibble of instruction being 8 not 0.
854 24 bit displacement goes to bytes 1..3 . */
855 *opcode |= OP4_BRANCH;
856 extension += 2;
857
858 addend >>= 1; /* Convert to word offset. */
859 opindx = EPIPHANY_OPERAND_SIMM24;
860 break;
861
862 case EPIPHANY_RELAX_MOV_IMM16:
863 *opcode |= OP4_IMM32;
864 extension += 3;
865
866 addend
867 = (((addend & 0xff00) << 12)
868 | (opcode[2] << 16)
869 | ((addend & 0x00ff) << 5)
870 | (opcode[1] << 8)
871 | opcode[0]);
872 displacement = &opcode[0];
873 opindx = EPIPHANY_OPERAND_IMM16;
874 break;
875
876 case EPIPHANY_RELAX_LDST_IMM11:
877 *opcode |= OP4_LDSTRD;
878 displacement = &opcode[0];
879 extension += 3;
880
881 if (addend < 0)
882 /* Convert twos-complement address value to sign-magnitude. */
883 addend = (-addend & 0x7ff) | 0x800;
884
885 addend
886 = (((addend & 0x7) << 5)
887 | opcode[0]
888 | ((addend & 0xff8) << 13)
889 | (opcode[1] << 8)
890 | (opcode[2] << 16));
891
892 opindx = EPIPHANY_OPERAND_DISP11;
893 break;
894
895 case EPIPHANY_RELAX_ARITH_SIMM3:
896 addend = ((addend & 7) << 5) | opcode[0];
897 opindx = EPIPHANY_OPERAND_SIMM3;
898 break;
899
900 case EPIPHANY_RELAX_LDST_IMM3:
901 addend = ((addend & 7) << 5) | opcode[0];
902 opindx = EPIPHANY_OPERAND_DISP3;
b7b2bb1d 903 break;
cfb8c092
NC
904
905 case EPIPHANY_RELAX_BRANCH_SHORT:
906 addend >>= 1; /* Convert to a word offset. */
907 displacement = & opcode[1];
908 opindx = EPIPHANY_OPERAND_SIMM8;
909 break;
910
911 case EPIPHANY_RELAX_MOV_IMM8:
912 addend
913 = (((addend & 0xff) << 5)
914 | opcode[0]
915 | (opcode[1] << 8));
916 opindx = EPIPHANY_OPERAND_IMM8;
917 break;
918
919 case EPIPHANY_RELAX_NONE:
920 case EPIPHANY_RELAX_NEED_RELAXING:
921 default: /* Anything else? */
922 as_bad ("unrecognized fragment subtype");
923 break;
924 }
925
926 /* Create a relocation for symbols that must be resolved by the linker.
927 Otherwise output the completed insn. */
928
929 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
930 || S_IS_EXTERNAL (fragP->fr_symbol)
931 || S_IS_WEAK (fragP->fr_symbol))
932 {
933 fixS *fixP;
934 const CGEN_OPERAND *operand
935 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx);
936 bfd_reloc_code_real_type reloc_type;
937
938 gas_assert (fragP->fr_cgen.insn != 0);
939
940 reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL);
941
942 fixP = gas_cgen_record_fixup (fragP,
943 /* Offset of insn in frag. */
944 (opcode - fragP->fr_literal),
945 fragP->fr_cgen.insn,
946 CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8,
947 operand,
948 reloc_type,
949 fragP->fr_symbol, fragP->fr_offset);
950 fixP->fx_r_type = fixP->fx_cgen.opinfo;
951 }
952
953 md_number_to_chars (displacement, (valueT) addend, extension + 1);
954
955 fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added. */
956}
957
958\f
959/* Functions concerning relocs. */
960
961/* The location from which a PC relative jump should be calculated,
962 given a PC relative reloc. */
963
964long
965md_pcrel_from_section (fixS *fixP, segT sec)
966{
967 if (fixP->fx_addsy != (symbolS *) NULL
968 && (!S_IS_DEFINED (fixP->fx_addsy)
969 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
970 || S_IS_EXTERNAL (fixP->fx_addsy)
971 || S_IS_WEAK (fixP->fx_addsy)))
972 return 0;
973
974 return fixP->fx_frag->fr_address + fixP->fx_where;
975}
976
977/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
978 Returns BFD_RELOC_NONE if no reloc type can be found.
979 *FIXP may be modified if desired. */
980
981bfd_reloc_code_real_type
982md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
983 const CGEN_OPERAND *operand,
984 fixS *fixP ATTRIBUTE_UNUSED)
985{
986 switch (operand->type)
987 {
988 case EPIPHANY_OPERAND_SIMM11:
989 return BFD_RELOC_EPIPHANY_SIMM11;
990 case EPIPHANY_OPERAND_DISP11:
991 return BFD_RELOC_EPIPHANY_IMM11;
992
993 case EPIPHANY_OPERAND_SIMM8:
994 return BFD_RELOC_EPIPHANY_SIMM8;
995 case EPIPHANY_OPERAND_SIMM24:
996 return BFD_RELOC_EPIPHANY_SIMM24;
997
998 case EPIPHANY_OPERAND_IMM8:
999 return BFD_RELOC_EPIPHANY_IMM8;
1000
1001 case EPIPHANY_OPERAND_IMM16:
1002 if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn)))
1003 return BFD_RELOC_EPIPHANY_HIGH;
1004 else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn)))
1005 return BFD_RELOC_EPIPHANY_LOW;
1006 else
1007 as_bad ("unknown imm16 operand");
1008 /* fall-thru */
1009
1010 default:
1011 break;
1012 }
1013 return BFD_RELOC_NONE;
1014}
1015
1016\f
1017/* Turn a string in input_line_pointer into a floating point constant
1018 of type TYPE, and store the appropriate bytes in *LITP. The number
1019 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1020 returned, or NULL on OK. */
1021
1022/* Equal to MAX_PRECISION in atof-ieee.c. */
1023#define MAX_LITTLENUMS 6
1024
1025char *
1026md_atof (int type, char *litP, int *sizeP)
1027{
1028 return ieee_md_atof (type, litP, sizeP, FALSE);
1029}
1030
1031/* Return true if can adjust the reloc to be relative to its section
1032 (such as .data) instead of relative to some symbol. */
1033
1034bfd_boolean
1035epiphany_fix_adjustable (fixS *fixP)
1036{
1037 bfd_reloc_code_real_type reloc_type;
1038
1039 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1040 {
1041 const CGEN_INSN *insn = fixP->fx_cgen.insn;
1042 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1043 const CGEN_OPERAND *operand =
1044 cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindex);
1045
1046 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1047 }
1048 else
1049 reloc_type = fixP->fx_r_type;
1050
1051 if (fixP->fx_addsy == NULL)
1052 return TRUE;
1053
1054 /* Prevent all adjustments to global symbols. */
1055 if (S_IS_EXTERNAL (fixP->fx_addsy))
1056 return FALSE;
1057
1058 if (S_IS_WEAK (fixP->fx_addsy))
1059 return FALSE;
1060
1061 if (pic_code
1062 && (reloc_type == BFD_RELOC_EPIPHANY_SIMM24
1063 || reloc_type == BFD_RELOC_EPIPHANY_SIMM8
1064 || reloc_type == BFD_RELOC_EPIPHANY_HIGH
1065 || reloc_type == BFD_RELOC_EPIPHANY_LOW))
1066 return FALSE;
1067
1068 /* Since we don't use partial_inplace, we must not reduce symbols in
1069 mergable sections to their section symbol. */
1070 if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
1071 return FALSE;
1072
1073 return TRUE;
1074}
1075
1076void
1077epiphany_elf_final_processing (void)
1078{
1079 elf_elfheader (stdoutput)->e_flags |= epiphany_flags;
1080}
1081
1082int
1083epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED)
1084{
1085 LITTLENUM_TYPE words[2];
1086
1087 switch (opinfo)
1088 {
1089 case BFD_RELOC_EPIPHANY_LOW:
1090 case BFD_RELOC_EPIPHANY_HIGH:
1091 break;
1092 default:
1093 return opinfo;
1094 }
1095
1096 /* Doing a %LOW or %HIGH. */
1097 switch (exp->X_op)
1098 {
1099 default:
1100 return opinfo;
1101 case O_big: /* Bignum. */
1102 if (exp->X_add_number > 0) /* Integer value too large. */
1103 return opinfo;
1104 }
1105
1106 /* Convert to SP number. */
1107 gen_to_words (words, 2, 8L);
1108 exp->X_add_number = words[1] | (words[0] << 16);
1109 exp->X_op = O_constant;
1110 return opinfo;
1111}
This page took 0.22684 seconds and 4 git commands to generate.