Constify more
[deliverable/binutils-gdb.git] / gas / config / tc-epiphany.c
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.
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. */
35 typedef 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 }
53 epiphany_insn;
54
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";
60
61 /* Flag to detect when switching to code section where insn alignment is
62 implied. */
63 static bfd_boolean force_code_align = FALSE;
64
65 static void
66 epiphany_elf_section_rtn (int i)
67 {
68 obj_elf_section (i);
69
70 if (force_code_align)
71 {
72 do_align (1, NULL, 0, 0);
73 force_code_align = FALSE;
74 }
75 }
76
77 static void
78 epiphany_elf_section_text (int i)
79 {
80 obj_elf_text (i);
81
82 do_align (1, NULL, 0, 0);
83 force_code_align = FALSE;
84 }
85
86 /* The target specific pseudo-ops which we support. */
87 const pseudo_typeS md_pseudo_table[] =
88 {
89 { "text", epiphany_elf_section_text, 0 },
90 { "sect", epiphany_elf_section_rtn, 0 },
91 /* .word should be 32 bits. */
92 { "word", cons, 4 },
93 { "cpu", s_ignore, 0 },
94 { "thumb_func", s_ignore, 0 },
95 { "code", s_ignore, 0 },
96 { NULL, NULL, 0 }
97 };
98
99 \f
100
101 enum options
102 {
103 OPTION_CPU_EPIPHANY = OPTION_MD_BASE,
104 OPTION_CPU_EPIPHANY16
105 };
106
107 struct option md_longopts[] =
108 {
109 { "mepiphany ", no_argument, NULL, OPTION_CPU_EPIPHANY },
110 { "mepiphany16", no_argument, NULL, OPTION_CPU_EPIPHANY16 },
111 { NULL, no_argument, NULL, 0 },
112 };
113
114 size_t md_longopts_size = sizeof (md_longopts);
115
116 const char * md_shortopts = "";
117
118 int
119 md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg ATTRIBUTE_UNUSED)
120 {
121 return 0; /* No target-specific options. */
122 }
123
124 void
125 md_show_usage (FILE * stream)
126 {
127 fprintf (stream, _("EPIPHANY specific command line options:\n"));
128 }
129
130 \f
131 void
132 md_begin (void)
133 {
134 /* Initialize the `cgen' interface. */
135
136 /* Set the machine number and endian. */
137 gas_cgen_cpu_desc = epiphany_cgen_cpu_open (CGEN_CPU_OPEN_MACHS,
138 bfd_mach_epiphany32,
139 CGEN_CPU_OPEN_ENDIAN,
140 CGEN_ENDIAN_LITTLE,
141 CGEN_CPU_OPEN_END);
142 epiphany_cgen_init_asm (gas_cgen_cpu_desc);
143
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);
146
147 /* Set the machine type. */
148 bfd_default_set_arch_mach (stdoutput, bfd_arch_epiphany, bfd_mach_epiphany32);
149 }
150
151 valueT
152 md_section_align (segT segment, valueT size)
153 {
154 int align = bfd_get_section_alignment (stdoutput, segment);
155
156 return ((size + (1 << align) - 1) & -(1 << align));
157 }
158
159 \f
160 /* Functions concerning relocs. */
161
162 long
163 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
164 {
165 abort ();
166 }
167
168 /* Write a value out to the object file, using the appropriate endianness. */
169
170 void
171 md_number_to_chars (char * buf, valueT val, int n)
172 {
173 number_to_chars_littleendian (buf, val, n);
174 }
175
176 int
177 epiphany_elf_section_flags (int flags,
178 int attr ATTRIBUTE_UNUSED,
179 int type ATTRIBUTE_UNUSED)
180 {
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;
187
188 return flags;
189 }
190
191 /* Non-zero if we are generating PIC code. */
192 int pic_code;
193
194 /* Epiphany er_flags. */
195 static int epiphany_flags = 0;
196
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.
203
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. */
207
208 struct epiphany_hi_fixup
209 {
210 /* Next HI fixup. */
211 struct epiphany_hi_fixup *next;
212
213 /* This fixup. */
214 fixS *fixp;
215
216 /* The section this fixup is in. */
217 segT seg;
218 };
219
220 \f
221 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
222 static symbolS * GOT_symbol;
223
224 static inline bfd_boolean
225 epiphany_PIC_related_p (symbolS *sym)
226 {
227 expressionS *exp;
228
229 if (! sym)
230 return FALSE;
231
232 if (sym == GOT_symbol)
233 return TRUE;
234
235 exp = symbol_get_value_expression (sym);
236
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));
242 }
243
244 /* Perform target dependent relocations that are done at compile time.
245 There aren't very many of these. */
246
247 void
248 epiphany_apply_fix (fixS *fixP, valueT *valP, segT seg)
249 {
250 if (fixP->fx_addsy == (symbolS *) NULL)
251 fixP->fx_done = 1;
252
253 if (((int) fixP->fx_r_type < (int) BFD_RELOC_UNUSED)
254 && fixP->fx_done)
255 {
256 /* Install EPIPHANY-dependent relocations HERE because nobody else
257 will. */
258 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
259 unsigned char *insn = (unsigned char *)where;
260 valueT value = * valP;
261
262 switch (fixP->fx_r_type)
263 {
264 default:
265 break;
266
267 case BFD_RELOC_NONE:
268 return;
269
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;
274 return;
275
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;
280 return;
281
282 case BFD_RELOC_EPIPHANY_SIMM8:
283 md_number_to_chars (where+1, value>>1, 1);
284 return;
285
286 case BFD_RELOC_EPIPHANY_SIMM24:
287 md_number_to_chars (where+1, value>>1, 3);
288 return;
289
290 case BFD_RELOC_EPIPHANY_HIGH:
291 value >>= 16;
292 /* fall thru */
293 case BFD_RELOC_EPIPHANY_LOW:
294 value = (((value & 0xff) << 5) | insn[0])
295 | (insn[1] << 8)
296 | ((value & 0xff00) << 12)
297 | (insn[2] << 16);
298 md_number_to_chars (where, value, 3);
299 return;
300 }
301 }
302
303 /* Just do the default if we can't special case. */
304 return gas_cgen_md_apply_fix (fixP, valP, seg);
305 }
306
307
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". */
310
311 static const unsigned char nop_pattern[] = { 0xa2, 0x01 };
312
313 void
314 epiphany_handle_align (fragS *fragp)
315 {
316 int bytes, fix;
317 char *p;
318
319 if (fragp->fr_type != rs_align_code)
320 return;
321
322 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
323 p = fragp->fr_literal + fragp->fr_fix;
324 fix = 0;
325
326 if (bytes & 1)
327 {
328 fix = 1;
329 *p++ = 0;
330 bytes--;
331 }
332
333 if (bytes & 2)
334 {
335 memcpy (p, nop_pattern, 2);
336 p += 2;
337 bytes -= 2;
338 fix += 2;
339 }
340 fragp->fr_fix += fix;
341 }
342 \f
343 /* Read a comma separated incrementing list of register names
344 and form a bit mask of upto 15 registers 0..14. */
345
346 static const char *
347 parse_reglist (const char * s, int * mask)
348 {
349 int regmask = 0;
350
351 while (*s)
352 {
353 long value;
354
355 while (*s == ' ')
356 ++s;
357
358 /* Parse a list with "," or "}" as limiters. */
359 const char *errmsg
360 = cgen_parse_keyword (gas_cgen_cpu_desc, &s,
361 &epiphany_cgen_opval_gr_names, &value);
362 if (errmsg)
363 return errmsg;
364
365 if (value > 15)
366 return _("register number too large for push/pop");
367
368 regmask |= 1 << value;
369 if (regmask < *mask)
370 return _("register is out of order");
371 *mask |= regmask;
372
373 while (*s==' ')
374 ++s;
375
376 if (*s == '}')
377 return NULL;
378 else if (*s++ == ',')
379 continue;
380 else
381 return _("bad register list");
382 }
383
384 return _("malformed reglist in push/pop");
385 }
386
387 \f
388 /* Assemble an instruction, push and pop pseudo instructions should have
389 already been expanded. */
390
391 static void
392 epiphany_assemble (const char *str)
393 {
394 epiphany_insn insn;
395 char *errmsg = 0;
396
397 memset (&insn, 0, sizeof (insn));
398
399 /* Initialize GAS's cgen interface for a new instruction. */
400 gas_cgen_init_parse ();
401
402 insn.insn = epiphany_cgen_assemble_insn
403 (gas_cgen_cpu_desc, str, &insn.fields, insn.buffer, & errmsg);
404
405 if (!insn.insn)
406 {
407 as_bad ("%s", errmsg);
408 return;
409 }
410
411 if (CGEN_INSN_BITSIZE (insn.insn) == 32)
412 {
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);
416 }
417 else
418 {
419 if (CGEN_INSN_BITSIZE (insn.insn) != 16)
420 abort ();
421
422 insn.orig_insn = insn.insn;
423
424 gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
425 CGEN_FIELDS_BITSIZE (&insn.fields),
426 1 /* relax_p */, NULL);
427 }
428
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")
432
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)
437
438 switch (insn.buffer[0] & 0xf)
439 {
440 /* Post-modify registers cannot be destinations. */
441 case OP4_LDSTR16P:
442 {
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))
447 {
448 as_bad ("%s", DISPMOD);
449 return;
450 }
451 if ((insn.fields.f_rd & 1) /* Odd-numbered register... */
452 && insn.fields.f_wordsize == OPW_DOUBLE) /* ...and 64 bit transfer. */
453 {
454 as_bad ("%s", LDSTODD);
455 return;
456 }
457 break;
458 }
459
460 case OP4_LDSTRP:
461 {
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))
467 {
468 as_bad ("%s", DISPMOD);
469 return;
470 }
471 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
472 /* Lsb of RD odd and 64 bit transfer. */
473 {
474 as_bad ("%s", LDSTODD);
475 return;
476 }
477 break;
478 }
479
480 case OP4_LDSTR16X:
481 case OP4_LDSTR16D:
482 {
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. */
486 {
487 as_bad ("%s", LDSTODD);
488 return;
489 }
490 break;
491 }
492
493 case OP4_LDSTRD:
494 {
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)))
501 {
502 as_bad ("%s", DISPMOD);
503 return;
504 }
505 }
506 /* fall-thru. */
507
508 case OP4_LDSTRX:
509 {
510 /* Check for unaligned load/store double. */
511 if ((insn.fields.f_rd6 & 1) && ADDR_SIZE (insn.buffer[0]) == OPW_DOUBLE)
512 {
513 as_bad ("%s", LDSTODD);
514 return;
515 }
516 break;
517 }
518
519 default:
520 break;
521 }
522 }
523
524 void
525 md_assemble (char *str)
526 {
527 const char * pperr = 0;
528 int regmask=0, push=0, pop=0;
529
530 /* Special-case push/pop instruction macros. */
531 if (0 == strncmp (str, "push {", 6))
532 {
533 char * s = str + 6;
534 push = 1;
535 pperr = parse_reglist (s, &regmask);
536 }
537 else if (0 == strncmp (str, "pop {", 5))
538 {
539 char * s = str + 5;
540 pop = 1;
541 pperr = parse_reglist (s, &regmask);
542 }
543
544 if (pperr)
545 {
546 as_bad ("%s", pperr);
547 return;
548 }
549
550 if (push && regmask)
551 {
552 char buff[20];
553 int i,p ATTRIBUTE_UNUSED;
554
555 epiphany_assemble ("mov r15,4");
556 epiphany_assemble ("sub sp,sp,r15");
557
558 for (i = 0, p = 1; i <= 15; ++i, regmask >>= 1)
559 {
560 if (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);
564 else
565 continue;
566 epiphany_assemble (buff);
567 }
568 return;
569 }
570 else if (pop && regmask)
571 {
572 char buff[20];
573 int i,p;
574
575 epiphany_assemble ("mov r15,4");
576
577 for (i = 15, p = 1 << 15; i >= 0; --i, p >>= 1)
578 if (regmask & p)
579 {
580 sprintf (buff, "ldr r%d,[sp],+r15", i);
581 epiphany_assemble (buff);
582 }
583 return;
584 }
585
586 epiphany_assemble (str);
587 }
588
589 /* The syntax in the manual says constants begin with '#'.
590 We just ignore it. */
591
592 void
593 md_operand (expressionS *expressionP)
594 {
595 if (*input_line_pointer == '#')
596 {
597 input_line_pointer++;
598 expression (expressionP);
599 }
600 }
601
602 symbolS *
603 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
604 {
605 return NULL;
606 }
607 \f
608 /* Interface to relax_segment. */
609
610 /* FIXME: Build table by hand, get it working, then machine generate. */
611
612 const relax_typeS md_relax_table[] =
613 {
614 /* The fields are:
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. */
619
620 /* The first entry must be unused because an `rlx_more' value of zero ends
621 each list. */
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. */
624
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 },
631
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 },
636
637 /* mov r,imm8. */
638 { 255, 0,0, EPIPHANY_RELAX_MOV_IMM16 },
639 /* mov r,imm16. */
640 { 65535, 0,2, EPIPHANY_RELAX_NONE },
641
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 }
646
647 };
648
649 static const EPIPHANY_RELAX_TYPES relax_insn[] =
650 {
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 */
667 };
668
669 long
670 epiphany_relax_frag (segT segment, fragS *fragP, long stretch)
671 {
672 /* Address of branch insn. */
673 long address ATTRIBUTE_UNUSED = fragP->fr_address + fragP->fr_fix - 2;
674 long growth = 0;
675
676 if (fragP->fr_subtype == EPIPHANY_RELAX_NEED_RELAXING)
677 {
678 EPIPHANY_RELAX_TYPES subtype = relax_insn [*fragP->fr_opcode & 0xf];
679
680 /* Special cases add/sub vs mov immediates. */
681 if (subtype == EPIPHANY_RELAX_ARITH_SIMM3)
682 {
683 if ((*fragP->fr_opcode & 0x10) == 0)
684 subtype = EPIPHANY_RELAX_MOV_IMM8;
685 }
686 else if (subtype == EPIPHANY_RELAX_ARITH_SIMM11)
687 {
688 if ((*fragP->fr_opcode & 0x10) == 0)
689 subtype = EPIPHANY_RELAX_MOV_IMM16;
690 }
691
692 /* Remember refinements for the future. */
693 fragP->fr_subtype = subtype;
694 }
695
696 growth = relax_frag (segment, fragP, stretch);
697
698 return growth;
699 }
700
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.
704
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
710 with a 0 value. */
711
712 int
713 md_estimate_size_before_relax (fragS *fragP, segT segment)
714 {
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))
723 {
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. */
727
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;
733
734 switch (subtype)
735 {
736 case EPIPHANY_RELAX_LDST_IMM3:
737 subtype = EPIPHANY_RELAX_LDST_IMM11;
738 break;
739 case EPIPHANY_RELAX_BRANCH_SHORT:
740 subtype = EPIPHANY_RELAX_BRANCH_LONG;
741 break;
742 case EPIPHANY_RELAX_MOV_IMM8:
743 subtype = EPIPHANY_RELAX_MOV_IMM16;
744 break;
745 case EPIPHANY_RELAX_ARITH_SIMM3:
746 subtype = EPIPHANY_RELAX_ARITH_SIMM11;
747 break;
748
749 default:
750 break;
751 }
752
753 fragP->fr_subtype = subtype;
754
755 {
756 const CGEN_INSN *insn;
757 int i;
758
759 /* Update the recorded insn. */
760
761 for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
762 {
763 if ((strcmp (CGEN_INSN_MNEMONIC (insn),
764 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
765 == 0)
766 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
767 break;
768 }
769
770 if (i == 4)
771 abort ();
772
773 fragP->fr_cgen.insn = insn;
774 }
775 }
776
777 return md_relax_table[fragP->fr_subtype].rlx_length;
778 }
779
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.
782
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. */
786
787 void
788 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
789 segT sec,
790 fragS *fragP)
791 {
792 char *opcode;
793 char *displacement;
794 int target_address;
795 int opcode_address;
796 int extension;
797 int addend;
798 int opindx = -1;
799
800 opcode = fragP->fr_opcode;
801
802 /* Address opcode resides at in file space. */
803 opcode_address = fragP->fr_address + fragP->fr_fix - 2;
804 extension = 0;
805 displacement = &opcode[1];
806
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))
811 {
812 /* Symbol must be resolved by linker. */
813 if (fragP->fr_offset & 1)
814 as_warn (_("Addend to unresolved symbol not on word boundary."));
815 addend = 0;
816 }
817 else
818 {
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));
822 }
823
824 /* Do all the housekeeping for frag conversions. */
825 switch (fragP->fr_subtype)
826 {
827 case EPIPHANY_RELAX_ARITH_SIMM11:
828 *opcode |= OP4_IMM32;
829 displacement = &opcode[0];
830 extension += 3;
831
832 addend
833 = (((addend & 0x7) << 7)
834 | opcode[0]
835 | ((addend & 0x7f8) << 13)
836 | (opcode[1] << 8)
837 | (opcode[2] << 16));
838
839 opindx = EPIPHANY_OPERAND_SIMM11;
840 break;
841
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;
846 extension += 2;
847
848 addend >>= 1; /* Convert to word offset. */
849 opindx = EPIPHANY_OPERAND_SIMM24;
850 break;
851
852 case EPIPHANY_RELAX_MOV_IMM16:
853 *opcode |= OP4_IMM32;
854 extension += 3;
855
856 addend
857 = (((addend & 0xff00) << 12)
858 | (opcode[2] << 16)
859 | ((addend & 0x00ff) << 5)
860 | (opcode[1] << 8)
861 | opcode[0]);
862 displacement = &opcode[0];
863 opindx = EPIPHANY_OPERAND_IMM16;
864 break;
865
866 case EPIPHANY_RELAX_LDST_IMM11:
867 *opcode |= OP4_LDSTRD;
868 displacement = &opcode[0];
869 extension += 3;
870
871 if (addend < 0)
872 /* Convert twos-complement address value to sign-magnitude. */
873 addend = (-addend & 0x7ff) | 0x800;
874
875 addend
876 = (((addend & 0x7) << 5)
877 | opcode[0]
878 | ((addend & 0xff8) << 13)
879 | (opcode[1] << 8)
880 | (opcode[2] << 16));
881
882 opindx = EPIPHANY_OPERAND_DISP11;
883 break;
884
885 case EPIPHANY_RELAX_ARITH_SIMM3:
886 addend = ((addend & 7) << 5) | opcode[0];
887 opindx = EPIPHANY_OPERAND_SIMM3;
888 break;
889
890 case EPIPHANY_RELAX_LDST_IMM3:
891 addend = ((addend & 7) << 5) | opcode[0];
892 opindx = EPIPHANY_OPERAND_DISP3;
893 break;
894
895 case EPIPHANY_RELAX_BRANCH_SHORT:
896 addend >>= 1; /* Convert to a word offset. */
897 displacement = & opcode[1];
898 opindx = EPIPHANY_OPERAND_SIMM8;
899 break;
900
901 case EPIPHANY_RELAX_MOV_IMM8:
902 addend
903 = (((addend & 0xff) << 5)
904 | opcode[0]
905 | (opcode[1] << 8));
906 opindx = EPIPHANY_OPERAND_IMM8;
907 break;
908
909 case EPIPHANY_RELAX_NONE:
910 case EPIPHANY_RELAX_NEED_RELAXING:
911 default: /* Anything else? */
912 as_bad ("unrecognized fragment subtype");
913 break;
914 }
915
916 /* Create a relocation for symbols that must be resolved by the linker.
917 Otherwise output the completed insn. */
918
919 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
920 || S_IS_EXTERNAL (fragP->fr_symbol)
921 || S_IS_WEAK (fragP->fr_symbol))
922 {
923 fixS *fixP;
924 const CGEN_OPERAND *operand
925 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx);
926 bfd_reloc_code_real_type reloc_type;
927
928 gas_assert (fragP->fr_cgen.insn != 0);
929
930 reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL);
931
932 fixP = gas_cgen_record_fixup (fragP,
933 /* Offset of insn in frag. */
934 (opcode - fragP->fr_literal),
935 fragP->fr_cgen.insn,
936 CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8,
937 operand,
938 reloc_type,
939 fragP->fr_symbol, fragP->fr_offset);
940 fixP->fx_r_type = fixP->fx_cgen.opinfo;
941 }
942
943 md_number_to_chars (displacement, (valueT) addend, extension + 1);
944
945 fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added. */
946 }
947
948 \f
949 /* Functions concerning relocs. */
950
951 /* The location from which a PC relative jump should be calculated,
952 given a PC relative reloc. */
953
954 long
955 md_pcrel_from_section (fixS *fixP, segT sec)
956 {
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)))
962 return 0;
963
964 return fixP->fx_frag->fr_address + fixP->fx_where;
965 }
966
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. */
970
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)
975 {
976 switch (operand->type)
977 {
978 case EPIPHANY_OPERAND_SIMM11:
979 return BFD_RELOC_EPIPHANY_SIMM11;
980 case EPIPHANY_OPERAND_DISP11:
981 return BFD_RELOC_EPIPHANY_IMM11;
982
983 case EPIPHANY_OPERAND_SIMM8:
984 return BFD_RELOC_EPIPHANY_SIMM8;
985 case EPIPHANY_OPERAND_SIMM24:
986 return BFD_RELOC_EPIPHANY_SIMM24;
987
988 case EPIPHANY_OPERAND_IMM8:
989 return BFD_RELOC_EPIPHANY_IMM8;
990
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;
996 else
997 as_bad ("unknown imm16 operand");
998 /* fall-thru */
999
1000 default:
1001 break;
1002 }
1003 return BFD_RELOC_NONE;
1004 }
1005
1006 \f
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. */
1011
1012 /* Equal to MAX_PRECISION in atof-ieee.c. */
1013 #define MAX_LITTLENUMS 6
1014
1015 const char *
1016 md_atof (int type, char *litP, int *sizeP)
1017 {
1018 return ieee_md_atof (type, litP, sizeP, FALSE);
1019 }
1020
1021 /* Return true if can adjust the reloc to be relative to its section
1022 (such as .data) instead of relative to some symbol. */
1023
1024 bfd_boolean
1025 epiphany_fix_adjustable (fixS *fixP)
1026 {
1027 bfd_reloc_code_real_type reloc_type;
1028
1029 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1030 {
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);
1035
1036 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1037 }
1038 else
1039 reloc_type = fixP->fx_r_type;
1040
1041 if (fixP->fx_addsy == NULL)
1042 return TRUE;
1043
1044 /* Prevent all adjustments to global symbols. */
1045 if (S_IS_EXTERNAL (fixP->fx_addsy))
1046 return FALSE;
1047
1048 if (S_IS_WEAK (fixP->fx_addsy))
1049 return FALSE;
1050
1051 if (pic_code
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))
1056 return FALSE;
1057
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)
1061 return FALSE;
1062
1063 return TRUE;
1064 }
1065
1066 void
1067 epiphany_elf_final_processing (void)
1068 {
1069 elf_elfheader (stdoutput)->e_flags |= epiphany_flags;
1070 }
1071
1072 int
1073 epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED)
1074 {
1075 LITTLENUM_TYPE words[2];
1076
1077 switch (opinfo)
1078 {
1079 case BFD_RELOC_EPIPHANY_LOW:
1080 case BFD_RELOC_EPIPHANY_HIGH:
1081 break;
1082 default:
1083 return opinfo;
1084 }
1085
1086 /* Doing a %LOW or %HIGH. */
1087 switch (exp->X_op)
1088 {
1089 default:
1090 return opinfo;
1091 case O_big: /* Bignum. */
1092 if (exp->X_add_number > 0) /* Integer value too large. */
1093 return opinfo;
1094 }
1095
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;
1100 return opinfo;
1101 }
This page took 0.054699 seconds and 4 git commands to generate.