* config/tc-txvu.c (md_assemble): Handle no separator between
[deliverable/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 const char comment_chars[] = ";";
31 const char line_comment_chars[] = "#";
32 const char line_separator_chars[] = "!";
33 const char EXP_CHARS[] = "eE";
34 const char FLT_CHARS[] = "dD";
35 \f
36 const char *md_shortopts = "";
37
38 struct option md_longopts[] =
39 {
40 /* insert options here */
41
42 {NULL, no_argument, NULL, 0}
43 };
44 size_t md_longopts_size = sizeof(md_longopts);
45
46 int
47 md_parse_option (c, arg)
48 int c;
49 char *arg;
50 {
51 return 0;
52 }
53
54 void
55 md_show_usage (stream)
56 FILE *stream;
57 {
58 #if 0
59 fprintf (stream, "TX VU options:\n");
60 #endif
61 }
62
63 /* Set by md_assemble for use by txvu_fill_insn. */
64 static subsegT prev_subseg;
65 static segT prev_seg;
66
67 /* The target specific pseudo-ops which we support. */
68 const pseudo_typeS md_pseudo_table[] =
69 {
70 { "word", cons, 4 },
71 { NULL, NULL, 0 }
72 };
73 \f
74 void
75 md_begin ()
76 {
77 flagword applicable;
78 segT seg;
79 subsegT subseg;
80
81 /* Save the current subseg so we can restore it [it's the default one and
82 we don't want the initial section to be .sbss. */
83 seg = now_seg;
84 subseg = now_subseg;
85
86 subseg_set (seg, subseg);
87
88 /* Initialize the opcode tables.
89 This involves computing the hash chains. */
90 txvu_opcode_init_tables (0);
91 }
92
93 /* We need to keep a list of fixups. We can't simply generate them as
94 we go, because that would require us to first create the frag, and
95 that would screw up references to ``.''. */
96
97 struct txvu_fixup
98 {
99 /* index into `txvu_operands' */
100 int opindex;
101 expressionS exp;
102 };
103
104 #define MAX_FIXUPS 5
105
106 static char * assemble_insn PARAMS ((char *, int));
107
108 void
109 md_assemble (str)
110 char *str;
111 {
112 #ifdef VERTICAL_BAR_SEPARATOR
113 char *p = strchr (str, '|');
114
115 if (p == NULL)
116 {
117 as_bad ("lower slot missing in `%s'", str);
118 return;
119 }
120
121 *p = 0;
122 assemble_insn (str, 0);
123 *p = '|';
124 assemble_insn (p + 1, 1);
125 #else
126 str = assemble_insn (str, 0);
127 /* Don't assemble next one if we couldn't assemble the first. */
128 if (str)
129 assemble_insn (str, 1);
130 #endif
131 }
132
133 /* Assemble one instruction.
134 LOWER_P is non-zero if assembling in the lower insn slot.
135 The result is a pointer to beyond the end of the scanned insn.
136 If this is the upper insn, the caller can pass back to result to us
137 parse the lower insn. */
138
139 static char *
140 assemble_insn (str, lower_p)
141 char *str;
142 int lower_p;
143 {
144 const struct txvu_opcode *opcode;
145 char *start;
146 TXVU_INSN insn_buf[2];
147 TXVU_INSN insn;
148
149 /* Skip leading white space. */
150 while (isspace (*str))
151 str++;
152
153 /* The instructions are stored in lists hashed by the first letter (though
154 we needn't care how they're hashed). Get the first in the list. */
155
156 if (lower_p)
157 opcode = txvu_lower_opcode_lookup_asm (str);
158 else
159 opcode = txvu_upper_opcode_lookup_asm (str);
160
161 /* Keep looking until we find a match. */
162
163 start = str;
164 for ( ; opcode != NULL; opcode = TXVU_OPCODE_NEXT_ASM (opcode))
165 {
166 int past_opcode_p, fc, num_suffixes, num_operands;
167 const unsigned char *syn;
168 struct txvu_fixup fixups[MAX_FIXUPS];
169
170 /* Ensure the mnemonic part matches. */
171 for (str = start, syn = opcode->mnemonic; *syn != '\0'; ++str, ++syn)
172 if (tolower (*str) != tolower (*syn))
173 break;
174 if (*syn != '\0')
175 continue;
176 if (isalpha (*str))
177 continue;
178
179 /* Scan the syntax string. If it doesn't match, try the next one. */
180
181 txvu_opcode_init_parse ();
182 insn = opcode->value;
183 fc = 0;
184 past_opcode_p = 0;
185 num_suffixes = 0;
186 num_operands = 0;
187
188 /* We don't check for (*str != '\0') here because we want to parse
189 any trailing fake arguments in the syntax string. */
190 for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; )
191 {
192 int mods,index;
193 const struct txvu_operand *operand;
194 const char *errmsg;
195
196 /* Non operand chars must match exactly. */
197 if (*syn < 128)
198 {
199 if (*str == *syn)
200 {
201 if (*syn == ' ')
202 past_opcode_p = 1;
203 ++syn;
204 ++str;
205 }
206 else
207 break;
208 continue;
209 }
210
211 /* We have a suffix or an operand. Pick out any modifiers. */
212 mods = 0;
213 index = TXVU_OPERAND_INDEX (*syn);
214 while (TXVU_MOD_P (txvu_operands[index].flags))
215 {
216 mods |= txvu_operands[index].flags & TXVU_MOD_BITS;
217 ++syn;
218 index = TXVU_OPERAND_INDEX (*syn);
219 }
220 operand = txvu_operands + index;
221
222 if (operand->flags & TXVU_OPERAND_FAKE)
223 {
224 if (operand->insert)
225 {
226 insn = (*operand->insert) (insn, operand, mods, 0, &errmsg);
227 /* If we get an error, go on to try the next insn. */
228 if (errmsg)
229 break;
230 }
231 ++syn;
232 }
233 /* Are we finished with suffixes? */
234 else if (!past_opcode_p)
235 {
236 int found;
237 char c;
238 char *s,*t;
239 long suf_value;
240
241 if (!(operand->flags & TXVU_OPERAND_SUFFIX))
242 as_fatal ("bad opcode table, missing suffix flag");
243
244 /* If we're at a space in the input string, we want to skip the
245 remaining suffixes. There may be some fake ones though, so
246 just go on to try the next one. */
247 if (*str == ' ')
248 {
249 ++syn;
250 continue;
251 }
252
253 s = str;
254
255 /* Pick the suffix out and parse it. */
256 for (t = *s == '.' ? s + 1 : s; *t && isalpha (*t); ++t)
257 continue;
258 c = *t;
259 *t = '\0';
260 suf_value = (*operand->parse) (&s, &errmsg);
261 *t = c;
262 if (errmsg)
263 {
264 /* This can happen in "blle foo" and we're currently using
265 the template "b%q%.n %j". The "bl" insn occurs later in
266 the table so "lle" isn't an illegal suffix. */
267 break;
268 }
269 /* Insert the suffix's value into the insn. */
270 if (operand->insert)
271 insn = (*operand->insert) (insn, operand,
272 mods, suf_value, NULL);
273 else
274 insn |= suf_value << operand->shift;
275
276 str = t;
277 ++syn;
278 }
279 else
280 /* This is an operand, either a register or an expression of
281 some kind. */
282 {
283 char c;
284 char *hold;
285 long value = 0;
286 expressionS exp;
287
288 if (operand->flags & TXVU_OPERAND_SUFFIX)
289 as_fatal ("bad opcode table, suffix wrong");
290
291 /* If this is not the first, there must be a comma. */
292 if (num_operands > 0)
293 {
294 if (*str != ',')
295 break;
296 ++str;
297 }
298
299 /* Is there anything left to parse?
300 We don't check for this at the top because we want to parse
301 any trailing fake arguments in the syntax string. */
302 if (*str == '\0')
303 break;
304
305 /* Parse the operand. */
306 if (operand->parse)
307 {
308 value = (*operand->parse) (&str, &errmsg);
309 if (errmsg)
310 break;
311 }
312 else
313 {
314 hold = input_line_pointer;
315 input_line_pointer = str;
316 expression (&exp);
317 str = input_line_pointer;
318 input_line_pointer = hold;
319
320 if (exp.X_op == O_illegal
321 || exp.X_op == O_absent)
322 break;
323 else if (exp.X_op == O_constant)
324 value = exp.X_add_number;
325 else if (exp.X_op == O_register)
326 as_fatal ("got O_register");
327 else
328 {
329 /* We need to generate a fixup for this expression. */
330 if (fc >= MAX_FIXUPS)
331 as_fatal ("too many fixups");
332 fixups[fc].exp = exp;
333 fixups[fc].opindex = index;
334 ++fc;
335 value = 0;
336 }
337 }
338
339 /* Insert the register or expression into the instruction. */
340 if (operand->insert)
341 {
342 const char *errmsg = NULL;
343 insn = (*operand->insert) (insn, operand, mods,
344 value, &errmsg);
345 #if 0
346 if (errmsg != (const char *) NULL)
347 as_warn (errmsg);
348 #endif
349 /* FIXME: We want to try shimm insns for limm ones. But if
350 the constant won't fit, we must go on to try the next
351 possibility. Where do we issue warnings for constants
352 that are too big then? At present, we'll flag the insn
353 as unrecognizable! Maybe have the "bad instruction"
354 error message include our `errmsg'? */
355 if (errmsg != (const char *) NULL)
356 break;
357 }
358 else
359 insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
360
361 ++syn;
362 ++num_operands;
363 }
364 }
365
366 /* If we're at the end of the syntax string, we're done. */
367 /* FIXME: try to move this to a separate function. */
368 if (*syn == '\0')
369 {
370 int i;
371 char *f;
372
373 /* For the moment we assume a valid `str' can only contain blanks
374 now. IE: We needn't try again with a longer version of the
375 insn and it is assumed that longer versions of insns appear
376 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
377
378 while (isspace (*str))
379 ++str;
380
381 if (*str != '\0'
382 #ifndef VERTICAL_BAR_SEPARATOR
383 && lower_p
384 #endif
385 )
386 as_bad ("junk at end of line: `%s'", str);
387
388 /* Write out the instruction.
389 It is important to fetch enough space in one call to `frag_more'.
390 We use (f - frag_now->fr_literal) to compute where we are and we
391 don't want frag_now to change between calls. */
392 f = frag_more (4);
393 md_number_to_chars (f, insn, 4);
394
395 /* Create any fixups. */
396 for (i = 0; i < fc; ++i)
397 {
398 int op_type, reloc_type;
399 const struct txvu_operand *operand;
400
401 /* Create a fixup for this operand.
402 At this point we do not use a bfd_reloc_code_real_type for
403 operands residing in the insn, but instead just use the
404 operand index. This lets us easily handle fixups for any
405 operand type, although that is admittedly not a very exciting
406 feature. We pick a BFD reloc type in md_apply_fix. */
407
408 op_type = fixups[i].opindex;
409 reloc_type = op_type + (int) BFD_RELOC_UNUSED;
410 operand = &txvu_operands[op_type];
411 fix_new_exp (frag_now,
412 ((f - frag_now->fr_literal)
413 + (operand->flags & TXVU_OPERAND_LIMM ? 4 : 0)), 4,
414 &fixups[i].exp,
415 (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0,
416 (bfd_reloc_code_real_type) reloc_type);
417 }
418
419 /* All done. */
420 return str;
421 }
422
423 /* Try the next entry. */
424 }
425
426 as_bad ("bad instruction `%s'", start);
427 return 0;
428 }
429
430 void
431 md_operand (expressionP)
432 expressionS *expressionP;
433 {
434 }
435
436 valueT
437 md_section_align (segment, size)
438 segT segment;
439 valueT size;
440 {
441 int align = bfd_get_section_alignment (stdoutput, segment);
442 return ((size + (1 << align) - 1) & (-1 << align));
443 }
444
445 symbolS *
446 md_undefined_symbol (name)
447 char *name;
448 {
449 return 0;
450 }
451 \f
452 /* Functions concerning relocs. */
453
454 /* The location from which a PC relative jump should be calculated,
455 given a PC relative reloc. */
456
457 long
458 md_pcrel_from_section (fixP, sec)
459 fixS *fixP;
460 segT sec;
461 {
462 if (fixP->fx_addsy != (symbolS *) NULL
463 && (! S_IS_DEFINED (fixP->fx_addsy)
464 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
465 {
466 /* The symbol is undefined (or is defined but not in this section).
467 Let the linker figure it out. */
468 return 0;
469 }
470
471 /* FIXME: `& -16L'? */
472 return (fixP->fx_frag->fr_address + fixP->fx_where) & -4L;
473 }
474
475 /* Apply a fixup to the object code. This is called for all the
476 fixups we generated by calls to fix_new_exp. At this point all symbol
477 values should be fully resolved, and we attempt to completely resolve the
478 reloc. If we can not do that, we determine the correct reloc code and put
479 it back in the fixup. */
480
481 int
482 md_apply_fix3 (fixP, valueP, seg)
483 fixS *fixP;
484 valueT *valueP;
485 segT seg;
486 {
487 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
488 valueT value;
489
490 as_fatal ("txvu md_apply_fix3\n");
491 }
492
493 /* Translate internal representation of relocation info to BFD target
494 format. */
495
496 arelent *
497 tc_gen_reloc (section, fixp)
498 asection *section;
499 fixS *fixp;
500 {
501 /* relocs not handled yet */
502 as_fatal ("txvu tc_gen_reloc\n");
503 }
504 \f
505 /* Write a value out to the object file, using the appropriate endianness. */
506
507 void
508 md_number_to_chars (buf, val, n)
509 char *buf;
510 valueT val;
511 int n;
512 {
513 if (target_big_endian)
514 number_to_chars_bigendian (buf, val, n);
515 else
516 number_to_chars_littleendian (buf, val, n);
517 }
518
519 /* Turn a string in input_line_pointer into a floating point constant of type
520 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
521 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
522 */
523
524 /* Equal to MAX_PRECISION in atof-ieee.c */
525 #define MAX_LITTLENUMS 6
526
527 char *
528 md_atof (type, litP, sizeP)
529 char type;
530 char *litP;
531 int *sizeP;
532 {
533 int i,prec;
534 LITTLENUM_TYPE words[MAX_LITTLENUMS];
535 LITTLENUM_TYPE *wordP;
536 char *t;
537 char *atof_ieee ();
538
539 switch (type)
540 {
541 case 'f':
542 case 'F':
543 case 's':
544 case 'S':
545 prec = 2;
546 break;
547
548 case 'd':
549 case 'D':
550 case 'r':
551 case 'R':
552 prec = 4;
553 break;
554
555 /* FIXME: Some targets allow other format chars for bigger sizes here. */
556
557 default:
558 *sizeP = 0;
559 return "Bad call to md_atof()";
560 }
561
562 t = atof_ieee (input_line_pointer, type, words);
563 if (t)
564 input_line_pointer = t;
565 *sizeP = prec * sizeof (LITTLENUM_TYPE);
566
567 if (target_big_endian)
568 {
569 for (i = 0; i < prec; i++)
570 {
571 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
572 litP += sizeof (LITTLENUM_TYPE);
573 }
574 }
575 else
576 {
577 for (i = prec - 1; i >= 0; i--)
578 {
579 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
580 litP += sizeof (LITTLENUM_TYPE);
581 }
582 }
583
584 return 0;
585 }
This page took 0.263881 seconds and 4 git commands to generate.