1 /* tc-txvu.c -- Assembler for the TX VU.
2 Copyright (C) 1997, 1998 Free Software Foundation.
4 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
25 /* Needed by opcode/txvu.h. */
27 #include "opcode/txvu.h"
30 static TXVU_INSN txvu_insert_operand
31 PARAMS ((TXVU_INSN
, const struct txvu_operand
*, int, offsetT
,
32 char *, unsigned int));
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";
40 /* Non-zero if in vu-mode. */
43 /* Non-zero if packing pke instructions in dma tags. */
44 static int dma_pack_pke_p
;
46 const char *md_shortopts
= "";
48 struct option md_longopts
[] =
50 /* insert options here */
52 {NULL
, no_argument
, NULL
, 0}
54 size_t md_longopts_size
= sizeof(md_longopts
);
57 md_parse_option (c
, arg
)
65 md_show_usage (stream
)
69 fprintf (stream
, "TX VU options:\n");
73 /* Set by md_assemble for use by txvu_fill_insn. */
74 static subsegT prev_subseg
;
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));
86 /* The target specific pseudo-ops which we support. */
87 const pseudo_typeS md_pseudo_table
[] =
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 */
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. */
115 subseg_set (seg
, subseg
);
117 /* Initialize the opcode tables.
118 This involves computing the hash chains. */
119 txvu_opcode_init_tables (0);
125 enum cputype
{ CPU_VUUP
, CPU_VULO
, CPU_DMA
, CPU_PKE
, CPU_GPUIF
};
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 ``.''. */
133 /* index into `txvu_operands' */
140 static int fixup_count
;
141 static struct txvu_fixup fixups
[MAX_FIXUPS
];
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
*,
151 static char * assemble_one_insn
PARAMS ((enum cputype
,
152 const struct txvu_opcode
*,
153 const struct txvu_operand
*,
154 char *, TXVU_INSN
*));
160 /* Skip leading white space. */
161 while (isspace (*str
))
166 if (strncasecmp (str
, "dma", 3) == 0)
168 else if (strncasecmp (str
, "gpuif", 5) == 0)
169 assemble_gpuif (str
);
177 /* Subroutine of md_assemble to assemble DMA instructions. */
185 assemble_one_insn (CPU_DMA
,
186 dma_opcode_lookup_asm (str
), dma_operands
,
190 /* Subroutine of md_assemble to assemble PKE instructions. */
198 assemble_one_insn (CPU_PKE
,
199 pke_opcode_lookup_asm (str
), pke_operands
,
203 /* Subroutine of md_assemble to assemble GPUIF instructions. */
211 assemble_one_insn (CPU_GPUIF
,
212 gpuif_opcode_lookup_asm (str
), gpuif_operands
,
216 /* Subroutine of md_assemble to assemble VU instructions. */
222 /* The lower instruction has the lower address.
223 Handle this by grabbing 8 bytes now, and then filling each word
225 char *f
= frag_more (8);
227 #ifdef VERTICAL_BAR_SEPARATOR
228 char *p
= strchr (str
, '|');
232 as_bad ("lower slot missing in `%s'", str
);
237 assemble_vu_insn (CPU_VUUP
,
238 txvu_upper_opcode_lookup_asm (str
), txvu_operands
,
241 assemble_vu_insn (CPU_VULO
,
242 txvu_lower_opcode_lookup_asm (str
), txvu_operands
,
245 str
= assemble_vu_insn (CPU_VUUP
,
246 txvu_upper_opcode_lookup_asm (str
), txvu_operands
,
248 /* Don't assemble next one if we couldn't assemble the first. */
250 assemble_vu_insn (CPU_VULO
,
251 txvu_lower_opcode_lookup_asm (str
), txvu_operands
,
257 assemble_vu_insn (cpu
, opcode
, operand_table
, str
, buf
)
259 const struct txvu_opcode
*opcode
;
260 const struct txvu_operand
*operand_table
;
267 str
= assemble_one_insn (cpu
, opcode
, operand_table
, str
, &insn
);
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);
277 /* Create any fixups. */
278 for (i
= 0; i
< fixup_count
; ++i
)
280 int op_type
, reloc_type
;
281 const struct txvu_operand
*operand
;
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. */
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,
295 (operand
->flags
& TXVU_OPERAND_RELATIVE_BRANCH
) != 0,
296 (bfd_reloc_code_real_type
) reloc_type
);
303 /* Assemble one instruction.
304 CPU indicates what component we're assembling for.
305 The assembled instruction is stored in INSN_BUF.
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. */
313 assemble_one_insn (cpu
, opcode
, operand_table
, str
, insn_buf
)
315 const struct txvu_opcode
*opcode
;
316 const struct txvu_operand
*operand_table
;
322 /* Keep looking until we find a match. */
325 for ( ; opcode
!= NULL
; opcode
= TXVU_OPCODE_NEXT_ASM (opcode
))
327 int past_opcode_p
, num_suffixes
, num_operands
;
328 const unsigned char *syn
;
330 /* Ensure the mnemonic part matches. */
331 for (str
= start
, syn
= opcode
->mnemonic
; *syn
!= '\0'; ++str
, ++syn
)
332 if (tolower (*str
) != tolower (*syn
))
337 /* Scan the syntax string. If it doesn't match, try the next one. */
339 txvu_opcode_init_parse ();
340 *insn_buf
= opcode
->value
;
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'; )
351 const struct txvu_operand
*operand
;
354 /* Non operand chars must match exactly.
355 Operand chars that are letters are not part of symbols
356 and are case insensitive. */
359 if (tolower (*str
) == tolower (*syn
))
371 /* We have a suffix or an operand. Pick out any modifiers. */
373 index
= TXVU_OPERAND_INDEX (*syn
);
374 while (TXVU_MOD_P (operand_table
[index
].flags
))
376 mods
|= operand_table
[index
].flags
& TXVU_MOD_BITS
;
378 index
= TXVU_OPERAND_INDEX (*syn
);
380 operand
= operand_table
+ index
;
382 if (operand
->flags
& TXVU_OPERAND_FAKE
)
387 (*operand
->insert
) (insn_buf
, operand
, mods
, 0, &errmsg
);
388 /* If we get an error, go on to try the next insn. */
394 /* Are we finished with suffixes? */
395 else if (!past_opcode_p
)
402 if (!(operand
->flags
& TXVU_OPERAND_SUFFIX
))
403 as_fatal ("bad opcode table, missing suffix flag");
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. */
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
)
424 suf_value
= (*operand
->parse
) (&s
, &errmsg
);
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
434 /* Insert the suffix's value into the insn. */
436 (*operand
->insert
) (insn_buf
, operand
,
437 mods
, suf_value
, NULL
);
439 *insn_buf
|= suf_value
<< operand
->shift
;
445 /* This is an operand, either a register or an expression of
453 if (operand
->flags
& TXVU_OPERAND_SUFFIX
)
454 as_fatal ("bad opcode table, suffix wrong");
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)
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 "". */
473 /* Parse the operand. */
477 value
= (*operand
->parse
) (&str
, &errmsg
);
483 hold
= input_line_pointer
;
484 input_line_pointer
= str
;
486 str
= input_line_pointer
;
487 input_line_pointer
= hold
;
489 if (exp
.X_op
== O_illegal
490 || exp
.X_op
== O_absent
)
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");
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
;
508 /* Insert the register or expression into the instruction. */
511 const char *errmsg
= NULL
;
512 (*operand
->insert
) (insn_buf
, operand
, mods
,
514 if (errmsg
!= (const char *) NULL
)
518 *insn_buf
|= (value
& ((1 << operand
->bits
) - 1)) << operand
->shift
;
525 /* If we're at the end of the syntax string, we're done. */
526 /* FIXME: try to move this to a separate function. */
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). */
536 while (isspace (*str
))
540 #ifndef VERTICAL_BAR_SEPARATOR
544 as_bad ("junk at end of line: `%s'", str
);
546 /* It's now up to the caller to emit the instruction and any
551 /* Try the next entry. */
554 as_bad ("bad instruction `%s'", start
);
559 md_operand (expressionP
)
560 expressionS
*expressionP
;
565 md_section_align (segment
, size
)
569 int align
= bfd_get_section_alignment (stdoutput
, segment
);
570 return ((size
+ (1 << align
) - 1) & (-1 << align
));
574 md_undefined_symbol (name
)
580 /* Functions concerning relocs. */
582 /* The location from which a PC relative jump should be calculated,
583 given a PC relative reloc. */
586 md_pcrel_from_section (fixP
, sec
)
590 if (fixP
->fx_addsy
!= (symbolS
*) NULL
591 && (! S_IS_DEFINED (fixP
->fx_addsy
)
592 || S_GET_SEGMENT (fixP
->fx_addsy
) != sec
))
594 /* The symbol is undefined (or is defined but not in this section).
595 Let the linker figure it out. */
599 /* FIXME: `& -16L'? */
600 return (fixP
->fx_frag
->fr_address
+ fixP
->fx_where
) & -8L;
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. */
610 md_apply_fix3 (fixP
, valueP
, seg
)
615 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
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. */
629 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
634 else if (fixP
->fx_pcrel
)
640 value
= fixP
->fx_offset
;
641 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
643 if (S_GET_SEGMENT (fixP
->fx_subsy
) == absolute_section
)
644 value
-= S_GET_VALUE (fixP
->fx_subsy
);
647 /* We can't actually support subtracting a symbol. */
648 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
649 "expression too complex");
654 /* Check for txvu_operand's. These are indicated with a reloc value
655 >= BFD_RELOC_UNUSED. */
657 if ((int) fixP
->fx_r_type
>= (int) BFD_RELOC_UNUSED
)
660 const struct txvu_operand
*operand
;
663 opindex
= (int) fixP
->fx_r_type
- (int) BFD_RELOC_UNUSED
;
665 operand
= &txvu_operands
[opindex
];
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
);
676 /* Nothing else to do here. */
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)
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
;
692 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
693 "unresolved expression that must be resolved");
700 switch (fixP
->fx_r_type
)
703 md_number_to_chars (where
, value
, 1);
706 md_number_to_chars (where
, value
, 2);
709 md_number_to_chars (where
, value
, 4);
716 fixP
->fx_addnumber
= value
;
721 /* Translate internal representation of relocation info to BFD target
725 tc_gen_reloc (section
, fixP
)
731 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
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
)
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
));
744 assert (!fixP
->fx_pcrel
== !reloc
->howto
->pc_relative
);
746 reloc
->addend
= fixP
->fx_addnumber
;
751 /* Write a value out to the object file, using the appropriate endianness. */
754 md_number_to_chars (buf
, val
, n
)
759 if (target_big_endian
)
760 number_to_chars_bigendian (buf
, val
, n
);
762 number_to_chars_littleendian (buf
, val
, n
);
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.
770 /* Equal to MAX_PRECISION in atof-ieee.c */
771 #define MAX_LITTLENUMS 6
774 md_atof (type
, litP
, sizeP
)
780 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
781 LITTLENUM_TYPE
*wordP
;
801 /* FIXME: Some targets allow other format chars for bigger sizes here. */
805 return "Bad call to md_atof()";
808 t
= atof_ieee (input_line_pointer
, type
, words
);
810 input_line_pointer
= t
;
811 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
813 if (target_big_endian
)
815 for (i
= 0; i
< prec
; i
++)
817 md_number_to_chars (litP
, (valueT
) words
[i
], sizeof (LITTLENUM_TYPE
));
818 litP
+= sizeof (LITTLENUM_TYPE
);
823 for (i
= prec
- 1; i
>= 0; i
--)
825 md_number_to_chars (litP
, (valueT
) words
[i
], sizeof (LITTLENUM_TYPE
));
826 litP
+= sizeof (LITTLENUM_TYPE
);
833 /* Insert an operand value into an instruction. */
836 txvu_insert_operand (insn
, operand
, mods
, val
, file
, line
)
838 const struct txvu_operand
*operand
;
844 if (operand
->bits
!= 32)
849 if ((operand
->flags
& TXVU_OPERAND_RELATIVE_BRANCH
) != 0)
853 if (file
== (char *) NULL
)
854 as_warn ("branch to misaligned address");
856 as_warn_where (file
, line
, "branch to misaligned address");
861 if ((operand
->flags
& TXVU_OPERAND_SIGNED
) != 0)
863 if ((operand
->flags
& TXVU_OPERAND_SIGNOPT
) != 0)
864 max
= (1 << operand
->bits
) - 1;
866 max
= (1 << (operand
->bits
- 1)) - 1;
867 min
= - (1 << (operand
->bits
- 1));
871 max
= (1 << operand
->bits
) - 1;
875 if ((operand
->flags
& TXVU_OPERAND_NEGATIVE
) != 0)
880 if (test
< (offsetT
) min
|| test
> (offsetT
) max
)
883 "operand out of range (%s not between %ld and %ld)";
886 sprint_value (buf
, test
);
887 if (file
== (char *) NULL
)
888 as_warn (err
, buf
, min
, max
);
890 as_warn_where (file
, line
, err
, buf
, min
, max
);
896 const char *errmsg
= NULL
;
897 (*operand
->insert
) (&insn
, operand
, mods
, (long) val
, &errmsg
);
898 if (errmsg
!= (const char *) NULL
)
902 insn
|= (((long) val
& ((1 << operand
->bits
) - 1))
915 s_dmapackpke (ignore
)
918 /* Syntax: .dmapackpke 0|1 */
919 if (*input_line_pointer
== '0')
921 else if (*input_line_pointer
== '1')
924 as_bad ("illegal argument to `.dmapackpke'");
926 input_line_pointer
++;
927 demand_empty_rest_of_line ();
937 s_enddmadata (ignore
)
966 vu_mode_p
= enable_p
;