* tc-txvu.c: First pass at dma/pke/gpuif support.
[deliverable/binutils-gdb.git] / gas / config / tc-txvu.c
1 /* tc-txvu.c -- Assembler for the TX VU.
2 Copyright (C) 1997, 1998 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
40 /* Non-zero if in vu-mode. */
41 static int vu_mode_p;
42
43 /* Non-zero if packing pke instructions in dma tags. */
44 static int dma_pack_pke_p;
45 \f
46 const char *md_shortopts = "";
47
48 struct option md_longopts[] =
49 {
50 /* insert options here */
51
52 {NULL, no_argument, NULL, 0}
53 };
54 size_t md_longopts_size = sizeof(md_longopts);
55
56 int
57 md_parse_option (c, arg)
58 int c;
59 char *arg;
60 {
61 return 0;
62 }
63
64 void
65 md_show_usage (stream)
66 FILE *stream;
67 {
68 #if 0
69 fprintf (stream, "TX VU options:\n");
70 #endif
71 }
72
73 /* Set by md_assemble for use by txvu_fill_insn. */
74 static subsegT prev_subseg;
75 static segT prev_seg;
76
77 static void s_dmadata PARAMS ((int));
78 static void s_dmapackpke PARAMS ((int));
79 static void s_enddirect PARAMS ((int));
80 static void s_enddmadata PARAMS ((int));
81 static void s_endgpuif PARAMS ((int));
82 static void s_endmpg PARAMS ((int));
83 static void s_endunpack PARAMS ((int));
84 static void s_vu PARAMS ((int));
85
86 /* The target specific pseudo-ops which we support. */
87 const pseudo_typeS md_pseudo_table[] =
88 {
89 { "word", cons, 4 },
90 { "dmadata", s_dmadata, 0 },
91 { "dmapackpke", s_dmapackpke, 0 },
92 { "enddirect", s_enddirect, 0 },
93 { "enddmadata", s_enddmadata, 0 },
94 { "endgpuif", s_endgpuif, 0 },
95 { "endmpg", s_endmpg, 0 },
96 { "endunpack", s_endunpack, 0 },
97 /* .vu,.endvu added to simplify debugging */
98 { "vu", s_vu, 1 },
99 { "endvu", s_vu, 0 },
100 { NULL, NULL, 0 }
101 };
102 \f
103 void
104 md_begin ()
105 {
106 flagword applicable;
107 segT seg;
108 subsegT subseg;
109
110 /* Save the current subseg so we can restore it [it's the default one and
111 we don't want the initial section to be .sbss. */
112 seg = now_seg;
113 subseg = now_subseg;
114
115 subseg_set (seg, subseg);
116
117 /* Initialize the opcode tables.
118 This involves computing the hash chains. */
119 txvu_opcode_init_tables (0);
120
121 vu_mode_p = 0;
122 dma_pack_pke_p = 0;
123 }
124 \f
125 enum cputype { CPU_VUUP, CPU_VULO, CPU_DMA, CPU_PKE, CPU_GPUIF };
126
127 /* We need to keep a list of fixups. We can't simply generate them as
128 we go, because that would require us to first create the frag, and
129 that would screw up references to ``.''. */
130
131 struct txvu_fixup
132 {
133 /* index into `txvu_operands' */
134 int opindex;
135 expressionS exp;
136 };
137
138 #define MAX_FIXUPS 5
139
140 static int fixup_count;
141 static struct txvu_fixup fixups[MAX_FIXUPS];
142
143 static void assemble_dma PARAMS ((char *));
144 static void assemble_gpuif PARAMS ((char *));
145 static void assemble_pke PARAMS ((char *));
146 static void assemble_vu PARAMS ((char *));
147 static char * assemble_vu_insn PARAMS ((enum cputype,
148 const struct txvu_opcode *,
149 const struct txvu_operand *,
150 char *, char *));
151 static char * assemble_one_insn PARAMS ((enum cputype,
152 const struct txvu_opcode *,
153 const struct txvu_operand *,
154 char *, TXVU_INSN *));
155
156 void
157 md_assemble (str)
158 char *str;
159 {
160 /* Skip leading white space. */
161 while (isspace (*str))
162 str++;
163
164 if (! vu_mode_p)
165 {
166 if (strncasecmp (str, "dma", 3) == 0)
167 assemble_dma (str);
168 else if (strncasecmp (str, "gpuif", 5) == 0)
169 assemble_gpuif (str);
170 else
171 assemble_pke (str);
172 }
173 else
174 assemble_vu (str);
175 }
176
177 /* Subroutine of md_assemble to assemble DMA instructions. */
178
179 static void
180 assemble_dma (str)
181 char *str;
182 {
183 TXVU_INSN buf[4];
184
185 assemble_one_insn (CPU_DMA,
186 dma_opcode_lookup_asm (str), dma_operands,
187 str, buf);
188 }
189
190 /* Subroutine of md_assemble to assemble PKE instructions. */
191
192 static void
193 assemble_pke (str)
194 char *str;
195 {
196 TXVU_INSN buf[4];
197
198 assemble_one_insn (CPU_PKE,
199 pke_opcode_lookup_asm (str), pke_operands,
200 str, buf);
201 }
202
203 /* Subroutine of md_assemble to assemble GPUIF instructions. */
204
205 static void
206 assemble_gpuif (str)
207 char *str;
208 {
209 TXVU_INSN buf[4];
210
211 assemble_one_insn (CPU_GPUIF,
212 gpuif_opcode_lookup_asm (str), gpuif_operands,
213 str, buf);
214 }
215
216 /* Subroutine of md_assemble to assemble VU instructions. */
217
218 static void
219 assemble_vu (str)
220 char *str;
221 {
222 /* The lower instruction has the lower address.
223 Handle this by grabbing 8 bytes now, and then filling each word
224 as appropriate. */
225 char *f = frag_more (8);
226
227 #ifdef VERTICAL_BAR_SEPARATOR
228 char *p = strchr (str, '|');
229
230 if (p == NULL)
231 {
232 as_bad ("lower slot missing in `%s'", str);
233 return;
234 }
235
236 *p = 0;
237 assemble_vu_insn (CPU_VUUP,
238 txvu_upper_opcode_lookup_asm (str), txvu_operands,
239 str, f + 4);
240 *p = '|';
241 assemble_vu_insn (CPU_VULO,
242 txvu_lower_opcode_lookup_asm (str), txvu_operands,
243 p + 1, f);
244 #else
245 str = assemble_vu_insn (CPU_VUUP,
246 txvu_upper_opcode_lookup_asm (str), txvu_operands,
247 str, f + 4);
248 /* Don't assemble next one if we couldn't assemble the first. */
249 if (str)
250 assemble_vu_insn (CPU_VULO,
251 txvu_lower_opcode_lookup_asm (str), txvu_operands,
252 str, f);
253 #endif
254 }
255
256 static char *
257 assemble_vu_insn (cpu, opcode, operand_table, str, buf)
258 enum cputype cpu;
259 const struct txvu_opcode *opcode;
260 const struct txvu_operand *operand_table;
261 char *str;
262 char *buf;
263 {
264 int i;
265 TXVU_INSN insn;
266
267 str = assemble_one_insn (cpu, opcode, operand_table, str, &insn);
268 if (str == NULL)
269 return NULL;
270
271 /* Write out the instruction.
272 Reminder: it is important to fetch enough space in one call to
273 `frag_more'. We use (f - frag_now->fr_literal) to compute where
274 we are and we don't want frag_now to change between calls. */
275 md_number_to_chars (buf, insn, 4);
276
277 /* Create any fixups. */
278 for (i = 0; i < fixup_count; ++i)
279 {
280 int op_type, reloc_type;
281 const struct txvu_operand *operand;
282
283 /* Create a fixup for this operand.
284 At this point we do not use a bfd_reloc_code_real_type for
285 operands residing in the insn, but instead just use the
286 operand index. This lets us easily handle fixups for any
287 operand type, although that is admittedly not a very exciting
288 feature. We pick a BFD reloc type in md_apply_fix. */
289
290 op_type = fixups[i].opindex;
291 reloc_type = op_type + (int) BFD_RELOC_UNUSED;
292 operand = &txvu_operands[op_type];
293 fix_new_exp (frag_now, buf - frag_now->fr_literal, 4,
294 &fixups[i].exp,
295 (operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0,
296 (bfd_reloc_code_real_type) reloc_type);
297 }
298
299 /* All done. */
300 return str;
301 }
302
303 /* Assemble one instruction.
304 CPU indicates what component we're assembling for.
305 The assembled instruction is stored in INSN_BUF.
306
307 The result is a pointer to beyond the end of the scanned insn
308 or NULL if an error occured. This is to handle the VU where two
309 instructions appear on one line. If this is the upper insn, the caller
310 can pass back to result to us parse the lower insn. */
311
312 static char *
313 assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
314 enum cputype cpu;
315 const struct txvu_opcode *opcode;
316 const struct txvu_operand *operand_table;
317 char *str;
318 TXVU_INSN *insn_buf;
319 {
320 char *start;
321
322 /* Keep looking until we find a match. */
323
324 start = str;
325 for ( ; opcode != NULL; opcode = TXVU_OPCODE_NEXT_ASM (opcode))
326 {
327 int past_opcode_p, num_suffixes, num_operands;
328 const unsigned char *syn;
329
330 /* Ensure the mnemonic part matches. */
331 for (str = start, syn = opcode->mnemonic; *syn != '\0'; ++str, ++syn)
332 if (tolower (*str) != tolower (*syn))
333 break;
334 if (*syn != '\0')
335 continue;
336
337 /* Scan the syntax string. If it doesn't match, try the next one. */
338
339 txvu_opcode_init_parse ();
340 *insn_buf = opcode->value;
341 fixup_count = 0;
342 past_opcode_p = 0;
343 num_suffixes = 0;
344 num_operands = 0;
345
346 /* We don't check for (*str != '\0') here because we want to parse
347 any trailing fake arguments in the syntax string. */
348 for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; )
349 {
350 int mods,index;
351 const struct txvu_operand *operand;
352 const char *errmsg;
353
354 /* Non operand chars must match exactly.
355 Operand chars that are letters are not part of symbols
356 and are case insensitive. */
357 if (*syn < 128)
358 {
359 if (tolower (*str) == tolower (*syn))
360 {
361 if (*syn == ' ')
362 past_opcode_p = 1;
363 ++syn;
364 ++str;
365 }
366 else
367 break;
368 continue;
369 }
370
371 /* We have a suffix or an operand. Pick out any modifiers. */
372 mods = 0;
373 index = TXVU_OPERAND_INDEX (*syn);
374 while (TXVU_MOD_P (operand_table[index].flags))
375 {
376 mods |= operand_table[index].flags & TXVU_MOD_BITS;
377 ++syn;
378 index = TXVU_OPERAND_INDEX (*syn);
379 }
380 operand = operand_table + index;
381
382 if (operand->flags & TXVU_OPERAND_FAKE)
383 {
384 if (operand->insert)
385 {
386 errmsg = NULL;
387 (*operand->insert) (insn_buf, operand, mods, 0, &errmsg);
388 /* If we get an error, go on to try the next insn. */
389 if (errmsg)
390 break;
391 }
392 ++syn;
393 }
394 /* Are we finished with suffixes? */
395 else if (!past_opcode_p)
396 {
397 int found;
398 char c;
399 char *s,*t;
400 long suf_value;
401
402 if (!(operand->flags & TXVU_OPERAND_SUFFIX))
403 as_fatal ("bad opcode table, missing suffix flag");
404
405 /* If we're at a space in the input string, we want to skip the
406 remaining suffixes. There may be some fake ones though, so
407 just go on to try the next one. */
408 if (*str == ' ')
409 {
410 ++syn;
411 continue;
412 }
413
414 s = str;
415
416 /* Pick the suffix out and parse it. */
417 /* ??? Hmmm ... there may not be any need to nul-terminate the
418 string, and it may in fact complicate things. */
419 for (t = *s == '.' ? s + 1 : s; *t && isalpha (*t); ++t)
420 continue;
421 c = *t;
422 *t = '\0';
423 errmsg = NULL;
424 suf_value = (*operand->parse) (&s, &errmsg);
425 *t = c;
426 if (errmsg)
427 {
428 /* This can happen, for example, in ARC's in "blle foo" and
429 we're currently using the template "b%q%.n %j". The "bl"
430 insn occurs later in the table so "lle" isn't an illegal
431 suffix. */
432 break;
433 }
434 /* Insert the suffix's value into the insn. */
435 if (operand->insert)
436 (*operand->insert) (insn_buf, operand,
437 mods, suf_value, NULL);
438 else
439 *insn_buf |= suf_value << operand->shift;
440
441 str = t;
442 ++syn;
443 }
444 else
445 /* This is an operand, either a register or an expression of
446 some kind. */
447 {
448 char c;
449 char *hold;
450 long value = 0;
451 expressionS exp;
452
453 if (operand->flags & TXVU_OPERAND_SUFFIX)
454 as_fatal ("bad opcode table, suffix wrong");
455
456 #if 0 /* commas are in the syntax string now */
457 /* If this is not the first, there must be a comma. */
458 if (num_operands > 0)
459 {
460 if (*str != ',')
461 break;
462 ++str;
463 }
464 #endif
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 /* ??? This doesn't allow operands with a legal value of "". */
470 if (*str == '\0')
471 break;
472
473 /* Parse the operand. */
474 if (operand->parse)
475 {
476 errmsg = NULL;
477 value = (*operand->parse) (&str, &errmsg);
478 if (errmsg)
479 break;
480 }
481 else
482 {
483 hold = input_line_pointer;
484 input_line_pointer = str;
485 expression (&exp);
486 str = input_line_pointer;
487 input_line_pointer = hold;
488
489 if (exp.X_op == O_illegal
490 || exp.X_op == O_absent)
491 break;
492 else if (exp.X_op == O_constant)
493 value = exp.X_add_number;
494 else if (exp.X_op == O_register)
495 as_fatal ("got O_register");
496 else
497 {
498 /* We need to generate a fixup for this expression. */
499 if (fixup_count >= MAX_FIXUPS)
500 as_fatal ("too many fixups");
501 fixups[fixup_count].exp = exp;
502 fixups[fixup_count].opindex = index;
503 ++fixup_count;
504 value = 0;
505 }
506 }
507
508 /* Insert the register or expression into the instruction. */
509 if (operand->insert)
510 {
511 const char *errmsg = NULL;
512 (*operand->insert) (insn_buf, operand, mods,
513 value, &errmsg);
514 if (errmsg != (const char *) NULL)
515 break;
516 }
517 else
518 *insn_buf |= (value & ((1 << operand->bits) - 1)) << operand->shift;
519
520 ++syn;
521 ++num_operands;
522 }
523 }
524
525 /* If we're at the end of the syntax string, we're done. */
526 /* FIXME: try to move this to a separate function. */
527 if (*syn == '\0')
528 {
529 int i;
530
531 /* For the moment we assume a valid `str' can only contain blanks
532 now. IE: We needn't try again with a longer version of the
533 insn and it is assumed that longer versions of insns appear
534 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
535
536 while (isspace (*str))
537 ++str;
538
539 if (*str != '\0'
540 #ifndef VERTICAL_BAR_SEPARATOR
541 && cpu != CPU_VUUP
542 #endif
543 )
544 as_bad ("junk at end of line: `%s'", str);
545
546 /* It's now up to the caller to emit the instruction and any
547 relocations. */
548 return str;
549 }
550
551 /* Try the next entry. */
552 }
553
554 as_bad ("bad instruction `%s'", start);
555 return 0;
556 }
557
558 void
559 md_operand (expressionP)
560 expressionS *expressionP;
561 {
562 }
563
564 valueT
565 md_section_align (segment, size)
566 segT segment;
567 valueT size;
568 {
569 int align = bfd_get_section_alignment (stdoutput, segment);
570 return ((size + (1 << align) - 1) & (-1 << align));
571 }
572
573 symbolS *
574 md_undefined_symbol (name)
575 char *name;
576 {
577 return 0;
578 }
579 \f
580 /* Functions concerning relocs. */
581
582 /* The location from which a PC relative jump should be calculated,
583 given a PC relative reloc. */
584
585 long
586 md_pcrel_from_section (fixP, sec)
587 fixS *fixP;
588 segT sec;
589 {
590 if (fixP->fx_addsy != (symbolS *) NULL
591 && (! S_IS_DEFINED (fixP->fx_addsy)
592 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
593 {
594 /* The symbol is undefined (or is defined but not in this section).
595 Let the linker figure it out. */
596 return 0;
597 }
598
599 /* FIXME: `& -16L'? */
600 return (fixP->fx_frag->fr_address + fixP->fx_where) & -8L;
601 }
602
603 /* Apply a fixup to the object code. This is called for all the
604 fixups we generated by calls to fix_new_exp. At this point all symbol
605 values should be fully resolved, and we attempt to completely resolve the
606 reloc. If we can not do that, we determine the correct reloc code and put
607 it back in the fixup. */
608
609 int
610 md_apply_fix3 (fixP, valueP, seg)
611 fixS *fixP;
612 valueT *valueP;
613 segT seg;
614 {
615 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
616 valueT value;
617
618 /* FIXME FIXME FIXME: The value we are passed in *valueP includes
619 the symbol values. Since we are using BFD_ASSEMBLER, if we are
620 doing this relocation the code in write.c is going to call
621 bfd_perform_relocation, which is also going to use the symbol
622 value. That means that if the reloc is fully resolved we want to
623 use *valueP since bfd_perform_relocation is not being used.
624 However, if the reloc is not fully resolved we do not want to use
625 *valueP, and must use fx_offset instead. However, if the reloc
626 is PC relative, we do want to use *valueP since it includes the
627 result of md_pcrel_from. This is confusing. */
628
629 if (fixP->fx_addsy == (symbolS *) NULL)
630 {
631 value = *valueP;
632 fixP->fx_done = 1;
633 }
634 else if (fixP->fx_pcrel)
635 {
636 value = *valueP;
637 }
638 else
639 {
640 value = fixP->fx_offset;
641 if (fixP->fx_subsy != (symbolS *) NULL)
642 {
643 if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
644 value -= S_GET_VALUE (fixP->fx_subsy);
645 else
646 {
647 /* We can't actually support subtracting a symbol. */
648 as_bad_where (fixP->fx_file, fixP->fx_line,
649 "expression too complex");
650 }
651 }
652 }
653
654 /* Check for txvu_operand's. These are indicated with a reloc value
655 >= BFD_RELOC_UNUSED. */
656
657 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
658 {
659 int opindex;
660 const struct txvu_operand *operand;
661 TXVU_INSN insn;
662
663 opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
664
665 operand = &txvu_operands[opindex];
666
667 /* Fetch the instruction, insert the fully resolved operand
668 value, and stuff the instruction back again. */
669 insn = bfd_getl32 ((unsigned char *) where);
670 insn = txvu_insert_operand (insn, operand, -1, (offsetT) value,
671 fixP->fx_file, fixP->fx_line);
672 bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
673
674 if (fixP->fx_done)
675 {
676 /* Nothing else to do here. */
677 return 1;
678 }
679
680 /* Determine a BFD reloc value based on the operand information.
681 We are only prepared to turn a few of the operands into relocs. */
682 /* FIXME: This test is a hack. */
683 if ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0)
684 {
685 assert ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0
686 && operand->bits == 11
687 && operand->shift == 0);
688 fixP->fx_r_type = BFD_RELOC_TXVU_11_PCREL;
689 }
690 else
691 {
692 as_bad_where (fixP->fx_file, fixP->fx_line,
693 "unresolved expression that must be resolved");
694 fixP->fx_done = 1;
695 return 1;
696 }
697 }
698 else
699 {
700 switch (fixP->fx_r_type)
701 {
702 case BFD_RELOC_8:
703 md_number_to_chars (where, value, 1);
704 break;
705 case BFD_RELOC_16:
706 md_number_to_chars (where, value, 2);
707 break;
708 case BFD_RELOC_32:
709 md_number_to_chars (where, value, 4);
710 break;
711 default:
712 abort ();
713 }
714 }
715
716 fixP->fx_addnumber = value;
717
718 return 1;
719 }
720
721 /* Translate internal representation of relocation info to BFD target
722 format. */
723
724 arelent *
725 tc_gen_reloc (section, fixP)
726 asection *section;
727 fixS *fixP;
728 {
729 arelent *reloc;
730
731 reloc = (arelent *) xmalloc (sizeof (arelent));
732
733 reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
734 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
735 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
736 if (reloc->howto == (reloc_howto_type *) NULL)
737 {
738 as_bad_where (fixP->fx_file, fixP->fx_line,
739 "internal error: can't export reloc type %d (`%s')",
740 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
741 return NULL;
742 }
743
744 assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
745
746 reloc->addend = fixP->fx_addnumber;
747
748 return reloc;
749 }
750 \f
751 /* Write a value out to the object file, using the appropriate endianness. */
752
753 void
754 md_number_to_chars (buf, val, n)
755 char *buf;
756 valueT val;
757 int n;
758 {
759 if (target_big_endian)
760 number_to_chars_bigendian (buf, val, n);
761 else
762 number_to_chars_littleendian (buf, val, n);
763 }
764
765 /* Turn a string in input_line_pointer into a floating point constant of type
766 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
767 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
768 */
769
770 /* Equal to MAX_PRECISION in atof-ieee.c */
771 #define MAX_LITTLENUMS 6
772
773 char *
774 md_atof (type, litP, sizeP)
775 char type;
776 char *litP;
777 int *sizeP;
778 {
779 int i,prec;
780 LITTLENUM_TYPE words[MAX_LITTLENUMS];
781 LITTLENUM_TYPE *wordP;
782 char *t;
783 char *atof_ieee ();
784
785 switch (type)
786 {
787 case 'f':
788 case 'F':
789 case 's':
790 case 'S':
791 prec = 2;
792 break;
793
794 case 'd':
795 case 'D':
796 case 'r':
797 case 'R':
798 prec = 4;
799 break;
800
801 /* FIXME: Some targets allow other format chars for bigger sizes here. */
802
803 default:
804 *sizeP = 0;
805 return "Bad call to md_atof()";
806 }
807
808 t = atof_ieee (input_line_pointer, type, words);
809 if (t)
810 input_line_pointer = t;
811 *sizeP = prec * sizeof (LITTLENUM_TYPE);
812
813 if (target_big_endian)
814 {
815 for (i = 0; i < prec; i++)
816 {
817 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
818 litP += sizeof (LITTLENUM_TYPE);
819 }
820 }
821 else
822 {
823 for (i = prec - 1; i >= 0; i--)
824 {
825 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
826 litP += sizeof (LITTLENUM_TYPE);
827 }
828 }
829
830 return 0;
831 }
832 \f
833 /* Insert an operand value into an instruction. */
834
835 static TXVU_INSN
836 txvu_insert_operand (insn, operand, mods, val, file, line)
837 TXVU_INSN insn;
838 const struct txvu_operand *operand;
839 int mods;
840 offsetT val;
841 char *file;
842 unsigned int line;
843 {
844 if (operand->bits != 32)
845 {
846 long min, max;
847 offsetT test;
848
849 if ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0)
850 {
851 if ((val & 7) != 0)
852 {
853 if (file == (char *) NULL)
854 as_warn ("branch to misaligned address");
855 else
856 as_warn_where (file, line, "branch to misaligned address");
857 }
858 val >>= 3;
859 }
860
861 if ((operand->flags & TXVU_OPERAND_SIGNED) != 0)
862 {
863 if ((operand->flags & TXVU_OPERAND_SIGNOPT) != 0)
864 max = (1 << operand->bits) - 1;
865 else
866 max = (1 << (operand->bits - 1)) - 1;
867 min = - (1 << (operand->bits - 1));
868 }
869 else
870 {
871 max = (1 << operand->bits) - 1;
872 min = 0;
873 }
874
875 if ((operand->flags & TXVU_OPERAND_NEGATIVE) != 0)
876 test = - val;
877 else
878 test = val;
879
880 if (test < (offsetT) min || test > (offsetT) max)
881 {
882 const char *err =
883 "operand out of range (%s not between %ld and %ld)";
884 char buf[100];
885
886 sprint_value (buf, test);
887 if (file == (char *) NULL)
888 as_warn (err, buf, min, max);
889 else
890 as_warn_where (file, line, err, buf, min, max);
891 }
892 }
893
894 if (operand->insert)
895 {
896 const char *errmsg = NULL;
897 (*operand->insert) (&insn, operand, mods, (long) val, &errmsg);
898 if (errmsg != (const char *) NULL)
899 as_warn (errmsg);
900 }
901 else
902 insn |= (((long) val & ((1 << operand->bits) - 1))
903 << operand->shift);
904
905 return insn;
906 }
907 \f
908 static void
909 s_dmadata (ignore)
910 int ignore;
911 {
912 }
913
914 static void
915 s_dmapackpke (ignore)
916 int ignore;
917 {
918 /* Syntax: .dmapackpke 0|1 */
919 if (*input_line_pointer == '0')
920 dma_pack_pke_p = 0;
921 else if (*input_line_pointer == '1')
922 dma_pack_pke_p = 1;
923 else
924 as_bad ("illegal argument to `.dmapackpke'");
925
926 input_line_pointer++;
927 demand_empty_rest_of_line ();
928 }
929
930 static void
931 s_enddirect (ignore)
932 int ignore;
933 {
934 }
935
936 static void
937 s_enddmadata (ignore)
938 int ignore;
939 {
940 }
941
942 static void
943 s_endgpuif (ignore)
944 int ignore;
945 {
946 }
947
948 static void
949 s_endmpg (ignore)
950 int ignore;
951 {
952 vu_mode_p = 0;
953 }
954
955 static void
956 s_endunpack (ignore)
957 int ignore;
958 {
959 vu_mode_p = 0;
960 }
961
962 static void
963 s_vu (enable_p)
964 int enable_p;
965 {
966 vu_mode_p = enable_p;
967 }
This page took 0.048459 seconds and 4 git commands to generate.