]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-epiphany.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gas / config / tc-epiphany.c
CommitLineData
cfb8c092 1/* tc-epiphany.c -- Assembler for the Adapteva EPIPHANY
250d07de 2 Copyright (C) 2009-2021 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);
e2d15955
JD
148
149 literal_prefix_dollar_hex = TRUE;
cfb8c092
NC
150}
151
152valueT
153md_section_align (segT segment, valueT size)
154{
fd361982 155 int align = bfd_section_alignment (segment);
cfb8c092 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 {
ca159256 553 char buff[32];
f86f5863
TS
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 {
ca159256 573 char buff[32];
f86f5863
TS
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;
9bb9c115
AM
730 const CGEN_INSN *insn;
731 int i;
cfb8c092
NC
732 /* We haven't relaxed this at all, so the relaxation type may be
733 completely wrong. Set the subtype correctly. */
734 epiphany_relax_frag (segment, fragP, 0);
735 subtype = fragP->fr_subtype;
736
737 switch (subtype)
738 {
739 case EPIPHANY_RELAX_LDST_IMM3:
740 subtype = EPIPHANY_RELAX_LDST_IMM11;
741 break;
742 case EPIPHANY_RELAX_BRANCH_SHORT:
743 subtype = EPIPHANY_RELAX_BRANCH_LONG;
744 break;
745 case EPIPHANY_RELAX_MOV_IMM8:
746 subtype = EPIPHANY_RELAX_MOV_IMM16;
747 break;
748 case EPIPHANY_RELAX_ARITH_SIMM3:
749 subtype = EPIPHANY_RELAX_ARITH_SIMM11;
750 break;
751
752 default:
753 break;
754 }
755
756 fragP->fr_subtype = subtype;
757
9bb9c115
AM
758 /* Update the recorded insn. */
759 for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
760 {
761 if (strcmp (CGEN_INSN_MNEMONIC (insn),
762 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn)) == 0
763 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
764 break;
765 }
cfb8c092 766
9bb9c115
AM
767 if (i == 4)
768 abort ();
cfb8c092 769
9bb9c115
AM
770 /* When changing from a 2-byte to 4-byte insn, don't leave
771 opcode bytes uninitialised. */
772 if (CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) < CGEN_INSN_BITSIZE (insn))
773 {
774 gas_assert (CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) == 16);
775 gas_assert (CGEN_INSN_BITSIZE (insn) == 32);
776 fragP->fr_opcode[2] = 0;
777 fragP->fr_opcode[3] = 0;
778 }
cfb8c092 779
9bb9c115 780 fragP->fr_cgen.insn = insn;
cfb8c092
NC
781 }
782
783 return md_relax_table[fragP->fr_subtype].rlx_length;
784}
785
786/* *FRAGP has been relaxed to its final size, and now needs to have
787 the bytes inside it modified to conform to the new size.
788
789 Called after relaxation is finished.
790 fragP->fr_type == rs_machine_dependent.
791 fragP->fr_subtype is the subtype of what the address relaxed to. */
792
793void
794md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
795 segT sec,
796 fragS *fragP)
797{
798 char *opcode;
799 char *displacement;
800 int target_address;
801 int opcode_address;
802 int extension;
803 int addend;
804 int opindx = -1;
805
806 opcode = fragP->fr_opcode;
807
808 /* Address opcode resides at in file space. */
809 opcode_address = fragP->fr_address + fragP->fr_fix - 2;
810 extension = 0;
811 displacement = &opcode[1];
812
813 /* Set up any addend necessary for branches. */
814 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
815 || S_IS_EXTERNAL (fragP->fr_symbol)
816 || S_IS_WEAK (fragP->fr_symbol))
817 {
818 /* Symbol must be resolved by linker. */
819 if (fragP->fr_offset & 1)
820 as_warn (_("Addend to unresolved symbol not on word boundary."));
821 addend = 0;
822 }
823 else
824 {
825 /* Address we want to reach in file space. */
826 target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
827 addend = (target_address - (opcode_address & -2));
828 }
829
830 /* Do all the housekeeping for frag conversions. */
831 switch (fragP->fr_subtype)
832 {
833 case EPIPHANY_RELAX_ARITH_SIMM11:
834 *opcode |= OP4_IMM32;
835 displacement = &opcode[0];
836 extension += 3;
837
838 addend
839 = (((addend & 0x7) << 7)
840 | opcode[0]
841 | ((addend & 0x7f8) << 13)
842 | (opcode[1] << 8)
843 | (opcode[2] << 16));
844
845 opindx = EPIPHANY_OPERAND_SIMM11;
846 break;
847
848 case EPIPHANY_RELAX_BRANCH_LONG:
849 /* Branches differ only in low nibble of instruction being 8 not 0.
850 24 bit displacement goes to bytes 1..3 . */
851 *opcode |= OP4_BRANCH;
852 extension += 2;
853
854 addend >>= 1; /* Convert to word offset. */
855 opindx = EPIPHANY_OPERAND_SIMM24;
856 break;
857
858 case EPIPHANY_RELAX_MOV_IMM16:
859 *opcode |= OP4_IMM32;
860 extension += 3;
861
862 addend
863 = (((addend & 0xff00) << 12)
864 | (opcode[2] << 16)
865 | ((addend & 0x00ff) << 5)
866 | (opcode[1] << 8)
867 | opcode[0]);
868 displacement = &opcode[0];
869 opindx = EPIPHANY_OPERAND_IMM16;
870 break;
871
872 case EPIPHANY_RELAX_LDST_IMM11:
873 *opcode |= OP4_LDSTRD;
874 displacement = &opcode[0];
875 extension += 3;
876
877 if (addend < 0)
878 /* Convert twos-complement address value to sign-magnitude. */
879 addend = (-addend & 0x7ff) | 0x800;
880
881 addend
882 = (((addend & 0x7) << 5)
883 | opcode[0]
884 | ((addend & 0xff8) << 13)
885 | (opcode[1] << 8)
886 | (opcode[2] << 16));
887
888 opindx = EPIPHANY_OPERAND_DISP11;
889 break;
890
891 case EPIPHANY_RELAX_ARITH_SIMM3:
892 addend = ((addend & 7) << 5) | opcode[0];
893 opindx = EPIPHANY_OPERAND_SIMM3;
894 break;
895
896 case EPIPHANY_RELAX_LDST_IMM3:
897 addend = ((addend & 7) << 5) | opcode[0];
898 opindx = EPIPHANY_OPERAND_DISP3;
b7b2bb1d 899 break;
cfb8c092
NC
900
901 case EPIPHANY_RELAX_BRANCH_SHORT:
902 addend >>= 1; /* Convert to a word offset. */
903 displacement = & opcode[1];
904 opindx = EPIPHANY_OPERAND_SIMM8;
905 break;
906
907 case EPIPHANY_RELAX_MOV_IMM8:
908 addend
909 = (((addend & 0xff) << 5)
910 | opcode[0]
911 | (opcode[1] << 8));
912 opindx = EPIPHANY_OPERAND_IMM8;
913 break;
914
915 case EPIPHANY_RELAX_NONE:
916 case EPIPHANY_RELAX_NEED_RELAXING:
917 default: /* Anything else? */
918 as_bad ("unrecognized fragment subtype");
919 break;
920 }
921
922 /* Create a relocation for symbols that must be resolved by the linker.
923 Otherwise output the completed insn. */
924
925 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
926 || S_IS_EXTERNAL (fragP->fr_symbol)
927 || S_IS_WEAK (fragP->fr_symbol))
928 {
929 fixS *fixP;
930 const CGEN_OPERAND *operand
931 = cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindx);
932 bfd_reloc_code_real_type reloc_type;
933
934 gas_assert (fragP->fr_cgen.insn != 0);
935
936 reloc_type = md_cgen_lookup_reloc (fragP->fr_cgen.insn, operand, NULL);
937
938 fixP = gas_cgen_record_fixup (fragP,
939 /* Offset of insn in frag. */
940 (opcode - fragP->fr_literal),
941 fragP->fr_cgen.insn,
942 CGEN_INSN_BITSIZE (fragP->fr_cgen.insn) / 8,
943 operand,
944 reloc_type,
945 fragP->fr_symbol, fragP->fr_offset);
946 fixP->fx_r_type = fixP->fx_cgen.opinfo;
947 }
948
949 md_number_to_chars (displacement, (valueT) addend, extension + 1);
950
951 fragP->fr_fix += (extension & -2); /* 0,2 or 4 bytes added. */
952}
953
954\f
955/* Functions concerning relocs. */
956
957/* The location from which a PC relative jump should be calculated,
958 given a PC relative reloc. */
959
960long
961md_pcrel_from_section (fixS *fixP, segT sec)
962{
963 if (fixP->fx_addsy != (symbolS *) NULL
964 && (!S_IS_DEFINED (fixP->fx_addsy)
965 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
966 || S_IS_EXTERNAL (fixP->fx_addsy)
967 || S_IS_WEAK (fixP->fx_addsy)))
968 return 0;
969
970 return fixP->fx_frag->fr_address + fixP->fx_where;
971}
972
973/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
974 Returns BFD_RELOC_NONE if no reloc type can be found.
975 *FIXP may be modified if desired. */
976
977bfd_reloc_code_real_type
978md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
979 const CGEN_OPERAND *operand,
980 fixS *fixP ATTRIBUTE_UNUSED)
981{
982 switch (operand->type)
983 {
984 case EPIPHANY_OPERAND_SIMM11:
985 return BFD_RELOC_EPIPHANY_SIMM11;
986 case EPIPHANY_OPERAND_DISP11:
987 return BFD_RELOC_EPIPHANY_IMM11;
988
989 case EPIPHANY_OPERAND_SIMM8:
990 return BFD_RELOC_EPIPHANY_SIMM8;
991 case EPIPHANY_OPERAND_SIMM24:
992 return BFD_RELOC_EPIPHANY_SIMM24;
993
994 case EPIPHANY_OPERAND_IMM8:
995 return BFD_RELOC_EPIPHANY_IMM8;
996
997 case EPIPHANY_OPERAND_IMM16:
998 if (0 == strcmp ("movt", CGEN_INSN_MNEMONIC (insn)))
999 return BFD_RELOC_EPIPHANY_HIGH;
1000 else if (0 == strcmp ("mov", CGEN_INSN_MNEMONIC (insn)))
1001 return BFD_RELOC_EPIPHANY_LOW;
1002 else
1003 as_bad ("unknown imm16 operand");
2b0f3761 1004 /* fallthru */
cfb8c092
NC
1005
1006 default:
1007 break;
1008 }
1009 return BFD_RELOC_NONE;
1010}
1011
1012\f
1013/* Turn a string in input_line_pointer into a floating point constant
1014 of type TYPE, and store the appropriate bytes in *LITP. The number
1015 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1016 returned, or NULL on OK. */
1017
6d4af3c2 1018const char *
cfb8c092
NC
1019md_atof (int type, char *litP, int *sizeP)
1020{
1021 return ieee_md_atof (type, litP, sizeP, FALSE);
1022}
1023
1024/* Return true if can adjust the reloc to be relative to its section
1025 (such as .data) instead of relative to some symbol. */
1026
1027bfd_boolean
1028epiphany_fix_adjustable (fixS *fixP)
1029{
1030 bfd_reloc_code_real_type reloc_type;
1031
1032 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1033 {
1034 const CGEN_INSN *insn = fixP->fx_cgen.insn;
1035 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1036 const CGEN_OPERAND *operand =
1037 cgen_operand_lookup_by_num (gas_cgen_cpu_desc, opindex);
1038
1039 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1040 }
1041 else
1042 reloc_type = fixP->fx_r_type;
1043
1044 if (fixP->fx_addsy == NULL)
1045 return TRUE;
1046
1047 /* Prevent all adjustments to global symbols. */
1048 if (S_IS_EXTERNAL (fixP->fx_addsy))
1049 return FALSE;
1050
1051 if (S_IS_WEAK (fixP->fx_addsy))
1052 return FALSE;
1053
1054 if (pic_code
1055 && (reloc_type == BFD_RELOC_EPIPHANY_SIMM24
1056 || reloc_type == BFD_RELOC_EPIPHANY_SIMM8
1057 || reloc_type == BFD_RELOC_EPIPHANY_HIGH
1058 || reloc_type == BFD_RELOC_EPIPHANY_LOW))
1059 return FALSE;
1060
1061 /* Since we don't use partial_inplace, we must not reduce symbols in
33eaf5de 1062 mergeable sections to their section symbol. */
cfb8c092
NC
1063 if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
1064 return FALSE;
1065
1066 return TRUE;
1067}
1068
1069void
1070epiphany_elf_final_processing (void)
1071{
1072 elf_elfheader (stdoutput)->e_flags |= epiphany_flags;
1073}
1074
1075int
1076epiphany_cgen_parse_fix_exp (int opinfo, expressionS *exp ATTRIBUTE_UNUSED)
1077{
1078 LITTLENUM_TYPE words[2];
1079
1080 switch (opinfo)
1081 {
1082 case BFD_RELOC_EPIPHANY_LOW:
1083 case BFD_RELOC_EPIPHANY_HIGH:
1084 break;
1085 default:
1086 return opinfo;
1087 }
1088
1089 /* Doing a %LOW or %HIGH. */
1090 switch (exp->X_op)
1091 {
1092 default:
1093 return opinfo;
1094 case O_big: /* Bignum. */
1095 if (exp->X_add_number > 0) /* Integer value too large. */
1096 return opinfo;
1097 }
1098
1099 /* Convert to SP number. */
1100 gen_to_words (words, 2, 8L);
1101 exp->X_add_number = words[1] | (words[0] << 16);
1102 exp->X_op = O_constant;
1103 return opinfo;
1104}