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