(insert_operand): Bring over possible change from branch.
[deliverable/binutils-gdb.git] / gas / config / tc-dvp.c
1 /* tc-dvp.c -- Assembler for the DVP
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 "sysdep.h"
24 #include "as.h"
25 #include "subsegs.h"
26 /* Needed by opcode/dvp.h. */
27 #include "dis-asm.h"
28 #include "opcode/dvp.h"
29 #include "elf/mips.h"
30
31 static long parse_dma_ild_autocount ();
32 static long parse_dma_ptr_autocount ();
33
34 static void insert_operand
35 PARAMS ((dvp_cpu, const dvp_opcode *, const dvp_operand *, int,
36 DVP_INSN *, offsetT, const char **));
37 static void insert_operand_final
38 PARAMS ((dvp_cpu, const dvp_operand *, int,
39 DVP_INSN *, offsetT, char *, unsigned int));
40
41 static int insert_file PARAMS ((const char *));
42
43 static int cur_vif_insn_length PARAMS ((void));
44 static void install_vif_length PARAMS ((char *, int));
45
46 const char comment_chars[] = ";";
47 const char line_comment_chars[] = "#";
48 const char line_separator_chars[] = "!";
49 const char EXP_CHARS[] = "eE";
50 const char FLT_CHARS[] = "dD";
51
52 /* Current assembler state.
53 Instructions like mpg and direct are followed by a restricted set of
54 instructions. In the case of a '*' length argument an end marker must
55 be provided. (e.g. mpg is followed by vu insns until a .EndMpg is
56 seen). */
57 typedef enum {
58 ASM_INIT, ASM_MPG, ASM_DIRECT, ASM_UNPACK, ASM_GIF, ASM_VU
59 } asm_state;
60 static asm_state cur_asm_state = ASM_INIT;
61
62 /* For variable length instructions, pointer to the initial frag
63 and pointer into that frag. These only hold valid values if
64 cur_asm_state is one of ASM_MPG, ASM_DIRECT, ASM_UNPACK. */
65 static fragS *cur_varlen_frag;
66 static char *cur_varlen_insn;
67 /* The length value specified in the insn, or -1 if '*'. */
68 static int cur_varlen_value;
69
70 /* Non-zero if packing vif instructions in dma tags. */
71 static int dma_pack_vif_p;
72
73 /* Non-zero if dma insns are to be included in the output.
74 This is the default, but writing "if (! no_dma)" is klunky. */
75 static int output_dma = 1;
76 /* Non-zero if vif insns are to be included in the output. */
77 static int output_vif = 1;
78 \f
79 const char *md_shortopts = "";
80
81 struct option md_longopts[] =
82 {
83 #define OPTION_NO_DMA (OPTION_MD_BASE + 1)
84 { "no-dma", no_argument, NULL, OPTION_NO_DMA },
85 #define OPTION_NO_DMA_VIF (OPTION_NO_DMA + 1)
86 { "no-dma-vif", no_argument, NULL, OPTION_NO_DMA_VIF },
87
88 {NULL, no_argument, NULL, 0}
89 };
90 size_t md_longopts_size = sizeof(md_longopts);
91
92 int
93 md_parse_option (c, arg)
94 int c;
95 char *arg;
96 {
97 switch (c)
98 {
99 case OPTION_NO_DMA :
100 output_dma = 0;
101 break;
102 case OPTION_NO_DMA_VIF :
103 output_dma = 0;
104 output_vif = 0;
105 break;
106 default :
107 return 0;
108 }
109 return 1;
110 }
111
112 void
113 md_show_usage (stream)
114 FILE *stream;
115 {
116 fprintf (stream, "\
117 DVP options:\n\
118 -no-dma do not include DMA instructions in the output\n\
119 -no-dma-vif do not include DMA or VIF instructions in the output\n\
120 ");
121 }
122
123 /* Set by md_assemble for use by dvp_fill_insn. */
124 static subsegT prev_subseg;
125 static segT prev_seg;
126
127 static void s_dmadata PARAMS ((int));
128 static void s_dmadata_implied PARAMS ((int));
129 static void s_enddmadata PARAMS ((int));
130 static void s_dmapackvif PARAMS ((int));
131 static void s_enddirect PARAMS ((int));
132 static void s_endgif PARAMS ((int));
133 static void s_endmpg PARAMS ((int));
134 static void s_endunpack PARAMS ((int));
135 static void s_state PARAMS ((int));
136
137 /* The target specific pseudo-ops which we support. */
138 const pseudo_typeS md_pseudo_table[] =
139 {
140 { "dmadata", s_dmadata, 0 },
141 { "dmapackvif", s_dmapackvif, 0 },
142 { "enddirect", s_enddirect, 0 },
143 { "enddmadata", s_enddmadata, 0 },
144 { "endgif", s_endgif, 0 },
145 { "endmpg", s_endmpg, 0 },
146 { "endunpack", s_endunpack, 0 },
147 /* .vu,.gif added to simplify debugging */
148 { "vu", s_state, ASM_VU },
149 { "gif", s_state, ASM_GIF },
150 { NULL, NULL, 0 }
151 };
152 \f
153 void
154 md_begin ()
155 {
156 flagword applicable;
157 segT seg;
158 subsegT subseg;
159
160 /* Save the current subseg so we can restore it [it's the default one and
161 we don't want the initial section to be .sbss. */
162 seg = now_seg;
163 subseg = now_subseg;
164
165 subseg_set (seg, subseg);
166
167 /* Initialize the opcode tables.
168 This involves computing the hash chains. */
169 dvp_opcode_init_tables (0);
170
171 cur_asm_state = ASM_INIT;
172 dma_pack_vif_p = 0;
173 }
174 \f
175 /* We need to keep a list of fixups. We can't simply generate them as
176 we go, because that would require us to first create the frag, and
177 that would screw up references to ``.''. */
178
179 struct dvp_fixup
180 {
181 /* index into `dvp_operands' */
182 int opindex;
183 /* byte offset from beginning of instruction */
184 int offset;
185 expressionS exp;
186 };
187
188 #define MAX_FIXUPS 5
189
190 static int fixup_count;
191 static struct dvp_fixup fixups[MAX_FIXUPS];
192
193 /* Given a cpu type and operand number, return a temporary reloc type
194 for use in generating the fixup that encodes the cpu type and operand. */
195 static int encode_fixup_reloc_type PARAMS ((dvp_cpu, int));
196 /* Given an encoded fixup reloc type, decode it into cpu and operand. */
197 static void decode_fixup_reloc_type PARAMS ((int, dvp_cpu *,
198 const dvp_operand **));
199
200 static void assemble_dma PARAMS ((char *));
201 static void assemble_gif PARAMS ((char *));
202 static void assemble_vif PARAMS ((char *));
203 static void assemble_vu PARAMS ((char *));
204 static const dvp_opcode * assemble_vu_insn PARAMS ((dvp_cpu,
205 const dvp_opcode *,
206 const dvp_operand *,
207 char **, char *));
208 static const dvp_opcode * assemble_one_insn PARAMS ((dvp_cpu,
209 const dvp_opcode *,
210 const dvp_operand *,
211 char **, DVP_INSN *));
212
213 /* Main entry point for assembling an instruction. */
214
215 void
216 md_assemble (str)
217 char *str;
218 {
219 /* Skip leading white space. */
220 while (isspace (*str))
221 str++;
222
223 if (cur_asm_state == ASM_INIT)
224 {
225 if (strncasecmp (str, "dma", 3) == 0)
226 assemble_dma (str);
227 else
228 assemble_vif (str);
229 }
230 else if (cur_asm_state == ASM_GIF)
231 assemble_gif (str);
232 else if (cur_asm_state == ASM_VU
233 || cur_asm_state == ASM_MPG)
234 assemble_vu (str);
235 else
236 as_fatal ("unknown parse state");
237 }
238
239 /* Subroutine of md_assemble to assemble DMA instructions. */
240
241 static void
242 assemble_dma (str)
243 char *str;
244 {
245 DVP_INSN insn_buf[4];
246 int len; /* Insn's length, in 32 bit words. */
247 char *f; /* Pointer to allocated frag. */
248 int i;
249 const dvp_opcode *opcode;
250
251 /*
252 Fill the first two words with VIF NOPs.
253 They may be over-written later if DmaPackPke is on.
254 initialize the remainder with zeros.
255 */
256 insn_buf[ 0] = 0;
257 insn_buf[ 1] = 0;
258 insn_buf[ 2] = 0;
259 insn_buf[ 3] = 0;
260
261 opcode = assemble_one_insn (DVP_DMA,
262 dma_opcode_lookup_asm (str), dma_operands,
263 &str, insn_buf);
264 if( opcode == NULL) return;
265 if( !output_dma) return;
266
267 len = 4;
268 f = frag_more( len * 4);
269
270 /* Write out the VIF / DMA instructions. */
271 for( i = 0; i < len; ++i)
272 md_number_to_chars( f + i * 4, insn_buf[i], 4);
273
274 /* Create any fixups. */
275 /* FIXME: It might eventually be possible to combine all the various
276 copies of this bit of code. */
277 for( i = 0; i < fixup_count; ++i)
278 {
279 int op_type, reloc_type, offset;
280 const dvp_operand *operand;
281
282 #if 0
283 /*
284 Create a fixup for this operand.
285 At this point we do not use a bfd_reloc_code_real_type for
286 operands residing in the insn, but instead just use the
287 operand index. This lets us easily handle fixups for any
288 operand type, although that is admittedly not a very exciting
289 feature. We pick a BFD reloc type in md_apply_fix.
290 */
291
292 op_type = fixups[i].opindex;
293 offset = fixups[i].offset;
294 reloc_type = encode_fixup_reloc_type (DVP_VIF, op_type);
295 operand = &vif_operands[op_type];
296 fix_new_exp (frag_now, f + offset - frag_now->fr_literal, 4,
297 &fixups[i].exp,
298 (operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0,
299 (bfd_reloc_code_real_type) reloc_type);
300 #endif
301 }
302 }
303
304 /* Subroutine of md_assemble to assemble VIF instructions. */
305
306 static void
307 assemble_vif (str)
308 char *str;
309 {
310 /* Space for the instruction.
311 The variable length insns can require much more space than this.
312 It is allocated later, when we know we have such an insn. */
313 DVP_INSN insn_buf[5];
314 /* Insn's length, in 32 bit words. */
315 int len;
316 /* Pointer to allocated frag. */
317 char *f;
318 int i;
319 const dvp_opcode *opcode;
320
321 opcode = assemble_one_insn (DVP_VIF,
322 vif_opcode_lookup_asm (str), vif_operands,
323 &str, insn_buf);
324 if (opcode == NULL)
325 return;
326
327 if (opcode->flags & VIF_OPCODE_LENVAR)
328 len = 1; /* actual data follows later */
329 else if (opcode->flags & VIF_OPCODE_LEN2)
330 len = 2;
331 else if (opcode->flags & VIF_OPCODE_LEN5)
332 len = 5;
333 else
334 len = 1;
335
336 /* We still have to switch modes (if mpg for example) so we can't exit
337 early if -no-vif. */
338 if (output_vif)
339 {
340 /* Reminder: it is important to fetch enough space in one call to
341 `frag_more'. We use (f - frag_now->fr_literal) to compute where
342 we are and we don't want frag_now to change between calls. */
343 f = frag_more (len * 4);
344
345 /* Write out the instruction. */
346 for (i = 0; i < len; ++i)
347 md_number_to_chars (f + i * 4, insn_buf[i], 4);
348
349 /* Create any fixups. */
350 /* FIXME: It might eventually be possible to combine all the various
351 copies of this bit of code. */
352 for (i = 0; i < fixup_count; ++i)
353 {
354 int op_type, reloc_type, offset;
355 const dvp_operand *operand;
356
357 /* Create a fixup for this operand.
358 At this point we do not use a bfd_reloc_code_real_type for
359 operands residing in the insn, but instead just use the
360 operand index. This lets us easily handle fixups for any
361 operand type, although that is admittedly not a very exciting
362 feature. We pick a BFD reloc type in md_apply_fix. */
363
364 op_type = fixups[i].opindex;
365 offset = fixups[i].offset;
366 reloc_type = encode_fixup_reloc_type (DVP_VIF, op_type);
367 operand = &vif_operands[op_type];
368 fix_new_exp (frag_now, f + offset - frag_now->fr_literal, 4,
369 &fixups[i].exp,
370 (operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0,
371 (bfd_reloc_code_real_type) reloc_type);
372 }
373 }
374
375 /* Handle variable length insns. */
376
377 if (opcode->flags & VIF_OPCODE_LENVAR)
378 {
379 /* Name of file to read data from. */
380 char *file;
381 /* Length in 32 bit words. */
382 int data_len;
383
384 file = NULL;
385 data_len = 0;
386 vif_get_var_data (&file, &data_len);
387 if (file)
388 {
389 int byte_len = insert_file (file);
390 if (output_vif)
391 install_vif_length (f, byte_len);
392 /* Update $.MpgLoc. */
393 vif_set_mpgloc (vif_get_mpgloc () + byte_len);
394 }
395 else
396 {
397 /* data_len == -1 means the value must be computed from
398 the data. */
399 if (data_len == 0 || data_len < -2)
400 as_bad ("invalid data length");
401 cur_varlen_frag = frag_now;
402 cur_varlen_insn = f;
403 cur_varlen_value = data_len;
404 if (opcode->flags & VIF_OPCODE_MPG)
405 cur_asm_state = ASM_MPG;
406 else if (opcode->flags & VIF_OPCODE_DIRECT)
407 cur_asm_state = ASM_DIRECT;
408 else if (opcode->flags & VIF_OPCODE_UNPACK)
409 cur_asm_state = ASM_UNPACK;
410 }
411 }
412 }
413
414 /* Subroutine of md_assemble to assemble GIF instructions. */
415
416 static void
417 assemble_gif (str)
418 char *str;
419 {
420 DVP_INSN insn_buf[4];
421 const dvp_opcode *opcode;
422
423 opcode = assemble_one_insn (DVP_GIF,
424 gif_opcode_lookup_asm (str), gif_operands,
425 &str, insn_buf);
426 if (opcode == NULL)
427 return;
428 }
429
430 /* Subroutine of md_assemble to assemble VU instructions. */
431
432 static void
433 assemble_vu (str)
434 char *str;
435 {
436 /* The lower instruction has the lower address.
437 Handle this by grabbing 8 bytes now, and then filling each word
438 as appropriate. */
439 char *f = frag_more (8);
440 const dvp_opcode *opcode;
441
442 #ifdef VERTICAL_BAR_SEPARATOR
443 char *p = strchr (str, '|');
444
445 if (p == NULL)
446 {
447 as_bad ("lower slot missing in `%s'", str);
448 return;
449 }
450
451 *p = 0;
452 opcode = assemble_vu_insn (DVP_VUUP,
453 vu_upper_opcode_lookup_asm (str), vu_operands,
454 &str, f + 4);
455 *p = '|';
456 if (opcode == NULL)
457 return;
458 str = p + 1;
459 assemble_vu_insn (DVP_VULO,
460 vu_lower_opcode_lookup_asm (str), vu_operands,
461 &str, f);
462 #else
463 opcode = assemble_vu_insn (DVP_VUUP,
464 vu_upper_opcode_lookup_asm (str), vu_operands,
465 &str, f + 4);
466 /* Don't assemble next one if we couldn't assemble the first. */
467 if (opcode)
468 assemble_vu_insn (DVP_VULO,
469 vu_lower_opcode_lookup_asm (str), vu_operands,
470 &str, f);
471 #endif
472 }
473
474 static const dvp_opcode *
475 assemble_vu_insn (cpu, opcode, operand_table, pstr, buf)
476 dvp_cpu cpu;
477 const dvp_opcode *opcode;
478 const dvp_operand *operand_table;
479 char **pstr;
480 char *buf;
481 {
482 int i;
483 DVP_INSN insn;
484
485 opcode = assemble_one_insn (cpu, opcode, operand_table, pstr, &insn);
486 if (opcode == NULL)
487 return NULL;
488
489 /* Write out the instruction.
490 Reminder: it is important to fetch enough space in one call to
491 `frag_more'. We use (f - frag_now->fr_literal) to compute where
492 we are and we don't want frag_now to change between calls. */
493 md_number_to_chars (buf, insn, 4);
494
495 /* Create any fixups. */
496 for (i = 0; i < fixup_count; ++i)
497 {
498 int op_type, reloc_type;
499 const dvp_operand *operand;
500
501 /* Create a fixup for this operand.
502 At this point we do not use a bfd_reloc_code_real_type for
503 operands residing in the insn, but instead just use the
504 operand index. This lets us easily handle fixups for any
505 operand type, although that is admittedly not a very exciting
506 feature. We pick a BFD reloc type in md_apply_fix. */
507
508 op_type = fixups[i].opindex;
509 reloc_type = encode_fixup_reloc_type (cpu, op_type);
510 operand = &vu_operands[op_type];
511 fix_new_exp (frag_now, buf - frag_now->fr_literal, 4,
512 &fixups[i].exp,
513 (operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0,
514 (bfd_reloc_code_real_type) reloc_type);
515 }
516
517 /* All done. */
518 return opcode;
519 }
520
521 /* Assemble one instruction at *PSTR.
522 CPU indicates what component we're assembling for.
523 The assembled instruction is stored in INSN_BUF.
524 OPCODE is a pointer to the head of the hash chain.
525
526 *PSTR is updated to point passed the parsed instruction.
527
528 If the insn is successfully parsed the result is a pointer to the opcode
529 entry that successfully matched and *PSTR is updated to point passed
530 the parsed insn. If an error occurs the result is NULL and *PSTR is left
531 at some random point in the string (??? may wish to leave it pointing where
532 the error occured). */
533
534 static const dvp_opcode *
535 assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
536 dvp_cpu cpu;
537 const dvp_opcode *opcode;
538 const dvp_operand *operand_table;
539 char **pstr;
540 DVP_INSN *insn_buf;
541 {
542 char *start, *str;
543
544 /* Keep looking until we find a match. */
545
546 start = str = *pstr;
547 for ( ; opcode != NULL; opcode = DVP_OPCODE_NEXT_ASM (opcode))
548 {
549 int past_opcode_p, num_suffixes, num_operands;
550 const unsigned char *syn;
551
552 /* Ensure the mnemonic part matches. */
553 for (str = start, syn = opcode->mnemonic; *syn != '\0'; ++str, ++syn)
554 if (tolower (*str) != tolower (*syn))
555 break;
556 if (*syn != '\0')
557 continue;
558
559 /* Scan the syntax string. If it doesn't match, try the next one. */
560
561 dvp_opcode_init_parse ();
562 insn_buf[ opcode->opcode_word] = opcode->value;
563 fixup_count = 0;
564 past_opcode_p = 0;
565 num_suffixes = 0;
566 num_operands = 0;
567
568 /* We don't check for (*str != '\0') here because we want to parse
569 any trailing fake arguments in the syntax string. */
570 for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; )
571 {
572 int mods,index;
573 const dvp_operand *operand;
574 const char *errmsg;
575
576 /* Non operand chars must match exactly.
577 Operand chars that are letters are not part of symbols
578 and are case insensitive. */
579 if (*syn < 128)
580 {
581 if (tolower (*str) == tolower (*syn))
582 {
583 if (*syn == ' ')
584 past_opcode_p = 1;
585 ++syn;
586 ++str;
587 }
588 else
589 break;
590 continue;
591 }
592
593 /* We have a suffix or an operand. Pick out any modifiers. */
594 mods = 0;
595 index = DVP_OPERAND_INDEX (*syn);
596 while (DVP_MOD_P (operand_table[index].flags))
597 {
598 mods |= operand_table[index].flags & DVP_MOD_BITS;
599 ++syn;
600 index = DVP_OPERAND_INDEX (*syn);
601 }
602 operand = operand_table + index;
603
604 if (operand->flags & DVP_OPERAND_FAKE)
605 {
606 if (operand->insert)
607 {
608 errmsg = NULL;
609 (*operand->insert) (opcode, operand, mods, insn_buf, 0,
610 &errmsg);
611 /* If we get an error, go on to try the next insn. */
612 if (errmsg)
613 break;
614 }
615 ++syn;
616 }
617 /* Are we finished with suffixes? */
618 else if (!past_opcode_p)
619 {
620 int found;
621 char c;
622 char *s,*t;
623 long suf_value;
624
625 if (!(operand->flags & DVP_OPERAND_SUFFIX))
626 as_fatal ("bad opcode table, missing suffix flag");
627
628 /* If we're at a space in the input string, we want to skip the
629 remaining suffixes. There may be some fake ones though, so
630 just go on to try the next one. */
631 if (*str == ' ')
632 {
633 ++syn;
634 continue;
635 }
636
637 s = str;
638
639 /* Pick the suffix out and parse it. */
640 /* ??? Hmmm ... there may not be any need to nul-terminate the
641 string, and it may in fact complicate things. */
642 for (t = (*s == '.' || *s == '/' || *s == '[') ? s + 1 : s;
643 *t && (isalnum (*t) || *t == ']');
644 ++t)
645 continue;
646 c = *t;
647 *t = '\0';
648 errmsg = NULL;
649 suf_value = (*operand->parse) (opcode, operand, mods, &s,
650 &errmsg);
651 *t = c;
652 if (errmsg)
653 {
654 /* This can happen, for example, in ARC's in "blle foo" and
655 we're currently using the template "b%q%.n %j". The "bl"
656 insn occurs later in the table so "lle" isn't an illegal
657 suffix. */
658 break;
659 }
660
661 /* Insert the suffix's value into the insn. */
662 insert_operand (cpu, opcode, operand, mods, insn_buf,
663 (offsetT) suf_value, &errmsg);
664
665 /* FIXME: For suffixes that have a null "" value,
666 this next line is wrong as we will skip over something
667 we're not supposed to. */
668 str = t;
669 ++syn;
670 }
671 else
672 /* This is an operand, either a register or an expression of
673 some kind. */
674 {
675 char c;
676 char *hold;
677 long value = 0;
678 expressionS exp;
679
680 if (operand->flags & DVP_OPERAND_SUFFIX)
681 as_fatal ("bad opcode table, suffix wrong");
682
683 #if 0 /* commas are in the syntax string now */
684 /* If this is not the first, there must be a comma. */
685 if (num_operands > 0)
686 {
687 if (*str != ',')
688 break;
689 ++str;
690 }
691 #endif
692
693 if( operand->flags & DVP_OPERAND_DMA_ILD)
694 {
695 s_dmadata_implied( 0);
696 ++syn;
697 break;
698 }
699
700 /* Is there anything left to parse?
701 We don't check for this at the top because we want to parse
702 any trailing fake arguments in the syntax string. */
703 /* ??? This doesn't allow operands with a legal value of "". */
704 if (*str == '\0')
705 break;
706
707 /* Parse the operand. */
708 if( operand->flags & DVP_OPERAND_DMA_ILD_AUTOCOUNT)
709 {
710 errmsg = 0;
711 value = parse_dma_ild_autocount( opcode, operand, mods, insn_buf, &str, &errmsg);
712 if( errmsg) break;
713 }
714 else if( operand->flags & DVP_OPERAND_DMA_PTR_AUTOCOUNT)
715 {
716 errmsg = 0;
717 value = parse_dma_ptr_autocount( opcode, operand, mods, insn_buf, &str, &errmsg);
718 if( errmsg) break;
719 }
720 else if (operand->parse)
721 {
722 errmsg = NULL;
723 value = (*operand->parse) (opcode, operand, mods,
724 &str, &errmsg);
725 if (errmsg)
726 break;
727 }
728 else
729 {
730 hold = input_line_pointer;
731 input_line_pointer = str;
732 expression (&exp);
733 str = input_line_pointer;
734 input_line_pointer = hold;
735
736 if (exp.X_op == O_illegal
737 || exp.X_op == O_absent)
738 break;
739 else if (exp.X_op == O_constant)
740 value = exp.X_add_number;
741 else if (exp.X_op == O_register)
742 as_fatal ("got O_register");
743 else
744 {
745 /* We need to generate a fixup for this expression. */
746 if (fixup_count >= MAX_FIXUPS)
747 as_fatal ("too many fixups");
748 fixups[fixup_count].exp = exp;
749 fixups[fixup_count].opindex = index;
750 fixups[fixup_count].offset = (operand->shift / 32) * 4;
751 ++fixup_count;
752 value = 0;
753 }
754 }
755
756 /* Insert the register or expression into the instruction. */
757 errmsg = NULL;
758 insert_operand (cpu, opcode, operand, mods, insn_buf,
759 (offsetT) value, &errmsg);
760 if (errmsg != (const char *) NULL)
761 break;
762
763 ++syn;
764 ++num_operands;
765 }
766 }
767
768 /* If we're at the end of the syntax string, we're done. */
769 if (*syn == '\0')
770 {
771 int i;
772
773 /* For the moment we assume a valid `str' can only contain blanks
774 now. IE: We needn't try again with a longer version of the
775 insn and it is assumed that longer versions of insns appear
776 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
777
778 while (isspace (*str))
779 ++str;
780
781 if (*str != '\0'
782 #ifndef VERTICAL_BAR_SEPARATOR
783 && cpu != DVP_VUUP
784 #endif
785 )
786 as_bad ("junk at end of line: `%s'", str);
787
788 /* It's now up to the caller to emit the instruction and any
789 relocations. */
790 *pstr = str;
791 return opcode;
792 }
793
794 /* Try the next entry. */
795 }
796
797 as_bad ("bad instruction `%s'", start);
798 return 0;
799 }
800
801 void
802 md_operand (expressionP)
803 expressionS *expressionP;
804 {
805 }
806
807 valueT
808 md_section_align (segment, size)
809 segT segment;
810 valueT size;
811 {
812 int align = bfd_get_section_alignment (stdoutput, segment);
813 return ((size + (1 << align) - 1) & (-1 << align));
814 }
815
816 symbolS *
817 md_undefined_symbol (name)
818 char *name;
819 {
820 return 0;
821 }
822
823 /* Called after parsing the file via md_after_pass_hook. */
824
825 void
826 dvp_parse_done ()
827 {
828 /* Check for missing .EndMpg, and supply one if necessary. */
829 if (cur_asm_state == ASM_MPG)
830 s_endmpg (0);
831 else if (cur_asm_state == ASM_DIRECT)
832 s_enddirect (0);
833 else if (cur_asm_state == ASM_UNPACK)
834 s_endunpack (0);
835 }
836 \f
837 /* Functions concerning relocs. */
838
839 /* Spacing between each cpu type's operand numbers.
840 Should be at least as bit as any operand table. */
841 #define RELOC_SPACING 256
842
843 /* Given a cpu type and operand number, return a temporary reloc type
844 for use in generating the fixup that encodes the cpu type and operand
845 number. */
846
847 static int
848 encode_fixup_reloc_type (cpu, opnum)
849 dvp_cpu cpu;
850 int opnum;
851 {
852 return (int) BFD_RELOC_UNUSED + ((int) cpu * RELOC_SPACING) + opnum;
853 }
854
855 /* Given a fixup reloc type, decode it into cpu type and operand. */
856
857 static void
858 decode_fixup_reloc_type (fixup_reloc, cpuP, operandP)
859 int fixup_reloc;
860 dvp_cpu *cpuP;
861 const dvp_operand **operandP;
862 {
863 dvp_cpu cpu = (fixup_reloc - (int) BFD_RELOC_UNUSED) / RELOC_SPACING;
864 int opnum = (fixup_reloc - (int) BFD_RELOC_UNUSED) % RELOC_SPACING;
865
866 *cpuP = cpu;
867 switch (cpu)
868 {
869 case DVP_VUUP : *operandP = &vu_operands[opnum]; break;
870 case DVP_VULO : *operandP = &vu_operands[opnum]; break;
871 case DVP_DMA : *operandP = &dma_operands[opnum]; break;
872 case DVP_VIF : *operandP = &vif_operands[opnum]; break;
873 case DVP_GIF : *operandP = &gif_operands[opnum]; break;
874 default : as_fatal ("bad fixup encoding");
875 }
876 }
877
878 /* Given a fixup reloc type, return a pointer to the operand
879
880 /* The location from which a PC relative jump should be calculated,
881 given a PC relative reloc. */
882
883 long
884 md_pcrel_from_section (fixP, sec)
885 fixS *fixP;
886 segT sec;
887 {
888 if (fixP->fx_addsy != (symbolS *) NULL
889 && (! S_IS_DEFINED (fixP->fx_addsy)
890 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
891 {
892 /* The symbol is undefined (or is defined but not in this section).
893 Let the linker figure it out. +8: branch offsets are relative to the
894 delay slot. */
895 return 8;
896 }
897
898 /* We assume this is a vu branch.
899 Offsets are calculated based on the address of the next insn. */
900 return ((fixP->fx_frag->fr_address + fixP->fx_where) & -8L) + 8;
901 }
902
903 /* Apply a fixup to the object code. This is called for all the
904 fixups we generated by calls to fix_new_exp. At this point all symbol
905 values should be fully resolved, and we attempt to completely resolve the
906 reloc. If we can not do that, we determine the correct reloc code and put
907 it back in the fixup. */
908
909 int
910 md_apply_fix3 (fixP, valueP, seg)
911 fixS *fixP;
912 valueT *valueP;
913 segT seg;
914 {
915 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
916 valueT value;
917
918 /* FIXME FIXME FIXME: The value we are passed in *valueP includes
919 the symbol values. Since we are using BFD_ASSEMBLER, if we are
920 doing this relocation the code in write.c is going to call
921 bfd_perform_relocation, which is also going to use the symbol
922 value. That means that if the reloc is fully resolved we want to
923 use *valueP since bfd_perform_relocation is not being used.
924 However, if the reloc is not fully resolved we do not want to use
925 *valueP, and must use fx_offset instead. However, if the reloc
926 is PC relative, we do want to use *valueP since it includes the
927 result of md_pcrel_from. This is confusing. */
928
929 if (fixP->fx_addsy == (symbolS *) NULL)
930 {
931 value = *valueP;
932 fixP->fx_done = 1;
933 }
934 else if (fixP->fx_pcrel)
935 {
936 value = *valueP;
937 }
938 else
939 {
940 value = fixP->fx_offset;
941 if (fixP->fx_subsy != (symbolS *) NULL)
942 {
943 if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
944 value -= S_GET_VALUE (fixP->fx_subsy);
945 else
946 {
947 /* We can't actually support subtracting a symbol. */
948 as_bad_where (fixP->fx_file, fixP->fx_line,
949 "expression too complex");
950 }
951 }
952 }
953
954 /* Check for dvp operand's. These are indicated with a reloc value
955 >= BFD_RELOC_UNUSED. */
956
957 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
958 {
959 dvp_cpu cpu;
960 const dvp_operand *operand;
961 DVP_INSN insn;
962
963 decode_fixup_reloc_type ((int) fixP->fx_r_type,
964 & cpu, & operand);
965
966 /* Fetch the instruction, insert the fully resolved operand
967 value, and stuff the instruction back again. */
968 insn = bfd_getl32 ((unsigned char *) where);
969 insert_operand_final (cpu, operand, DVP_MOD_THIS_WORD, &insn,
970 (offsetT) value, fixP->fx_file, fixP->fx_line);
971 bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
972
973 if (fixP->fx_done)
974 {
975 /* Nothing else to do here. */
976 return 1;
977 }
978
979 /* Determine a BFD reloc value based on the operand information.
980 We are only prepared to turn a few of the operands into relocs. */
981 /* FIXME: This test is a hack. */
982 if ((operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0)
983 {
984 assert ((operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0
985 && operand->bits == 11
986 && operand->shift == 0);
987 fixP->fx_r_type = BFD_RELOC_MIPS_DVP_11_PCREL;
988 }
989 else
990 {
991 as_bad_where (fixP->fx_file, fixP->fx_line,
992 "unresolved expression that must be resolved");
993 fixP->fx_done = 1;
994 return 1;
995 }
996 }
997 else
998 {
999 switch (fixP->fx_r_type)
1000 {
1001 case BFD_RELOC_8:
1002 md_number_to_chars (where, value, 1);
1003 break;
1004 case BFD_RELOC_16:
1005 md_number_to_chars (where, value, 2);
1006 break;
1007 case BFD_RELOC_32:
1008 md_number_to_chars (where, value, 4);
1009 break;
1010 default:
1011 abort ();
1012 }
1013 }
1014
1015 fixP->fx_addnumber = value;
1016
1017 return 1;
1018 }
1019
1020 /* Translate internal representation of relocation info to BFD target
1021 format. */
1022
1023 arelent *
1024 tc_gen_reloc (section, fixP)
1025 asection *section;
1026 fixS *fixP;
1027 {
1028 arelent *reloc;
1029
1030 reloc = (arelent *) xmalloc (sizeof (arelent));
1031
1032 reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
1033 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1034 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1035 if (reloc->howto == (reloc_howto_type *) NULL)
1036 {
1037 as_bad_where (fixP->fx_file, fixP->fx_line,
1038 "internal error: can't export reloc type %d (`%s')",
1039 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
1040 return NULL;
1041 }
1042
1043 assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1044
1045 reloc->addend = fixP->fx_addnumber;
1046
1047 return reloc;
1048 }
1049 \f
1050 /* Write a value out to the object file, using the appropriate endianness. */
1051
1052 void
1053 md_number_to_chars (buf, val, n)
1054 char *buf;
1055 valueT val;
1056 int n;
1057 {
1058 if (target_big_endian)
1059 number_to_chars_bigendian (buf, val, n);
1060 else
1061 number_to_chars_littleendian (buf, val, n);
1062 }
1063
1064 /* Turn a string in input_line_pointer into a floating point constant of type
1065 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1066 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1067 */
1068
1069 /* Equal to MAX_PRECISION in atof-ieee.c */
1070 #define MAX_LITTLENUMS 6
1071
1072 char *
1073 md_atof (type, litP, sizeP)
1074 char type;
1075 char *litP;
1076 int *sizeP;
1077 {
1078 int i,prec;
1079 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1080 LITTLENUM_TYPE *wordP;
1081 char *t;
1082 char *atof_ieee ();
1083
1084 switch (type)
1085 {
1086 case 'f':
1087 case 'F':
1088 case 's':
1089 case 'S':
1090 prec = 2;
1091 break;
1092
1093 case 'd':
1094 case 'D':
1095 case 'r':
1096 case 'R':
1097 prec = 4;
1098 break;
1099
1100 /* FIXME: Some targets allow other format chars for bigger sizes here. */
1101
1102 default:
1103 *sizeP = 0;
1104 return "Bad call to md_atof()";
1105 }
1106
1107 t = atof_ieee (input_line_pointer, type, words);
1108 if (t)
1109 input_line_pointer = t;
1110 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1111
1112 if (target_big_endian)
1113 {
1114 for (i = 0; i < prec; i++)
1115 {
1116 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
1117 litP += sizeof (LITTLENUM_TYPE);
1118 }
1119 }
1120 else
1121 {
1122 for (i = prec - 1; i >= 0; i--)
1123 {
1124 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
1125 litP += sizeof (LITTLENUM_TYPE);
1126 }
1127 }
1128
1129 return 0;
1130 }
1131 \f
1132 /*
1133 Compute the auto-count value for a DMA tag with inline data.
1134 */
1135 static long
1136 parse_dma_ild_autocount( opcode, operand, mods, insn_buf, pstr, errmsg)
1137 const dvp_opcode *opcode;
1138 const dvp_operand *operand;
1139 int mods;
1140 DVP_INSN *insn_buf;
1141 char **pstr;
1142 const char **errmsg;
1143 {
1144 char *start = *pstr;
1145 char *end = start;
1146 long retval;
1147
1148 #if 0
1149 /* FIXME: unfinished */
1150 evaluate the operand as an expression
1151 store the value to the count field
1152 compute the length as _$EndDma-.
1153 #endif
1154
1155 *pstr = end;
1156 return 0;
1157 }
1158
1159 /* Scan a symbol and return a pointer to one past the end. */
1160 #define issymchar(ch) (isalnum(ch) || ch == '_')
1161 static char *
1162 scan_symbol( sym)
1163 char *sym;
1164 {
1165 while( *sym && issymchar( *sym))
1166 ++sym;
1167 return sym;
1168 }
1169
1170 /*
1171 Compute the auto-count value for a DMA tag with out-of-line data.
1172 */
1173 static long
1174 parse_dma_ptr_autocount( opcode, operand, mods, insn_buf, pstr, errmsg)
1175 const dvp_opcode *opcode;
1176 const dvp_operand *operand;
1177 int mods;
1178 DVP_INSN *insn_buf;
1179 char **pstr;
1180 const char **errmsg;
1181 {
1182 char *start = *pstr;
1183 char *end = start;
1184 long retval;
1185
1186 /* Data reference must be a .DmaData label. */
1187 struct symbol *label, *label2;
1188 const char *name;
1189 char *name2;
1190 int len;
1191 long count;
1192
1193 label = label2 = 0;
1194 if( is_name_beginner( *start) )
1195 {
1196 char c;
1197
1198 end = scan_symbol( start);
1199 c = *end;
1200 *end = 0;
1201 label = symbol_find( start);
1202 *end = c;
1203 }
1204 if( label )
1205 {
1206 name = S_GET_NAME( label);
1207 len = strlen( name) + 1;
1208 name2 = xmalloc( len + 2);
1209 name2[ 0] = '_';
1210 name2[ 1] = '$';
1211 memcpy( name2+2, name, len); /* copy original name & \0 */
1212 label2 = symbol_find( name2);
1213 free( name2);
1214 }
1215 if( label == 0 || label2 == 0 )
1216 {
1217 *errmsg = "2nd operand must be a .DmaData label";
1218 return 0;
1219 }
1220
1221 /* The second operand's value is the value of "symbol". */
1222 retval = S_GET_VALUE( label);
1223
1224 /* The computed count value is val(symbol2) - val(symbol). */
1225 count = S_GET_VALUE( label2) - retval;
1226
1227 /* Store the count field. */
1228 count &= 0x0000ffff;
1229 insn_buf[ 4] &= 0xffff0000;
1230 insn_buf[ 4] |= count & 0x0000ffff;
1231
1232 *pstr = end;
1233 return retval;
1234 }
1235 \f
1236 /* Return length in bytes of the variable length VIF insn
1237 currently being assembled. */
1238
1239 static int
1240 cur_vif_insn_length ()
1241 {
1242 int byte_len;
1243 fragS *f;
1244
1245 if (cur_varlen_frag == frag_now)
1246 byte_len = frag_more (0) - cur_varlen_insn - 4; /* -4 for mpg itself */
1247 else
1248 {
1249 byte_len = (cur_varlen_frag->fr_fix + cur_varlen_frag->fr_offset -
1250 (cur_varlen_insn - cur_varlen_frag->fr_literal)) - 4;
1251 for (f = cur_varlen_frag->fr_next; f != frag_now; f = f->fr_next)
1252 byte_len += f->fr_fix + f->fr_offset;
1253 byte_len += frag_now_fix ();
1254 }
1255
1256 return byte_len;
1257 }
1258
1259 /* Install length LEN, in bytes, in the vif insn at BUF.
1260 The bytes in BUF are in target order. */
1261
1262 static void
1263 install_vif_length (buf, len)
1264 char *buf;
1265 int len;
1266 {
1267 char cmd = buf[3];
1268
1269 if ((cmd & 0x70) == 0x40)
1270 {
1271 /* mpg */
1272 len /= 4;
1273 /* ??? Worry about data /= 4 cuts off? */
1274 if (len > 256)
1275 as_bad ("`mpg' data length must be between 1 and 256");
1276 buf[2] = len == 256 ? 0 : len;
1277 }
1278 else if ((cmd & 0x70) == 0x50)
1279 {
1280 /* direct/directhl */
1281 /* ??? Worry about data /= 16 cuts off? */
1282 len /= 16;
1283 if (len > 65536)
1284 as_bad ("`direct' data length must be between 1 and 65536");
1285 len = len == 65536 ? 0 : len;
1286 buf[0] = len;
1287 buf[1] = len >> 8;
1288 }
1289 else if ((cmd & 0x60) == 0x60)
1290 {
1291 /* unpack */
1292 /* FIXME */
1293 }
1294 else
1295 as_fatal ("bad call to install_vif_length");
1296 }
1297
1298 /* Insert a file into the output.
1299 -I is used to specify where to find the file.
1300 The result is the number of bytes inserted.
1301 If an error occurs an error message is printed and zero is returned. */
1302
1303 static int
1304 insert_file (file)
1305 const char *file;
1306 {
1307 FILE *f;
1308 char buf[256];
1309 int i, n, total;
1310 char *path;
1311
1312 path = xmalloc (strlen (file) + include_dir_maxlen + 5 /*slop*/);
1313 f = NULL;
1314 for (i = 0; i < include_dir_count; i++)
1315 {
1316 strcpy (path, include_dirs[i]);
1317 strcat (path, "/");
1318 strcat (path, file);
1319 if ((f = fopen (path, FOPEN_RB)) != NULL)
1320 break;
1321 }
1322 free (path);
1323 if (f == NULL)
1324 f = fopen (file, FOPEN_RB);
1325 if (f == NULL)
1326 {
1327 as_bad ("unable to read file `%s'", file);
1328 return 0;
1329 }
1330
1331 total = 0;
1332 do {
1333 n = fread (buf, 1, sizeof (buf), f);
1334 if (n > 0)
1335 {
1336 char *fr = frag_more (n);
1337 memcpy (fr, buf, n);
1338 total += n;
1339 }
1340 } while (n > 0);
1341
1342 fclose (f);
1343 /* We assume the file is smaller than 2^31 bytes.
1344 Ok, we shouldn't make any assumptions. Later. */
1345 return total;
1346 }
1347
1348 /* Insert an operand value into an instruction. */
1349
1350 static void
1351 insert_operand (cpu, opcode, operand, mods, insn_buf, val, errmsg)
1352 dvp_cpu cpu;
1353 const dvp_opcode *opcode;
1354 const dvp_operand *operand;
1355 int mods;
1356 DVP_INSN *insn_buf;
1357 offsetT val;
1358 const char **errmsg;
1359 {
1360 if (operand->insert)
1361 {
1362 (*operand->insert) (opcode, operand, mods, insn_buf, (long) val, errmsg);
1363 }
1364 else
1365 {
1366 #if 0 /* FIXME: revisit */
1367 /* We currently assume a field does not cross a word boundary. */
1368 int shift = ((mods & DVP_MOD_THIS_WORD)
1369 ? (operand->shift & 31)
1370 : operand->shift);
1371 DVP_INSN *p = insn_buf + (shift / 32);
1372 if (operand->bits == 32)
1373 *p = val;
1374 else
1375 {
1376 shift = shift % 32;
1377 *p |= ((long) val & ((1 << operand->bits) - 1)) << shift;
1378 }
1379 #else
1380 /* We currently assume a field does not cross a word boundary. */
1381 if (operand->bits == 32)
1382 insn_buf[ operand->word] = val;
1383 else
1384 {
1385 long temp = (long) val & ((1 << operand->bits) - 1);
1386 insn_buf[ operand->word] |= temp << operand->shift;
1387 }
1388 }
1389 #endif
1390 }
1391
1392 /* Insert an operand's final value into an instruction.
1393 Here we can give warning messages about operand values if we want to. */
1394
1395 static void
1396 insert_operand_final (cpu, operand, mods, insn_buf, val, file, line)
1397 dvp_cpu cpu;
1398 const dvp_operand *operand;
1399 int mods;
1400 DVP_INSN *insn_buf;
1401 offsetT val;
1402 char *file;
1403 unsigned int line;
1404 {
1405 if (operand->bits != 32)
1406 {
1407 offsetT min, max, test;
1408
1409 if ((operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0)
1410 {
1411 if ((val & 7) != 0)
1412 {
1413 if (file == (char *) NULL)
1414 as_warn ("branch to misaligned address");
1415 else
1416 as_warn_where (file, line, "branch to misaligned address");
1417 }
1418 val >>= 3;
1419 }
1420
1421 if ((operand->flags & DVP_OPERAND_SIGNED) != 0)
1422 {
1423 if ((operand->flags & DVP_OPERAND_SIGNOPT) != 0)
1424 max = (1 << operand->bits) - 1;
1425 else
1426 max = (1 << (operand->bits - 1)) - 1;
1427 min = - (1 << (operand->bits - 1));
1428 }
1429 else
1430 {
1431 max = (1 << operand->bits) - 1;
1432 min = 0;
1433 }
1434
1435 if ((operand->flags & DVP_OPERAND_NEGATIVE) != 0)
1436 test = - val;
1437 else
1438 test = val;
1439
1440 if (test < (offsetT) min || test > (offsetT) max)
1441 {
1442 const char *err =
1443 "operand out of range (%s not between %ld and %ld)";
1444 char buf[100];
1445
1446 sprint_value (buf, test);
1447 if (file == (char *) NULL)
1448 as_warn (err, buf, min, max);
1449 else
1450 as_warn_where (file, line, err, buf, min, max);
1451 }
1452 }
1453
1454 {
1455 const char *errmsg = NULL;
1456 insert_operand (cpu, NULL, operand, mods, insn_buf, val, &errmsg);
1457 if (errmsg != NULL)
1458 as_warn_where (file, line, errmsg);
1459 }
1460 }
1461 \f
1462 static short dmadata_state = 0;
1463 static const char *dmadata_name;
1464
1465 /* Non-zero if .DmaData was implied by a real (non-pseudo) opcode. */
1466 static int implied_dmadata_p = 0;
1467
1468 static void
1469 s_dmadata_implied( ignore)
1470 int ignore;
1471 {
1472 if( dmadata_state != 0 )
1473 {
1474 as_bad( "DmaData blocks cannot be nested.");
1475 }
1476 dmadata_state = 1;
1477 dmadata_name = 0;
1478 }
1479
1480 static void
1481 s_dmadata( ignore)
1482 int ignore;
1483 {
1484 char *name, c;
1485
1486 dmadata_name = 0;
1487
1488 if( dmadata_state != 0 )
1489 {
1490 as_bad( "DmaData blocks cannot be nested.");
1491 ignore_rest_of_line();
1492 return;
1493 }
1494 dmadata_state = 1;
1495
1496 SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
1497 name = input_line_pointer;
1498
1499 if( !is_name_beginner( *name) )
1500 {
1501 as_bad( "invalid identifier for \".DmaData\"");
1502 obstack_1grow( &cond_obstack, 0); /*FIXME what is this for?*/
1503 ignore_rest_of_line();
1504 return;
1505 }
1506
1507 c = get_symbol_end();
1508 line_label = colon( name); /* user-defined label */
1509 dmadata_name = line_label->bsym->name;
1510 *input_line_pointer = c;
1511
1512 demand_empty_rest_of_line();
1513 }
1514
1515 static void
1516 s_enddmadata( ignore)
1517 int ignore;
1518 {
1519 if( dmadata_state != 1)
1520 {
1521 as_warn( ".EndDmaData encountered outside a DmaData block -- ignored.");
1522 ignore_rest_of_line();
1523 dmadata_name = 0;
1524 }
1525 dmadata_state = 0;
1526 demand_empty_rest_of_line();
1527
1528 /*
1529 * "label" points to beginning of block
1530 * Create a name for the final label like _$<name>
1531 */
1532 if( dmadata_name) {
1533 int temp;
1534 char *name;
1535
1536 temp = strlen( dmadata_name) + 1;
1537 name = xmalloc( temp + 2);
1538 name[ 0] = '_';
1539 name[ 1] = '$';
1540 memcpy( name+2, dmadata_name, temp); /* copy original name & \0 */
1541 colon( name);
1542 free( name);
1543 }
1544 }
1545 \f
1546 static void
1547 s_dmapackvif( ignore)
1548 int ignore;
1549 {
1550 /* Syntax: .dmapackvif 0|1 */
1551 struct symbol *label; /* Points to symbol */
1552 char *name; /* points to name of symbol */
1553
1554 SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
1555 switch( *input_line_pointer++ )
1556 {
1557 case '0':
1558 dma_pack_vif_p = 0;
1559 break;
1560 case '1':
1561 dma_pack_vif_p = 1;
1562 break;
1563 default:
1564 as_bad( "illegal argument to `.DmaPackPke'");
1565 }
1566 demand_empty_rest_of_line();
1567 }
1568
1569 static void
1570 s_enddirect (ignore)
1571 int ignore;
1572 {
1573 int byte_len;
1574
1575 if (cur_asm_state != ASM_DIRECT)
1576 {
1577 as_bad ("`.enddirect' has no matching `direct' instruction");
1578 return;
1579 }
1580
1581 byte_len = cur_vif_insn_length ();
1582 if (cur_varlen_value != -1
1583 && cur_varlen_value * 16 != byte_len)
1584 as_warn ("length in `direct' instruction does not match length of data");
1585 if (output_vif)
1586 install_vif_length (cur_varlen_insn, byte_len);
1587
1588 cur_asm_state = ASM_INIT;
1589
1590 /* These needn't be reset, but to catch bugs they are. */
1591 cur_varlen_frag = NULL;
1592 cur_varlen_insn = NULL;
1593 cur_varlen_value = 0;
1594 }
1595
1596 static void
1597 s_endmpg (ignore)
1598 int ignore;
1599 {
1600 int byte_len;
1601
1602 if (cur_asm_state != ASM_MPG)
1603 {
1604 as_bad ("`.endmpg' has no matching `mpg' instruction");
1605 return;
1606 }
1607
1608 byte_len = cur_vif_insn_length ();
1609 if (cur_varlen_value != -1
1610 && cur_varlen_value * 8 != byte_len)
1611 as_warn ("length in `mpg' instruction does not match length of data");
1612 if (output_vif)
1613 install_vif_length (cur_varlen_insn, byte_len);
1614
1615 cur_asm_state = ASM_INIT;
1616
1617 /* These needn't be reset, but to catch bugs they are. */
1618 cur_varlen_frag = NULL;
1619 cur_varlen_insn = NULL;
1620 cur_varlen_value = 0;
1621
1622 /* Update $.MpgLoc. */
1623 vif_set_mpgloc (vif_get_mpgloc () + byte_len);
1624 }
1625
1626 static void
1627 s_endunpack (ignore)
1628 int ignore;
1629 {
1630 int byte_len;
1631
1632 if (cur_asm_state != ASM_UNPACK)
1633 {
1634 as_bad ("`.endunpack' has no matching `unpack' instruction");
1635 return;
1636 }
1637
1638 byte_len = cur_vif_insn_length ();
1639 #if 0 /* unpack doesn't support prespecifying a length */
1640 if (cur_varlen_value * 16 != bytelen)
1641 as_warn ("length in `direct' instruction does not match length of data");
1642 #endif
1643 if (output_vif)
1644 install_vif_length (cur_varlen_insn, byte_len);
1645
1646 cur_asm_state = ASM_INIT;
1647
1648 /* These needn't be reset, but to catch bugs they are. */
1649 cur_varlen_frag = NULL;
1650 cur_varlen_insn = NULL;
1651 cur_varlen_value = 0;
1652
1653 /* Update $.UnpackLoc. */
1654 vif_set_unpackloc (vif_get_unpackloc () + byte_len);
1655 }
1656
1657 static void
1658 s_state (state)
1659 int state;
1660 {
1661 cur_asm_state = state;
1662 }
1663
1664 static void
1665 s_endgif (ignore)
1666 int ignore;
1667 {
1668 }
1669 \f
1670 /* Parse a DMA data spec which can be either of '*' or a quad word count. */
1671
1672 static int
1673 parse_dma_count( pstr, errmsg)
1674 char **pstr;
1675 const char **errmsg;
1676 {
1677 char *str = *pstr;
1678 long count, value;
1679 expressionS exp;
1680
1681 if( *str == '*' )
1682 {
1683 ++*pstr;
1684 /* -1 is a special marker to caller to tell it the count is to be
1685 computed from the data. */
1686 return -1;
1687 }
1688
1689 expression( &exp);
1690 if( exp.X_op == O_illegal
1691 || exp.X_op == O_absent )
1692 ;
1693 else if( exp.X_op == O_constant )
1694 value = exp.X_add_number;
1695 else if( exp.X_op == O_register )
1696 as_fatal( "got O_register");
1697 else
1698 {
1699 /* We need to generate a fixup for this expression. */
1700 if( fixup_count >= MAX_FIXUPS )
1701 as_fatal( "too many fixups");
1702 fixups[fixup_count].exp = exp;
1703 fixups[fixup_count].opindex = 0 /*FIXME*/;
1704 fixups[fixup_count].offset = 0 /*FIXME*/;
1705 ++fixup_count;
1706 value = 0;
1707 }
1708
1709 if( isdigit( *str) ) /* ????????needs to accept an expression*/
1710 {
1711 char *start = str;
1712 while( *str && *str != ',' )
1713 ++str;
1714 if( *str != ',' )
1715 {
1716 *errmsg = "invalid dma count";
1717 return 0;
1718 }
1719 count = atoi (start);
1720 *pstr = str;
1721 return(count);
1722 }
1723
1724 *errmsg = "invalid dma count";
1725 return 0;
1726 }
This page took 0.065659 seconds and 4 git commands to generate.