Sun Sep 20 00:58:12 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
[deliverable/binutils-gdb.git] / gas / config / tc-dvp.c
CommitLineData
276dd6ef 1/* tc-dvp.c -- Assembler for the DVP
f7306261 2 Copyright (C) 1997, 1998 Free Software Foundation.
209fb346
DE
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>
1ece1d56 23
209fb346 24#include "as.h"
f6428b86 25#include "subsegs.h"
276dd6ef 26/* Needed by opcode/dvp.h. */
f6428b86 27#include "dis-asm.h"
276dd6ef 28#include "opcode/dvp.h"
3a6b8910 29#include "elf/mips.h"
95bfad6d 30
1ece1d56
DE
31#ifdef USE_STDARG
32#include <stdarg.h>
33#else
34#include <varargs.h>
35#endif
36
8b901ef8
DE
37/* Value of VIF `nop' instruction. */
38#define VIFNOP 0
39
ba4be194
DE
40#define MIN(a,b) ((a) < (b) ? (a) : (b))
41
1ece1d56
DE
42/* Compute DMA operand index number of OP. */
43#define DMA_OPERAND_INDEX(op) ((op) - dma_operands)
19f12fb4 44
91572941
DE
45/* Our local label prefix. */
46#define LOCAL_LABEL_PREFIX ".L"
47/* Label prefix for end markers used in autocounts. */
48#define END_LABEL_PREFIX ".L.end."
9152beba
DE
49/* Label to use for unique labels. */
50#define UNIQUE_LABEL_PREFIX ".L.dvptmp."
07b20428
DE
51/* Prefix for mips version of labels defined in vu code.
52 Note that symbols that begin with '$' are local symbols
53 on mips targets, so we can't begin it with '$'. */
cb74aaa5 54#define VU_LABEL_PREFIX "_$"
1554baf3
DE
55/* Prefix for symbols at start of vu overlays, in r5900 space. */
56#define VUOVERLAY_START_PREFIX "__start_"
91572941 57
1ece1d56 58static long parse_float PARAMS ((char **, const char **));
57d0c830 59static symbolS * create_label PARAMS ((const char *, const char *));
b6d331b9 60static symbolS * create_colon_label PARAMS ((int, const char *, const char *));
57d0c830 61static char * unique_name PARAMS ((const char *));
5dccb8b0
DE
62static char * vuoverlay_section_name PARAMS ((symbolS *));
63static void create_vuoverlay_section PARAMS ((const char *, symbolS *,
1554baf3 64 symbolS *, symbolS *));
07b20428 65static symbolS * compute_mpgloc PARAMS ((symbolS *, symbolS *, symbolS *));
fa3671a3
DE
66static int compute_nloop PARAMS ((gif_type, int, int));
67static void check_nloop PARAMS ((gif_type, int, int, int,
68 char *, unsigned int));
07b20428 69static long eval_expr PARAMS ((dvp_cpu, int, int, const char *, ...));
1ece1d56 70static long parse_dma_addr_autocount ();
8151801a 71static void inline_dma_data PARAMS ((int, DVP_INSN *));
e9cb12e4 72static void setup_dma_autocount PARAMS ((const char *, DVP_INSN *, int));
8dddf63f 73
6856244d
DE
74static void insert_operand
75 PARAMS ((dvp_cpu, const dvp_opcode *, const dvp_operand *, int,
76 DVP_INSN *, offsetT, const char **));
77static void insert_operand_final
78 PARAMS ((dvp_cpu, const dvp_operand *, int,
79 DVP_INSN *, offsetT, char *, unsigned int));
020ba60b 80
8b901ef8
DE
81static void insert_mpg_marker PARAMS ((unsigned long));
82static void insert_unpack_marker PARAMS ((unsigned long));
83static int insert_file PARAMS ((const char *,
84 void (*) PARAMS ((unsigned long)),
85 unsigned long, int));
e033023f 86
a6756468
DE
87static int vif_insn_type PARAMS ((char));
88static int vif_length_value PARAMS ((char, int, int, int));
b4cbabb8 89static void install_vif_length PARAMS ((char *, int));
e033023f 90
209fb346
DE
91const char comment_chars[] = ";";
92const char line_comment_chars[] = "#";
93const char line_separator_chars[] = "!";
94const char EXP_CHARS[] = "eE";
95const char FLT_CHARS[] = "dD";
8b901ef8 96\f
e033023f
DE
97/* Current assembler state.
98 Instructions like mpg and direct are followed by a restricted set of
fe9efeb6
DE
99 instructions. In the case of a '*' length argument an end marker must
100 be provided. (e.g. mpg is followed by vu insns until a .EndMpg is
498fcb9c
DE
101 seen).
102
103 Allowed state transitions:
c94a25c2
DE
104 ASM_INIT <--> ASM_MPG
105 ASM_DIRECT <--> ASM_GIF
e4d77412 106 ASM_UNPACK <--> ASM_GIF
c94a25c2 107 ASM_VU
e4d77412 108 ASM_GIF
c94a25c2
DE
109
110 FIXME: Make the ASM_INIT -> ASM_VU a one way transition.
111 ".vu" must be seen at the top of the file,
112 and cannot be switched out of.
498fcb9c
DE
113*/
114
e1b747c4 115typedef enum {
e4d77412 116 ASM_INIT, ASM_DIRECT, ASM_MPG, ASM_UNPACK, ASM_VU, ASM_GIF, ASM_MAX
e1b747c4 117} asm_state;
498fcb9c
DE
118
119/* We need to maintain a stack of the current and previous status to handle
120 such things as "direct ...; gifpacked ... ; .endgif ; .enddirect". */
121#define MAX_STATE_DEPTH 2
122static asm_state asm_state_stack[MAX_STATE_DEPTH];
123/* Current state's index in the stack. */
e4d77412 124static int cur_state_level;
498fcb9c 125/* Macro to fetch the current state. */
e4d77412 126#define CUR_ASM_STATE (asm_state_stack[cur_state_level])
498fcb9c
DE
127
128/* Functions to push/pop the state stack. */
129static void push_asm_state PARAMS ((asm_state));
130static void pop_asm_state PARAMS ((int));
e4d77412 131static void set_asm_state PARAMS ((asm_state, const char *));
07b20428
DE
132
133/* Set to non-zero if any non-vu insn seen.
134 Used to control type of relocations emitted. */
135static int non_vu_insn_seen_p = 0;
8b901ef8 136\f
b6d331b9 137/* Current cpu (machine variant) type state.
57d0c830
DE
138 We copy the mips16 way of recording what the current machine type is in
139 the code. A label is created whenever necessary and has an "other" value
140 the denotes the machine type. */
b6d331b9 141static dvp_cpu cur_cpu;
57d0c830 142/* Record the current mach type. */
b6d331b9 143static void record_mach PARAMS ((dvp_cpu, int));
3b4389e2
DE
144/* Force emission of mach type label at next insn.
145 This isn't static as TC_START_LABEL uses it. */
146int force_mach_label PARAMS ((void));
b6d331b9
DE
147/* Given a dvp_cpu value, return the STO_DVP value to use. */
148static int cpu_sto PARAMS ((dvp_cpu, const char **));
57d0c830 149
91572941 150/* Nonzero if inside .DmaData. */
8151801a 151static int dma_data_state = 0;
91572941 152/* Label of .DmaData (internally generated for inline data). */
8151801a
DE
153static const char *dma_data_name;
154
8b901ef8
DE
155/* Variable length VIF insn support. */
156/* Label at start of insn's data. */
157static symbolS *vif_data_start;
158/* Label at end of insn's data. */
159static symbolS *vif_data_end;
160
1554baf3
DE
161/* Special symbol $.mpgloc. The value is in bytes.
162 This value is kept absolute, for simplicity. */
8b901ef8 163static symbolS *mpgloc_sym;
8b901ef8 164
c3b51879 165/* Handle of the current vu overlay section. */
1554baf3
DE
166static segT vuoverlay_section;
167
c3b51879 168/* The overlay table section is a table mapping lma's to vma's. */
1554baf3 169static segT vuoverlay_table_section;
c3b51879
DE
170/* String table to record section names in the overlay table. */
171static segT vuoverlay_string_section;
1554baf3
DE
172
173/* Table to map vu space labels to their overlay sections.
174 Labels in vu space are first put in the ABS section to simplify
175 PC relative branch calculations (s1 - s2 isn't supported if they're
176 in different sections). Before the file is written out the labels
177 are moved to their overlay section. */
178typedef struct ovlysym {
179 struct ovlysym *next;
180 segT sec;
181 symbolS *sym;
182} ovlysymS;
183static ovlysymS *ovlysym_table;
184
8b901ef8
DE
185/* GIF insn support. */
186/* Type of insn. */
187static int gif_insn_type;
188/* Name of label of insn's data. */
8151801a 189static const char *gif_data_name;
8b901ef8 190/* Pointer to frag of insn. */
fa3671a3
DE
191static fragS *gif_insn_frag;
192/* Pointer to current gif insn in gif_insn_frag. */
193static char *gif_insn_frag_loc;
fe9efeb6 194/* The length value specified in the insn, or -1 if '*'. */
8b901ef8 195static int gif_user_value;
b5d20cf6 196
83920d29
DE
197/* Count of vu insns seen since the last mpg.
198 Set to -1 to disable automatic mpg insertion. */
199static int vu_count;
200
b4cbabb8
DE
201/* Non-zero if packing vif instructions in dma tags. */
202static int dma_pack_vif_p;
fe9efeb6
DE
203
204/* Non-zero if dma insns are to be included in the output.
205 This is the default, but writing "if (! no_dma)" is klunky. */
08847198 206static int output_dma = 1;
b4cbabb8
DE
207/* Non-zero if vif insns are to be included in the output. */
208static int output_vif = 1;
8b901ef8
DE
209
210/* Current opcode/operand for use by md_operand. */
211static const dvp_opcode *cur_opcode;
212static const dvp_operand *cur_operand;
213
214/* Options for the `caller' argument to s_endmpg. */
215typedef enum { ENDMPG_USER, ENDMPG_INTERNAL, ENDMPG_MIDDLE } endmpg_caller;
07b20428
DE
216
217/* Relaxation support. */
218#define RELAX_MPG 1
219#define RELAX_DIRECT 2
220/* vu insns aren't relaxed, but they use machine dependent frags so we
221 must handle them during relaxation */
222#define RELAX_VU 3
223#define RELAX_ENCODE(type, growth) (10 + (growth))
224#define RELAX_GROWTH(state) ((state) - 10)
225/* Return non-zero if STATE represents a relaxed state. */
226#define RELAX_DONE_P(state) ((state) >= 10)
209fb346
DE
227\f
228const char *md_shortopts = "";
229
230struct option md_longopts[] =
231{
fe9efeb6
DE
232#define OPTION_NO_DMA (OPTION_MD_BASE + 1)
233 { "no-dma", no_argument, NULL, OPTION_NO_DMA },
b4cbabb8
DE
234#define OPTION_NO_DMA_VIF (OPTION_NO_DMA + 1)
235 { "no-dma-vif", no_argument, NULL, OPTION_NO_DMA_VIF },
209fb346
DE
236
237 {NULL, no_argument, NULL, 0}
238};
fe9efeb6 239size_t md_longopts_size = sizeof(md_longopts);
209fb346
DE
240
241int
242md_parse_option (c, arg)
243 int c;
244 char *arg;
245{
fe9efeb6
DE
246 switch (c)
247 {
248 case OPTION_NO_DMA :
249 output_dma = 0;
250 break;
b4cbabb8 251 case OPTION_NO_DMA_VIF :
fe9efeb6 252 output_dma = 0;
b4cbabb8 253 output_vif = 0;
fe9efeb6
DE
254 break;
255 default :
256 return 0;
257 }
258 return 1;
209fb346
DE
259}
260
261void
262md_show_usage (stream)
263 FILE *stream;
264{
fe9efeb6
DE
265 fprintf (stream, "\
266DVP options:\n\
267-no-dma do not include DMA instructions in the output\n\
b4cbabb8 268-no-dma-vif do not include DMA or VIF instructions in the output\n\
fe9efeb6 269");
209fb346
DE
270}
271
b5d20cf6 272static void s_dmadata PARAMS ((int));
3b2215c2 273static void s_enddmadata PARAMS ((int));
b4cbabb8 274static void s_dmapackvif PARAMS ((int));
b5d20cf6 275static void s_enddirect PARAMS ((int));
b5d20cf6
DE
276static void s_endmpg PARAMS ((int));
277static void s_endunpack PARAMS ((int));
498fcb9c 278static void s_endgif PARAMS ((int));
e4d77412 279static void s_vu PARAMS ((int));
30596dfc 280static void s_dvp_func PARAMS ((int));
b5d20cf6 281
209fb346
DE
282/* The target specific pseudo-ops which we support. */
283const pseudo_typeS md_pseudo_table[] =
284{
1ece1d56 285 { "word", cons, 4 },
fa3671a3 286 { "quad", cons, 16 },
1ece1d56
DE
287 { "dmadata", s_dmadata, 0 },
288 { "dmapackvif", s_dmapackvif, 0 },
289 { "enddirect", s_enddirect, 0 },
290 { "enddmadata", s_enddmadata, 0 },
8b901ef8 291 { "endmpg", s_endmpg, ENDMPG_USER },
1ece1d56 292 { "endunpack", s_endunpack, 0 },
498fcb9c 293 { "endgif", s_endgif, 0 },
e4d77412 294 { "vu", s_vu, 0 },
30596dfc
DE
295 /* We need to intercept .func/.endfunc so that we can prepend _$.
296 ??? Not sure this is right though as _$foo is the lma version. */
297 { "func", s_dvp_func, 0 },
298 { "endfunc", s_dvp_func, 1 },
1ece1d56 299 { NULL, NULL, 0 }
209fb346
DE
300};
301\f
302void
303md_begin ()
304{
f6428b86
DE
305 /* Initialize the opcode tables.
306 This involves computing the hash chains. */
276dd6ef 307 dvp_opcode_init_tables (0);
b5d20cf6 308
3b4389e2
DE
309 /* Force a mach type label for the first insn. */
310 force_mach_label ();
57d0c830
DE
311
312 /* Initialize the parsing state. */
e4d77412 313 set_asm_state (ASM_INIT, NULL);
57d0c830 314
7f28a81d
DE
315 /* Pack vif insns in dma tags by default. */
316 dma_pack_vif_p = 1;
83920d29
DE
317
318 /* Disable automatic mpg insertion. */
319 vu_count = -1;
8b901ef8 320
1554baf3 321 /* Initialize $.mpgloc. */
8b901ef8 322 mpgloc_sym = expr_build_uconstant (0);
cb74aaa5 323
1554baf3
DE
324 /* Create the vu overlay table section. */
325 {
326 /* Must preserve the current seg/subseg. It is the initial one. */
327 segT orig_seg = now_seg;
328 subsegT orig_subseg = now_subseg;
c3b51879
DE
329
330 vuoverlay_table_section = subseg_new (SHNAME_DVP_OVERLAY_TABLE, 0);
7f7d7bc0 331 record_alignment (now_seg, 2);
c3b51879
DE
332 vuoverlay_string_section = subseg_new (SHNAME_DVP_OVERLAY_STRTAB, 0);
333 /* Ensure first byte in executable is zero. So what if we waste
334 a few bytes. */
335 FRAG_APPEND_1_CHAR (0);
336
1554baf3
DE
337 subseg_set (orig_seg, orig_subseg);
338 }
339
cb74aaa5
DE
340 /* Set the type of the output file to r5900. */
341 bfd_set_arch_mach (stdoutput, bfd_arch_mips, 5900);
209fb346 342}
f7306261 343\f
f6428b86
DE
344/* We need to keep a list of fixups. We can't simply generate them as
345 we go, because that would require us to first create the frag, and
346 that would screw up references to ``.''. */
347
276dd6ef 348struct dvp_fixup
f6428b86 349{
07b20428
DE
350 /* the cpu this fixup is associated with */
351 dvp_cpu cpu;
276dd6ef 352 /* index into `dvp_operands' */
f6428b86 353 int opindex;
e033023f
DE
354 /* byte offset from beginning of instruction */
355 int offset;
8b901ef8
DE
356 /* user specified value [when there is one] */
357 int user_value;
358 /* wl,cl values, only used with unpack insn */
359 short wl,cl;
360 /* the expression */
f6428b86
DE
361 expressionS exp;
362};
363
364#define MAX_FIXUPS 5
365
f7306261 366static int fixup_count;
276dd6ef 367static struct dvp_fixup fixups[MAX_FIXUPS];
f7306261 368
95bfad6d
DE
369/* Given a cpu type and operand number, return a temporary reloc type
370 for use in generating the fixup that encodes the cpu type and operand. */
3a6b8910 371static int encode_fixup_reloc_type PARAMS ((dvp_cpu, int));
95bfad6d 372/* Given an encoded fixup reloc type, decode it into cpu and operand. */
3a6b8910 373static void decode_fixup_reloc_type PARAMS ((int, dvp_cpu *,
276dd6ef 374 const dvp_operand **));
95bfad6d 375
b5d20cf6 376static void assemble_dma PARAMS ((char *));
b4cbabb8
DE
377static void assemble_gif PARAMS ((char *));
378static void assemble_vif PARAMS ((char *));
b5d20cf6 379static void assemble_vu PARAMS ((char *));
3a6b8910
DE
380static const dvp_opcode * assemble_vu_insn PARAMS ((dvp_cpu,
381 const dvp_opcode *,
382 const dvp_operand *,
383 char **, char *));
384static const dvp_opcode * assemble_one_insn PARAMS ((dvp_cpu,
385 const dvp_opcode *,
386 const dvp_operand *,
07b20428 387 int, int,
3a6b8910
DE
388 char **, DVP_INSN *));
389
390/* Main entry point for assembling an instruction. */
f6428b86 391
209fb346
DE
392void
393md_assemble (str)
394 char *str;
b5d20cf6 395{
f7306261
DE
396 /* Skip leading white space. */
397 while (isspace (*str))
398 str++;
399
8151801a 400 /* After a gif tag, no insns can appear until a .endgif is seen. */
498fcb9c 401 if (CUR_ASM_STATE == ASM_GIF)
8151801a
DE
402 {
403 as_bad ("missing .endgif");
498fcb9c 404 pop_asm_state (1);
e4d77412 405 /* We still parse the instruction. */
498fcb9c 406 }
8151801a 407
498fcb9c 408 if (CUR_ASM_STATE == ASM_INIT)
b5d20cf6
DE
409 {
410 if (strncasecmp (str, "dma", 3) == 0)
411 assemble_dma (str);
1ece1d56 412 else if (strncasecmp (str, "gif", 3) == 0)
19f12fb4 413 assemble_gif (str);
b5d20cf6 414 else
b4cbabb8 415 assemble_vif (str);
07b20428 416 non_vu_insn_seen_p = 1;
b5d20cf6 417 }
e4d77412
FCE
418 else if (CUR_ASM_STATE == ASM_DIRECT
419 || CUR_ASM_STATE == ASM_UNPACK)
07b20428
DE
420 {
421 assemble_gif (str);
422 non_vu_insn_seen_p = 1;
423 }
498fcb9c
DE
424 else if (CUR_ASM_STATE == ASM_VU
425 || CUR_ASM_STATE == ASM_MPG)
b5d20cf6 426 assemble_vu (str);
e033023f 427 else
8b901ef8 428 as_fatal ("internal error: unknown parse state");
b5d20cf6
DE
429}
430
f7306261 431/* Subroutine of md_assemble to assemble DMA instructions. */
b5d20cf6
DE
432
433static void
434assemble_dma (str)
435 char *str;
436{
7f28a81d 437 DVP_INSN insn_buf[2];
1ece1d56
DE
438 /* Insn's length, in 32 bit words. */
439 int len;
440 /* Pointer to allocated frag. */
441 char *f;
442 int i;
443 const dvp_opcode *opcode;
444
e9cb12e4
DE
445 if (output_dma)
446 {
447 /* Do an implicit alignment to a 16 byte boundary.
448 Do it now so that inline dma data labels are at the right place. */
8b901ef8
DE
449 /* ??? One can certainly argue all this implicit alignment is
450 questionable. The thing is assembler programming is all that will
451 mostly likely ever be done and not doing so forces an extra [and
452 arguably unnecessary] burden on the programmer. */
e9cb12e4
DE
453 frag_align (4, 0, 0);
454 record_alignment (now_seg, 4);
455 }
456
457 /* This is the DMA tag. */
1ece1d56
DE
458 insn_buf[0] = 0;
459 insn_buf[1] = 0;
1ece1d56
DE
460
461 opcode = assemble_one_insn (DVP_DMA,
462 dma_opcode_lookup_asm (str), dma_operands,
07b20428 463 0, 0, &str, insn_buf);
1ece1d56
DE
464 if (opcode == NULL)
465 return;
466 if (!output_dma)
467 return;
468
b6d331b9 469 record_mach (DVP_DMA, 0);
57d0c830 470
7f28a81d 471 f = frag_more (8);
1ece1d56
DE
472
473 /* Write out the DMA instruction. */
7f28a81d 474 for (i = 0; i < 2; ++i)
1ece1d56 475 md_number_to_chars (f + i * 4, insn_buf[i], 4);
f7306261 476
1ece1d56
DE
477 /* Create any fixups. */
478 /* FIXME: It might eventually be possible to combine all the various
479 copies of this bit of code. */
480 for (i = 0; i < fixup_count; ++i)
3b2215c2 481 {
1ece1d56
DE
482 int op_type, reloc_type, offset;
483 const dvp_operand *operand;
3b2215c2 484
1ece1d56
DE
485 /* Create a fixup for this operand.
486 At this point we do not use a bfd_reloc_code_real_type for
487 operands residing in the insn, but instead just use the
488 operand index. This lets us easily handle fixups for any
489 operand type, although that is admittedly not a very exciting
490 feature. We pick a BFD reloc type in md_apply_fix. */
491
492 op_type = fixups[i].opindex;
493 offset = fixups[i].offset;
494 reloc_type = encode_fixup_reloc_type (DVP_DMA, op_type);
495 operand = &dma_operands[op_type];
496 fix_new_exp (frag_now, f + offset - frag_now->fr_literal, 4,
497 &fixups[i].exp,
498 (operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0,
499 (bfd_reloc_code_real_type) reloc_type);
3b2215c2 500 }
7f28a81d
DE
501
502 /* The upper two words are vif insns. */
503 record_mach (DVP_VIF, 0);
504
505 /* If not doing dma/vif packing, fill out the insn with vif nops.
506 ??? We take advantage of the fact that the default fill value of zero
507 is the vifnop insn. This occurs for example when handling mpg
508 alignment. It also occurs when one dma tag immediately follows the
509 previous one. */
510 if (! dma_pack_vif_p)
511 {
512 f = frag_more (8);
7f28a81d
DE
513 md_number_to_chars (f + 0, VIFNOP, 4);
514 md_number_to_chars (f + 4, VIFNOP, 4);
515 }
b5d20cf6
DE
516}
517
b4cbabb8 518/* Subroutine of md_assemble to assemble VIF instructions. */
b5d20cf6
DE
519
520static void
b4cbabb8 521assemble_vif (str)
b5d20cf6
DE
522 char *str;
523{
95bfad6d
DE
524 /* Space for the instruction.
525 The variable length insns can require much more space than this.
526 It is allocated later, when we know we have such an insn. */
276dd6ef 527 DVP_INSN insn_buf[5];
95bfad6d
DE
528 /* Insn's length, in 32 bit words. */
529 int len;
95bfad6d
DE
530 /* Pointer to allocated frag. */
531 char *f;
8b901ef8 532 int i,wl,cl;
3a6b8910 533 const dvp_opcode *opcode;
8b901ef8
DE
534 fragS * insn_frag;
535 /* Name of file to read data from. */
536 const char *file;
537 /* Length in 32 bit words. */
538 int data_len;
b25ce8e1
DE
539 /* Macro expansion, if there is one. */
540 char * macstr;
541
542 /* First check for macros. */
543 macstr = dvp_expand_macro (vif_macros, vif_macro_count, str);
544 if (macstr)
545 {
546 /* The macro may expand into several insns (delimited with '\n'),
547 so loop. */
548 char * next = macstr;
549 do
550 {
551 char *p = strchr (next, '\n');
552 if (p)
553 *p = 0;
554 assemble_vif (next);
555 next = p ? p + 1 : 0;
556 }
557 while (next);
558 free (macstr);
559 return;
560 }
95bfad6d 561
b4cbabb8
DE
562 opcode = assemble_one_insn (DVP_VIF,
563 vif_opcode_lookup_asm (str), vif_operands,
07b20428 564 0, 0, &str, insn_buf);
3a6b8910 565 if (opcode == NULL)
95bfad6d
DE
566 return;
567
b4cbabb8 568 if (opcode->flags & VIF_OPCODE_LENVAR)
e033023f 569 len = 1; /* actual data follows later */
b4cbabb8 570 else if (opcode->flags & VIF_OPCODE_LEN2)
3a6b8910 571 len = 2;
b4cbabb8 572 else if (opcode->flags & VIF_OPCODE_LEN5)
3a6b8910 573 len = 5;
95bfad6d 574 else
3a6b8910
DE
575 len = 1;
576
fe9efeb6 577 /* We still have to switch modes (if mpg for example) so we can't exit
b4cbabb8 578 early if -no-vif. */
8b901ef8 579
b4cbabb8 580 if (output_vif)
95bfad6d 581 {
83920d29 582 /* Record the mach before doing the alignment so that we properly
8b901ef8
DE
583 disassemble any inserted vifnop's. For mpg and direct insns
584 force the recording of the mach type for the next insn. The data
585 will switch the mach type and we want to ensure it's switched
586 back. */
83920d29 587
8b901ef8 588 if (opcode->flags & (VIF_OPCODE_MPG | VIF_OPCODE_DIRECT))
b6d331b9
DE
589 record_mach (DVP_VIF, 1);
590 else
591 record_mach (DVP_VIF, 0);
57d0c830 592
8b901ef8
DE
593 /* For variable length instructions record a fixup that is the symbol
594 marking the end of the data. eval_expr will queue the fixup
595 which will then be emitted later. */
596 if (opcode->flags & VIF_OPCODE_LENVAR)
597 {
598 char *name;
599
600 asprintf (&name, "%s%s", LOCAL_LABEL_PREFIX,
601 unique_name ("varlen"));
602 vif_data_end = symbol_new (name, now_seg, 0, 0);
603 symbol_table_insert (vif_data_end);
07b20428 604 fixups[fixup_count].cpu = DVP_VIF;
8b901ef8
DE
605 fixups[fixup_count].exp.X_op = O_symbol;
606 fixups[fixup_count].exp.X_add_symbol = vif_data_end;
607 fixups[fixup_count].exp.X_add_number = 0;
608 fixups[fixup_count].opindex = vif_operand_datalen_special;
609 fixups[fixup_count].offset = 0;
610
611 /* See what the user specified. */
612 vif_get_var_data (&file, &data_len);
613 if (file)
614 data_len = -1;
615 fixups[fixup_count].user_value = data_len;
616 /* Get the wl,cl values. Only useful for the unpack insn but
617 it doesn't hurt to always record them. */
618 vif_get_wl_cl (&wl, &cl);
619 fixups[fixup_count].wl = wl;
620 fixups[fixup_count].cl = cl;
621 ++fixup_count;
622 }
623
624 /* Obtain space in which to store the instruction. */
625
83920d29
DE
626 if (opcode->flags & VIF_OPCODE_MPG)
627 {
8b901ef8
DE
628 /* The data must be aligned on a 64 bit boundary (so the mpg insn
629 comes just before that 64 bit boundary).
630 Do this by putting the mpg insn in a relaxable fragment
631 with a symbol that marks the beginning of the aligned data. */
632
050ac694 633 /* Ensure relaxable fragments are in their own fragment.
79cb0c8a 634 Otherwise md_apply_fix3 mishandles fixups to insns earlier
a9589a2c 635 in the fragment (because we set fr_opcode for the `mpg' insn
79cb0c8a 636 because it can move in the fragment). */
050ac694
DE
637 frag_wane (frag_now);
638 frag_new (0);
639
07b20428
DE
640 /* One could combine the previous two lines with the following.
641 They're not for clarity: keep separate the actions being
642 performed. */
643
644 /* This dance with frag_grow is so we can record frag_now in
645 insn_frag. frag_var always changes frag_now. We must allocate
646 the maximal amount of space we need so there's room to move
647 the insn in the frag during relaxation. */
8b901ef8
DE
648 frag_grow (8);
649 /* Allocate space for the fixed part. */
650 f = frag_more (4);
651 insn_frag = frag_now;
652
653 frag_var (rs_machine_dependent,
654 4, /* max chars */
07b20428
DE
655 0, /* variable part is empty at present */
656 RELAX_MPG, /* subtype */
8b901ef8
DE
657 NULL, /* no symbol */
658 0, /* offset */
659 f); /* opcode */
660
83920d29
DE
661 frag_align (3, 0, 0);
662 record_alignment (now_seg, 3);
8b901ef8
DE
663
664 /* Put a symbol at the start of data. The relaxation code uses
665 this to figure out how many bytes to insert. $.mpgloc
1554baf3 666 calculations use it. The disassembler uses it. The overlay
c371a664
DE
667 tracking table uses it.
668 Update $.mpgloc.
669 Create an overlay section. */
8b901ef8
DE
670 {
671 int mpgloc = vif_get_mpgloc ();
c371a664
DE
672 const char * section_name;
673
5dccb8b0
DE
674 /* Update $.mpgloc if explicitly set.
675 Otherwise just use the current value. */
c371a664
DE
676 if (mpgloc != -1)
677 {
678 /* The value is recorded in bytes, mpgloc is in dwords. */
679 mpgloc_sym = expr_build_uconstant (mpgloc * 8);
680 }
c371a664 681
5dccb8b0 682 section_name = vuoverlay_section_name (mpgloc_sym);
1554baf3
DE
683 vif_data_start = create_colon_label (STO_DVP_VU,
684 VUOVERLAY_START_PREFIX,
685 section_name);
686 insn_frag->fr_symbol = vif_data_start;
687
5dccb8b0 688 create_vuoverlay_section (section_name, mpgloc_sym,
c371a664 689 vif_data_start, vif_data_end);
8b901ef8 690 }
83920d29
DE
691 }
692 else if (opcode->flags & VIF_OPCODE_DIRECT)
693 {
8b901ef8
DE
694 /* The data must be aligned on a 128 bit boundary (so the direct insn
695 comes just before that 128 bit boundary).
696 Do this by putting the direct insn in a relaxable fragment.
697 with a symbol that marks the beginning of the aligned data. */
698
050ac694 699 /* Ensure relaxable fragments are in their own fragment.
79cb0c8a
DE
700 Otherwise md_apply_fix3 mishandles fixups to insns earlier
701 in the fragment (because we set fr_opcode for the `direct' insn
702 because it can move in the fragment). */
050ac694
DE
703 frag_wane (frag_now);
704 frag_new (0);
705
07b20428
DE
706 /* One could combine the previous two lines with the following.
707 They're not for clarity: keep separate the actions being
708 performed. */
709
710 /* This dance with frag_grow is so we can record frag_now in
711 insn_frag. frag_var always changes frag_now. We must allocate
712 the maximal amount of space we need so there's room to move
713 the insn in the frag during relaxation. */
8b901ef8
DE
714 frag_grow (16);
715 /* Allocate space for the fixed part. */
716 f = frag_more (4);
717 insn_frag = frag_now;
718
719 frag_var (rs_machine_dependent,
720 12, /* max chars */
07b20428
DE
721 0, /* variable part is empty at present */
722 RELAX_DIRECT, /* subtype */
8b901ef8
DE
723 NULL, /* no symbol */
724 0, /* offset */
725 f); /* opcode */
726
83920d29
DE
727 frag_align (4, 0, 0);
728 record_alignment (now_seg, 4);
83920d29 729
8b901ef8
DE
730 /* Put a symbol at the start of data. The relaxation code uses
731 this to figure out how many bytes to insert. */
732 vif_data_start = create_colon_label (0, LOCAL_LABEL_PREFIX,
733 unique_name ("direct"));
734 insn_frag->fr_symbol = vif_data_start;
735 }
736 else if (opcode->flags & VIF_OPCODE_UNPACK)
737 {
738 f = frag_more (len * 4);
739 insn_frag = frag_now;
740 /* Put a symbol at the start of data. $.unpackloc calculations
741 use it. */
40f3c6f8
DE
742 /* ??? $.unpackloc is gone. Is this also used for data length
743 verification? */
8b901ef8
DE
744 vif_data_start = create_colon_label (STO_DVP_VIF, LOCAL_LABEL_PREFIX,
745 unique_name ("unpack"));
8b901ef8
DE
746 }
747 else
748 {
749 /* Reminder: it is important to fetch enough space in one call to
750 `frag_more'. We use (f - frag_now->fr_literal) to compute where
751 we are and we don't want frag_now to change between calls. */
752 f = frag_more (len * 4);
753 insn_frag = frag_now;
754 }
fe9efeb6
DE
755
756 /* Write out the instruction. */
757 for (i = 0; i < len; ++i)
758 md_number_to_chars (f + i * 4, insn_buf[i], 4);
759
760 /* Create any fixups. */
761 /* FIXME: It might eventually be possible to combine all the various
762 copies of this bit of code. */
763 for (i = 0; i < fixup_count; ++i)
764 {
765 int op_type, reloc_type, offset;
766 const dvp_operand *operand;
8b901ef8 767 fixS *fixP;
f7306261 768
fe9efeb6
DE
769 /* Create a fixup for this operand.
770 At this point we do not use a bfd_reloc_code_real_type for
771 operands residing in the insn, but instead just use the
772 operand index. This lets us easily handle fixups for any
773 operand type, although that is admittedly not a very exciting
774 feature. We pick a BFD reloc type in md_apply_fix. */
775
776 op_type = fixups[i].opindex;
777 offset = fixups[i].offset;
b4cbabb8
DE
778 reloc_type = encode_fixup_reloc_type (DVP_VIF, op_type);
779 operand = &vif_operands[op_type];
8b901ef8
DE
780 fixP = fix_new_exp (insn_frag, f + offset - insn_frag->fr_literal, 4,
781 &fixups[i].exp,
782 (operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0,
783 (bfd_reloc_code_real_type) reloc_type);
784 fixP->tc_fix_data.user_value = fixups[i].user_value;
785 fixP->tc_fix_data.wl = fixups[i].wl;
786 fixP->tc_fix_data.cl = fixups[i].cl;
787
788 /* Set fx_tcbit so other parts of the code know this fixup is for
789 a vif insn. */
790 fixP->fx_tcbit = 1;
fe9efeb6 791 }
95bfad6d 792 }
e033023f 793
e1b747c4
DE
794 /* Handle variable length insns. */
795
b4cbabb8 796 if (opcode->flags & VIF_OPCODE_LENVAR)
e033023f 797 {
8b901ef8 798 /* See what the user specified. */
b4cbabb8 799 vif_get_var_data (&file, &data_len);
ba4be194 800
e033023f
DE
801 if (file)
802 {
1fb06680
DE
803 int byte_len;
804
ba4be194
DE
805 /* The handling for each of mpg,direct,unpack is basically the same:
806 - emit a label to set the mach type for the data we're inserting
807 - switch to the new assembler state
808 - insert the file
809 - call the `end' handler */
810
1fb06680 811 if (opcode->flags & VIF_OPCODE_MPG)
ba4be194
DE
812 {
813 record_mach (DVP_VUUP, 1);
e4d77412 814 set_asm_state (ASM_MPG, "mpg");
8b901ef8
DE
815 byte_len = insert_file (file, insert_mpg_marker, 0, 256 * 8);
816 s_endmpg (ENDMPG_INTERNAL);
ba4be194 817 }
1fb06680 818 else if (opcode->flags & VIF_OPCODE_DIRECT)
ba4be194
DE
819 {
820 record_mach (DVP_GIF, 1);
e4d77412 821 set_asm_state (ASM_DIRECT, "direct");
8b901ef8 822 byte_len = insert_file (file, NULL, 0, 0);
ba4be194
DE
823 s_enddirect (1);
824 }
1fb06680 825 else if (opcode->flags & VIF_OPCODE_UNPACK)
1fb06680 826 {
8b901ef8 827 int max_len = 0; /*unpack_max_byte_len (insn_buf[0]);*/
e4d77412 828 set_asm_state (ASM_UNPACK, "unpack");
8b901ef8
DE
829 byte_len = insert_file (file, NULL /*insert_unpack_marker*/,
830 insn_buf[0], max_len);
ba4be194 831 s_endunpack (1);
1fb06680 832 }
ba4be194 833 else
8b901ef8 834 as_fatal ("internal error: unknown cpu type for variable length vif insn");
e033023f 835 }
8b901ef8 836 else /* file == NULL */
e033023f
DE
837 {
838 /* data_len == -1 means the value must be computed from
839 the data. */
a9589a2c 840 if (data_len <= -2)
e033023f 841 as_bad ("invalid data length");
ba4be194 842
8b901ef8
DE
843 if (output_vif && data_len != -1)
844 install_vif_length (f, data_len);
845
b4cbabb8 846 if (opcode->flags & VIF_OPCODE_MPG)
83920d29 847 {
e4d77412 848 set_asm_state (ASM_MPG, "mpg");
83920d29
DE
849 /* Enable automatic mpg insertion every 256 insns. */
850 vu_count = 0;
851 }
b4cbabb8 852 else if (opcode->flags & VIF_OPCODE_DIRECT)
e4d77412 853 set_asm_state (ASM_DIRECT, "direct");
b4cbabb8 854 else if (opcode->flags & VIF_OPCODE_UNPACK)
e4d77412 855 set_asm_state (ASM_UNPACK, "unpack");
e033023f
DE
856 }
857 }
b5d20cf6
DE
858}
859
e4d77412
FCE
860/* Subroutine of md_assemble to assemble GIF instructions.
861 We assume CUR_ASM_STATE is one of ASM_{INIT,DIRECT,UNPACK}. */
b5d20cf6
DE
862
863static void
b4cbabb8 864assemble_gif (str)
b5d20cf6
DE
865 char *str;
866{
276dd6ef 867 DVP_INSN insn_buf[4];
3a6b8910 868 const dvp_opcode *opcode;
8151801a
DE
869 char *f;
870 int i;
871
872 insn_buf[0] = insn_buf[1] = insn_buf[2] = insn_buf[3] = 0;
f7306261 873
b4cbabb8
DE
874 opcode = assemble_one_insn (DVP_GIF,
875 gif_opcode_lookup_asm (str), gif_operands,
07b20428 876 0, 0, &str, insn_buf);
3a6b8910 877 if (opcode == NULL)
95bfad6d 878 return;
8151801a
DE
879
880 /* Do an implicit alignment to a 16 byte boundary. */
881 frag_align (4, 0, 0);
882 record_alignment (now_seg, 4);
883
9152beba
DE
884 /* Insert a label so we can compute the number of quadwords when the
885 .endgif is seen. This is put before the mach type label because gif
886 insns are followed by data and we don't want the disassembler to try
887 to disassemble them as mips insns (since it uses the st_other field)
888 of the closest label to choose the mach type and since we don't have
889 a special st_other value for "data". */
8b901ef8
DE
890 gif_data_name = S_GET_NAME (create_colon_label (0, LOCAL_LABEL_PREFIX,
891 unique_name ("gifdata")));
9152beba 892
b6d331b9 893 record_mach (DVP_GIF, 1);
57d0c830 894
fa3671a3
DE
895 gif_insn_frag_loc = f = frag_more (16);
896 gif_insn_frag = frag_now;
8151801a
DE
897 for (i = 0; i < 4; ++i)
898 md_number_to_chars (f + i * 4, insn_buf[i], 4);
899
8151801a
DE
900 /* Record the type of the gif tag so we know how to compute nloop
901 in s_endgif. */
902 if (strcmp (opcode->mnemonic, "gifpacked") == 0)
903 gif_insn_type = GIF_PACKED;
904 else if (strcmp (opcode->mnemonic, "gifreglist") == 0)
905 gif_insn_type = GIF_REGLIST;
906 else if (strcmp (opcode->mnemonic, "gifimage") == 0)
907 gif_insn_type = GIF_IMAGE;
908 else
909 abort ();
498fcb9c 910 push_asm_state (ASM_GIF);
b5d20cf6
DE
911}
912
913/* Subroutine of md_assemble to assemble VU instructions. */
914
915static void
916assemble_vu (str)
917 char *str;
209fb346 918{
07b20428 919 int i;
57d0c830
DE
920 char *f;
921 const dvp_opcode *opcode;
07b20428
DE
922 /* The lower instruction has the lower address so insns[0] = lower insn,
923 insns[1] = upper insn. */
924 DVP_INSN insns[2];
925 fragS * insn_frag;
57d0c830 926
83920d29
DE
927 /* Handle automatic mpg insertion if enabled. */
928 if (CUR_ASM_STATE == ASM_MPG
929 && vu_count == 256)
8b901ef8 930 insert_mpg_marker (0);
83920d29
DE
931
932 /* Do an implicit alignment to a 8 byte boundary. */
933 frag_align (3, 0, 0);
934 record_alignment (now_seg, 3);
935
b6d331b9 936 record_mach (DVP_VUUP, 0);
57d0c830 937
61e09fac 938#ifdef VERTICAL_BAR_SEPARATOR
f6428b86
DE
939 char *p = strchr (str, '|');
940
941 if (p == NULL)
942 {
8b9286ec 943 as_bad ("lower instruction missing");
f6428b86
DE
944 return;
945 }
946
947 *p = 0;
07b20428
DE
948 opcode = assemble_one_insn (DVP_VUUP,
949 vu_upper_opcode_lookup_asm (str), vu_operands,
950 0, 4, &str, &insns[1]);
f6428b86 951 *p = '|';
3a6b8910 952 str = p + 1;
61e09fac 953#else
07b20428 954 opcode = assemble_one_insn (DVP_VUUP,
3a6b8910 955 vu_upper_opcode_lookup_asm (str), vu_operands,
07b20428 956 0, 4, &str, &insns[1]);
61e09fac 957#endif
19f12fb4
DE
958
959 /* Don't assemble next one if we couldn't assemble the first. */
960 if (opcode == NULL)
961 return;
f6428b86 962
8b9286ec
DE
963 if (*str == 0)
964 {
965 as_bad ("lower instruction missing");
966 return;
967 }
968
07b20428
DE
969 /* Assemble the lower insn.
970 Pass `fixup_count' for `init_fixup_count' so that we don't clobber
971 any fixups the upper insn had. */
972 opcode = assemble_one_insn (DVP_VULO,
973 vu_lower_opcode_lookup_asm (str), vu_operands,
974 fixup_count, 0, &str, &insns[0]);
3a6b8910 975 if (opcode == NULL)
07b20428 976 return;
f6428b86 977
07b20428
DE
978 /* If there were fixups and we're inside mpg, create a machine dependent
979 fragment so that we can record the current value of $.mpgloc in fr_symbol.
f7306261
DE
980 Reminder: it is important to fetch enough space in one call to
981 `frag_more'. We use (f - frag_now->fr_literal) to compute where
982 we are and we don't want frag_now to change between calls. */
07b20428
DE
983 if (fixup_count != 0
984 && CUR_ASM_STATE == ASM_MPG)
985 {
986 symbolS * cur_mpgloc;
987
988 /* Ensure we get a new frag. */
989 frag_wane (frag_now);
990 frag_new (0);
991
992 /* Compute the current $.mpgloc. */
993 cur_mpgloc = compute_mpgloc (mpgloc_sym, vif_data_start,
994 expr_build_dot ());
995
996 /* We need to use frag_now afterwards, so we can't just call frag_var.
997 Instead we use frag_more and save the value of frag_now in
998 insn_frag. */
999 f = frag_more (8);
1000 insn_frag = frag_now;
1001 /* Turn the frag into a machine dependent frag. */
1002 frag_variant (rs_machine_dependent,
1003 0, /* max chars */
1004 0, /* no variable part */
1005 RELAX_VU, /* subtype */
1006 cur_mpgloc, /* $.mpgloc */
1007 0, /* offset */
1008 NULL); /* opcode */
1009 }
1010 else
1011 {
1012 f = frag_more (8);
1013 insn_frag = frag_now;
1014 }
1015
1016 /* Write out the instructions. */
1017 md_number_to_chars (f, insns[0], 4);
1018 md_number_to_chars (f + 4, insns[1], 4);
f6428b86 1019
f7306261
DE
1020 /* Create any fixups. */
1021 for (i = 0; i < fixup_count; ++i)
1022 {
1023 int op_type, reloc_type;
276dd6ef 1024 const dvp_operand *operand;
07b20428 1025 dvp_cpu cpu;
f7306261
DE
1026
1027 /* Create a fixup for this operand.
1028 At this point we do not use a bfd_reloc_code_real_type for
1029 operands residing in the insn, but instead just use the
1030 operand index. This lets us easily handle fixups for any
1031 operand type, although that is admittedly not a very exciting
1032 feature. We pick a BFD reloc type in md_apply_fix. */
1033
07b20428 1034 cpu = fixups[i].cpu;
f7306261 1035 op_type = fixups[i].opindex;
95bfad6d 1036 reloc_type = encode_fixup_reloc_type (cpu, op_type);
276dd6ef 1037 operand = &vu_operands[op_type];
07b20428
DE
1038
1039 /* Branch operands inside mpg have to be handled specially.
1040 We want a pc relative relocation in a section different from our own.
1041 See the br-2.s dejagnu testcase for a good example. */
1042 if (CUR_ASM_STATE == ASM_MPG
1043 && (operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0)
1044 {
1045 symbolS *e1,*e2,*diff_expr;
1046
1047 /* For "br foo" we want "foo - (. + 8)". */
1048 e1 = expr_build_binary (O_add, insn_frag->fr_symbol,
1049 expr_build_uconstant (8));
1050 e2 = make_expr_symbol (&fixups[i].exp);
1051 diff_expr = expr_build_binary (O_subtract, e2, e1);
1052 fixups[i].exp.X_op = O_symbol;
1053 fixups[i].exp.X_add_symbol = diff_expr;
1054 fixups[i].exp.X_add_number = 0;
1055 }
1056
1057 fix_new_exp (insn_frag, f + fixups[i].offset - insn_frag->fr_literal, 4,
f7306261 1058 &fixups[i].exp,
07b20428
DE
1059 CUR_ASM_STATE == ASM_MPG /* pcrel */
1060 ? 0
1061 : (operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0,
f7306261
DE
1062 (bfd_reloc_code_real_type) reloc_type);
1063 }
1064
07b20428
DE
1065 /* If this was the "loi" pseudo-insn, we need to set the `i' bit. */
1066 if (strcmp (opcode->mnemonic, "loi") == 0)
1067 f[7] |= 0x80;
1068
1069 /* Increment the vu insn counter.
1070 If get reach 256 we need to insert an `mpg'. */
1071 ++vu_count;
f7306261
DE
1072}
1073
3a6b8910 1074/* Assemble one instruction at *PSTR.
f7306261
DE
1075 CPU indicates what component we're assembling for.
1076 The assembled instruction is stored in INSN_BUF.
3a6b8910 1077 OPCODE is a pointer to the head of the hash chain.
07b20428
DE
1078 INIT_FIXUP_COUNT is the initial value for `fixup_count'.
1079 It exists to allow the fixups for multiple calls to this insn to be
1080 queued up before actually emitting them.
3a6b8910 1081 *PSTR is updated to point passed the parsed instruction.
f7306261 1082
3a6b8910
DE
1083 If the insn is successfully parsed the result is a pointer to the opcode
1084 entry that successfully matched and *PSTR is updated to point passed
1085 the parsed insn. If an error occurs the result is NULL and *PSTR is left
1086 at some random point in the string (??? may wish to leave it pointing where
1087 the error occured). */
1088
1089static const dvp_opcode *
07b20428
DE
1090assemble_one_insn (cpu, opcode, operand_table, init_fixup_count, fixup_offset,
1091 pstr, insn_buf)
3a6b8910 1092 dvp_cpu cpu;
276dd6ef
DE
1093 const dvp_opcode *opcode;
1094 const dvp_operand *operand_table;
07b20428
DE
1095 int init_fixup_count;
1096 int fixup_offset;
3a6b8910 1097 char **pstr;
276dd6ef 1098 DVP_INSN *insn_buf;
f7306261 1099{
3a6b8910 1100 char *start, *str;
f6428b86
DE
1101
1102 /* Keep looking until we find a match. */
1103
3a6b8910 1104 start = str = *pstr;
276dd6ef 1105 for ( ; opcode != NULL; opcode = DVP_OPCODE_NEXT_ASM (opcode))
f6428b86 1106 {
91572941 1107 int past_opcode_p, num_suffixes;
f6428b86 1108 const unsigned char *syn;
f6428b86
DE
1109
1110 /* Ensure the mnemonic part matches. */
1111 for (str = start, syn = opcode->mnemonic; *syn != '\0'; ++str, ++syn)
1112 if (tolower (*str) != tolower (*syn))
1113 break;
1114 if (*syn != '\0')
1115 continue;
f6428b86
DE
1116
1117 /* Scan the syntax string. If it doesn't match, try the next one. */
1118
276dd6ef 1119 dvp_opcode_init_parse ();
91572941 1120 insn_buf[opcode->opcode_word] = opcode->value;
07b20428 1121 fixup_count = init_fixup_count;
f6428b86
DE
1122 past_opcode_p = 0;
1123 num_suffixes = 0;
f6428b86
DE
1124
1125 /* We don't check for (*str != '\0') here because we want to parse
1126 any trailing fake arguments in the syntax string. */
1127 for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; )
1128 {
1129 int mods,index;
276dd6ef 1130 const dvp_operand *operand;
f6428b86 1131 const char *errmsg;
8b901ef8 1132 long value;
f6428b86 1133
fbe2ad46
DE
1134 /* Non operand chars must match exactly.
1135 Operand chars that are letters are not part of symbols
1136 and are case insensitive. */
f6428b86
DE
1137 if (*syn < 128)
1138 {
fbe2ad46 1139 if (tolower (*str) == tolower (*syn))
f6428b86
DE
1140 {
1141 if (*syn == ' ')
1142 past_opcode_p = 1;
1143 ++syn;
1144 ++str;
1145 }
1146 else
1147 break;
1148 continue;
1149 }
1150
1151 /* We have a suffix or an operand. Pick out any modifiers. */
1152 mods = 0;
276dd6ef
DE
1153 index = DVP_OPERAND_INDEX (*syn);
1154 while (DVP_MOD_P (operand_table[index].flags))
f6428b86 1155 {
276dd6ef 1156 mods |= operand_table[index].flags & DVP_MOD_BITS;
f6428b86 1157 ++syn;
276dd6ef 1158 index = DVP_OPERAND_INDEX (*syn);
f6428b86 1159 }
f7306261 1160 operand = operand_table + index;
f6428b86 1161
276dd6ef 1162 if (operand->flags & DVP_OPERAND_FAKE)
f6428b86 1163 {
a48a6f23 1164 long value = 0;
91572941
DE
1165
1166 if (operand->flags & DVP_OPERAND_DMA_INLINE)
1167 {
8151801a 1168 inline_dma_data ((mods & DVP_OPERAND_AUTOCOUNT) != 0,
91572941
DE
1169 insn_buf);
1170 ++syn;
1171 continue;
1172 }
1173
a48a6f23
DE
1174 if (operand->parse)
1175 {
1176 errmsg = NULL;
1177 value = (*operand->parse) (opcode, operand, mods,
1178 &str, &errmsg);
1179 if (errmsg)
1180 break;
1181 }
f6428b86
DE
1182 if (operand->insert)
1183 {
f62a42d0 1184 errmsg = NULL;
a48a6f23
DE
1185 (*operand->insert) (opcode, operand, mods, insn_buf,
1186 (offsetT) value, &errmsg);
f6428b86
DE
1187 /* If we get an error, go on to try the next insn. */
1188 if (errmsg)
1189 break;
1190 }
1191 ++syn;
8b901ef8 1192 continue;
f6428b86 1193 }
8b901ef8 1194
f6428b86 1195 /* Are we finished with suffixes? */
8b901ef8 1196 if (!past_opcode_p)
f6428b86 1197 {
f6428b86
DE
1198 long suf_value;
1199
276dd6ef 1200 if (!(operand->flags & DVP_OPERAND_SUFFIX))
8b901ef8 1201 as_fatal ("internal error: bad opcode table, missing suffix flag");
f6428b86 1202
1554baf3
DE
1203 /* Parse the suffix. If we're at a space in the input string
1204 there are no more suffixes. Suffix parse routines must be
1205 prepared to deal with this. */
f7306261 1206 errmsg = NULL;
19f12fb4 1207 suf_value = (*operand->parse) (opcode, operand, mods, &str,
95bfad6d 1208 &errmsg);
f6428b86
DE
1209 if (errmsg)
1210 {
fbe2ad46
DE
1211 /* This can happen, for example, in ARC's in "blle foo" and
1212 we're currently using the template "b%q%.n %j". The "bl"
1213 insn occurs later in the table so "lle" isn't an illegal
1214 suffix. */
f6428b86
DE
1215 break;
1216 }
6856244d 1217
f6428b86 1218 /* Insert the suffix's value into the insn. */
6856244d
DE
1219 insert_operand (cpu, opcode, operand, mods, insn_buf,
1220 (offsetT) suf_value, &errmsg);
f6428b86 1221
f6428b86 1222 ++syn;
8b901ef8 1223 continue;
f6428b86 1224 }
f6428b86 1225
8b901ef8
DE
1226 /* This is an operand, either a register or an expression of
1227 some kind. */
1228
1229 value = 0;
1230
1231 if (operand->flags & DVP_OPERAND_SUFFIX)
1232 as_fatal ("internal error: bad opcode table, suffix wrong");
f6428b86 1233
8b901ef8
DE
1234 /* Is there anything left to parse?
1235 We don't check for this at the top because we want to parse
1236 any trailing fake arguments in the syntax string. */
1237 /* ??? This doesn't allow operands with a legal value of "". */
1238 if (*str == '\0')
1239 break;
1240
1241 /* Parse the operand. */
1242 if (operand->flags & DVP_OPERAND_FLOAT)
1243 {
1244 errmsg = 0;
1245 value = parse_float (&str, &errmsg);
1246 if (errmsg)
f6428b86 1247 break;
8b901ef8
DE
1248 }
1249 else if ((operand->flags & DVP_OPERAND_DMA_ADDR)
1250 && (mods & DVP_OPERAND_AUTOCOUNT))
1251 {
1252 errmsg = 0;
1253 value = parse_dma_addr_autocount (opcode, operand, mods,
1254 insn_buf, &str, &errmsg);
1255 if (errmsg)
1256 break;
1257 }
1258 else
1259 {
1260 char *origstr,*hold;
1261 expressionS exp;
f6428b86 1262
8b901ef8
DE
1263 /* First see if there is a special parser. */
1264 origstr = str;
1265 if (operand->parse)
f6428b86 1266 {
f7306261 1267 errmsg = NULL;
95bfad6d
DE
1268 value = (*operand->parse) (opcode, operand, mods,
1269 &str, &errmsg);
71af45ec
DE
1270 if (errmsg)
1271 break;
f6428b86 1272 }
8b901ef8
DE
1273
1274 /* If there wasn't a special parser, or there was and it
1275 left the input stream unchanged, use the general
1276 expression parser. */
1277 if (str == origstr)
f6428b86
DE
1278 {
1279 hold = input_line_pointer;
1280 input_line_pointer = str;
8b901ef8
DE
1281 /* Set cur_{opcode,operand} for md_operand. */
1282 cur_opcode = opcode;
1283 cur_operand = operand;
f6428b86 1284 expression (&exp);
8b901ef8 1285 cur_opcode = NULL;
f6428b86
DE
1286 str = input_line_pointer;
1287 input_line_pointer = hold;
1288
71af45ec
DE
1289 if (exp.X_op == O_illegal
1290 || exp.X_op == O_absent)
1291 break;
f6428b86 1292 else if (exp.X_op == O_constant)
71af45ec 1293 value = exp.X_add_number;
f6428b86 1294 else if (exp.X_op == O_register)
8b901ef8 1295 as_fatal ("internal error: got O_register");
f6428b86
DE
1296 else
1297 {
1298 /* We need to generate a fixup for this expression. */
f7306261 1299 if (fixup_count >= MAX_FIXUPS)
8b901ef8 1300 as_fatal ("internal error: too many fixups");
07b20428 1301 fixups[fixup_count].cpu = cpu;
f7306261
DE
1302 fixups[fixup_count].exp = exp;
1303 fixups[fixup_count].opindex = index;
1ece1d56
DE
1304 /* FIXME: Revisit. Do we really need operand->word?
1305 The endianness of a 128 bit DMAtag is rather
1306 twisted. How about defining word 0 as the word with
1307 the lowest address and basing operand-shift off that.
1308 operand->word could then be deleted. */
07b20428 1309 fixups[fixup_count].offset = fixup_offset;
1ece1d56 1310 if (operand->word != 0)
07b20428 1311 fixups[fixup_count].offset += operand->word * 4;
1ece1d56 1312 else
07b20428 1313 fixups[fixup_count].offset += (operand->shift / 32) * 4;
f7306261 1314 ++fixup_count;
f6428b86
DE
1315 value = 0;
1316 }
1317 }
8b901ef8 1318 }
f6428b86 1319
8b901ef8
DE
1320 /* Insert the register or expression into the instruction. */
1321 errmsg = NULL;
1322 insert_operand (cpu, opcode, operand, mods, insn_buf,
1323 (offsetT) value, &errmsg);
1324 if (errmsg != (const char *) NULL)
1325 break;
f6428b86 1326
8b901ef8 1327 ++syn;
f6428b86
DE
1328 }
1329
1330 /* If we're at the end of the syntax string, we're done. */
f6428b86
DE
1331 if (*syn == '\0')
1332 {
1333 int i;
f6428b86
DE
1334
1335 /* For the moment we assume a valid `str' can only contain blanks
1336 now. IE: We needn't try again with a longer version of the
1337 insn and it is assumed that longer versions of insns appear
1338 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
1339
1340 while (isspace (*str))
1341 ++str;
1342
61e09fac
DE
1343 if (*str != '\0'
1344#ifndef VERTICAL_BAR_SEPARATOR
3a6b8910 1345 && cpu != DVP_VUUP
61e09fac
DE
1346#endif
1347 )
f6428b86
DE
1348 as_bad ("junk at end of line: `%s'", str);
1349
f7306261
DE
1350 /* It's now up to the caller to emit the instruction and any
1351 relocations. */
3a6b8910
DE
1352 *pstr = str;
1353 return opcode;
f6428b86
DE
1354 }
1355
1356 /* Try the next entry. */
1357 }
1358
1359 as_bad ("bad instruction `%s'", start);
61e09fac 1360 return 0;
209fb346 1361}
498fcb9c 1362\f
b6d331b9 1363/* Given a dvp cpu type, return it's STO_DVP value.
7f28a81d 1364 The label prefix to use is stored in *PNAME. */
b6d331b9
DE
1365
1366static int
1367cpu_sto (cpu, pname)
1368 dvp_cpu cpu;
1369 const char **pname;
1370{
1371 switch (cpu)
1372 {
1373 case DVP_DMA : *pname = ".dma."; return STO_DVP_DMA;
1374 case DVP_VIF : *pname = ".vif."; return STO_DVP_VIF;
1375 case DVP_GIF : *pname = ".gif."; return STO_DVP_GIF;
1376 case DVP_VUUP : *pname = ".vu."; return STO_DVP_VU;
1377 }
1378 abort ();
1379}
1380
1381/* Record the current mach type in the object file.
1382 If FORCE_NEXT_P is non-zero, force a label to be emitted the next time
1383 we're called. This is useful for variable length instructions that can
1384 have labels embedded within them. */
57d0c830
DE
1385
1386static void
b6d331b9
DE
1387record_mach (cpu, force_next_p)
1388 dvp_cpu cpu;
1389 int force_next_p;
57d0c830
DE
1390{
1391 symbolS *label;
b6d331b9
DE
1392 const char *name;
1393 int sto;
57d0c830 1394
b6d331b9 1395 if (cpu == cur_cpu)
57d0c830
DE
1396 return;
1397
b6d331b9
DE
1398 sto = cpu_sto (cpu, &name);
1399
1400 label = create_colon_label (sto, "", unique_name (name));
57d0c830 1401
b6d331b9
DE
1402 if (force_next_p)
1403 cur_cpu = DVP_UNKNOWN;
1404 else
1405 cur_cpu = cpu;
57d0c830
DE
1406}
1407
3b4389e2
DE
1408/* Force emission of mach type label at next insn.
1409 This isn't static as TC_START_LABEL uses it.
1410 The result is the value of TC_START_LABEL. */
1411
1412int
1413force_mach_label ()
1414{
1415 cur_cpu = DVP_UNKNOWN;
1416 return 1;
1417}
1418
e4d77412 1419/* Push the current parsing state to NEW_STATE. */
498fcb9c
DE
1420
1421static void
1422push_asm_state (new_state)
1423 asm_state new_state;
1424{
e4d77412
FCE
1425 asm_state cur_state = CUR_ASM_STATE;
1426
1427 ++cur_state_level;
1428 if (cur_state_level == MAX_STATE_DEPTH)
8b901ef8 1429 as_fatal ("internal error: unexpected state push");
e4d77412 1430 asm_state_stack[cur_state_level] = new_state;
498fcb9c
DE
1431}
1432
1433/* TOP_OK_P is non-zero if it's ok that we're at the top of the stack.
e4d77412 1434 If so we reset the state to ASM_INIT. */
209fb346 1435
498fcb9c
DE
1436static void
1437pop_asm_state (top_ok_p)
1438 int top_ok_p;
1439{
e4d77412 1440 if (cur_state_level == 0)
498fcb9c 1441 {
e4d77412 1442 if (! top_ok_p)
8b901ef8 1443 as_fatal ("internal error: unexpected state pop");
e4d77412 1444 CUR_ASM_STATE = ASM_INIT;
498fcb9c
DE
1445 }
1446 else
e4d77412 1447 --cur_state_level;
498fcb9c
DE
1448}
1449
e4d77412
FCE
1450/* Set the top level assembler state. */
1451
498fcb9c 1452static void
e4d77412 1453set_asm_state (state, insn_name)
498fcb9c 1454 asm_state state;
e4d77412 1455 const char *insn_name;
498fcb9c 1456{
e4d77412
FCE
1457 if (insn_name)
1458 {
1459 if (CUR_ASM_STATE != ASM_INIT)
1460 as_bad ("illegal place for `%s' instruction", insn_name);
1461 }
1462 cur_state_level = 0;
498fcb9c
DE
1463 CUR_ASM_STATE = state;
1464}
1465\f
209fb346
DE
1466void
1467md_operand (expressionP)
1468 expressionS *expressionP;
1469{
8b901ef8
DE
1470 /* Check if this is a '*' for mpgloc. */
1471 if (cur_opcode
1472 && (cur_opcode->flags & VIF_OPCODE_MPG) != 0
1473 && (cur_operand->flags & DVP_OPERAND_VU_ADDRESS) != 0
1474 && *input_line_pointer == '*')
1475 {
1476 expressionP->X_op = O_symbol;
1477 expressionP->X_add_symbol = mpgloc_sym;
1478 expressionP->X_add_number = 0;
1479
8b901ef8
DE
1480 /* Advance over the '*'. */
1481 ++input_line_pointer;
e4d77412 1482 return;
8b901ef8 1483 }
209fb346
DE
1484}
1485
1486valueT
1487md_section_align (segment, size)
1488 segT segment;
1489 valueT size;
1490{
1491 int align = bfd_get_section_alignment (stdoutput, segment);
1492 return ((size + (1 << align) - 1) & (-1 << align));
1493}
1494
1495symbolS *
1496md_undefined_symbol (name)
1497 char *name;
1498{
1499 return 0;
1500}
e1b747c4
DE
1501
1502/* Called after parsing the file via md_after_pass_hook. */
1503
1504void
69312dac 1505dvp_after_pass_hook ()
e1b747c4 1506{
7f28a81d
DE
1507 /* If doing dma packing, ensure the last dma tag is filled out. */
1508 if (dma_pack_vif_p)
1509 {
1510 /* Nothing to do as vifnops are zero and frag_align at beginning
1511 of dmatag is all we need. */
1512 }
1513
d3c6610c
DE
1514#if 0 /* ??? Doesn't work unless we keep track of the nested include file
1515 level. */
e1b747c4 1516 /* Check for missing .EndMpg, and supply one if necessary. */
498fcb9c 1517 if (CUR_ASM_STATE == ASM_MPG)
8b901ef8 1518 s_endmpg (ENDMPG_INTERNAL);
498fcb9c 1519 else if (CUR_ASM_STATE == ASM_DIRECT)
e1b747c4 1520 s_enddirect (0);
498fcb9c 1521 else if (CUR_ASM_STATE == ASM_UNPACK)
e1b747c4 1522 s_endunpack (0);
d3c6610c 1523#endif
e1b747c4 1524}
69312dac 1525
07b20428 1526/* Called via tc_frob_label when a label is defined. */
69312dac
DE
1527
1528void
1529dvp_frob_label (sym)
1530 symbolS *sym;
1531{
07b20428
DE
1532 const char * name = S_GET_NAME (sym);
1533
b6d331b9
DE
1534 /* All labels in vu code must be specially marked for the disassembler.
1535 The disassembler ignores all previous information at each new label
1536 (that has a higher address than the last one). */
69312dac
DE
1537 if (CUR_ASM_STATE == ASM_MPG
1538 || CUR_ASM_STATE == ASM_VU)
1539 S_SET_OTHER (sym, STO_DVP_VU);
07b20428
DE
1540
1541 /* If inside an mpg, move vu space labels to their own section and create
cb74aaa5 1542 the corresponding _$ version in normal space. */
07b20428
DE
1543
1544 if (CUR_ASM_STATE == ASM_MPG
1545 /* Only do this special processing for user specified symbols.
1546 Not sure how we can distinguish them other than by some prefix. */
cb74aaa5
DE
1547 && *name != '.' && *name != '$'
1548 /* Check for recursive invocation creating the _$name. */
c371a664
DE
1549 && strncmp (name, VU_LABEL_PREFIX, sizeof (VU_LABEL_PREFIX) - 1) != 0
1550 /* -gstabs creates FAKE_LABEL_NAME labels. There's probably a better
1551 test than this. */
1552 && ! S_IS_LOCAL (sym))
07b20428 1553 {
1554baf3 1554 /* Move this symbol to the vu overlay. */
07b20428
DE
1555 symbolS * cur_mpgloc = compute_mpgloc (mpgloc_sym, vif_data_start,
1556 expr_build_dot ());
1554baf3
DE
1557#if 0 /* Don't do this now, leave in ABS and then move to overlay
1558 section before file is written. */
1559 S_SET_SEGMENT (sym, vuoverlay_section);
1560#else
1561 /* Record the overlay section this symbol is in. */
1562 {
1563 ovlysymS *p = (ovlysymS *) xmalloc (sizeof (ovlysymS));
1564 p->next = ovlysym_table;
1565 p->sec = vuoverlay_section;
1566 p->sym = sym;
1567 ovlysym_table = p;
1568 }
07b20428 1569 S_SET_SEGMENT (sym, expr_section);
1554baf3 1570#endif
07b20428
DE
1571 sym->sy_value = cur_mpgloc->sy_value;
1572 sym->sy_frag = &zero_address_frag;
1573
cb74aaa5 1574 /* Create the _$ symbol in normal space. */
07b20428
DE
1575 create_colon_label (STO_DVP_VU, VU_LABEL_PREFIX, name);
1576 }
69312dac 1577}
1554baf3
DE
1578
1579/* Move vu space symbols into their overlay sections.
1580 Called via tc_frob_file. */
1581
1582void
1583dvp_frob_file ()
1584{
1585 ovlysymS *p;
1586
1587 for (p = ovlysym_table; p; p = p->next)
1588 {
1589 /* See the comment near tc_frob_file in write.c.
1590 We are responsible for updating sym->bsym->value. */
1591 S_SET_SEGMENT (p->sym, p->sec);
1592 /* Adjust for the section's vma. */
79259a91
DE
1593 /* FIXME: bfd doesn't get this right, it adds the section vma
1594 back in (in elf.c:swap_out_syms). As a workaround the
1595 section vma is assumed to be zero. Of course, there might
1596 not be a point in setting it to non-zero anyway. */
1554baf3
DE
1597 p->sym->bsym->value -= bfd_get_section_vma (stdoutput, p->sec);
1598 }
1599}
209fb346 1600\f
8b901ef8
DE
1601/* mpg/direct alignment is handled via relaxation */
1602
1603/* Return an initial guess of the length by which a fragment must grow to
1604 hold a branch to reach its destination.
1605 Also updates fr_type/fr_subtype as necessary.
1606
1607 Called just before doing relaxation.
1608 Any symbol that is now undefined will not become defined.
1609 The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1610 Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1611 Although it may not be explicit in the frag, pretend fr_var starts with a
1612 0 value. */
1613
1614int
1615md_estimate_size_before_relax (fragP, segment)
1616 fragS * fragP;
1617 segT segment;
1618{
1619 /* Our initial estimate is always 0. */
1620 return 0;
1621}
1622
1623/* Perform the relaxation.
2dc7ca50 1624 STRETCH is the amount the start of the frag has already been shifted by.
8b901ef8 1625 All we have to do is figure out how many bytes we need to insert to
07b20428
DE
1626 get to the recorded symbol (which is at the required alignment).
1627 This function is also called for machine dependent vu insn frags.
1628 In this case the growth is always 0. */
8b901ef8
DE
1629
1630long
1631dvp_relax_frag (fragP, stretch)
1632 fragS * fragP;
1633 long stretch;
1634{
1635 /* Address of variable part. */
1636 long address = fragP->fr_address + fragP->fr_fix;
1637 /* Symbol marking start of data. */
1638 symbolS * symbolP = fragP->fr_symbol;
1639 /* Address of the symbol. */
07b20428 1640 long target;
8b901ef8
DE
1641 long growth;
1642
1643 /* subtype >= 10 means "done" */
07b20428 1644 if (RELAX_DONE_P (fragP->fr_subtype))
8b901ef8
DE
1645 return 0;
1646
07b20428
DE
1647 /* vu insn? */
1648 if (fragP->fr_subtype == RELAX_VU)
1649 {
1650 fragP->fr_subtype = RELAX_ENCODE (RELAX_VU, 0);
1651 return 0;
1652 }
1653
1654 target = S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address;
1655
1656 if (fragP->fr_subtype == RELAX_MPG)
8b901ef8 1657 {
2dc7ca50
DE
1658 /* The frag the symbol is in hasn't been relaxed yet so any .org
1659 adjustments haven't been applied to it. We know the symbol
1660 is the address of the next frag so adjust target by stretch. */
1661 target += stretch;
8b901ef8
DE
1662 growth = target - address;
1663 if (growth < 0)
1664 as_fatal ("internal error: bad mpg alignment handling");
07b20428 1665 fragP->fr_subtype = RELAX_ENCODE (RELAX_MPG, growth);
8b901ef8
DE
1666 return growth;
1667 }
1668
07b20428 1669 if (fragP->fr_subtype == RELAX_DIRECT)
8b901ef8 1670 {
2dc7ca50
DE
1671 /* The frag the symbol is in hasn't been relaxed yet so any .org
1672 adjustments haven't been applied to it. We know the symbol
1673 is the address of the next frag so adjust target by stretch. */
1674 target += stretch;
8b901ef8
DE
1675 growth = target - address;
1676 if (growth < 0)
1677 as_fatal ("internal error: bad direct alignment handling");
07b20428 1678 fragP->fr_subtype = RELAX_ENCODE (RELAX_DIRECT, growth);
8b901ef8
DE
1679 return growth;
1680 }
1681
1682 as_fatal ("internal error: unknown fr_subtype");
1683}
1684
1685/* *fragP has been relaxed to its final size, and now needs to have
1686 the bytes inside it modified to conform to the new size.
1687
1688 Called after relaxation is finished.
1689 fragP->fr_type == rs_machine_dependent.
1690 fragP->fr_subtype is the subtype of what the address relaxed to. */
1691
1692void
1693md_convert_frag (abfd, sec, fragP)
1694 bfd * abfd;
1695 segT sec;
1696 fragS * fragP;
1697{
07b20428 1698 int growth = RELAX_GROWTH (fragP->fr_subtype);
8b901ef8
DE
1699
1700 fragP->fr_fix += growth;
1701
1702 if (growth != 0)
1703 {
1704 /* We had to grow this fragment. Shift the mpg/direct insn to the end
1705 (so it abuts the following data). */
1706 DVP_INSN insn = bfd_getl32 (fragP->fr_opcode);
1707 md_number_to_chars (fragP->fr_opcode, VIFNOP, 4);
bfb27620
DE
1708 if (growth > 4)
1709 md_number_to_chars (fragP->fr_opcode + 4, VIFNOP, 4);
8b901ef8 1710 if (growth > 8)
bfb27620 1711 md_number_to_chars (fragP->fr_opcode + 8, VIFNOP, 4);
8b901ef8
DE
1712 md_number_to_chars (fragP->fr_literal + fragP->fr_fix - 4, insn, 4);
1713
1714 /* Adjust fr_opcode so md_apply_fix3 works with the right bytes. */
1715 fragP->fr_opcode += growth;
1716 }
1717}
1718\f
209fb346
DE
1719/* Functions concerning relocs. */
1720
95bfad6d 1721/* Spacing between each cpu type's operand numbers.
7f28a81d 1722 Should be at least as big as any operand table. */
95bfad6d
DE
1723#define RELOC_SPACING 256
1724
1725/* Given a cpu type and operand number, return a temporary reloc type
1726 for use in generating the fixup that encodes the cpu type and operand
1727 number. */
1728
1729static int
1730encode_fixup_reloc_type (cpu, opnum)
3a6b8910 1731 dvp_cpu cpu;
95bfad6d
DE
1732 int opnum;
1733{
1734 return (int) BFD_RELOC_UNUSED + ((int) cpu * RELOC_SPACING) + opnum;
1735}
1736
1737/* Given a fixup reloc type, decode it into cpu type and operand. */
1738
1739static void
1740decode_fixup_reloc_type (fixup_reloc, cpuP, operandP)
1741 int fixup_reloc;
3a6b8910 1742 dvp_cpu *cpuP;
276dd6ef 1743 const dvp_operand **operandP;
95bfad6d 1744{
3a6b8910 1745 dvp_cpu cpu = (fixup_reloc - (int) BFD_RELOC_UNUSED) / RELOC_SPACING;
95bfad6d
DE
1746 int opnum = (fixup_reloc - (int) BFD_RELOC_UNUSED) % RELOC_SPACING;
1747
1748 *cpuP = cpu;
1749 switch (cpu)
1750 {
3a6b8910
DE
1751 case DVP_VUUP : *operandP = &vu_operands[opnum]; break;
1752 case DVP_VULO : *operandP = &vu_operands[opnum]; break;
1753 case DVP_DMA : *operandP = &dma_operands[opnum]; break;
b4cbabb8
DE
1754 case DVP_VIF : *operandP = &vif_operands[opnum]; break;
1755 case DVP_GIF : *operandP = &gif_operands[opnum]; break;
8b901ef8 1756 default : as_fatal ("internal error: bad fixup encoding");
95bfad6d
DE
1757 }
1758}
1759
209fb346
DE
1760/* The location from which a PC relative jump should be calculated,
1761 given a PC relative reloc. */
1762
1763long
1764md_pcrel_from_section (fixP, sec)
1765 fixS *fixP;
1766 segT sec;
1767{
1768 if (fixP->fx_addsy != (symbolS *) NULL
1769 && (! S_IS_DEFINED (fixP->fx_addsy)
1770 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1771 {
8b901ef8
DE
1772 /* If fx_tcbit is set this is for a vif insn and thus should never
1773 happen in correct code. */
1774 /* ??? The error message could be a bit more descriptive. */
1775 if (fixP->fx_tcbit)
1776 as_bad ("unable to compute length of vif insn");
209fb346 1777 /* The symbol is undefined (or is defined but not in this section).
b6675c1a
DE
1778 Let the linker figure it out. +8: branch offsets are relative to the
1779 delay slot. */
1780 return 8;
209fb346
DE
1781 }
1782
8b901ef8
DE
1783 /* If fx_tcbit is set, this is a vif end-of-variable-length-insn marker.
1784 In this case the offset is relative to the start of data.
1785 Otherwise we assume this is a vu branch. In this case
1786 offsets are calculated based on the address of the next insn. */
1787 if (fixP->fx_tcbit)
1788 {
1789 /* As a further refinement, if fr_opcode is NULL this is `unpack'
1790 which doesn't involve any relaxing. */
1791 if (fixP->fx_frag->fr_opcode == NULL)
1792 return fixP->fx_frag->fr_address + fixP->fx_where + 4;
1793 else
1794 return fixP->fx_frag->fr_address + fixP->fx_frag->fr_fix;
1795 }
1796 else
1797 return ((fixP->fx_frag->fr_address + fixP->fx_where) & -8L) + 8;
209fb346
DE
1798}
1799
1800/* Apply a fixup to the object code. This is called for all the
1801 fixups we generated by calls to fix_new_exp. At this point all symbol
1802 values should be fully resolved, and we attempt to completely resolve the
1803 reloc. If we can not do that, we determine the correct reloc code and put
1804 it back in the fixup. */
1805
1806int
1807md_apply_fix3 (fixP, valueP, seg)
1808 fixS *fixP;
1809 valueT *valueP;
1810 segT seg;
1811{
1812 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
1813 valueT value;
1814
020ba60b
DE
1815 /* FIXME FIXME FIXME: The value we are passed in *valueP includes
1816 the symbol values. Since we are using BFD_ASSEMBLER, if we are
1817 doing this relocation the code in write.c is going to call
1818 bfd_perform_relocation, which is also going to use the symbol
1819 value. That means that if the reloc is fully resolved we want to
1820 use *valueP since bfd_perform_relocation is not being used.
1821 However, if the reloc is not fully resolved we do not want to use
1822 *valueP, and must use fx_offset instead. However, if the reloc
1823 is PC relative, we do want to use *valueP since it includes the
1824 result of md_pcrel_from. This is confusing. */
1825
1826 if (fixP->fx_addsy == (symbolS *) NULL)
1827 {
1828 value = *valueP;
1829 fixP->fx_done = 1;
1830 }
1831 else if (fixP->fx_pcrel)
1832 {
1833 value = *valueP;
1834 }
1835 else
1836 {
1837 value = fixP->fx_offset;
1838 if (fixP->fx_subsy != (symbolS *) NULL)
1839 {
1840 if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
1841 value -= S_GET_VALUE (fixP->fx_subsy);
1842 else
1843 {
1844 /* We can't actually support subtracting a symbol. */
1845 as_bad_where (fixP->fx_file, fixP->fx_line,
1846 "expression too complex");
1847 }
1848 }
1849 }
1850
1ece1d56 1851 /* Check for dvp operands. These are indicated with a reloc value
020ba60b
DE
1852 >= BFD_RELOC_UNUSED. */
1853
1854 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1855 {
3a6b8910 1856 dvp_cpu cpu;
276dd6ef
DE
1857 const dvp_operand *operand;
1858 DVP_INSN insn;
8b901ef8
DE
1859 fragS *fragP = fixP->fx_frag;
1860
1861 /* If this was a relaxable insn, the opcode may have moved. Find it. */
1862 if (fragP->fr_opcode != NULL)
1863 where = fragP->fr_opcode;
020ba60b 1864
95bfad6d
DE
1865 decode_fixup_reloc_type ((int) fixP->fx_r_type,
1866 & cpu, & operand);
020ba60b 1867
8b901ef8
DE
1868 /* For variable length vif insn data lengths, validate the user specified
1869 value or install the computed value in the instruction. */
1870 if (cpu == DVP_VIF
1871 && (operand - vif_operands) == vif_operand_datalen_special)
1872 {
a6756468 1873 int insn_type = vif_insn_type (where[3]);
8b901ef8
DE
1874 value = vif_length_value (where[3],
1875 fixP->tc_fix_data.wl, fixP->tc_fix_data.cl,
1876 value);
1877 if (fixP->tc_fix_data.user_value != -1)
1878 {
a6756468
DE
1879 /* We can't do this for unpack insns with wl > cl. */
1880 if ((insn_type != VIF_OPCODE_UNPACK
1881 || (fixP->tc_fix_data.wl <= fixP->tc_fix_data.cl))
1882 && fixP->tc_fix_data.user_value != value)
8b901ef8
DE
1883 as_warn_where (fixP->fx_file, fixP->fx_line,
1884 "specified length value doesn't match computed value");
1885 /* Don't override the user specified value. */
1886 }
1887 else
1888 {
1889 if (output_vif)
1890 {
1891 install_vif_length (where, value);
1892 }
1893 }
1894 fixP->fx_done = 1;
1895 return 1;
1896 }
1897
fa3671a3
DE
1898 /* For the gif nloop operand, if it was specified by the user ensure
1899 it matches the value we computed. */
1900 if (cpu == DVP_GIF
1901 && (operand - gif_operands) == gif_operand_nloop)
1902 {
1903 value = compute_nloop (fixP->tc_fix_data.type,
1904 fixP->tc_fix_data.nregs,
1905 value);
8b901ef8 1906 if (fixP->tc_fix_data.user_value != -1)
fa3671a3
DE
1907 {
1908 check_nloop (fixP->tc_fix_data.type,
1909 fixP->tc_fix_data.nregs,
8b901ef8 1910 fixP->tc_fix_data.user_value,
fa3671a3
DE
1911 value,
1912 fixP->fx_file, fixP->fx_line);
1913 /* Don't override the user specified value. */
1914 fixP->fx_done = 1;
1915 return 1;
1916 }
1917 }
1918
e4d77412
FCE
1919 /* ??? It might be cleaner to not do this at all here (when ! fx_done)
1920 and leave it to bfd_install_relocation. */
1921 if ((operand->flags & DVP_OPERAND_RELOC_U15_S3) != 0)
1922 value >>= 3;
1923 else if ((operand->flags & DVP_OPERAND_RELOC_11_S4) != 0)
1924 value >>= 4;
1925
020ba60b 1926 /* Fetch the instruction, insert the fully resolved operand
1ece1d56
DE
1927 value, and stuff the instruction back again. The fixup is recorded
1928 at the appropriate word so pass DVP_MOD_THIS_WORD so any offset
1929 specified in the tables is ignored. */
020ba60b 1930 insn = bfd_getl32 ((unsigned char *) where);
6856244d
DE
1931 insert_operand_final (cpu, operand, DVP_MOD_THIS_WORD, &insn,
1932 (offsetT) value, fixP->fx_file, fixP->fx_line);
020ba60b
DE
1933 bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
1934
8b901ef8
DE
1935 /* If this is mpgloc/unpackloc, we're done. */
1936 if (operand->flags & (DVP_OPERAND_VU_ADDRESS | DVP_OPERAND_UNPACK_ADDRESS))
1937 fixP->fx_done = 1;
1938
020ba60b
DE
1939 if (fixP->fx_done)
1940 {
1941 /* Nothing else to do here. */
1942 return 1;
1943 }
1944
1945 /* Determine a BFD reloc value based on the operand information.
1946 We are only prepared to turn a few of the operands into relocs. */
276dd6ef 1947 if ((operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0)
020ba60b 1948 {
1ece1d56 1949 assert (operand->bits == 11
020ba60b 1950 && operand->shift == 0);
07b20428
DE
1951
1952 /* The fixup isn't recorded as a pc relative branch to some label.
1953 Instead a complicated expression is used to compute the desired
1954 value. Well, that didn't work and we have to emit a reloc.
1955 Things are tricky because the result we want is the difference
1956 of two addresses in a section potentially different from the one
1957 the reloc is in. Ugh.
1958 The solution is to emit two relocs, one that adds the target
1959 address and one that subtracts the source address + 8 (the
1960 linker will perform the byte->dword conversion).
1961 This is rather complicated and rather than risk breaking
1962 existing code we fall back on the old way if the file only
1963 contains vu code. In this case the file is intended to
1964 be fully linked with other vu code and thus we have a normal
1965 situation where the relocation directly corresponds to the
1966 branch insn. */
1967
1968 if (non_vu_insn_seen_p)
1969 {
1970 as_bad_where (fixP->fx_file, fixP->fx_line,
1971 "can't handle mpg loaded vu code with branch relocations");
7ebb61af
DE
1972 fixP->fx_done = 1;
1973 return 1;
07b20428
DE
1974 }
1975 else
1976 {
1977 fixP->fx_r_type = BFD_RELOC_MIPS_DVP_11_PCREL;
1978 }
020ba60b 1979 }
91572941
DE
1980 else if ((operand->flags & DVP_OPERAND_DMA_ADDR) != 0
1981 || (operand->flags & DVP_OPERAND_DMA_NEXT) != 0)
1ece1d56
DE
1982 {
1983 assert (operand->bits == 27
1984 && operand->shift == 4);
1985 fixP->fx_r_type = BFD_RELOC_MIPS_DVP_27_S4;
1986 }
e4d77412
FCE
1987 else if ((operand->flags & DVP_OPERAND_RELOC_11_S4) != 0)
1988 {
1989 assert (operand->bits == 11
1990 && operand->shift == 0);
1991 fixP->fx_r_type = BFD_RELOC_MIPS_DVP_11_S4;
1992 /* ??? bfd_install_relocation will duplicate what we've done to
1993 install the addend, so tell it not to. This is an instance
1994 where setting partial_inplace to true has some use. */
1995 value = 0;
1996 }
1997 else if ((operand->flags & DVP_OPERAND_RELOC_U15_S3) != 0)
1998 {
1999 assert (operand->bits == 15
2000 && operand->shift == 0);
2001 fixP->fx_r_type = BFD_RELOC_MIPS_DVP_U15_S3;
2002 /* ??? bfd_install_relocation will duplicate what we've done to
2003 install the addend, so tell it not to. This is an instance
2004 where setting partial_inplace to true has some use. */
2005 value = 0;
2006 }
020ba60b
DE
2007 else
2008 {
2009 as_bad_where (fixP->fx_file, fixP->fx_line,
2010 "unresolved expression that must be resolved");
2011 fixP->fx_done = 1;
2012 return 1;
2013 }
2014 }
1554baf3 2015 else if (fixP->fx_done)
020ba60b 2016 {
1554baf3
DE
2017 /* We're finished with this fixup. Install it because
2018 bfd_install_relocation won't be called to do it. */
020ba60b
DE
2019 switch (fixP->fx_r_type)
2020 {
2021 case BFD_RELOC_8:
2022 md_number_to_chars (where, value, 1);
2023 break;
2024 case BFD_RELOC_16:
2025 md_number_to_chars (where, value, 2);
2026 break;
2027 case BFD_RELOC_32:
2028 md_number_to_chars (where, value, 4);
2029 break;
5dccb8b0
DE
2030 case BFD_RELOC_64:
2031 md_number_to_chars (where, value, 8);
2032 break;
020ba60b 2033 default:
8b901ef8 2034 as_fatal ("internal error: unexpected fixup");
020ba60b
DE
2035 }
2036 }
1554baf3
DE
2037 else
2038 {
2039 /* bfd_install_relocation will be called to finish things up. */
2040 }
020ba60b 2041
1554baf3
DE
2042 /* Tuck `value' away for use by tc_gen_reloc.
2043 See the comment describing fx_addnumber in write.h. */
020ba60b
DE
2044 fixP->fx_addnumber = value;
2045
2046 return 1;
209fb346
DE
2047}
2048
2049/* Translate internal representation of relocation info to BFD target
2050 format. */
2051
2052arelent *
020ba60b 2053tc_gen_reloc (section, fixP)
209fb346 2054 asection *section;
020ba60b 2055 fixS *fixP;
209fb346 2056{
020ba60b
DE
2057 arelent *reloc;
2058
2059 reloc = (arelent *) xmalloc (sizeof (arelent));
2060
2061 reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
2062 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
2063 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
2064 if (reloc->howto == (reloc_howto_type *) NULL)
2065 {
2066 as_bad_where (fixP->fx_file, fixP->fx_line,
2067 "internal error: can't export reloc type %d (`%s')",
2068 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
2069 return NULL;
2070 }
2071
2072 assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
2073
2074 reloc->addend = fixP->fx_addnumber;
2075
2076 return reloc;
209fb346
DE
2077}
2078\f
2079/* Write a value out to the object file, using the appropriate endianness. */
2080
2081void
2082md_number_to_chars (buf, val, n)
2083 char *buf;
2084 valueT val;
2085 int n;
2086{
2087 if (target_big_endian)
2088 number_to_chars_bigendian (buf, val, n);
2089 else
2090 number_to_chars_littleendian (buf, val, n);
2091}
2092
2093/* Turn a string in input_line_pointer into a floating point constant of type
2094 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
2095 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
2096*/
2097
2098/* Equal to MAX_PRECISION in atof-ieee.c */
2099#define MAX_LITTLENUMS 6
2100
2101char *
2102md_atof (type, litP, sizeP)
2103 char type;
2104 char *litP;
2105 int *sizeP;
2106{
2107 int i,prec;
2108 LITTLENUM_TYPE words[MAX_LITTLENUMS];
2109 LITTLENUM_TYPE *wordP;
2110 char *t;
2111 char *atof_ieee ();
2112
2113 switch (type)
2114 {
2115 case 'f':
2116 case 'F':
2117 case 's':
2118 case 'S':
2119 prec = 2;
2120 break;
2121
2122 case 'd':
2123 case 'D':
2124 case 'r':
2125 case 'R':
2126 prec = 4;
2127 break;
2128
2129 /* FIXME: Some targets allow other format chars for bigger sizes here. */
2130
2131 default:
2132 *sizeP = 0;
2133 return "Bad call to md_atof()";
2134 }
2135
2136 t = atof_ieee (input_line_pointer, type, words);
2137 if (t)
2138 input_line_pointer = t;
2139 *sizeP = prec * sizeof (LITTLENUM_TYPE);
2140
2141 if (target_big_endian)
2142 {
2143 for (i = 0; i < prec; i++)
2144 {
2145 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
2146 litP += sizeof (LITTLENUM_TYPE);
2147 }
2148 }
2149 else
2150 {
2151 for (i = prec - 1; i >= 0; i--)
2152 {
2153 md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE));
2154 litP += sizeof (LITTLENUM_TYPE);
2155 }
2156 }
2157
2158 return 0;
2159}
020ba60b 2160\f
91572941
DE
2161/* Miscellaneous utilities. */
2162
19f12fb4
DE
2163/* Parse a 32 bit floating point number.
2164 The result is those 32 bits as an integer. */
2165
2166static long
2167parse_float (pstr, errmsg)
2168 char **pstr;
2169 const char **errmsg;
2170{
e4d77412
FCE
2171 if ((*pstr)[0] == '0'
2172 && ((*pstr)[1] == 'x' || (*pstr)[1] == 'X'))
2173 {
2174 long value;
2175 (*pstr) += 2;
2176 value = strtol (*pstr, pstr, 16);
2177 return value;
2178 }
2179 else
2180 {
2181 LITTLENUM_TYPE words[MAX_LITTLENUMS];
2182 *pstr = atof_ieee (*pstr, 'f', words);
2183 return (words[0] << 16) | words[1];
2184 }
19f12fb4 2185}
8dddf63f 2186
91572941 2187/* Scan a symbol and return a pointer to one past the end. */
8dddf63f 2188
8dddf63f
DE
2189#define issymchar(ch) (isalnum(ch) || ch == '_')
2190static char *
1ece1d56 2191scan_symbol (sym)
8dddf63f
DE
2192 char *sym;
2193{
1ece1d56
DE
2194 while (*sym && issymchar (*sym))
2195 ++sym;
2196 return sym;
8dddf63f
DE
2197}
2198
8b901ef8 2199/* Evaluate an expression for an operand.
1ece1d56
DE
2200 The result is the value of the expression if it can be evaluated,
2201 or 0 if it cannot (say because some symbols haven't been defined yet)
8151801a
DE
2202 in which case a fixup is queued.
2203
2204 If OPINDEX is 0, don't queue any fixups, just return 0. */
1ece1d56
DE
2205
2206static long
2207#ifdef USE_STDARG
07b20428 2208eval_expr (dvp_cpu cpu, int opindex, int offset, const char *fmt, ...)
1ece1d56 2209#else
07b20428
DE
2210eval_expr (cpu, opindex, offset, fmt, va_alist)
2211 dvp_cpu cpu;
1ece1d56
DE
2212 int opindex,offset;
2213 const char *fmt;
2214 va_dcl
2215#endif
2216{
2217 long value;
2218 va_list ap;
2219 char *str,*save_input;
2220 expressionS exp;
2221
2222#ifdef USE_STDARG
2223 va_start (ap, fmt);
2224#else
2225 va_start (ap);
2226#endif
2227 vasprintf (&str, fmt, ap);
2228 va_end (ap);
2229
2230 save_input = input_line_pointer;
2231 input_line_pointer = str;
2232 expression (&exp);
2233 input_line_pointer = save_input;
2234 free (str);
2235 if (exp.X_op == O_constant)
2236 value = exp.X_add_number;
2237 else
8dddf63f 2238 {
8151801a
DE
2239 if (opindex != 0)
2240 {
07b20428 2241 fixups[fixup_count].cpu = cpu;
8151801a
DE
2242 fixups[fixup_count].exp = exp;
2243 fixups[fixup_count].opindex = opindex;
2244 fixups[fixup_count].offset = offset;
8b901ef8
DE
2245 fixups[fixup_count].user_value = -1;
2246 fixups[fixup_count].wl = -1;
2247 fixups[fixup_count].cl = -1;
8151801a
DE
2248 ++fixup_count;
2249 }
1ece1d56 2250 value = 0;
8dddf63f 2251 }
1ece1d56
DE
2252 return value;
2253}
8dddf63f 2254
1ece1d56 2255/* Create a label named by concatenating PREFIX to NAME. */
8dddf63f 2256
57d0c830 2257static symbolS *
1ece1d56
DE
2258create_label (prefix, name)
2259 const char *prefix, *name;
2260{
2261 int namelen = strlen (name);
2262 int prefixlen = strlen (prefix);
2263 char *fullname;
57d0c830 2264 symbolS *result;
1ece1d56
DE
2265
2266 fullname = xmalloc (prefixlen + namelen + 1);
2267 strcpy (fullname, prefix);
2268 strcat (fullname, name);
2269 result = symbol_find_or_make (fullname);
2270 free (fullname);
2271 return result;
2272}
8dddf63f 2273
1ece1d56 2274/* Create a label named by concatenating PREFIX to NAME,
b6d331b9
DE
2275 and define it as `.'.
2276 STO, if non-zero, is the st_other value to assign to this label.
3b4389e2 2277 If STO is zero `cur_cpu', call force_mach_label to force record_mach to
b6d331b9 2278 emit a cpu label. Otherwise the disassembler gets confused. */
8dddf63f 2279
57d0c830 2280static symbolS *
b6d331b9
DE
2281create_colon_label (sto, prefix, name)
2282 int sto;
1ece1d56
DE
2283 const char *prefix, *name;
2284{
2285 int namelen = strlen (name);
2286 int prefixlen = strlen (prefix);
2287 char *fullname;
57d0c830 2288 symbolS *result;
1ece1d56
DE
2289
2290 fullname = xmalloc (prefixlen + namelen + 1);
2291 strcpy (fullname, prefix);
2292 strcat (fullname, name);
2293 result = colon (fullname);
b6d331b9
DE
2294 if (sto)
2295 S_SET_OTHER (result, sto);
2296 else
3b4389e2 2297 force_mach_label ();
1ece1d56
DE
2298 free (fullname);
2299 return result;
8dddf63f 2300}
91572941 2301
57d0c830
DE
2302/* Return a malloc'd string useful in creating unique labels.
2303 PREFIX is the prefix to use or NULL if we're to pick one. */
91572941
DE
2304
2305static char *
57d0c830
DE
2306unique_name (prefix)
2307 const char *prefix;
91572941
DE
2308{
2309 static int counter;
2310 char *result;
2311
57d0c830 2312 if (prefix == NULL)
9152beba 2313 prefix = UNIQUE_LABEL_PREFIX;
57d0c830 2314 asprintf (&result, "%s%d", prefix, counter);
91572941
DE
2315 ++counter;
2316 return result;
2317}
1554baf3
DE
2318\f
2319/* VU support. */
2320
2321/* Return the name of the overlay section.
2322 It must be unique among all overlays in the executable. */
2323
2324static char *
2325vuoverlay_section_name (addr)
5dccb8b0 2326 symbolS *addr;
1554baf3
DE
2327{
2328 char *section_name;
2329 char *file;
2330 unsigned int lineno;
2331 unsigned int fileno;
2332 /* One mpg may actually result in several, counter keeps track of this. */
2333 static int counter;
2334
2335 as_where (&file, &lineno);
2336 for (fileno = 0; *file; ++file)
2337 fileno = (fileno << 1) + *file;
5dccb8b0 2338 if (addr->sy_value.X_op == O_constant)
c3b51879 2339 asprintf (&section_name, "%s.0x%x.%u.%u.%d", SHNAME_DVP_OVERLAY_PREFIX,
5dccb8b0
DE
2340 (int) S_GET_VALUE (addr), fileno, lineno, counter);
2341 else
c3b51879 2342 asprintf (&section_name, "%s.unknvma.%u.%u.%d", SHNAME_DVP_OVERLAY_PREFIX,
5dccb8b0 2343 fileno, lineno, counter);
1554baf3
DE
2344 ++counter;
2345 return section_name;
2346}
2347
2348/* Create a shadow section for VU code that starts at ADDR in vu space.
2349 START_LABEL and END_LABEL, if non-NULL, are symbols marking the start and
2350 end of the section. If NULL, no overlay tracking information is output. */
2351
2352static void
2353create_vuoverlay_section (section_name, addr, start_label, end_label)
2354 const char *section_name;
5dccb8b0
DE
2355 /* Remember, expressions are recorded as symbols. */
2356 symbolS *addr;
1554baf3
DE
2357 symbolS *start_label, *end_label;
2358{
2359 /* Must preserve the current seg/subseg. */
2360 segT orig_seg = now_seg;
2361 subsegT orig_subseg = now_subseg;
2362
c3b51879 2363 /* Create and get handle of a vu overlay section. All vu symbols go here.
1554baf3
DE
2364 The section name must be unique in the entire executable.
2365 We achieve this by encoding the source file name and file number. Ick.
2366 ??? A cleaner way would be if mpg took a new argument that named the
2367 overlay. */
2368 vuoverlay_section = subseg_new (section_name, 0);
7a701825 2369 bfd_set_section_flags (stdoutput, vuoverlay_section, SEC_CODE);
1554baf3
DE
2370 /* There's no point in setting the section vma as we can't get the linker
2371 to preserve it. But what the heck ... It might be useful to the
2372 objdump user. */
79259a91
DE
2373#if 0 /* FIXME: bfd's elf.c:swap_out_syms always emits symbol values with
2374 the section vma added in so we can't do this. */
5dccb8b0
DE
2375 if (addr->sy_value.X_op == O_constant)
2376 bfd_set_section_vma (stdoutput, vuoverlay_section, S_GET_VALUE (addr));
79259a91 2377#endif
1554baf3
DE
2378 /* The size of the section won't be known until we see the .endmpg,
2379 but we can compute it from the start and end labels. */
2380 /* FIXME: This causes the section to occupy space in the file. */
2381 if (start_label)
2382 frag_var (rs_space, 1, 1, (relax_substateT) 0,
2383 expr_build_binary (O_subtract, end_label, start_label),
2384 (offsetT) 0, (char *) 0);
2385#if 0
2386 /* Create a symbol marking the start of the section. */
2387 begin_label = create_colon_label (STO_DVP_VU, "__start_", section_name);
2388#endif
2389
c371a664 2390#if 0 /* already done */
1554baf3
DE
2391 /* Initialize $.mpgloc. */
2392 mpgloc_sym = expr_build_uconstant (addr);
c371a664 2393#endif
1554baf3
DE
2394
2395#if 0 /* $.mpgloc is kept in the ABS section. */
2396 S_SET_SEGMENT (mpgloc_sym, vuoverlay_section);
2397#endif
2398
2399 /* Add an entry to the vu overlay table. */
2400 if (start_label)
2401 {
1554baf3 2402 expressionS exp;
c3b51879
DE
2403 const char *p;
2404 symbolS * name_label;
2405
2406 /* Put the section name in the overlay string table. */
2407
2408 subseg_set (vuoverlay_string_section, 0);
2409 name_label = create_colon_label (0, LOCAL_LABEL_PREFIX,
2410 unique_name ("secstr"));
2411 /* FIXME: should be a utility to do this. */
2412 for (p = section_name; *p; ++p)
2413 FRAG_APPEND_1_CHAR (*p);
2414 FRAG_APPEND_1_CHAR (0);
1554baf3
DE
2415
2416 subseg_set (vuoverlay_table_section, 0);
2417
c3b51879
DE
2418 /* FIXME: should be a utility to do these. */
2419 /* Offset into string table. */
2420 exp.X_op = O_symbol;
2421 exp.X_add_symbol = name_label;
2422 exp.X_add_number = 0;
7f7d7bc0 2423 emit_expr (&exp, 4);
c3b51879 2424
1554baf3
DE
2425 /* The section's lma. */
2426 exp.X_op = O_symbol;
2427 exp.X_add_symbol = start_label;
2428 exp.X_add_number = 0;
7f7d7bc0 2429 emit_expr (&exp, 4);
1554baf3
DE
2430
2431 /* The section's vma. */
5dccb8b0
DE
2432 exp.X_op = O_symbol;
2433 exp.X_add_symbol = addr;
2434 exp.X_add_number = 0;
7f7d7bc0 2435 emit_expr (&exp, 4);
1554baf3
DE
2436 }
2437
2438 /* Restore the original seg/subseg. */
2439 subseg_set (orig_seg, orig_subseg);
2440}
07b20428
DE
2441
2442/* Compute a value for $.mpgloc given a symbol at the start of a chunk
2443 of code, the $.mpgloc value for the start, and a symbol at the end
2444 of the chunk of code. */
2445
2446static symbolS *
2447compute_mpgloc (startloc, startsym, endsym)
2448 symbolS * startloc;
2449 symbolS * startsym;
2450 symbolS * endsym;
2451{
2452 symbolS *s;
2453
2454 s = expr_build_binary (O_subtract, endsym, startsym);
2455 s = expr_build_binary (O_add, startloc, s);
2456 return s;
2457}
8b901ef8 2458\f
fa3671a3
DE
2459/* Compute a value for nloop. */
2460
2461static int
2462compute_nloop (type, nregs, bytes)
2463 gif_type type;
2464 int nregs, bytes;
2465{
2466 int computed_nloop;
2467
2468 switch (type)
2469 {
2470 case GIF_PACKED :
2471 /* We can't compute a value if no regs were specified and there is a
2472 non-zero amount of data. Just set to something useful, a warning
2473 will be issued later. */
2474 if (nregs == 0)
2475 nregs = 1;
2476 computed_nloop = (bytes >> 4) / nregs;
2477 break;
2478 case GIF_REGLIST :
2479 if (nregs == 0)
2480 nregs = 1;
2481 computed_nloop = (bytes >> 3) / nregs;
2482 break;
2483 case GIF_IMAGE :
2484 computed_nloop = bytes >> 4;
2485 break;
2486 }
2487
2488 return computed_nloop;
2489}
2490
2491/* Issue a warning if the user specified nloop value doesn't match the
2492 computed value. */
2493
2494static void
2495check_nloop (type, nregs, user_nloop, computed_nloop, file, line)
2496 gif_type type;
2497 int nregs,user_nloop,computed_nloop;
2498 char *file;
2499 unsigned int line;
2500{
2501 if (user_nloop != computed_nloop)
2502 as_warn_where (file, line, "nloop value does not match amount of data");
2503}
91572941 2504\f
e9cb12e4
DE
2505/* Compute the auto-count value for a DMA tag.
2506 INLINE_P is non-zero if the dma data is inline. */
91572941
DE
2507
2508static void
e9cb12e4 2509setup_dma_autocount (name, insn_buf, inline_p)
91572941
DE
2510 const char *name;
2511 DVP_INSN *insn_buf;
e9cb12e4 2512 int inline_p;
91572941
DE
2513{
2514 long count;
2515
e9cb12e4
DE
2516 if (inline_p)
2517 {
2518 /* -1: The count is the number of following quadwords, so skip the one
2519 containing the dma tag. */
07b20428 2520 count = eval_expr (DVP_DMA, dma_operand_count, 0,
e9cb12e4
DE
2521 "((%s%s - %s) >> 4) - 1", END_LABEL_PREFIX, name, name);
2522 }
2523 else
2524 {
2525 /* We don't want to subtract 1 here as the begin and end labels
2526 properly surround the data we want to compute the length of. */
07b20428 2527 count = eval_expr (DVP_DMA, dma_operand_count, 0,
e9cb12e4
DE
2528 "(%s%s - %s) >> 4", END_LABEL_PREFIX, name, name);
2529 }
91572941
DE
2530
2531 /* Store the count field. */
e9cb12e4
DE
2532 insn_buf[0] &= 0xffff0000;
2533 insn_buf[0] |= count & 0x0000ffff;
91572941
DE
2534}
2535
2536/* Record that inline data follows. */
2537
2538static void
8151801a 2539inline_dma_data (autocount_p, insn_buf)
91572941
DE
2540 int autocount_p;
2541 DVP_INSN *insn_buf;
2542{
8151801a 2543 if (dma_data_state != 0 )
91572941
DE
2544 {
2545 as_bad ("DmaData blocks cannot be nested.");
2546 return;
2547 }
2548
8151801a 2549 dma_data_state = 1;
91572941
DE
2550
2551 if (autocount_p)
2552 {
b6d331b9 2553 dma_data_name = S_GET_NAME (create_colon_label (0, "", unique_name (NULL)));
e9cb12e4 2554 setup_dma_autocount (dma_data_name, insn_buf, 1);
91572941
DE
2555 }
2556 else
8151801a 2557 dma_data_name = 0;
91572941
DE
2558}
2559
2560/* Compute the auto-count value for a DMA tag with out-of-line data. */
2561
2562static long
2563parse_dma_addr_autocount (opcode, operand, mods, insn_buf, pstr, errmsg)
2564 const dvp_opcode *opcode;
2565 const dvp_operand *operand;
2566 int mods;
2567 DVP_INSN *insn_buf;
2568 char **pstr;
2569 const char **errmsg;
2570{
2571 char *start = *pstr;
2572 char *end = start;
2573 long retval;
2574 /* Data reference must be a .DmaData label. */
57d0c830 2575 symbolS *label, *label2, *endlabel;
91572941
DE
2576 const char *name;
2577 char c;
2578
2579 label = label2 = 0;
2580 if (! is_name_beginner (*start))
2581 {
2582 *errmsg = "invalid .DmaData label";
2583 return 0;
2584 }
2585
2586 name = start;
2587 end = scan_symbol (name);
2588 c = *end;
2589 *end = 0;
2590 label = symbol_find_or_make (name);
2591 *end = c;
2592
7a701825
DE
2593 /* Use the same prefix as vu labels here. */
2594 label2 = create_label (VU_LABEL_PREFIX, name);
91572941
DE
2595 endlabel = create_label (END_LABEL_PREFIX, name);
2596
07b20428 2597 retval = eval_expr (DVP_DMA, dma_operand_addr, 4, name);
91572941 2598
e9cb12e4 2599 setup_dma_autocount (name, insn_buf, 0);
91572941
DE
2600
2601 *pstr = end;
2602 return retval;
2603}
8dddf63f 2604\f
a6756468
DE
2605/* Compute the type of vif insn of IBYTE.
2606 IBYTE is the msb of the insn.
2607 This is only used for mpg,direct,unpack insns.
2608 The result is one of VIF_OPCODE_{DIRECT,DIRECTHL,MPG,UNPACK}. */
2609
2610static int
2611vif_insn_type (ibyte)
2612 char ibyte;
2613{
2614 switch (ibyte & 0x70)
2615 {
2616 case 0x50 :
2617 return (ibyte & 1) ? VIF_OPCODE_DIRECTHL : VIF_OPCODE_DIRECT;
2618 case 0x40 :
2619 return VIF_OPCODE_MPG;
2620 case 0x60 :
2621 case 0x70 :
2622 return VIF_OPCODE_UNPACK;
2623 default :
2624 as_fatal ("internal error: bad call to vif_insn_type");
2625 }
2626}
2627
8b901ef8 2628/* Return the length value to insert in a VIF instruction whose upper
a6756468 2629 byte is IBYTE and whose data length is BYTES.
8b901ef8
DE
2630 WL,CL are used for unpack insns and are the stcycl values in effect.
2631 This does not do the max -> 0 conversion. */
e1b747c4
DE
2632
2633static int
a6756468
DE
2634vif_length_value (ibyte, wl, cl, bytes)
2635 char ibyte;
8b901ef8
DE
2636 int wl,cl;
2637 int bytes;
e1b747c4 2638{
a6756468 2639 switch (ibyte & 0x70)
e1b747c4 2640 {
8b901ef8
DE
2641 case 0x50 : /* direct */
2642 /* ??? Worry about data /= 16 cuts off? */
2643 return bytes / 16;
2644 case 0x40 : /* mpg */
2645 /* ??? Worry about data /= 8 cuts off? */
2646 return bytes / 8;
2647 case 0x60 : /* unpack */
2648 case 0x70 :
a6756468 2649 return vif_unpack_len_value (ibyte & 15, wl, cl, bytes);
8b901ef8
DE
2650 default :
2651 as_fatal ("internal error: bad call to vif_length_value");
e1b747c4 2652 }
e1b747c4
DE
2653}
2654
8b901ef8
DE
2655/* Install length LEN in the vif insn at BUF.
2656 LEN is the actual value to store, except that the max->0 conversion
2657 hasn't been done (we do it).
e033023f
DE
2658 The bytes in BUF are in target order. */
2659
2660static void
b4cbabb8 2661install_vif_length (buf, len)
e033023f
DE
2662 char *buf;
2663 int len;
2664{
a6756468 2665 unsigned char ibyte = buf[3];
e033023f 2666
a6756468 2667 if ((ibyte & 0x70) == 0x40)
e033023f
DE
2668 {
2669 /* mpg */
e033023f 2670 if (len > 256)
d476d46a
DE
2671 as_bad ("`mpg' data length must be between 1 and 256");
2672 buf[2] = len == 256 ? 0 : len;
e033023f 2673 }
a6756468 2674 else if ((ibyte & 0x70) == 0x50)
e033023f
DE
2675 {
2676 /* direct/directhl */
d476d46a
DE
2677 if (len > 65536)
2678 as_bad ("`direct' data length must be between 1 and 65536");
2679 len = len == 65536 ? 0 : len;
2680 buf[0] = len;
2681 buf[1] = len >> 8;
e033023f 2682 }
a6756468 2683 else if ((ibyte & 0x60) == 0x60)
e033023f
DE
2684 {
2685 /* unpack */
8b901ef8 2686 /* len == -1 means wl,cl are unknown and thus we can't compute
65309b98
DE
2687 a useful value */
2688 if (len == -1)
2689 {
2690 as_bad ("missing `stcycle', can't compute length of `unpack' insn");
2691 len = 1;
2692 }
a9589a2c
DE
2693 if (len < 0 || len > 256)
2694 as_bad ("`unpack' data length must be between 0 and 256");
2695 /* 256 is recorded as 0 in the insn */
57d0c830
DE
2696 len = len == 256 ? 0 : len;
2697 buf[2] = len;
e033023f
DE
2698 }
2699 else
8b901ef8 2700 as_fatal ("internal error: bad call to install_vif_length");
e033023f
DE
2701}
2702
8b901ef8
DE
2703/* Finish off the current set of mpg insns, and start a new set.
2704 The IGNORE arg exists because insert_unpack_marker uses it and both
2705 of these functions are passed to insert_file. */
ba4be194
DE
2706
2707static void
8b901ef8
DE
2708insert_mpg_marker (ignore)
2709 unsigned long ignore;
ba4be194 2710{
8b901ef8
DE
2711 s_endmpg (ENDMPG_MIDDLE);
2712 /* mpgloc is updated by s_endmpg. */
ba4be194
DE
2713 md_assemble ("mpg *,*");
2714 /* Record the cpu type in case we're in the middle of reading binary
2715 data. */
2716 record_mach (DVP_VUUP, 0);
2717}
2718
8b901ef8
DE
2719/* Finish off the current unpack insn and start a new one.
2720 INSN0 is the first word of the insn and is used to figure out what
2721 kind of unpack insn it is. */
2722
2723static void
2724insert_unpack_marker (insn0)
2725 unsigned long insn0;
2726{
2727}
2728
e033023f 2729/* Insert a file into the output.
ba4be194 2730 The -I arg passed to GAS is used to specify where to find the file.
8b901ef8
DE
2731 INSERT_MARKER if non-NULL is called every SIZE bytes with an argument of
2732 INSERT_MARKER_ARG. This is used by the mpg insn to insert mpg's every 256
2733 insns and by the unpack insn.
e033023f
DE
2734 The result is the number of bytes inserted.
2735 If an error occurs an error message is printed and zero is returned. */
2736
2737static int
8b901ef8 2738insert_file (file, insert_marker, insert_marker_arg, size)
e033023f 2739 const char *file;
8b901ef8
DE
2740 void (*insert_marker) PARAMS ((unsigned long));
2741 unsigned long insert_marker_arg;
ba4be194 2742 int size;
e033023f
DE
2743{
2744 FILE *f;
2745 char buf[256];
ba4be194 2746 int i, n, total, left_before_marker;
fe9efeb6 2747 char *path;
e033023f 2748
fe9efeb6
DE
2749 path = xmalloc (strlen (file) + include_dir_maxlen + 5 /*slop*/);
2750 f = NULL;
2751 for (i = 0; i < include_dir_count; i++)
2752 {
2753 strcpy (path, include_dirs[i]);
2754 strcat (path, "/");
2755 strcat (path, file);
2756 if ((f = fopen (path, FOPEN_RB)) != NULL)
2757 break;
2758 }
2759 free (path);
2760 if (f == NULL)
2761 f = fopen (file, FOPEN_RB);
e033023f
DE
2762 if (f == NULL)
2763 {
2764 as_bad ("unable to read file `%s'", file);
2765 return 0;
2766 }
2767
2768 total = 0;
ba4be194 2769 left_before_marker = 0;
e033023f 2770 do {
ba4be194
DE
2771 int bytes;
2772 if (insert_marker)
2773 bytes = MIN (size - left_before_marker, sizeof (buf));
2774 else
2775 bytes = sizeof (buf);
2776 n = fread (buf, 1, bytes, f);
e033023f
DE
2777 if (n > 0)
2778 {
2779 char *fr = frag_more (n);
2780 memcpy (fr, buf, n);
2781 total += n;
ba4be194
DE
2782 if (insert_marker)
2783 {
2784 left_before_marker += n;
2785 if (left_before_marker > size)
8b901ef8 2786 as_fatal ("internal error: file insertion sanity checky failed");
ba4be194
DE
2787 if (left_before_marker == size)
2788 {
8b901ef8 2789 (*insert_marker) (insert_marker_arg);
ba4be194
DE
2790 left_before_marker = 0;
2791 }
2792 }
e033023f
DE
2793 }
2794 } while (n > 0);
2795
2796 fclose (f);
fe9efeb6 2797 /* We assume the file is smaller than 2^31 bytes.
ba4be194 2798 Ok, we shouldn't make any assumptions. */
e033023f
DE
2799 return total;
2800}
2801
020ba60b
DE
2802/* Insert an operand value into an instruction. */
2803
6856244d
DE
2804static void
2805insert_operand (cpu, opcode, operand, mods, insn_buf, val, errmsg)
3a6b8910 2806 dvp_cpu cpu;
6856244d 2807 const dvp_opcode *opcode;
276dd6ef 2808 const dvp_operand *operand;
020ba60b 2809 int mods;
6856244d
DE
2810 DVP_INSN *insn_buf;
2811 offsetT val;
2812 const char **errmsg;
2813{
2814 if (operand->insert)
2815 {
2816 (*operand->insert) (opcode, operand, mods, insn_buf, (long) val, errmsg);
2817 }
2818 else
2819 {
b4cbabb8
DE
2820 /* We currently assume a field does not cross a word boundary. */
2821 int shift = ((mods & DVP_MOD_THIS_WORD)
2822 ? (operand->shift & 31)
2823 : operand->shift);
8151801a
DE
2824 /* FIXME: revisit */
2825 if (operand->word == 0)
b4cbabb8 2826 {
8151801a
DE
2827 int word = (mods & DVP_MOD_THIS_WORD) ? 0 : (shift / 32);
2828 if (operand->bits == 32)
2829 insn_buf[word] = val;
2830 else
2831 {
2832 shift = shift % 32;
2833 insn_buf[word] |= ((long) val & ((1 << operand->bits) - 1)) << shift;
2834 }
b4cbabb8 2835 }
6856244d
DE
2836 else
2837 {
8151801a
DE
2838 int word = (mods & DVP_MOD_THIS_WORD) ? 0 : operand->word;
2839 if (operand->bits == 32)
2840 insn_buf[word] = val;
2841 else
2842 {
2843 long temp = (long) val & ((1 << operand->bits) - 1);
2844 insn_buf[word] |= temp << operand->shift;
2845 }
6856244d
DE
2846 }
2847 }
2848}
2849
2850/* Insert an operand's final value into an instruction.
2851 Here we can give warning messages about operand values if we want to. */
2852
2853static void
2854insert_operand_final (cpu, operand, mods, insn_buf, val, file, line)
2855 dvp_cpu cpu;
2856 const dvp_operand *operand;
2857 int mods;
2858 DVP_INSN *insn_buf;
020ba60b
DE
2859 offsetT val;
2860 char *file;
2861 unsigned int line;
2862{
2863 if (operand->bits != 32)
2864 {
b6675c1a 2865 offsetT min, max, test;
020ba60b 2866
07b20428 2867 /* ??? This test belongs more properly in the insert handler. */
276dd6ef 2868 if ((operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0)
020ba60b
DE
2869 {
2870 if ((val & 7) != 0)
2871 {
2872 if (file == (char *) NULL)
2873 as_warn ("branch to misaligned address");
2874 else
2875 as_warn_where (file, line, "branch to misaligned address");
2876 }
2877 val >>= 3;
2878 }
07b20428
DE
2879 /* ??? This test belongs more properly in the insert handler. */
2880 else if ((operand->flags & DVP_OPERAND_VU_ADDRESS) != 0)
2881 {
2882 if ((val & 7) != 0)
2883 {
2884 if (file == (char *) NULL)
2885 as_warn ("misaligned vu address");
2886 else
2887 as_warn_where (file, line, "misaligned vu address");
2888 }
2889 val >>= 3;
2890 }
020ba60b 2891
276dd6ef 2892 if ((operand->flags & DVP_OPERAND_SIGNED) != 0)
020ba60b 2893 {
276dd6ef 2894 if ((operand->flags & DVP_OPERAND_SIGNOPT) != 0)
020ba60b
DE
2895 max = (1 << operand->bits) - 1;
2896 else
2897 max = (1 << (operand->bits - 1)) - 1;
2898 min = - (1 << (operand->bits - 1));
2899 }
2900 else
2901 {
2902 max = (1 << operand->bits) - 1;
2903 min = 0;
2904 }
2905
276dd6ef 2906 if ((operand->flags & DVP_OPERAND_NEGATIVE) != 0)
020ba60b
DE
2907 test = - val;
2908 else
2909 test = val;
2910
2911 if (test < (offsetT) min || test > (offsetT) max)
2912 {
2913 const char *err =
2914 "operand out of range (%s not between %ld and %ld)";
2915 char buf[100];
2916
2917 sprint_value (buf, test);
2918 if (file == (char *) NULL)
2919 as_warn (err, buf, min, max);
2920 else
2921 as_warn_where (file, line, err, buf, min, max);
2922 }
2923 }
2924
6856244d
DE
2925 {
2926 const char *errmsg = NULL;
2927 insert_operand (cpu, NULL, operand, mods, insn_buf, val, &errmsg);
2928 if (errmsg != NULL)
2929 as_warn_where (file, line, errmsg);
2930 }
020ba60b 2931}
b5d20cf6 2932\f
91572941 2933/* DVP pseudo ops. */
3b2215c2
JL
2934
2935static void
1ece1d56 2936s_dmadata (ignore)
3b2215c2
JL
2937 int ignore;
2938{
1ece1d56 2939 char *name, c;
63589bf4 2940
8151801a 2941 dma_data_name = 0;
3b2215c2 2942
8151801a 2943 if (dma_data_state != 0)
4411d964 2944 {
1ece1d56
DE
2945 as_bad ("DmaData blocks cannot be nested.");
2946 ignore_rest_of_line ();
2947 return;
3b2215c2 2948 }
8151801a 2949 dma_data_state = 1;
4411d964 2950
1ece1d56
DE
2951 SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */
2952 name = input_line_pointer;
4411d964 2953
1ece1d56 2954 if (!is_name_beginner (*name))
3b2215c2 2955 {
1ece1d56
DE
2956 as_bad ("invalid identifier for \".DmaData\"");
2957 ignore_rest_of_line ();
2958 return;
3b2215c2 2959 }
b5d20cf6 2960
e7201c9e
DE
2961 /* Do an implicit alignment to a 16 byte boundary. */
2962 frag_align (4, 0, 0);
2963 record_alignment (now_seg, 4);
2964
1ece1d56
DE
2965 c = get_symbol_end ();
2966 line_label = colon (name); /* user-defined label */
8151801a 2967 dma_data_name = S_GET_NAME (line_label);
1ece1d56 2968 *input_line_pointer = c;
63589bf4 2969
3b4389e2
DE
2970 /* Force emission of a machine type label for the next insn. */
2971 force_mach_label ();
2972
1ece1d56 2973 demand_empty_rest_of_line ();
3b2215c2 2974}
b5d20cf6 2975
3b2215c2 2976static void
1ece1d56 2977s_enddmadata (ignore)
3b2215c2
JL
2978 int ignore;
2979{
8151801a 2980 if (dma_data_state != 1)
3b2215c2 2981 {
1ece1d56
DE
2982 as_warn (".EndDmaData encountered outside a DmaData block -- ignored.");
2983 ignore_rest_of_line ();
8151801a 2984 dma_data_name = 0;
3b2215c2 2985 }
8151801a 2986 dma_data_state = 0;
1ece1d56
DE
2987 demand_empty_rest_of_line ();
2988
e9cb12e4
DE
2989 /* If count provided, verify it is correct. */
2990 /* ... */
2991
89036011
DE
2992 /* Fill the data out to a multiple of 16 bytes. */
2993 /* FIXME: Are the fill contents right? */
2994 frag_align (4, 0, 0);
2995
1ece1d56
DE
2996 /* "label" points to beginning of block.
2997 Create a name for the final label like _$<name>. */
8151801a 2998 if (dma_data_name)
89036011 2999 create_colon_label (0, END_LABEL_PREFIX, dma_data_name);
b5d20cf6 3000}
91572941 3001
b5d20cf6 3002static void
1ece1d56 3003s_dmapackvif (ignore)
4411d964 3004 int ignore;
b5d20cf6 3005{
1ece1d56 3006 /* Syntax: .dmapackvif 0|1 */
63589bf4 3007
1ece1d56
DE
3008 /* Leading whitespace is part of operand. */
3009 SKIP_WHITESPACE ();
3010 switch (*input_line_pointer++)
63589bf4 3011 {
3b2215c2 3012 case '0':
1ece1d56
DE
3013 dma_pack_vif_p = 0;
3014 break;
3b2215c2 3015 case '1':
1ece1d56
DE
3016 dma_pack_vif_p = 1;
3017 break;
63589bf4 3018 default:
7f28a81d 3019 as_bad ("illegal argument to `.dmapackvif'");
63589bf4 3020 }
1ece1d56 3021 demand_empty_rest_of_line ();
b5d20cf6
DE
3022}
3023
ba4be194
DE
3024/* INTERNAL_P is non-zero if invoked internally by this file rather than
3025 by the user. In this case we don't touch the input stream. */
3026
b5d20cf6 3027static void
ba4be194
DE
3028s_enddirect (internal_p)
3029 int internal_p;
b5d20cf6 3030{
498fcb9c 3031 if (CUR_ASM_STATE != ASM_DIRECT)
e1b747c4
DE
3032 {
3033 as_bad ("`.enddirect' has no matching `direct' instruction");
3034 return;
3035 }
3036
8b901ef8
DE
3037 /* Record in the end data symbol the current location. */
3038 if (now_seg != S_GET_SEGMENT (vif_data_end))
3039 as_bad (".enddirect in different section");
3040 vif_data_end->sy_frag = frag_now;
3041 S_SET_VALUE (vif_data_end, (valueT) frag_now_fix ());
e1b747c4 3042
e4d77412 3043 pop_asm_state (1);
498fcb9c 3044
8b901ef8
DE
3045 /* Needn't be reset, but to catch bugs it is. */
3046 vif_data_end = NULL;
498fcb9c 3047
ba4be194
DE
3048 if (! internal_p)
3049 demand_empty_rest_of_line ();
498fcb9c
DE
3050}
3051
8b901ef8
DE
3052/* CALLER denotes who's calling us.
3053 If ENDMPG_USER then .endmpg was found in the input stream.
3054 If ENDMPG_INTERNAL then we've been invoked to finish off file insertion.
3055 If ENDMPG_MIDDLE then we've been invoked in the middle of a long stretch
3056 of vu code. */
83920d29 3057
498fcb9c 3058static void
8b901ef8
DE
3059s_endmpg (caller)
3060 int caller;
498fcb9c 3061{
498fcb9c
DE
3062 if (CUR_ASM_STATE != ASM_MPG)
3063 {
3064 as_bad ("`.endmpg' has no matching `mpg' instruction");
3065 return;
3066 }
3067
8b901ef8
DE
3068 /* Record in the end data symbol the current location. */
3069 if (now_seg != S_GET_SEGMENT (vif_data_end))
3070 as_bad (".endmpg in different section");
3071 vif_data_end->sy_frag = frag_now;
3072 S_SET_VALUE (vif_data_end, (valueT) frag_now_fix ());
3073
3074 /* Update $.mpgloc.
3075 We have to leave the old value alone as it may be used in fixups
07b20428
DE
3076 already recorded. Since compute_mpgloc allocates a new symbol for the
3077 result we're ok. The new value is the old value plus the number of
8b901ef8 3078 double words in this chunk. */
07b20428 3079 mpgloc_sym = compute_mpgloc (mpgloc_sym, vif_data_start, vif_data_end);
498fcb9c 3080
e4d77412 3081 pop_asm_state (1);
498fcb9c 3082
8b901ef8
DE
3083 /* Needn't be reset, but to catch bugs it is. */
3084 vif_data_end = NULL;
498fcb9c 3085
83920d29 3086 /* Reset the vu insn counter. */
8b901ef8
DE
3087 if (caller != ENDMPG_MIDDLE)
3088 vu_count = -1;
498fcb9c 3089
8b901ef8 3090 if (caller == ENDMPG_USER)
83920d29 3091 demand_empty_rest_of_line ();
498fcb9c
DE
3092}
3093
ba4be194
DE
3094/* INTERNAL_P is non-zero if invoked internally by this file rather than
3095 by the user. In this case we don't touch the input stream. */
3096
498fcb9c 3097static void
ba4be194
DE
3098s_endunpack (internal_p)
3099 int internal_p;
498fcb9c 3100{
498fcb9c
DE
3101 if (CUR_ASM_STATE != ASM_UNPACK)
3102 {
3103 as_bad ("`.endunpack' has no matching `unpack' instruction");
3104 return;
3105 }
3106
8b901ef8 3107 /* Record in the end data symbol the current location. */
40f3c6f8
DE
3108 /* ??? $.unpackloc is gone. Is this also used for data length
3109 verification? */
8b901ef8
DE
3110 if (now_seg != S_GET_SEGMENT (vif_data_end))
3111 as_bad (".endunpack in different section");
3112 vif_data_end->sy_frag = frag_now;
3113 S_SET_VALUE (vif_data_end, (valueT) frag_now_fix ());
65309b98 3114
050ac694
DE
3115 /* Round up to next word boundary. */
3116 frag_align (2, 0, 0);
3117
e4d77412 3118 pop_asm_state (1);
fe9efeb6 3119
8b901ef8
DE
3120 /* Needn't be reset, but to catch bugs it is. */
3121 vif_data_end = NULL;
498fcb9c 3122
ba4be194
DE
3123 if (! internal_p)
3124 demand_empty_rest_of_line ();
b5d20cf6
DE
3125}
3126
8151801a
DE
3127static void
3128s_endgif (ignore)
3129 int ignore;
3130{
fa3671a3 3131 int bytes;
d030671b
DE
3132 int specified_nloop = gif_nloop ();
3133 int computed_nloop;
3134 int nregs = gif_nregs ();
fa3671a3
DE
3135 char *file;
3136 unsigned int line;
3137
3138 as_where (&file, &line);
8151801a 3139
498fcb9c 3140 if (CUR_ASM_STATE != ASM_GIF)
8151801a
DE
3141 {
3142 as_bad (".endgif doesn't follow a gif tag");
3143 return;
3144 }
e4d77412 3145 pop_asm_state (1);
8151801a 3146
fa3671a3
DE
3147 /* Fill out to proper boundary.
3148 ??? This may cause eval_expr to always queue a fixup. So be it. */
3149 switch (gif_insn_type)
8151801a 3150 {
fa3671a3
DE
3151 case GIF_PACKED : frag_align (4, 0, 0); break;
3152 case GIF_REGLIST : frag_align (3, 0, 0); break;
3153 case GIF_IMAGE : frag_align (4, 0, 0); break;
8151801a
DE
3154 }
3155
8b901ef8
DE
3156 /* The -16 is because the `gif_data_name' label is emitted at the
3157 start of the gif tag. If we're in a different frag from the one we
3158 started with, this can't be computed until much later. To cope we queue
3159 a fixup and deal with it then.
fa3671a3
DE
3160 ??? The other way to handle this is by having expr() compute "syma - symb"
3161 when they're in different fragments but the difference is constant.
3162 Not sure how much of a slowdown that will introduce though. */
3163 fixup_count = 0;
07b20428 3164 bytes = eval_expr (DVP_GIF, gif_operand_nloop, 0, ". - %s - 16", gif_data_name);
fa3671a3
DE
3165
3166 /* Compute a value for nloop if we can. */
3167
3168 if (fixup_count == 0)
8151801a 3169 {
fa3671a3 3170 computed_nloop = compute_nloop (gif_insn_type, nregs, bytes);
d030671b 3171
fa3671a3
DE
3172 /* If the user specified nloop, verify it. */
3173 if (specified_nloop != -1)
8b901ef8
DE
3174 check_nloop (gif_insn_type, nregs,
3175 specified_nloop, computed_nloop,
fa3671a3
DE
3176 file, line);
3177 }
d030671b 3178
fa3671a3
DE
3179 /* If computation of nloop can't be done yet, queue a fixup and do it later.
3180 Otherwise validate nloop if specified or write the computed value into
d030671b 3181 the insn. */
fa3671a3
DE
3182
3183 if (fixup_count != 0)
d030671b 3184 {
fa3671a3
DE
3185 /* FIXME: It might eventually be possible to combine all the various
3186 copies of this bit of code. */
3187 int op_type, reloc_type, offset;
3188 const dvp_operand *operand;
3189 fixS *fix;
3190
3191 op_type = fixups[0].opindex;
3192 offset = fixups[0].offset;
3193 reloc_type = encode_fixup_reloc_type (DVP_GIF, op_type);
3194 operand = &gif_operands[op_type];
3195 fix = fix_new_exp (gif_insn_frag,
8b901ef8
DE
3196 (gif_insn_frag_loc + offset
3197 - gif_insn_frag->fr_literal),
fa3671a3
DE
3198 4, &fixups[0].exp, 0,
3199 (bfd_reloc_code_real_type) reloc_type);
3200 /* Record user specified value so we can test it when we compute the
3201 actual value. */
3202 fix->tc_fix_data.type = gif_insn_type;
3203 fix->tc_fix_data.nregs = nregs;
8b901ef8 3204 fix->tc_fix_data.user_value = specified_nloop;
8151801a 3205 }
fa3671a3
DE
3206 else if (specified_nloop != -1)
3207 ; /* nothing to do */
8151801a
DE
3208 else
3209 {
fa3671a3 3210 DVP_INSN insn = bfd_getl32 (gif_insn_frag_loc);
8151801a
DE
3211 insert_operand_final (DVP_GIF, &gif_operands[gif_operand_nloop],
3212 DVP_MOD_THIS_WORD, &insn,
d030671b 3213 (offsetT) computed_nloop, file, line);
fa3671a3 3214 bfd_putl32 ((bfd_vma) insn, gif_insn_frag_loc);
8151801a
DE
3215 }
3216
8b901ef8 3217 /* These needn't be reset, but to catch bugs they are. */
8151801a 3218 gif_data_name = NULL;
8b901ef8
DE
3219 gif_insn_frag = NULL;
3220 gif_insn_frag_loc = NULL;
3221
8151801a
DE
3222 demand_empty_rest_of_line ();
3223}
3224
b5d20cf6 3225static void
e4d77412
FCE
3226s_vu (ignore)
3227 int ignore;
b5d20cf6 3228{
d3c6610c
DE
3229 /* If in MPG state and the user requests to change to VU state,
3230 leave the state as MPG. This happens when we see an mpg followed
07b20428
DE
3231 by a .include that has .vu. Note that no attempt is made to support
3232 an include depth > 1 for this case. */
e4d77412 3233 if (CUR_ASM_STATE == ASM_MPG)
d3c6610c
DE
3234 return;
3235
e4d77412
FCE
3236 /* We need to set up things for $.mpgloc calculations. */
3237 /* FIXME: May need to check that we're not clobbering currently
3238 in use versions of these. Also need to worry about which section
3239 the .vu is issued in. On the other hand, ".vu" isn't intended
3240 to be supported everywhere. */
3241 vif_data_start = expr_build_dot ();
3242 mpgloc_sym = expr_build_uconstant (0);
5dccb8b0 3243#if 0 /* ??? wip */
e4d77412
FCE
3244 create_vuoverlay_section (vuoverlay_section_name (NULL), mpgloc_sym,
3245 NULL, NULL);
1554baf3 3246#endif
07b20428 3247
e4d77412 3248 set_asm_state (ASM_VU, ".vu");
4411d964 3249
d3c6610c 3250 demand_empty_rest_of_line ();
e1b747c4 3251}
30596dfc
DE
3252
3253/* Same as read.c:s_func except prepend VU_LABEL_PREFIX by default. */
3254
3255static void
3256s_dvp_func (end_p)
3257 int end_p;
3258{
3259 do_s_func (end_p, VU_LABEL_PREFIX);
3260}
This page took 0.220359 seconds and 4 git commands to generate.