Changes so that GAS will build - not work - just build.
[deliverable/binutils-gdb.git] / gas / config / tc-fr30.c
CommitLineData
f3dc77c2
DE
1/* tc-fr30.c -- Assembler for the Fujitsu FR30.
2 Copyright (C) 1998 Free Software Foundation.
d22910f6
DB
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23 This file is work in progress and was copied from m32r/tc-m32r.c in
24 order to all gas/configure to run with the target fr30-unknown-elf.
25 Other than changing all occurances for m32r to fr30, this file has not
26 been customized for fr30 in any way.
27 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
28
29#include <stdio.h>
30#include <ctype.h>
31#include "as.h"
32#include "subsegs.h"
33#include "symcat.h"
34#include "cgen-opc.h"
35#include "cgen.h"
36
37/* Linked list of symbols that are debugging symbols to be defined as the
38 beginning of the current instruction. */
39typedef struct sym_link
40{
8f83181c
NC
41 struct sym_link * next;
42 symbolS * symbol;
d22910f6
DB
43} sym_linkS;
44
8f83181c 45static sym_linkS * debug_sym_link = (sym_linkS *) NULL;
d22910f6
DB
46
47/* Structure to hold all of the different components describing
48 an individual instruction. */
49typedef struct
50{
51 const CGEN_INSN * insn;
52 const CGEN_INSN * orig_insn;
53 CGEN_FIELDS fields;
54#if CGEN_INT_INSN_P
55 CGEN_INSN_INT buffer [1];
56#define INSN_VALUE(buf) (*(buf))
57#else
58 unsigned char buffer [CGEN_MAX_INSN_SIZE];
59#define INSN_VALUE(buf) (buf)
60#endif
61 char * addr;
62 fragS * frag;
63 int num_fixups;
64 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
65 int indices [MAX_OPERAND_INSTANCES];
8f83181c 66 sym_linkS * debug_sym_link;
d22910f6
DB
67}
68fr30_insn;
69
70/* prev_insn.insn is non-null if last insn was a 16 bit insn on a 32 bit
71 boundary (i.e. was the first of two 16 bit insns). */
72static fr30_insn prev_insn;
73
74/* Non-zero if we've seen a relaxable insn since the last 32 bit
75 alignment request. */
76static int seen_relaxable_p = 0;
77
78/* Non-zero if -relax specified, in which case sufficient relocs are output
79 for the linker to do relaxing.
80 We do simple forms of relaxing internally, but they are always done.
81 This flag does not apply to them. */
82static int fr30_relax;
83
84#if 0 /* not supported yet */
85/* If non-NULL, pointer to cpu description file to read.
86 This allows runtime additions to the assembler. */
87static const char * fr30_cpu_desc;
88#endif
89
90/* Non-zero if warn when a high/shigh reloc has no matching low reloc.
91 Each high/shigh reloc must be paired with it's low cousin in order to
92 properly calculate the addend in a relocatable link (since there is a
93 potential carry from the low to the high/shigh).
94 This option is off by default though for user-written assembler code it
95 might make sense to make the default be on (i.e. have gcc pass a flag
96 to turn it off). This warning must not be on for GCC created code as
97 optimization may delete the low but not the high/shigh (at least we
98 shouldn't assume or require it to). */
99static int warn_unmatched_high = 0;
100
101/* stuff for .scomm symbols. */
102static segT sbss_section;
103static asection scom_section;
104static asymbol scom_symbol;
105
106const char comment_chars[] = ";";
107const char line_comment_chars[] = "#";
108const char line_separator_chars[] = "";
109const char EXP_CHARS[] = "eE";
110const char FLT_CHARS[] = "dD";
111
112/* Relocations against symbols are done in two
113 parts, with a HI relocation and a LO relocation. Each relocation
114 has only 16 bits of space to store an addend. This means that in
115 order for the linker to handle carries correctly, it must be able
116 to locate both the HI and the LO relocation. This means that the
117 relocations must appear in order in the relocation table.
118
119 In order to implement this, we keep track of each unmatched HI
120 relocation. We then sort them so that they immediately precede the
121 corresponding LO relocation. */
122
123struct fr30_hi_fixup
124{
125 struct fr30_hi_fixup * next; /* Next HI fixup. */
126 fixS * fixp; /* This fixup. */
127 segT seg; /* The section this fixup is in. */
128
129};
130
131/* The list of unmatched HI relocs. */
132
133static struct fr30_hi_fixup * fr30_hi_fixup_list;
134
135\f
136#define FR30_SHORTOPTS ""
137const char * md_shortopts = FR30_SHORTOPTS;
138
139struct option md_longopts[] =
140{
141 /* Sigh. I guess all warnings must now have both variants. */
142#define OPTION_WARN_UNMATCHED (OPTION_MD_BASE + 4)
143 {"warn-unmatched-high", OPTION_WARN_UNMATCHED},
144 {"Wuh", OPTION_WARN_UNMATCHED},
145#define OPTION_NO_WARN_UNMATCHED (OPTION_MD_BASE + 5)
146 {"no-warn-unmatched-high", OPTION_WARN_UNMATCHED},
147 {"Wnuh", OPTION_WARN_UNMATCHED},
148
149#if 0 /* not supported yet */
150#define OPTION_RELAX (OPTION_MD_BASE + 6)
151 {"relax", no_argument, NULL, OPTION_RELAX},
152#define OPTION_CPU_DESC (OPTION_MD_BASE + 7)
153 {"cpu-desc", required_argument, NULL, OPTION_CPU_DESC},
154#endif
155
156 {NULL, no_argument, NULL, 0}
157};
158size_t md_longopts_size = sizeof (md_longopts);
159
160int
161md_parse_option (c, arg)
162 int c;
163 char * arg;
164{
165 switch (c)
166 {
167 case OPTION_WARN_UNMATCHED:
168 warn_unmatched_high = 1;
169 break;
170
171 case OPTION_NO_WARN_UNMATCHED:
172 warn_unmatched_high = 0;
173 break;
174
175#if 0 /* not supported yet */
176 case OPTION_RELAX:
177 fr30_relax = 1;
178 break;
179 case OPTION_CPU_DESC:
180 fr30_cpu_desc = arg;
181 break;
182#endif
183
184 default:
185 return 0;
186 }
187 return 1;
188}
189
190void
191md_show_usage (stream)
192 FILE * stream;
193{
194 fprintf (stream, _(" FR30 specific command line options:\n"));
195
196 fprintf (stream, _("\
197 -warn-unmatched-high warn when an (s)high reloc has no matching low reloc\n"));
198 fprintf (stream, _("\
199 -no-warn-unmatched-high do not warn about missing low relocs\n"));
200 fprintf (stream, _("\
201 -Wuh synonym for -warn-unmatched-high\n"));
202 fprintf (stream, _("\
203 -Wnuh synonym for -no-warn-unmatched-high\n"));
204
205#if 0
206 fprintf (stream, _("\
207 -relax create linker relaxable code\n"));
208 fprintf (stream, _("\
209 -cpu-desc provide runtime cpu description file\n"));
210#endif
211}
212
213static void fill_insn PARAMS ((int));
214static void fr30_scomm PARAMS ((int));
215static void debug_sym PARAMS ((int));
216static void expand_debug_syms PARAMS ((sym_linkS *, int));
217
218/* Set by md_assemble for use by fr30_fill_insn. */
219static subsegT prev_subseg;
220static segT prev_seg;
221
222/* The target specific pseudo-ops which we support. */
223const pseudo_typeS md_pseudo_table[] =
224{
225 { "word", cons, 4 },
226 { "fillinsn", fill_insn, 0 },
227 { "scomm", fr30_scomm, 0 },
228 { "debugsym", debug_sym, 0 },
229 { NULL, NULL, 0 }
230};
231
232/* FIXME: Should be machine generated. */
233#define NOP_INSN 0x7000
234#define PAR_NOP_INSN 0xf000 /* can only be used in 2nd slot */
235
236/* When we align the .text section, insert the correct NOP pattern.
237 N is the power of 2 alignment. LEN is the length of pattern FILL.
238 MAX is the maximum number of characters to skip when doing the alignment,
239 or 0 if there is no maximum. */
240
241int
242fr30_do_align (n, fill, len, max)
243 int n;
244 const char * fill;
245 int len;
246 int max;
247{
248 /* Only do this if the fill pattern wasn't specified. */
249 if (fill == NULL
250 && (now_seg->flags & SEC_CODE) != 0
251 /* Only do this special handling if aligning to at least a
252 4 byte boundary. */
253 && n > 1
254 /* Only do this special handling if we're allowed to emit at
255 least two bytes. */
256 && (max == 0 || max > 1))
257 {
258 static const unsigned char nop_pattern[] = { 0xf0, 0x00 };
259
260#if 0
261 /* First align to a 2 byte boundary, in case there is an odd .byte. */
262 /* FIXME: How much memory will cause gas to use when assembling a big
263 program? Perhaps we can avoid the frag_align call? */
264 frag_align (1, 0, 0);
265#endif
266 /* Next align to a 4 byte boundary (we know n >= 2) using a parallel
267 nop. */
268 frag_align_pattern (2, nop_pattern, sizeof nop_pattern, 0);
269 /* If doing larger alignments use a repeating sequence of appropriate
270 nops. */
271 if (n > 2)
272 {
273 static const unsigned char multi_nop_pattern[] =
274 { 0x70, 0x00, 0xf0, 0x00 };
275 frag_align_pattern (n, multi_nop_pattern, sizeof multi_nop_pattern,
276 max ? max - 2 : 0);
277 }
278
279 prev_insn.insn = NULL;
280 return 1;
281 }
282
283 return 0;
284}
285
286/* If the last instruction was the first of 2 16 bit insns,
287 output a nop to move the PC to a 32 bit boundary.
288
289 This is done via an alignment specification since branch relaxing
290 may make it unnecessary.
291
292 Internally, we need to output one of these each time a 32 bit insn is
293 seen after an insn that is relaxable. */
294
295static void
296fill_insn (ignore)
297 int ignore;
298{
299 (void) fr30_do_align (2, NULL, 0, 0);
300 prev_insn.insn = NULL;
301 seen_relaxable_p = 0;
302}
303
304/* Record the symbol so that when we output the insn, we can create
305 a symbol that is at the start of the instruction. This is used
306 to emit the label for the start of a breakpoint without causing
307 the assembler to emit a NOP if the previous instruction was a
308 16 bit instruction. */
309
310static void
311debug_sym (ignore)
312 int ignore;
313{
314 register char *name;
315 register char delim;
316 register char *end_name;
317 register symbolS *symbolP;
318 register sym_linkS *link;
319
320 name = input_line_pointer;
321 delim = get_symbol_end ();
322 end_name = input_line_pointer;
323
324 if ((symbolP = symbol_find (name)) == NULL
325 && (symbolP = md_undefined_symbol (name)) == NULL)
326 {
327 symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
328 }
329
330 symbol_table_insert (symbolP);
331 if (S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section)
332 /* xgettext:c-format */
333 as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
334
335 else
336 {
337 link = (sym_linkS *) xmalloc (sizeof (sym_linkS));
338 link->symbol = symbolP;
339 link->next = debug_sym_link;
340 debug_sym_link = link;
341 symbolP->local = 1;
342 }
343
344 *end_name = delim;
345 demand_empty_rest_of_line ();
346}
347
348/* Second pass to expanding the debug symbols, go through linked
349 list of symbols and reassign the address. */
350
351static void
352expand_debug_syms (syms, align)
353 sym_linkS *syms;
354 int align;
355{
356 char *save_input_line = input_line_pointer;
357 sym_linkS *next_syms;
358
359 if (!syms)
360 return;
361
362 (void) fr30_do_align (align, NULL, 0, 0);
363 for (; syms != (sym_linkS *)0; syms = next_syms)
364 {
365 symbolS *symbolP = syms->symbol;
366 next_syms = syms->next;
367 input_line_pointer = ".\n";
368 pseudo_set (symbolP);
369 free ((char *)syms);
370 }
371
372 input_line_pointer = save_input_line;
373}
374
375/* Cover function to fill_insn called after a label and at end of assembly.
376 The result is always 1: we're called in a conditional to see if the
377 current line is a label. */
378
379int
380fr30_fill_insn (done)
381 int done;
382{
383 if (prev_seg != NULL)
384 {
385 segT seg = now_seg;
386 subsegT subseg = now_subseg;
387
388 subseg_set (prev_seg, prev_subseg);
389
390 fill_insn (0);
391
392 subseg_set (seg, subseg);
393 }
394
395 if (done && debug_sym_link)
396 {
397 expand_debug_syms (debug_sym_link, 1);
398 debug_sym_link = (sym_linkS *)0;
399 }
400
401 return 1;
402}
403\f
404void
405md_begin ()
406{
407 flagword applicable;
408 segT seg;
409 subsegT subseg;
410
411 /* Initialize the `cgen' interface. */
412
413 /* Set the machine number and endian. */
414 gas_cgen_opcode_desc = fr30_cgen_opcode_open (0 /* mach number */,
415 target_big_endian ?
416 CGEN_ENDIAN_BIG
417 : CGEN_ENDIAN_LITTLE);
418 fr30_cgen_init_asm (gas_cgen_opcode_desc);
419
420 /* This is a callback from cgen to gas to parse operands. */
421 cgen_set_parse_operand_fn (gas_cgen_opcode_desc, gas_cgen_parse_operand);
422
423#if 0 /* not supported yet */
424 /* If a runtime cpu description file was provided, parse it. */
425 if (fr30_cpu_desc != NULL)
426 {
427 const char * errmsg;
428
429 errmsg = cgen_read_cpu_file (gas_cgen_opcode_desc, fr30_cpu_desc);
430 if (errmsg != NULL)
431 as_bad ("%s: %s", fr30_cpu_desc, errmsg);
432 }
433#endif
434
435 /* Save the current subseg so we can restore it [it's the default one and
436 we don't want the initial section to be .sbss]. */
437 seg = now_seg;
438 subseg = now_subseg;
439
440 /* The sbss section is for local .scomm symbols. */
441 sbss_section = subseg_new (".sbss", 0);
442
443 /* This is copied from perform_an_assembly_pass. */
444 applicable = bfd_applicable_section_flags (stdoutput);
445 bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC);
446
447#if 0 /* What does this do? [see perform_an_assembly_pass] */
448 seg_info (bss_section)->bss = 1;
449#endif
450
451 subseg_set (seg, subseg);
452
453 /* We must construct a fake section similar to bfd_com_section
454 but with the name .scommon. */
455 scom_section = bfd_com_section;
456 scom_section.name = ".scommon";
457 scom_section.output_section = & scom_section;
458 scom_section.symbol = & scom_symbol;
459 scom_section.symbol_ptr_ptr = & scom_section.symbol;
460 scom_symbol = * bfd_com_section.symbol;
461 scom_symbol.name = ".scommon";
462 scom_symbol.section = & scom_section;
463}
464
465void
466md_assemble (str)
467 char * str;
468{
469#if 0
470 fr30_insn insn;
471 char * errmsg;
472 char * str2 = NULL;
473
474 /* Initialize GAS's cgen interface for a new instruction. */
475 gas_cgen_init_parse ();
476
477 insn.debug_sym_link = debug_sym_link;
478 debug_sym_link = (sym_linkS *)0;
479
480 insn.insn = fr30_cgen_assemble_insn
481 (gas_cgen_opcode_desc, str, & insn.fields, insn.buffer, & errmsg);
482
483 if (!insn.insn)
484 {
485 as_bad (errmsg);
486 return;
487 }
488
489 if (CGEN_INSN_BITSIZE (insn.insn) == 32)
490 {
491 /* 32 bit insns must live on 32 bit boundaries. */
492 if (prev_insn.insn || seen_relaxable_p)
493 {
494 /* ??? If calling fill_insn too many times turns us into a memory
495 pig, can we call a fn to assemble a nop instead of
496 !seen_relaxable_p? */
497 fill_insn (0);
498 }
499
500 expand_debug_syms (insn.debug_sym_link, 2);
501
502 /* Doesn't really matter what we pass for RELAX_P here. */
503 gas_cgen_finish_insn (insn.insn, insn.buffer,
504 CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
505 }
506 else
507 {
508 int on_32bit_boundary_p;
509
510 if (CGEN_INSN_BITSIZE (insn.insn) != 16)
511 abort();
512
513 insn.orig_insn = insn.insn;
514
515 /* Compute whether we're on a 32 bit boundary or not.
516 prev_insn.insn is NULL when we're on a 32 bit boundary. */
517 on_32bit_boundary_p = prev_insn.insn == NULL;
518
519 expand_debug_syms (insn.debug_sym_link, 1);
520
521 {
522 int i;
523 finished_insnS fi;
524
525 /* Ensure each pair of 16 bit insns is in the same frag. */
526 frag_grow (4);
527
528 gas_cgen_finish_insn (insn.orig_insn, insn.buffer,
529 CGEN_FIELDS_BITSIZE (& insn.fields),
530 1 /*relax_p*/, &fi);
531 insn.addr = fi.addr;
532 insn.frag = fi.frag;
533 insn.num_fixups = fi.num_fixups;
534 for (i = 0; i < fi.num_fixups; ++i)
535 insn.fixups[i] = fi.fixups[i];
536 }
537
538 /* Keep track of whether we've seen a pair of 16 bit insns.
539 prev_insn.insn is NULL when we're on a 32 bit boundary. */
540 if (on_32bit_boundary_p)
541 prev_insn = insn;
542 else
543 prev_insn.insn = NULL;
544
545 /* If the insn needs the following one to be on a 32 bit boundary
546 (e.g. subroutine calls), fill this insn's slot. */
547 if (on_32bit_boundary_p
548 && CGEN_INSN_ATTR (insn.orig_insn, CGEN_INSN_FILL_SLOT) != 0)
549 fill_insn (0);
550
551 /* If this is a relaxable insn (can be replaced with a larger version)
552 mark the fact so that we can emit an alignment directive for a
553 following 32 bit insn if we see one. */
554 if (CGEN_INSN_ATTR (insn.orig_insn, CGEN_INSN_RELAXABLE) != 0)
555 seen_relaxable_p = 1;
556 }
557
558 /* Set these so fr30_fill_insn can use them. */
559 prev_seg = now_seg;
560 prev_subseg = now_subseg;
561#endif
562}
563
564/* The syntax in the manual says constants begin with '#'.
565 We just ignore it. */
566
567void
568md_operand (expressionP)
569 expressionS * expressionP;
570{
571 if (* input_line_pointer == '#')
572 {
573 input_line_pointer ++;
574 expression (expressionP);
575 }
576}
577
578valueT
579md_section_align (segment, size)
580 segT segment;
581 valueT size;
582{
583 int align = bfd_get_section_alignment (stdoutput, segment);
584 return ((size + (1 << align) - 1) & (-1 << align));
585}
586
587symbolS *
588md_undefined_symbol (name)
589 char * name;
590{
591 return 0;
592}
593\f
594/* .scomm pseudo-op handler.
595
596 This is a new pseudo-op to handle putting objects in .scommon.
597 By doing this the linker won't need to do any work and more importantly
598 it removes the implicit -G arg necessary to correctly link the object file.
599*/
600
601static void
602fr30_scomm (ignore)
603 int ignore;
604{
605 register char * name;
606 register char c;
607 register char * p;
608 offsetT size;
609 register symbolS * symbolP;
610 offsetT align;
611 int align2;
612
613 name = input_line_pointer;
614 c = get_symbol_end ();
615
616 /* just after name is now '\0' */
617 p = input_line_pointer;
618 * p = c;
619 SKIP_WHITESPACE ();
620 if (* input_line_pointer != ',')
621 {
622 as_bad (_("Expected comma after symbol-name: rest of line ignored."));
623 ignore_rest_of_line ();
624 return;
625 }
626
627 input_line_pointer ++; /* skip ',' */
628 if ((size = get_absolute_expression ()) < 0)
629 {
630 /* xgettext:c-format */
631 as_warn (_(".SCOMMon length (%ld.) <0! Ignored."), (long) size);
632 ignore_rest_of_line ();
633 return;
634 }
635
636 /* The third argument to .scomm is the alignment. */
637 if (* input_line_pointer != ',')
638 align = 8;
639 else
640 {
641 ++ input_line_pointer;
642 align = get_absolute_expression ();
643 if (align <= 0)
644 {
645 as_warn (_("ignoring bad alignment"));
646 align = 8;
647 }
648 }
649 /* Convert to a power of 2 alignment. */
650 if (align)
651 {
652 for (align2 = 0; (align & 1) == 0; align >>= 1, ++ align2)
653 continue;
654 if (align != 1)
655 {
656 as_bad (_("Common alignment not a power of 2"));
657 ignore_rest_of_line ();
658 return;
659 }
660 }
661 else
662 align2 = 0;
663
664 * p = 0;
665 symbolP = symbol_find_or_make (name);
666 * p = c;
667
668 if (S_IS_DEFINED (symbolP))
669 {
670 /* xgettext:c-format */
671 as_bad (_("Ignoring attempt to re-define symbol `%s'."),
672 S_GET_NAME (symbolP));
673 ignore_rest_of_line ();
674 return;
675 }
676
677 if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
678 {
679 /* xgettext:c-format */
680 as_bad (_("Length of .scomm \"%s\" is already %ld. Not changed to %ld."),
681 S_GET_NAME (symbolP),
682 (long) S_GET_VALUE (symbolP),
683 (long) size);
684
685 ignore_rest_of_line ();
686 return;
687 }
688
689 if (symbolP->local)
690 {
691 segT old_sec = now_seg;
692 int old_subsec = now_subseg;
693 char * pfrag;
694
695 record_alignment (sbss_section, align2);
696 subseg_set (sbss_section, 0);
697
698 if (align2)
699 frag_align (align2, 0, 0);
700
701 if (S_GET_SEGMENT (symbolP) == sbss_section)
702 symbolP->sy_frag->fr_symbol = 0;
703
704 symbolP->sy_frag = frag_now;
705
706 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
707 (char *) 0);
708 * pfrag = 0;
709 S_SET_SIZE (symbolP, size);
710 S_SET_SEGMENT (symbolP, sbss_section);
711 S_CLEAR_EXTERNAL (symbolP);
712 subseg_set (old_sec, old_subsec);
713 }
714 else
715 {
716 S_SET_VALUE (symbolP, (valueT) size);
717 S_SET_ALIGN (symbolP, align2);
718 S_SET_EXTERNAL (symbolP);
719 S_SET_SEGMENT (symbolP, & scom_section);
720 }
721
722 demand_empty_rest_of_line ();
723}
724\f
725/* Interface to relax_segment. */
726
727/* FIXME: Build table by hand, get it working, then machine generate. */
728
729const relax_typeS md_relax_table[] =
730{
731/* The fields are:
732 1) most positive reach of this state,
733 2) most negative reach of this state,
734 3) how many bytes this mode will add to the size of the current frag
735 4) which index into the table to try if we can't fit into this one. */
736
737 /* The first entry must be unused because an `rlx_more' value of zero ends
738 each list. */
739 {1, 1, 0, 0},
740
741 /* The displacement used by GAS is from the end of the 2 byte insn,
742 so we subtract 2 from the following. */
743 /* 16 bit insn, 8 bit disp -> 10 bit range.
744 This doesn't handle a branch in the right slot at the border:
745 the "& -4" isn't taken into account. It's not important enough to
746 complicate things over it, so we subtract an extra 2 (or + 2 in -ve
747 case). */
748 {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
749 /* 32 bit insn, 24 bit disp -> 26 bit range. */
750 {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
751 /* Same thing, but with leading nop for alignment. */
752 {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
753};
754
755long
756fr30_relax_frag (fragP, stretch)
757 fragS * fragP;
758 long stretch;
759{
760 /* Address of branch insn. */
761 long address = fragP->fr_address + fragP->fr_fix - 2;
762 long growth = 0;
763
764 /* Keep 32 bit insns aligned on 32 bit boundaries. */
765 if (fragP->fr_subtype == 2)
766 {
767 if ((address & 3) != 0)
768 {
769 fragP->fr_subtype = 3;
770 growth = 2;
771 }
772 }
773 else if (fragP->fr_subtype == 3)
774 {
775 if ((address & 3) == 0)
776 {
777 fragP->fr_subtype = 2;
778 growth = -2;
779 }
780 }
781 else
782 {
783 growth = relax_frag (fragP, stretch);
784
785 /* Long jump on odd halfword boundary? */
786 if (fragP->fr_subtype == 2 && (address & 3) != 0)
787 {
788 fragP->fr_subtype = 3;
789 growth += 2;
790 }
791 }
792
793 return growth;
794}
795
796/* Return an initial guess of the length by which a fragment must grow to
797 hold a branch to reach its destination.
798 Also updates fr_type/fr_subtype as necessary.
799
800 Called just before doing relaxation.
801 Any symbol that is now undefined will not become defined.
802 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
803 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
804 Although it may not be explicit in the frag, pretend fr_var starts with a
805 0 value. */
806
807int
808md_estimate_size_before_relax (fragP, segment)
809 fragS * fragP;
810 segT segment;
811{
812 int old_fr_fix = fragP->fr_fix;
813
814 /* The only thing we have to handle here are symbols outside of the
815 current segment. They may be undefined or in a different segment in
816 which case linker scripts may place them anywhere.
817 However, we can't finish the fragment here and emit the reloc as insn
818 alignment requirements may move the insn about. */
819
820 if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
821 {
822 /* The symbol is undefined in this segment.
823 Change the relaxation subtype to the max allowable and leave
824 all further handling to md_convert_frag. */
825 fragP->fr_subtype = 2;
826
827#if 0 /* Can't use this, but leave in for illustration. */
828 /* Change 16 bit insn to 32 bit insn. */
829 fragP->fr_opcode[0] |= 0x80;
830
831 /* Increase known (fixed) size of fragment. */
832 fragP->fr_fix += 2;
833
834 /* Create a relocation for it. */
835 fix_new (fragP, old_fr_fix, 4,
836 fragP->fr_symbol,
837 fragP->fr_offset, 1 /* pcrel */,
838 /* FIXME: Can't use a real BFD reloc here.
839 gas_cgen_md_apply_fix3 can't handle it. */
840 BFD_RELOC_FR30_26_PCREL);
841
842 /* Mark this fragment as finished. */
843 frag_wane (fragP);
844#else
845 {
846 const CGEN_INSN * insn;
847 int i;
848
849 /* Update the recorded insn.
850 Fortunately we don't have to look very far.
851 FIXME: Change this to record in the instruction the next higher
852 relaxable insn to use. */
853 for (i = 0, insn = fragP->fr_cgen.insn; i < 4; i++, insn++)
854 {
855 if ((strcmp (CGEN_INSN_MNEMONIC (insn),
856 CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
857 == 0)
858 && CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX))
859 break;
860 }
861 if (i == 4)
862 abort ();
863
864 fragP->fr_cgen.insn = insn;
865 return 2;
866 }
867#endif
868 }
869
870 return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
871}
872
873/* *fragP has been relaxed to its final size, and now needs to have
874 the bytes inside it modified to conform to the new size.
875
876 Called after relaxation is finished.
877 fragP->fr_type == rs_machine_dependent.
878 fragP->fr_subtype is the subtype of what the address relaxed to. */
879
880void
881md_convert_frag (abfd, sec, fragP)
882 bfd * abfd;
883 segT sec;
884 fragS * fragP;
885{
886#if 0
887 char * opcode;
888 char * displacement;
889 int target_address;
890 int opcode_address;
891 int extension;
892 int addend;
893
894 opcode = fragP->fr_opcode;
895
896 /* Address opcode resides at in file space. */
897 opcode_address = fragP->fr_address + fragP->fr_fix - 2;
898
899 switch (fragP->fr_subtype)
900 {
901 case 1 :
902 extension = 0;
903 displacement = & opcode[1];
904 break;
905 case 2 :
906 opcode[0] |= 0x80;
907 extension = 2;
908 displacement = & opcode[1];
909 break;
910 case 3 :
911 opcode[2] = opcode[0] | 0x80;
912 md_number_to_chars (opcode, PAR_NOP_INSN, 2);
913 opcode_address += 2;
914 extension = 4;
915 displacement = & opcode[3];
916 break;
917 default :
918 abort ();
919 }
920
921 if (S_GET_SEGMENT (fragP->fr_symbol) != sec)
922 {
923 /* symbol must be resolved by linker */
924 if (fragP->fr_offset & 3)
925 as_warn (_("Addend to unresolved symbol not on word boundary."));
926 addend = fragP->fr_offset >> 2;
927 }
928 else
929 {
930 /* Address we want to reach in file space. */
931 target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
932 target_address += fragP->fr_symbol->sy_frag->fr_address;
933 addend = (target_address - (opcode_address & -4)) >> 2;
934 }
935
936 /* Create a relocation for symbols that must be resolved by the linker.
937 Otherwise output the completed insn. */
938
939 if (S_GET_SEGMENT (fragP->fr_symbol) != sec)
940 {
941 assert (fragP->fr_subtype != 1);
942 assert (fragP->fr_cgen.insn != 0);
943 gas_cgen_record_fixup (fragP,
944 /* Offset of branch insn in frag. */
945 fragP->fr_fix + extension - 4,
946 fragP->fr_cgen.insn,
947 4 /*length*/,
948 /* FIXME: quick hack */
949#if 0
950 CGEN_OPERAND_ENTRY (fragP->fr_cgen.opindex),
951#else
952 CGEN_OPERAND_ENTRY (FR30_OPERAND_DISP24),
953#endif
954 fragP->fr_cgen.opinfo,
955 fragP->fr_symbol, fragP->fr_offset);
956 }
957
958#define SIZE_FROM_RELAX_STATE(n) ((n) == 1 ? 1 : 3)
959
960 md_number_to_chars (displacement, (valueT) addend,
961 SIZE_FROM_RELAX_STATE (fragP->fr_subtype));
962
963 fragP->fr_fix += extension;
964#endif
965}
966\f
967/* Functions concerning relocs. */
968
969/* The location from which a PC relative jump should be calculated,
970 given a PC relative reloc. */
971
972long
973md_pcrel_from_section (fixP, sec)
974 fixS * fixP;
975 segT sec;
976{
977 if (fixP->fx_addsy != (symbolS *) NULL
978 && (! S_IS_DEFINED (fixP->fx_addsy)
979 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
980 {
981 /* The symbol is undefined (or is defined but not in this section).
982 Let the linker figure it out. */
983 return 0;
984 }
985
986 return (fixP->fx_frag->fr_address + fixP->fx_where) & -4L;
987}
988
989/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
990 Returns BFD_RELOC_NONE if no reloc type can be found.
991 *FIXP may be modified if desired. */
992
993bfd_reloc_code_real_type
994md_cgen_lookup_reloc (insn, operand, fixP)
995 const CGEN_INSN * insn;
996 const CGEN_OPERAND * operand;
997 fixS * fixP;
998{
999#if 0
1000 switch (CGEN_OPERAND_TYPE (operand))
1001 {
1002 case FR30_OPERAND_DISP8 : return BFD_RELOC_FR30_10_PCREL;
1003 case FR30_OPERAND_DISP16 : return BFD_RELOC_FR30_18_PCREL;
1004 case FR30_OPERAND_DISP24 : return BFD_RELOC_FR30_26_PCREL;
1005 case FR30_OPERAND_UIMM24 : return BFD_RELOC_FR30_24;
1006 case FR30_OPERAND_HI16 :
1007 case FR30_OPERAND_SLO16 :
1008 case FR30_OPERAND_ULO16 :
1009 /* If low/high/shigh/sda was used, it is recorded in `opinfo'. */
1010 if (fixP->tc_fix_data.opinfo != 0)
1011 return fixP->tc_fix_data.opinfo;
1012 break;
1013 default : /* avoid -Wall warning */
1014 break;
1015 }
1016#endif
1017 return BFD_RELOC_NONE;
1018}
1019
d22910f6
DB
1020
1021/* Return BFD reloc type from opinfo field in a fixS.
1022 It's tricky using fx_r_type in fr30_frob_file because the values
1023 are BFD_RELOC_UNUSED + operand number. */
1024#define FX_OPINFO_R_TYPE(f) ((f)->tc_fix_data.opinfo)
1025
d22910f6
DB
1026/* See whether we need to force a relocation into the output file.
1027 This is used to force out switch and PC relative relocations when
1028 relaxing. */
1029
1030int
1031fr30_force_relocation (fix)
1032 fixS * fix;
1033{
1034 if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1035 || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1036 return 1;
1037
1038 if (! fr30_relax)
1039 return 0;
1040
1041 return (fix->fx_pcrel
1042 || 0 /* ??? */);
1043}
1044\f
1045/* Write a value out to the object file, using the appropriate endianness. */
1046
1047void
1048md_number_to_chars (buf, val, n)
1049 char * buf;
1050 valueT val;
1051 int n;
1052{
1053 if (target_big_endian)
1054 number_to_chars_bigendian (buf, val, n);
1055 else
1056 number_to_chars_littleendian (buf, val, n);
1057}
1058
1059/* Turn a string in input_line_pointer into a floating point constant of type
1060 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1061 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1062*/
1063
1064/* Equal to MAX_PRECISION in atof-ieee.c */
1065#define MAX_LITTLENUMS 6
1066
1067char *
1068md_atof (type, litP, sizeP)
1069 char type;
1070 char *litP;
1071 int *sizeP;
1072{
1073 int i;
1074 int prec;
1075 LITTLENUM_TYPE words [MAX_LITTLENUMS];
1076 char * t;
1077 char * atof_ieee ();
1078
1079 switch (type)
1080 {
1081 case 'f':
1082 case 'F':
1083 case 's':
1084 case 'S':
1085 prec = 2;
1086 break;
1087
1088 case 'd':
1089 case 'D':
1090 case 'r':
1091 case 'R':
1092 prec = 4;
1093 break;
1094
1095 /* FIXME: Some targets allow other format chars for bigger sizes here. */
1096
1097 default:
1098 * sizeP = 0;
1099 return _("Bad call to md_atof()");
1100 }
1101
1102 t = atof_ieee (input_line_pointer, type, words);
1103 if (t)
1104 input_line_pointer = t;
1105 * sizeP = prec * sizeof (LITTLENUM_TYPE);
1106
1107 if (target_big_endian)
1108 {
1109 for (i = 0; i < prec; i++)
1110 {
1111 md_number_to_chars (litP, (valueT) words[i],
1112 sizeof (LITTLENUM_TYPE));
1113 litP += sizeof (LITTLENUM_TYPE);
1114 }
1115 }
1116 else
1117 {
1118 for (i = prec - 1; i >= 0; i--)
1119 {
1120 md_number_to_chars (litP, (valueT) words[i],
1121 sizeof (LITTLENUM_TYPE));
1122 litP += sizeof (LITTLENUM_TYPE);
1123 }
1124 }
1125
1126 return 0;
1127}
1128
This page took 0.065192 seconds and 4 git commands to generate.