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