* config/tc-txvu.c (assemble_insn): Commas moved to opcode table.
[binutils-gdb.git] / gas / config / tc-txvu.c
1 /* tc-txvu.c -- Assembler for the TX VU.
2 Copyright (C) 1997 Free Software Foundation.
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 #include <stdio.h>
22 #include <ctype.h>
23 #include "as.h"
24 #include "subsegs.h"
25 /* Needed by opcode/txvu.h. */
26 #include "dis-asm.h"
27 #include "opcode/txvu.h"
28 #include "elf/txvu.h"
29
30 static TXVU_INSN txvu_insert_operand
31 PARAMS ((TXVU_INSN, const struct txvu_operand *, int, offsetT,
32 char *, unsigned int));
33
34 const char comment_chars[] = ";";
35 const char line_comment_chars[] = "#";
36 const char line_separator_chars[] = "!";
37 const char EXP_CHARS[] = "eE";
38 const char FLT_CHARS[] = "dD";
39 \f
40 const char *md_shortopts = "";
41
42 struct option md_longopts[] =
43 {
44 /* insert options here */
45
46 {NULL, no_argument, NULL, 0}
47 };
48 size_t md_longopts_size = sizeof(md_longopts);
49
50 int
51 md_parse_option (c, arg)
52 int c;
53 char *arg;
54 {
55 return 0;
56 }
57
58 void
59 md_show_usage (stream)
60 FILE *stream;
61 {
62 #if 0
63 fprintf (stream, "TX VU options:\n");
64 #endif
65 }
66
67 /* Set by md_assemble for use by txvu_fill_insn. */
68 static subsegT prev_subseg;
69 static segT prev_seg;
70
71 /* The target specific pseudo-ops which we support. */
72 const pseudo_typeS md_pseudo_table[] =
73 {
74 { "word", cons, 4 },
75 { NULL, NULL, 0 }
76 };
77 \f
78 void
79 md_begin ()
80 {
81 flagword applicable;
82 segT seg;
83 subsegT subseg;
84
85 /* Save the current subseg so we can restore it [it's the default one and
86 we don't want the initial section to be .sbss. */
87 seg = now_seg;
88 subseg = now_subseg;
89
90 subseg_set (seg, subseg);
91
92 /* Initialize the opcode tables.
93 This involves computing the hash chains. */
94 txvu_opcode_init_tables (0);
95 }
96
97 /* We need to keep a list of fixups. We can't simply generate them as
98 we go, because that would require us to first create the frag, and
99 that would screw up references to ``.''. */
100
101 struct txvu_fixup
102 {
103 /* index into `txvu_operands' */
104 int opindex;
105 expressionS exp;
106 };
107
108 #define MAX_FIXUPS 5
109
110 static char * assemble_insn PARAMS ((char *, int, char *));
111
112 void
113 md_assemble (str)
114 char *str;
115 {
116 /* The lower instruction has the lower address.
117 Handle this by grabbing 8 bytes now, and then filling each word
118 as appropriate. */
119 char *f = frag_more (8);
120
121 #ifdef VERTICAL_BAR_SEPARATOR
122 char *p = strchr (str, '|');
123
124 if (p == NULL)
125 {
126 as_bad ("lower slot missing in `%s'", str);
127 return;
128 }
129
130 *p = 0;
131 assemble_insn (str, 0, f + 4);
132 *p = '|';
133 assemble_insn (p + 1, 1, f);
134 #else
135 str = assemble_insn (str, 0, f + 4);
136 /* Don't assemble next one if we couldn't assemble the first. */
137 if (str)
138 assemble_insn (str, 1, f);
139 #endif
140 }
141
142 /* Assemble one instruction.
143 LOWER_P is non-zero if assembling in the lower insn slot.
144 The result is a pointer to beyond the end of the scanned insn
145 or NULL if an error occured.
146 If this is the upper insn, the caller can pass back to result to us
147 parse the lower insn. */
148
149 static char *
150 assemble_insn (str, lower_p, buf)
151 char *str;
152 int lower_p;
153 char *buf;
154 {
155 const struct txvu_opcode *opcode;
156 char *start;
157 TXVU_INSN insn_buf[2];
158 TXVU_INSN insn;
159
160 /* Skip leading white space. */
161 while (isspace (*str))
162 str++;
163
164 /* The instructions are stored in lists hashed by the first letter (though
165 we needn't care how they're hashed). Get the first in the list. */
166
167 if (lower_p)
168 opcode = txvu_lower_opcode_lookup_asm (str);
169 else
170 opcode = txvu_upper_opcode_lookup_asm (str);
171
172 /* Keep looking until we find a match. */
173
174 start = str;
175 for ( ; opcode != NULL; opcode = TXVU_OPCODE_NEXT_ASM (opcode))
176 {
177 int past_opcode_p, fc, num_suffixes, num_operands;
178 const unsigned char *syn;
179 struct txvu_fixup fixups[MAX_FIXUPS];
180
181 /* Ensure the mnemonic part matches. */
182 for (str = start, syn = opcode->mnemonic; *syn != '\0'; ++str, ++syn)
183 if (tolower (*str) != tolower (*syn))
184 break;
185 if (*syn != '\0')
186 continue;
187 if (isalpha (*str))
188 continue;
189
190 /* Scan the syntax string. If it doesn't match, try the next one. */
191
192 txvu_opcode_init_parse ();
193 insn = opcode->value;
194 fc = 0;
195 past_opcode_p = 0;
196 num_suffixes = 0;
197 num_operands = 0;
198
199 /* We don't check for (*str != '\0') here because we want to parse
200 any trailing fake arguments in the syntax string. */
201 for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; )
202 {
203 int mods,index;
204 const struct txvu_operand *operand;
205 const char *errmsg;
206
207 /* Non operand chars must match exactly. */
208 if (*syn < 128)
209 {
210 if (*str == *syn)
211 {
212 if (*syn == ' ')
213 past_opcode_p = 1;
214 ++syn;
215 ++str;
216 }
217 else
218 break;
219 continue;
220 }
221
222 /* We have a suffix or an operand. Pick out any modifiers. */
223 mods = 0;
224 index = TXVU_OPERAND_INDEX (*syn);
225 while (TXVU_MOD_P (txvu_operands[index].flags))
226 {
227 mods |= txvu_operands[index].flags & TXVU_MOD_BITS;
228 ++syn;
229 index = TXVU_OPERAND_INDEX (*syn);
230 }
231 operand = txvu_operands + index;
232
233 if (operand->flags & TXVU_OPERAND_FAKE)
234 {
235 if (operand->insert)
236 {
237 insn = (*operand->insert) (insn, operand, mods, 0, &errmsg);
238 /* If we get an error, go on to try the next insn. */
239 if (errmsg)
240 break;
241 }
242 ++syn;
243 }
244 /* Are we finished with suffixes? */
245 else if (!past_opcode_p)
246 {
247 int found;
248 char c;
249 char *s,*t;
250 long suf_value;
251
252 if (!(operand->flags & TXVU_OPERAND_SUFFIX))
253 as_fatal ("bad opcode table, missing suffix flag");
254
255 /* If we're at a space in the input string, we want to skip the
256 remaining suffixes. There may be some fake ones though, so
257 just go on to try the next one. */
258 if (*str == ' ')
259 {
260 ++syn;
261 continue;
262 }
263
264 s = str;
265
266 /* Pick the suffix out and parse it. */
267 for (t = *s == '.' ? s + 1 : s; *t && isalpha (*t); ++t)
268 continue;
269 c = *t;
270 *t = '\0';
271 suf_value = (*operand->parse) (&s, &errmsg);
272 *t = c;
273 if (errmsg)
274 {
275 /* This can happen in "blle foo" and we're currently using
276 the template "b%q%.n %j". The "bl" insn occurs later in
277 the table so "lle" isn't an illegal suffix. */
278 break;
279 }
280 /* Insert the suffix's value into the insn. */
281 if (operand->insert)
282 insn = (*operand->insert) (insn, operand,
283 mods, suf_value, NULL);
284 else
285 insn |= suf_value << operand->shift;
286
287 str = t;
288 ++syn;
289 }
290 else
291 /* This is an operand, either a register or an expression of
292 some kind. */
293 {
294 char c;
295 char *hold;
296 long value = 0;
297 expressionS exp;
298
299 if (operand->flags & TXVU_OPERAND_SUFFIX)
300 as_fatal ("bad opcode table, suffix wrong");
301
302 #if 0 /* commas are in the syntax string now */
303 /* If this is not the first, there must be a comma. */
304 if (num_operands > 0)
305 {
306 if (*str != ',')
307 break;
308 ++str;
309 }
310 #endif
311
312 /* Is there anything left to parse?
313 We don't check for this at the top because we want to parse
314 any trailing fake arguments in the syntax string. */
315 if (*str == '\0')
316 break;
317
318 /* Parse the operand. */
319 if (operand->parse)
320 {
321 value = (*operand->parse) (&str, &errmsg);
322 if (errmsg)
323 break;
324 }
325 else
326 {
327 hold = input_line_pointer;
328 input_line_pointer = str;
329 expression (&exp);
330 str = input_line_pointer;
331 input_line_pointer = hold;
332
333 if (exp.X_op == O_illegal
334 || exp.X_op == O_absent)
335 break;
336 else if (exp.X_op == O_constant)
337 value = exp.X_add_number;
338 else if (exp.X_op == O_register)
339 as_fatal ("got O_register");
340 else
341 {
342 /* We need to generate a fixup for this expression. */
343 if (fc >= MAX_FIXUPS)
344 as_fatal ("too many fixups");
345 fixups[fc].exp = exp;
346 fixups[fc].opindex = index;
347 ++fc;
348 value = 0;
349 }
350 }
351
352 /* Insert the register or expression into the instruction. */
353 if (operand->insert)
354 {
355 const char *errmsg = NULL;
356 insn = (*operand->insert) (insn, operand, mods,
357 value, &errmsg);
358 #if 0
359 if (errmsg != (const char *) NULL)
360 as_warn (errmsg);
361 #endif
362 /* FIXME: We want to try shimm insns for limm ones. But if
363 the constant won't fit, we must go on to try the next
364 possibility. Where do we issue warnings for constants
365 that are too big then? At present, we'll flag the insn
366 as unrecognizable! Maybe have the "bad instruction"
367 error message include our `errmsg'? */
368 if (errmsg != (const char *) NULL)
369 break;
370 }
371 else
372 insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
373
374 ++syn;
375 ++num_operands;
376 }
377 }
378
379 /* If we're at the end of the syntax string, we're done. */
380 /* FIXME: try to move this to a separate function. */
381 if (*syn == '\0')
382 {
383 int i;
384
385 /* For the moment we assume a valid `str' can only contain blanks
386 now. IE: We needn't try again with a longer version of the
387 insn and it is assumed that longer versions of insns appear
388 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
389
390 while (isspace (*str))
391 ++str;
392
393 if (*str != '\0'
394 #ifndef VERTICAL_BAR_SEPARATOR
395 && lower_p
396 #endif
397 )
398 as_bad ("junk at end of line: `%s'", str);
399
400 /* Write out the instruction.
401 Reminder: it is important to fetch enough space in one call to
402 `frag_more'. We use (f - frag_now->fr_literal) to compute where
403 we are and we don't want frag_now to change between calls. */
404 md_number_to_chars (buf, insn, 4);
405
406 /* Create any fixups. */
407 for (i = 0; i < fc; ++i)
408 {
409 int op_type, reloc_type;
410 const struct txvu_operand *operand;
411
412 /* Create a fixup for this operand.
413 At this point we do not use a bfd_reloc_code_real_type for
414 operands residing in the insn, but instead just use the
415 operand index. This lets us easily handle fixups for any
416 operand type, although that is admittedly not a very exciting
417 feature. We pick a BFD reloc type in md_apply_fix. */
418
419 op_type = fixups[i].opindex;
420 reloc_type = op_type + (int) BFD_RELOC_UNUSED;
421 operand = &txvu_operands[op_type];
422 fix_new_exp (frag_now, buf - frag_now->fr_literal, 4,
423 &fixups[i].exp,
424 (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0,
425 (bfd_reloc_code_real_type) reloc_type);
426 }
427
428 /* All done. */
429 return str;
430 }
431
432 /* Try the next entry. */
433 }
434
435 as_bad ("bad instruction `%s'", start);
436 return 0;
437 }
438
439 void
440 md_operand (expressionP)
441 expressionS *expressionP;
442 {
443 }
444
445 valueT
446 md_section_align (segment, size)
447 segT segment;
448 valueT size;
449 {
450 int align = bfd_get_section_alignment (stdoutput, segment);
451 return ((size + (1 << align) - 1) & (-1 << align));
452 }
453
454 symbolS *
455 md_undefined_symbol (name)
456 char *name;
457 {
458 return 0;
459 }
460 \f
461 /* Functions concerning relocs. */
462
463 /* The location from which a PC relative jump should be calculated,
464 given a PC relative reloc. */
465
466 long
467 md_pcrel_from_section (fixP, sec)
468 fixS *fixP;
469 segT sec;
470 {
471 if (fixP->fx_addsy != (symbolS *) NULL
472 && (! S_IS_DEFINED (fixP->fx_addsy)
473 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
474 {
475 /* The symbol is undefined (or is defined but not in this section).
476 Let the linker figure it out. */
477 return 0;
478 }
479
480 /* FIXME: `& -16L'? */
481 return (fixP->fx_frag->fr_address + fixP->fx_where) & -8L;
482 }
483
484 /* Apply a fixup to the object code. This is called for all the
485 fixups we generated by calls to fix_new_exp. At this point all symbol
486 values should be fully resolved, and we attempt to completely resolve the
487 reloc. If we can not do that, we determine the correct reloc code and put
488 it back in the fixup. */
489
490 int
491 md_apply_fix3 (fixP, valueP, seg)
492 fixS *fixP;
493 valueT *valueP;
494 segT seg;
495 {
496 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
497 valueT value;
498
499 /* FIXME FIXME FIXME: The value we are passed in *valueP includes
500 the symbol values. Since we are using BFD_ASSEMBLER, if we are
501 doing this relocation the code in write.c is going to call
502 bfd_perform_relocation, which is also going to use the symbol
503 value. That means that if the reloc is fully resolved we want to
504 use *valueP since bfd_perform_relocation is not being used.
505 However, if the reloc is not fully resolved we do not want to use
506 *valueP, and must use fx_offset instead. However, if the reloc
507 is PC relative, we do want to use *valueP since it includes the
508 result of md_pcrel_from. This is confusing. */
509
510 if (fixP->fx_addsy == (symbolS *) NULL)
511 {
512 value = *valueP;
513 fixP->fx_done = 1;
514 }
515 else if (fixP->fx_pcrel)
516 {
517 value = *valueP;
518 }
519 else
520 {
521 value = fixP->fx_offset;
522 if (fixP->fx_subsy != (symbolS *) NULL)
523 {
524 if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
525 value -= S_GET_VALUE (fixP->fx_subsy);
526 else
527 {
528 /* We can't actually support subtracting a symbol. */
529 as_bad_where (fixP->fx_file, fixP->fx_line,
530 "expression too complex");
531 }
532 }
533 }
534
535 /* Check for txvu_operand's. These are indicated with a reloc value
536 >= BFD_RELOC_UNUSED. */
537
538 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
539 {
540 int opindex;
541 const struct txvu_operand *operand;
542 TXVU_INSN insn;
543
544 opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
545
546 operand = &txvu_operands[opindex];
547
548 /* Fetch the instruction, insert the fully resolved operand
549 value, and stuff the instruction back again. */
550 insn = bfd_getl32 ((unsigned char *) where);
551 insn = txvu_insert_operand (insn, operand, -1, (offsetT) value,
552 fixP->fx_file, fixP->fx_line);
553 bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
554
555 if (fixP->fx_done)
556 {
557 /* Nothing else to do here. */
558 return 1;
559 }
560
561 /* Determine a BFD reloc value based on the operand information.
562 We are only prepared to turn a few of the operands into relocs. */
563 /* FIXME: This test is a hack. */
564 if ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0)
565 {
566 assert ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0
567 && operand->bits == 11
568 && operand->shift == 0);
569 fixP->fx_r_type = BFD_RELOC_TXVU_11_PCREL;
570 }
571 else
572 {
573 as_bad_where (fixP->fx_file, fixP->fx_line,
574 "unresolved expression that must be resolved");
575 fixP->fx_done = 1;
576 return 1;
577 }
578 }
579 else
580 {
581 switch (fixP->fx_r_type)
582 {
583 case BFD_RELOC_8:
584 md_number_to_chars (where, value, 1);
585 break;
586 case BFD_RELOC_16:
587 md_number_to_chars (where, value, 2);
588 break;
589 case BFD_RELOC_32:
590 md_number_to_chars (where, value, 4);
591 break;
592 default:
593 abort ();
594 }
595 }
596
597 fixP->fx_addnumber = value;
598
599 return 1;
600 }
601
602 /* Translate internal representation of relocation info to BFD target
603 format. */
604
605 arelent *
606 tc_gen_reloc (section, fixP)
607 asection *section;
608 fixS *fixP;
609 {
610 arelent *reloc;
611
612 reloc = (arelent *) xmalloc (sizeof (arelent));
613
614 reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
615 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
616 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
617 if (reloc->howto == (reloc_howto_type *) NULL)
618 {
619 as_bad_where (fixP->fx_file, fixP->fx_line,
620 "internal error: can't export reloc type %d (`%s')",
621 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
622 return NULL;
623 }
624
625 assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
626
627 reloc->addend = fixP->fx_addnumber;
628
629 return reloc;
630 }
631 \f
632 /* Write a value out to the object file, using the appropriate endianness. */
633
634 void
635 md_number_to_chars (buf, val, n)
636 char *buf;
637 valueT val;
638 int n;
639 {
640 if (target_big_endian)
641 number_to_chars_bigendian (buf, val, n);
642 else
643 number_to_chars_littleendian (buf, val, n);
644 }
645
646 /* Turn a string in input_line_pointer into a floating point constant of type
647 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
648 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
649 */
650
651 /* Equal to MAX_PRECISION in atof-ieee.c */
652 #define MAX_LITTLENUMS 6
653
654 char *
655 md_atof (type, litP, sizeP)
656 char type;
657 char *litP;
658 int *sizeP;
659 {
660 int i,prec;
661 LITTLENUM_TYPE words[MAX_LITTLENUMS];
662 LITTLENUM_TYPE *wordP;
663 char *t;
664 char *atof_ieee ();
665
666 switch (type)
667 {
668 case 'f':
669 case 'F':
670 case 's':
671 case 'S':
672 prec = 2;
673 break;
674
675 case 'd':
676 case 'D':
677 case 'r':
678 case 'R':
679 prec = 4;
680 break;
681
682 /* FIXME: Some targets allow other format chars for bigger sizes here. */
683
684 default:
685 *sizeP = 0;
686 return "Bad call to md_atof()";
687 }
688
689 t = atof_ieee (input_line_pointer, type, words);
690 if (t)
691 input_line_pointer = t;
692 *sizeP = prec * sizeof (LITTLENUM_TYPE);
693
694 if (target_big_endian)
695 {
696 for (i = 0; i < prec; i++)
697 {
698 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
699 litP += sizeof (LITTLENUM_TYPE);
700 }
701 }
702 else
703 {
704 for (i = prec - 1; i >= 0; i--)
705 {
706 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
707 litP += sizeof (LITTLENUM_TYPE);
708 }
709 }
710
711 return 0;
712 }
713 \f
714 /* Insert an operand value into an instruction. */
715
716 static TXVU_INSN
717 txvu_insert_operand (insn, operand, mods, val, file, line)
718 TXVU_INSN insn;
719 const struct txvu_operand *operand;
720 int mods;
721 offsetT val;
722 char *file;
723 unsigned int line;
724 {
725 if (operand->bits != 32)
726 {
727 long min, max;
728 offsetT test;
729
730 if ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0)
731 {
732 if ((val & 7) != 0)
733 {
734 if (file == (char *) NULL)
735 as_warn ("branch to misaligned address");
736 else
737 as_warn_where (file, line, "branch to misaligned address");
738 }
739 val >>= 3;
740 }
741
742 if ((operand->flags & TXVU_OPERAND_SIGNED) != 0)
743 {
744 if ((operand->flags & TXVU_OPERAND_SIGNOPT) != 0)
745 max = (1 << operand->bits) - 1;
746 else
747 max = (1 << (operand->bits - 1)) - 1;
748 min = - (1 << (operand->bits - 1));
749 }
750 else
751 {
752 max = (1 << operand->bits) - 1;
753 min = 0;
754 }
755
756 if ((operand->flags & TXVU_OPERAND_NEGATIVE) != 0)
757 test = - val;
758 else
759 test = val;
760
761 if (test < (offsetT) min || test > (offsetT) max)
762 {
763 const char *err =
764 "operand out of range (%s not between %ld and %ld)";
765 char buf[100];
766
767 sprint_value (buf, test);
768 if (file == (char *) NULL)
769 as_warn (err, buf, min, max);
770 else
771 as_warn_where (file, line, err, buf, min, max);
772 }
773 }
774
775 if (operand->insert)
776 {
777 const char *errmsg;
778
779 errmsg = NULL;
780 insn = (*operand->insert) (insn, operand, mods, (long) val, &errmsg);
781 if (errmsg != (const char *) NULL)
782 as_warn (errmsg);
783 }
784 else
785 insn |= (((long) val & ((1 << operand->bits) - 1))
786 << operand->shift);
787
788 return insn;
789 }