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