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