* config/tc-arc.c (arc_insert_operand): Change reg parm to pointer
[binutils-gdb.git] / gas / config / tc-arc.c
1 /* tc-arc.c -- Assembler for the ARC
2 Copyright (C) 1994 Free Software Foundation, Inc.
3 Contributed by Doug Evans (dje@cygnus.com).
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 2, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include <stdio.h>
22 #include <ctype.h>
23 #include "as.h"
24 #include "subsegs.h"
25 #include "opcode/arc.h"
26
27 extern int target_big_endian;
28
29 static arc_insn arc_insert_operand PARAMS ((arc_insn insn,
30 const struct arc_operand *operand,
31 int mods,
32 const struct arc_operand_value *reg,
33 offsetT val,
34 char *file, unsigned int line));
35
36 static void s_data1 PARAMS ((void));
37 static void s_seg PARAMS ((int));
38 static void s_proc PARAMS ((int));
39 static void s_reserve PARAMS ((int));
40 static void s_common PARAMS ((int));
41
42 const pseudo_typeS md_pseudo_table[] =
43 {
44 {"align", s_align_bytes, 0}, /* Defaulting is invalid (0) */
45 {"common", s_common, 0},
46 {"global", s_globl, 0},
47 {"half", cons, 2},
48 {"optim", s_ignore, 0},
49 {"proc", s_proc, 0},
50 {"reserve", s_reserve, 0},
51 {"seg", s_seg, 0},
52 {"skip", s_space, 0},
53 {"word", cons, 4},
54 {"xword", cons, 8},
55 {"pushsection", obj_elf_section, 0},
56 {"popsection", obj_elf_previous, 0},
57 {"uahalf", cons, 2},
58 {"uaword", cons, 4},
59 {"uaxword", cons, 8},
60 {NULL, 0, 0},
61 };
62
63 const int md_short_jump_size = 4;
64 const int md_long_jump_size = 4;
65 const int md_reloc_size = 12; /* Size of relocation record */
66
67 /* This array holds the chars that always start a comment. If the
68 pre-processor is disabled, these aren't very useful */
69 const char comment_chars[] = "#";
70
71 /* This array holds the chars that only start a comment at the beginning of
72 a line. If the line seems to have the form '# 123 filename'
73 .line and .file directives will appear in the pre-processed output */
74 /* Note that input_file.c hand checks for '#' at the beginning of the
75 first line of the input file. This is because the compiler outputs
76 #NO_APP at the beginning of its output. */
77 /* Also note that comments started like this one will always
78 work if '/' isn't otherwise defined. */
79 const char line_comment_chars[] = "#";
80
81 const char line_separator_chars[] = "";
82
83 /* Chars that can be used to separate mant from exp in floating point nums */
84 const char EXP_CHARS[] = "eE";
85
86 /* Chars that mean this number is a floating point constant */
87 /* As in 0f12.456 */
88 /* or 0d1.2345e12 */
89 const char FLT_CHARS[] = "rRsSfFdDxXpP";
90
91 static const char *arc_condition_codes[] =
92 {
93 "al", "eq", "ne", "p", "n", "c", "nc", "v",
94 "nv", "gt", "ge", "lt", "le", "hi", "ls", "pnz"
95 };
96
97 static struct hash_control *arc_ops_hash = NULL;
98 static struct hash_control *arc_suffix_hash = NULL;
99 static struct hash_control *arc_reg_hash = NULL;
100 \f
101 const char *md_shortopts = "m:";
102 struct option md_longopts[] = {
103 {NULL, no_argument, NULL, 0}
104 };
105 size_t md_longopts_size = sizeof(md_longopts);
106
107 /* Non-zero if we accept the mul/mulu and variable shift insns. */
108 static int have_mult = 0;
109
110 /*
111 * md_parse_option
112 *
113 * Invocation line includes a switch not recognized by the base assembler.
114 * See if it's a processor-specific option.
115 */
116
117 int
118 md_parse_option (c, arg)
119 int c;
120 char *arg;
121 {
122 switch (c)
123 {
124 case 'm':
125 if (strcmp (arg, "mult") == 0)
126 have_mult = 1;
127 else
128 {
129 as_bad ("invalid architecture -m%s", arg);
130 return 0;
131 }
132 break;
133
134 default:
135 return 0;
136 }
137
138 return 1;
139 }
140
141 void
142 md_show_usage (stream)
143 FILE *stream;
144 {
145 fprintf (stream, "\
146 ARC options:\n\
147 -mmult recognize the mul/mulu and variable shift instructions\n");
148 }
149
150 /* This function is called once, at assembler startup time. It should
151 set up all the tables, etc. that the MD part of the assembler will need. */
152 void
153 md_begin ()
154 {
155 register unsigned int i = 0;
156 char *last;
157
158 target_big_endian = 1;
159
160 if ((arc_ops_hash = hash_new ()) == NULL
161 || (arc_suffix_hash = hash_new ()) == NULL
162 || (arc_reg_hash = hash_new ()) == NULL)
163 as_fatal ("Virtual memory exhausted");
164
165 #if 0
166 for (i = 0; i < arc_opcodes_count; i++)
167 hash_insert (arc_ops_hash, arc_opcodes[i].name, (PTR) (arc_opcodes + i));
168 #endif
169
170 /* Only put the first entry of each equivalently named suffix in the
171 table. */
172 last = "";
173 for (i = 0; i < arc_suffixes_count; i++)
174 {
175 if (strcmp (arc_suffixes[i].name, last) != 0)
176 hash_insert (arc_suffix_hash, arc_suffixes[i].name, (PTR) (arc_suffixes + i));
177 last = arc_suffixes[i].name;
178 }
179
180 /* ??? This is the simple version. See tc-arm.c for something snazzier. */
181 for (i = 0; i < arc_reg_names_count; i++)
182 hash_insert (arc_reg_hash, arc_reg_names[i].name, (PTR) (arc_reg_names + i));
183
184 /* This initializes a few things in arc-opc.c that we need. */
185 arc_opcode_init_tables (have_mult ? ARC_HAVE_MULT_SHIFT : 0);
186 }
187 \f
188 /* Insert an operand value into an instruction.
189 If REG is non-NULL, it is a register number and ignore VAL. */
190
191 static arc_insn
192 arc_insert_operand (insn, operand, mods, reg, val, file, line)
193 arc_insn insn;
194 const struct arc_operand *operand;
195 int mods;
196 const struct arc_operand_value *reg;
197 offsetT val;
198 char *file;
199 unsigned int line;
200 {
201 if (operand->bits != 32)
202 {
203 long min, max;
204 offsetT test;
205
206 if ((operand->flags & ARC_OPERAND_SIGNED) != 0)
207 {
208 if ((operand->flags & ARC_OPERAND_SIGNOPT) != 0)
209 max = (1 << operand->bits) - 1;
210 else
211 max = (1 << (operand->bits - 1)) - 1;
212 min = - (1 << (operand->bits - 1));
213 }
214 else
215 {
216 max = (1 << operand->bits) - 1;
217 min = 0;
218 }
219
220 if ((operand->flags & ARC_OPERAND_NEGATIVE) != 0)
221 test = - val;
222 else
223 test = val;
224
225 if (test < (offsetT) min || test > (offsetT) max)
226 {
227 const char *err =
228 "operand out of range (%s not between %ld and %ld)";
229 char buf[100];
230
231 sprint_value (buf, test);
232 if (file == (char *) NULL)
233 as_warn (err, buf, min, max);
234 else
235 as_warn_where (file, line, err, buf, min, max);
236 }
237 }
238
239 if (operand->insert)
240 {
241 const char *errmsg;
242
243 errmsg = NULL;
244 insn = (*operand->insert) (insn, operand, mods, reg, (long) val, &errmsg);
245 if (errmsg != (const char *) NULL)
246 as_warn (errmsg);
247 }
248 else
249 insn |= (((long) val & ((1 << operand->bits) - 1))
250 << operand->shift);
251
252 return insn;
253 }
254
255 /* We need to keep a list of fixups. We can't simply generate them as
256 we go, because that would require us to first create the frag, and
257 that would screw up references to ``.''. */
258
259 struct arc_fixup
260 {
261 expressionS exp;
262 /* index into `arc_operands' */
263 int opindex;
264 };
265
266 #define MAX_INSN_FIXUPS 5
267
268 /* This routine is called for each instruction to be assembled. */
269
270 void
271 md_assemble (str)
272 char *str;
273 {
274 const struct arc_opcode *opcode,*opcode_end;
275 char *start;
276 arc_insn insn;
277 bfd_reloc_code_real_type reloc;
278
279 /* Skip leading white space. */
280 while (isspace (*str))
281 str++;
282
283 /* The instructions are sorted by the first letter. Scan the opcode table
284 until we find the right one. */
285 opcode_end = arc_opcodes + arc_opcodes_count;
286 for (opcode = arc_opcodes; opcode < opcode_end; opcode++)
287 if (*opcode->syntax == *str)
288 break;
289 if (opcode == opcode_end)
290 {
291 as_bad ("bad instruction `%s'", str);
292 return;
293 }
294
295 /* Keep looking until we find a match. If we haven't found a match, and the
296 first character no longer matches, we needn't look any further. */
297 start = str;
298 for ( ; opcode < opcode_end && *opcode->syntax == *start; ++opcode)
299 {
300 int past_opcode_p;
301 char *syn;
302 struct arc_fixup fixups[MAX_INSN_FIXUPS];
303 int fc,limm_reloc_p;
304
305 /* Scan the syntax string. If it doesn't match, try the next one. */
306
307 arc_opcode_init_insert ();
308 insn = opcode->value;
309 reloc = BFD_RELOC_NONE;
310 fc = 0;
311 past_opcode_p = 0;
312
313 /* Used as a sanity check. If we need a limm reloc, make sure we ask
314 for an extra 4 bytes from frag_more. */
315 limm_reloc_p = 0;
316
317 /* We don't check for (*str != '\0') here because we want to parse
318 any trailing fake arguments in the syntax string. */
319 for (str = start, syn = opcode->syntax; *syn != '\0'; )
320 {
321 int mods;
322 const struct arc_operand *operand;
323
324 /* Non operand chars must match exactly. */
325 if (*syn != '%' || *++syn == '%')
326 {
327 /* Handle '+' specially as we want to allow "ld r0,[sp-4]". */
328 if (*syn == '+' && *str == '-')
329 {
330 /* Skip over syn's +, but leave str's - alone.
331 That makes the case identical to "ld r0,[sp+-4]". */
332 ++syn;
333 }
334 else if (*str != *syn)
335 break;
336 else
337 {
338 if (*syn == ' ')
339 past_opcode_p = 1;
340 ++syn;
341 ++str;
342 }
343 continue;
344 }
345
346 /* We have an operand. Pick out any modifiers. */
347 mods = 0;
348 while (ARC_MOD_P (arc_operands[arc_operand_map[*syn]].flags))
349 {
350 mods |= arc_operands[arc_operand_map[*syn]].flags & ARC_MOD_BITS;
351 ++syn;
352 }
353 operand = arc_operands + arc_operand_map[*syn];
354 if (operand->fmt == 0)
355 as_fatal ("unknown syntax format character `%c'", *syn);
356
357 if (operand->flags & ARC_OPERAND_FAKE)
358 {
359 const char *errmsg = NULL;
360 if (operand->insert)
361 {
362 insn = (*operand->insert) (insn, operand, mods, NULL, 0, &errmsg);
363 /* If we get an error, go on to try the next insn. */
364 if (errmsg)
365 break;
366 }
367 ++syn;
368 }
369 /* Are we finished with suffixes? */
370 else if (!past_opcode_p)
371 {
372 int found;
373 char c;
374 char *s,*t;
375 const struct arc_operand_value *suf,*suffix,*suffix_end;
376
377 if (!(operand->flags & ARC_OPERAND_SUFFIX))
378 abort ();
379
380 /* If we're at a space in the input string, we want to skip the
381 remaining suffixes. There may be some fake ones though, so
382 just go on to try the next one. */
383 if (*str == ' ')
384 {
385 ++syn;
386 continue;
387 }
388
389 s = str;
390 if (mods & ARC_MOD_DOT)
391 {
392 if (*s != '.')
393 break;
394 ++s;
395 }
396 else
397 {
398 /* This can happen in "b.nd foo" and we're currently looking
399 for "%q" (ie: a condition code suffix). */
400 if (*s == '.')
401 {
402 ++syn;
403 continue;
404 }
405 }
406
407 /* Pick the suffix out and look it up via the hash table. */
408 for (t = s; *t && isalpha (*t); ++t)
409 continue;
410 c = *t;
411 *t = '\0';
412 suf = hash_find (arc_suffix_hash, s);
413 *t = c;
414 if (!suf)
415 {
416 /* This can happen in "blle foo" and we're currently using
417 the template "b%q%.n %j". The "bl" insn occurs later in
418 the table so "lle" isn't an illegal suffix. */
419 break;
420 }
421
422 /* Is it the right type? Note that the same character is used
423 several times, so we have to examine all of them. This is
424 relatively efficient as equivalent entries are kept
425 together. If it's not the right type, don't increment `str'
426 so we try the next one in the series. */
427 found = 0;
428 suffix_end = arc_suffixes + arc_suffixes_count;
429 for (suffix = suf;
430 suffix < suffix_end && strcmp (suffix->name, suf->name) == 0;
431 suffix++)
432 {
433 if (arc_operands[suffix->type].fmt == *syn)
434 {
435 /* Insert the suffix's value into the insn. */
436 if (operand->insert)
437 insn = (*operand->insert) (insn, operand,
438 mods, NULL, suffix->value,
439 NULL);
440 else
441 insn |= suffix->value << operand->shift;
442
443 str = t;
444 found = 1;
445 break;
446 }
447 }
448 ++syn;
449 if (!found)
450 /* There's nothing to do except, go on to try the next one.
451 ??? This test can be deleted when we're done. */
452 ;
453 }
454 else
455 /* This is either a register or an expression of some kind. */
456 {
457 char c;
458 char *hold;
459 const struct arc_operand_value *reg;
460 long value;
461 expressionS ex;
462
463 if (operand->flags & ARC_OPERAND_SUFFIX)
464 abort ();
465
466 /* Is there anything left to parse?
467 We don't check for this at the top because we want to parse
468 any trailing fake arguments in the syntax string. */
469 if (*str == '\0')
470 break;
471
472 /* Is this a syntax character? Eg: is there a '[' present when
473 there shouldn't be? */
474 if (!isalnum (*str)
475 /* '.' as in ".LLC0" */
476 && *str != '.'
477 /* '_' as in "_print" */
478 && *str != '_'
479 /* '-' as in "[fp-4]" */
480 && *str != '-')
481 break;
482
483 /* Is it a register? */
484 value = 0;
485 hold = str;
486 while (*str && (isalnum (*str) || *str == '_'))
487 ++str;
488 c = *str;
489 *str = '\0';
490 reg = hash_find (arc_reg_hash, hold);
491 *str = c;
492 if (!reg)
493 {
494 /* Restore `str', it wasn't a register. */
495 str = hold;
496
497 /* Gather the operand. */
498 hold = input_line_pointer;
499 input_line_pointer = str;
500 expression (&ex);
501 str = input_line_pointer;
502 input_line_pointer = hold;
503
504 if (ex.X_op == O_illegal)
505 as_bad ("illegal operand");
506 else if (ex.X_op == O_absent)
507 as_bad ("missing operand");
508 else if (ex.X_op == O_constant)
509 {
510 value = ex.X_add_number;
511 }
512 else
513 {
514 /* We need to generate a fixup for this expression.
515 If this is a register constant (IE: one whose register
516 value gets stored as 61-63) then this must be a limm.
517 We don't support shimm relocs. */
518 if (fc >= MAX_INSN_FIXUPS)
519 as_fatal ("too many fixups");
520 fixups[fc].exp = ex;
521
522 /* ??? This bit could use some cleaning up. Referencing
523 the format chars like this goes against style. */
524 #define IS_REG_OPERAND(o) ((o) == 'a' || (o) == 'b' || (o) == 'c')
525 if (IS_REG_OPERAND (*syn))
526 {
527 const char *junk;
528 fixups[fc].opindex = arc_operand_map['L'];
529 limm_reloc_p = 1;
530 /* Tell insert_reg we need a limm. This is needed
531 because the value at this point is zero, a shimm.
532 ??? Hack city. */
533 (*arc_operands[arc_operand_map['Q']].insert)
534 (insn, operand, mods, reg, 0L, &junk);
535 }
536 else
537 fixups[fc].opindex = arc_operand_map[*syn];
538 ++fc;
539 value = 0;
540 }
541 }
542
543 /* Insert the register or expression into the instruction. */
544 if (operand->insert)
545 {
546 const char *errmsg = NULL;
547 insn = (*operand->insert) (insn, operand, mods,
548 reg, (long) value, &errmsg);
549 #if 0
550 if (errmsg != (const char *) NULL)
551 as_warn (errmsg);
552 #endif
553 /* FIXME: We want to try shimm insns for limm ones. But if
554 the constant won't fit, we must go on to try the next
555 possibility. Where do we issue warnings for constants
556 that are too big then? At present, we'll flag the insn
557 as unrecognizable! Maybe have the "bad instruction"
558 error message include our `errmsg'? */
559 if (errmsg != (const char *) NULL)
560 break;
561 }
562 else
563 insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
564
565 ++syn;
566 }
567 }
568
569 if (*syn == '\0')
570 {
571 int i;
572 char *f;
573 long limm;
574
575 /* We've found a matching insn.
576 ??? For the moment we assume a valid `str' can only contain blanks
577 now. IE: We needn't try again with a longer version of the
578 insn. */
579
580 while (isspace (*str))
581 ++str;
582
583 if (*str != '\0')
584 as_bad ("junk at end of line: `%s'", str);
585
586 /* Write out the instruction. */
587 f = frag_more (4);
588 md_number_to_chars (f, insn, 4);
589
590 if (arc_opcode_limm_p (&limm))
591 {
592 char *f2 = frag_more (4);
593 md_number_to_chars (f2, limm, 4);
594 }
595 else if (limm_reloc_p)
596 /* Ahh! We need a limm reloc, but the tables think we don't. */
597 abort ();
598
599 /* Create any fixups. At this point we do not use a
600 bfd_reloc_code_real_type, but instead just use the operand index.
601 This lets us easily handle fixups for any operand type, although
602 that is admittedly not a very exciting feature. We pick a BFD
603 reloc type in md_apply_fix. */
604 for (i = 0; i < fc; i++)
605 {
606 const struct arc_operand *operand;
607
608 operand = &arc_operands[fixups[i].opindex];
609 fix_new_exp (frag_now,
610 ((f - frag_now->fr_literal)
611 + (operand->fmt == 'L' ? 4 : 0)), 4,
612 &fixups[i].exp,
613 (operand->flags & ARC_OPERAND_RELATIVE) != 0,
614 ((bfd_reloc_code_real_type)
615 (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
616 }
617
618 /* All done. */
619 return;
620 }
621
622 /* Try the next entry. */
623 }
624
625 as_bad ("bad instruction `%s'", start);
626 }
627 \f
628 /*
629 * sort of like s_lcomm
630 *
631 */
632 #ifndef OBJ_ELF
633 static int max_alignment = 15;
634 #endif
635
636 static void
637 s_reserve (ignore)
638 int ignore;
639 {
640 char *name;
641 char *p;
642 char c;
643 int align;
644 int size;
645 int temp;
646 symbolS *symbolP;
647
648 name = input_line_pointer;
649 c = get_symbol_end ();
650 p = input_line_pointer;
651 *p = c;
652 SKIP_WHITESPACE ();
653
654 if (*input_line_pointer != ',')
655 {
656 as_bad ("Expected comma after name");
657 ignore_rest_of_line ();
658 return;
659 }
660
661 ++input_line_pointer;
662
663 if ((size = get_absolute_expression ()) < 0)
664 {
665 as_bad ("BSS length (%d.) <0! Ignored.", size);
666 ignore_rest_of_line ();
667 return;
668 } /* bad length */
669
670 *p = 0;
671 symbolP = symbol_find_or_make (name);
672 *p = c;
673
674 if (strncmp (input_line_pointer, ",\"bss\"", 6) != 0
675 && strncmp (input_line_pointer, ",\".bss\"", 7) != 0)
676 {
677 as_bad ("bad .reserve segment -- expected BSS segment");
678 return;
679 }
680
681 if (input_line_pointer[2] == '.')
682 input_line_pointer += 7;
683 else
684 input_line_pointer += 6;
685 SKIP_WHITESPACE ();
686
687 if (*input_line_pointer == ',')
688 {
689 ++input_line_pointer;
690
691 SKIP_WHITESPACE ();
692 if (*input_line_pointer == '\n')
693 {
694 as_bad ("Missing alignment");
695 return;
696 }
697
698 align = get_absolute_expression ();
699 #ifndef OBJ_ELF
700 if (align > max_alignment)
701 {
702 align = max_alignment;
703 as_warn ("Alignment too large: %d. assumed.", align);
704 }
705 #endif
706 if (align < 0)
707 {
708 align = 0;
709 as_warn ("Alignment negative. 0 assumed.");
710 }
711
712 record_alignment (bss_section, align);
713
714 /* convert to a power of 2 alignment */
715 for (temp = 0; (align & 1) == 0; align >>= 1, ++temp);;
716
717 if (align != 1)
718 {
719 as_bad ("Alignment not a power of 2");
720 ignore_rest_of_line ();
721 return;
722 } /* not a power of two */
723
724 align = temp;
725 } /* if has optional alignment */
726 else
727 align = 0;
728
729 if ((S_GET_SEGMENT (symbolP) == bss_section
730 || !S_IS_DEFINED (symbolP))
731 #ifdef OBJ_AOUT
732 && S_GET_OTHER (symbolP) == 0
733 && S_GET_DESC (symbolP) == 0
734 #endif
735 )
736 {
737 if (! need_pass_2)
738 {
739 char *pfrag;
740 segT current_seg = now_seg;
741 subsegT current_subseg = now_subseg;
742
743 subseg_set (bss_section, 1); /* switch to bss */
744
745 if (align)
746 frag_align (align, 0); /* do alignment */
747
748 /* detach from old frag */
749 if (S_GET_SEGMENT(symbolP) == bss_section)
750 symbolP->sy_frag->fr_symbol = NULL;
751
752 symbolP->sy_frag = frag_now;
753 pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,
754 size, (char *)0);
755 *pfrag = 0;
756
757 S_SET_SEGMENT (symbolP, bss_section);
758
759 subseg_set (current_seg, current_subseg);
760 }
761 }
762 else
763 {
764 as_warn("Ignoring attempt to re-define symbol %s.", name);
765 } /* if not redefining */
766
767 demand_empty_rest_of_line ();
768 }
769
770 static void
771 s_common (ignore)
772 int ignore;
773 {
774 char *name;
775 char c;
776 char *p;
777 int temp, size;
778 symbolS *symbolP;
779
780 name = input_line_pointer;
781 c = get_symbol_end ();
782 /* just after name is now '\0' */
783 p = input_line_pointer;
784 *p = c;
785 SKIP_WHITESPACE ();
786 if (*input_line_pointer != ',')
787 {
788 as_bad ("Expected comma after symbol-name");
789 ignore_rest_of_line ();
790 return;
791 }
792 input_line_pointer++; /* skip ',' */
793 if ((temp = get_absolute_expression ()) < 0)
794 {
795 as_bad (".COMMon length (%d.) <0! Ignored.", temp);
796 ignore_rest_of_line ();
797 return;
798 }
799 size = temp;
800 *p = 0;
801 symbolP = symbol_find_or_make (name);
802 *p = c;
803 if (S_IS_DEFINED (symbolP))
804 {
805 as_bad ("Ignoring attempt to re-define symbol");
806 ignore_rest_of_line ();
807 return;
808 }
809 if (S_GET_VALUE (symbolP) != 0)
810 {
811 if (S_GET_VALUE (symbolP) != size)
812 {
813 as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
814 S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
815 }
816 }
817 else
818 {
819 #ifndef OBJ_ELF
820 S_SET_VALUE (symbolP, (valueT) size);
821 S_SET_EXTERNAL (symbolP);
822 #endif
823 }
824 assert (symbolP->sy_frag == &zero_address_frag);
825 if (*input_line_pointer != ',')
826 {
827 as_bad ("Expected comma after common length");
828 ignore_rest_of_line ();
829 return;
830 }
831 input_line_pointer++;
832 SKIP_WHITESPACE ();
833 if (*input_line_pointer != '"')
834 {
835 temp = get_absolute_expression ();
836 #ifndef OBJ_ELF
837 if (temp > max_alignment)
838 {
839 temp = max_alignment;
840 as_warn ("Common alignment too large: %d. assumed", temp);
841 }
842 #endif
843 if (temp < 0)
844 {
845 temp = 0;
846 as_warn ("Common alignment negative; 0 assumed");
847 }
848 #ifdef OBJ_ELF
849 if (symbolP->local)
850 {
851 segT old_sec;
852 int old_subsec;
853 char *p;
854 int align;
855
856 allocate_bss:
857 old_sec = now_seg;
858 old_subsec = now_subseg;
859 align = temp;
860 record_alignment (bss_section, align);
861 subseg_set (bss_section, 0);
862 if (align)
863 frag_align (align, 0);
864 if (S_GET_SEGMENT (symbolP) == bss_section)
865 symbolP->sy_frag->fr_symbol = 0;
866 symbolP->sy_frag = frag_now;
867 p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
868 (char *) 0);
869 *p = 0;
870 S_SET_SEGMENT (symbolP, bss_section);
871 S_CLEAR_EXTERNAL (symbolP);
872 subseg_set (old_sec, old_subsec);
873 }
874 else
875 #endif
876 {
877 allocate_common:
878 S_SET_VALUE (symbolP, (valueT) size);
879 #ifdef OBJ_ELF
880 S_SET_ALIGN (symbolP, temp);
881 #endif
882 S_SET_EXTERNAL (symbolP);
883 /* should be common, but this is how gas does it for now */
884 S_SET_SEGMENT (symbolP, bfd_und_section_ptr);
885 }
886 }
887 else
888 {
889 input_line_pointer++;
890 /* @@ Some use the dot, some don't. Can we get some consistency?? */
891 if (*input_line_pointer == '.')
892 input_line_pointer++;
893 /* @@ Some say data, some say bss. */
894 if (strncmp (input_line_pointer, "bss\"", 4)
895 && strncmp (input_line_pointer, "data\"", 5))
896 {
897 while (*--input_line_pointer != '"')
898 ;
899 input_line_pointer--;
900 goto bad_common_segment;
901 }
902 while (*input_line_pointer++ != '"')
903 ;
904 goto allocate_common;
905 }
906 demand_empty_rest_of_line ();
907 return;
908
909 {
910 bad_common_segment:
911 p = input_line_pointer;
912 while (*p && *p != '\n')
913 p++;
914 c = *p;
915 *p = '\0';
916 as_bad ("bad .common segment %s", input_line_pointer + 1);
917 *p = c;
918 input_line_pointer = p;
919 ignore_rest_of_line ();
920 return;
921 }
922 }
923
924 static void
925 s_seg (ignore)
926 int ignore;
927 {
928
929 if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
930 {
931 input_line_pointer += 6;
932 s_text (0);
933 return;
934 }
935 if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
936 {
937 input_line_pointer += 6;
938 s_data (0);
939 return;
940 }
941 if (strncmp (input_line_pointer, "\"data1\"", 7) == 0)
942 {
943 input_line_pointer += 7;
944 s_data1 ();
945 return;
946 }
947 if (strncmp (input_line_pointer, "\"bss\"", 5) == 0)
948 {
949 input_line_pointer += 5;
950 /* We only support 2 segments -- text and data -- for now, so
951 things in the "bss segment" will have to go into data for now.
952 You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
953 subseg_set (data_section, 255); /* FIXME-SOMEDAY */
954 return;
955 }
956 as_bad ("Unknown segment type");
957 demand_empty_rest_of_line ();
958 }
959
960 static void
961 s_data1 ()
962 {
963 subseg_set (data_section, 1);
964 demand_empty_rest_of_line ();
965 }
966
967 static void
968 s_proc (ignore)
969 int ignore;
970 {
971 while (!is_end_of_line[(unsigned char) *input_line_pointer])
972 {
973 ++input_line_pointer;
974 }
975 ++input_line_pointer;
976 }
977 \f
978 /* Turn a string in input_line_pointer into a floating point constant of type
979 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
980 emitted is stored in *sizeP.
981 An error message is returned, or NULL on OK. */
982
983 /* Equal to MAX_PRECISION in atof-ieee.c */
984 #define MAX_LITTLENUMS 6
985
986 char *
987 md_atof (type, litP, sizeP)
988 char type;
989 char *litP;
990 int *sizeP;
991 {
992 int prec;
993 LITTLENUM_TYPE words[MAX_LITTLENUMS];
994 LITTLENUM_TYPE *wordP;
995 char *t;
996 char *atof_ieee ();
997
998 switch (type)
999 {
1000 case 'f':
1001 case 'F':
1002 prec = 2;
1003 break;
1004
1005 case 'd':
1006 case 'D':
1007 prec = 4;
1008 break;
1009
1010 default:
1011 *sizeP = 0;
1012 return "bad call to md_atof";
1013 }
1014
1015 t = atof_ieee (input_line_pointer, type, words);
1016 if (t)
1017 input_line_pointer = t;
1018 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1019 for (wordP = words; prec--;)
1020 {
1021 md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
1022 litP += sizeof (LITTLENUM_TYPE);
1023 }
1024
1025 return NULL;
1026 }
1027
1028 /* Write a value out to the object file, using the appropriate
1029 endianness. */
1030
1031 void
1032 md_number_to_chars (buf, val, n)
1033 char *buf;
1034 valueT val;
1035 int n;
1036 {
1037 number_to_chars_bigendian (buf, val, n);
1038 }
1039
1040 /* Round up a section size to the appropriate boundary. */
1041
1042 valueT
1043 md_section_align (segment, size)
1044 segT segment;
1045 valueT size;
1046 {
1047 int align = bfd_get_section_alignment (stdoutput, segment);
1048
1049 return ((size + (1 << align) - 1) & (-1 << align));
1050 }
1051
1052 /* We don't have any form of relaxing. */
1053
1054 int
1055 md_estimate_size_before_relax (fragp, seg)
1056 fragS *fragp;
1057 asection *seg;
1058 {
1059 abort ();
1060 }
1061
1062 const relax_typeS md_relax_table[] =
1063 {
1064 { 0 }
1065 };
1066
1067 /* Convert a machine dependent frag. We never generate these. */
1068
1069 void
1070 md_convert_frag (abfd, sec, fragp)
1071 bfd *abfd;
1072 asection *sec;
1073 fragS *fragp;
1074 {
1075 abort ();
1076 }
1077
1078 /* Parse an operand that is machine-specific.
1079 We just return without modifying the expression if we have nothing to do. */
1080
1081 /* ARGSUSED */
1082 void
1083 md_operand (expressionP)
1084 expressionS *expressionP;
1085 {
1086 }
1087
1088 /* We have no need to default values of symbols. */
1089
1090 /* ARGSUSED */
1091 symbolS *
1092 md_undefined_symbol (name)
1093 char *name;
1094 {
1095 return 0;
1096 } /* md_undefined_symbol() */
1097 \f
1098 /* Functions concerning relocs. */
1099
1100 /* The location from which a PC relative jump should be calculated,
1101 given a PC relative reloc. */
1102
1103 long
1104 md_pcrel_from (fixP)
1105 fixS *fixP;
1106 {
1107 if (fixP->fx_addsy != (symbolS *) NULL
1108 && ! S_IS_DEFINED (fixP->fx_addsy))
1109 {
1110 /* This makes a branch to an undefined symbol be a branch to the
1111 current location. */
1112 return 4;
1113 }
1114
1115 /* Return the address of the delay slot. */
1116 return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size;
1117 }
1118
1119 /* Apply a fixup to the object code. This is called for all the
1120 fixups we generated by the call to fix_new_exp, above. In the call
1121 above we used a reloc code which was the largest legal reloc code
1122 plus the operand index. Here we undo that to recover the operand
1123 index. At this point all symbol values should be fully resolved,
1124 and we attempt to completely resolve the reloc. If we can not do
1125 that, we determine the correct reloc code and put it back in the
1126 fixup. */
1127
1128 int
1129 md_apply_fix (fixP, valueP)
1130 fixS *fixP;
1131 valueT *valueP;
1132 {
1133 /*char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;*/
1134 valueT value;
1135
1136 /* FIXME FIXME FIXME: The value we are passed in *valueP includes
1137 the symbol values. Since we are using BFD_ASSEMBLER, if we are
1138 doing this relocation the code in write.c is going to call
1139 bfd_perform_relocation, which is also going to use the symbol
1140 value. That means that if the reloc is fully resolved we want to
1141 use *valueP since bfd_perform_relocation is not being used.
1142 However, if the reloc is not fully resolved we do not want to use
1143 *valueP, and must use fx_offset instead. However, if the reloc
1144 is PC relative, we do want to use *valueP since it includes the
1145 result of md_pcrel_from. This is confusing. */
1146
1147 if (fixP->fx_addsy == (symbolS *) NULL)
1148 {
1149 value = *valueP;
1150 fixP->fx_done = 1;
1151 }
1152 else if (fixP->fx_pcrel)
1153 value = *valueP;
1154 else
1155 {
1156 value = fixP->fx_offset;
1157 if (fixP->fx_subsy != (symbolS *) NULL)
1158 {
1159 if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
1160 value -= S_GET_VALUE (fixP->fx_subsy);
1161 else
1162 {
1163 /* We can't actually support subtracting a symbol. */
1164 as_bad_where (fixP->fx_file, fixP->fx_line,
1165 "expression too complex");
1166 }
1167 }
1168 }
1169
1170 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1171 {
1172 int opindex;
1173 const struct arc_operand *operand;
1174 char *where;
1175 arc_insn insn;
1176
1177 opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1178
1179 operand = &arc_operands[opindex];
1180
1181 /* Fetch the instruction, insert the fully resolved operand
1182 value, and stuff the instruction back again. */
1183 where = fixP->fx_frag->fr_literal + fixP->fx_where;
1184 insn = bfd_getb32 ((unsigned char *) where);
1185 insn = arc_insert_operand (insn, operand, -1, NULL, (offsetT) value,
1186 fixP->fx_file, fixP->fx_line);
1187 bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
1188
1189 if (fixP->fx_done)
1190 {
1191 /* Nothing else to do here. */
1192 return 1;
1193 }
1194
1195 /* Determine a BFD reloc value based on the operand information.
1196 We are only prepared to turn a few of the operands into relocs.
1197 FIXME: Selecting the reloc type is a bit haphazard; perhaps
1198 there should be a new field in the operand table. */
1199 if ((operand->flags & ARC_OPERAND_RELATIVE) != 0
1200 && operand->bits == 20
1201 && operand->shift == 7)
1202 fixP->fx_r_type = BFD_RELOC_ARC_B22_PCREL;
1203 else if ((operand->flags & ARC_OPERAND_ABSOLUTE) != 0
1204 && operand->bits == 32
1205 && operand->shift == 32)
1206 fixP->fx_r_type = BFD_RELOC_32;
1207 else
1208 {
1209 as_bad_where (fixP->fx_file, fixP->fx_line,
1210 "unresolved expression that must be resolved");
1211 fixP->fx_done = 1;
1212 return 1;
1213 }
1214 }
1215 else
1216 {
1217 switch (fixP->fx_r_type)
1218 {
1219 case BFD_RELOC_32:
1220 md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1221 value, 4);
1222 break;
1223 case BFD_RELOC_16:
1224 md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1225 value, 2);
1226 break;
1227 case BFD_RELOC_8:
1228 md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1229 value, 1);
1230 break;
1231 default:
1232 abort ();
1233 }
1234 }
1235
1236 #ifdef OBJ_ELF
1237 fixP->fx_addnumber = value;
1238 #else
1239 fixP->fx_addnumber = 0;
1240 #endif
1241
1242 return 1;
1243 }
1244
1245 /* Translate internal representation of relocation info to BFD target
1246 format. */
1247
1248 arelent *
1249 tc_gen_reloc (section, fixP)
1250 asection *section;
1251 fixS *fixP;
1252 {
1253 arelent *reloc;
1254
1255 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
1256
1257 reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
1258 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1259 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1260 if (reloc->howto == (reloc_howto_type *) NULL)
1261 {
1262 as_bad_where (fixP->fx_file, fixP->fx_line,
1263 "internal error: can't export reloc type %d (`%s')",
1264 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
1265 return NULL;
1266 }
1267 reloc->addend = fixP->fx_addnumber;
1268
1269 assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1270
1271 return reloc;
1272 }