diff options
author | Doug Evans <dje@google.com> | 1998-02-21 02:12:15 +0000 |
---|---|---|
committer | Doug Evans <dje@google.com> | 1998-02-21 02:12:15 +0000 |
commit | 8151801a092be04feffab9ca3d2098d1f7397f18 (patch) | |
tree | d119839e2a2f901687865d7e546edfa430dfece6 /gas/config | |
parent | c2b2e0f0f3590e6a2be0ffe4d14498d8b1d90969 (diff) | |
download | gdb-8151801a092be04feffab9ca3d2098d1f7397f18.zip gdb-8151801a092be04feffab9ca3d2098d1f7397f18.tar.gz gdb-8151801a092be04feffab9ca3d2098d1f7397f18.tar.bz2 |
(asm_state): New state ASM_GIF.
(gif_{insn_type,data_name,insn_frag}): New static locals.
(md_assemble): Watch for .endgif if in ASM_GIF state.
(assemble_gif): Complete.
(s_endgif): Complete.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-dvp.c | 195 |
1 files changed, 156 insertions, 39 deletions
diff --git a/gas/config/tc-dvp.c b/gas/config/tc-dvp.c index 38a65ef..885fa6b 100644 --- a/gas/config/tc-dvp.c +++ b/gas/config/tc-dvp.c @@ -49,7 +49,7 @@ static struct symbol * create_colon_label PARAMS ((const char *, const char *)); static char * unique_name PARAMS ((void)); static long eval_expr PARAMS ((int, int, const char *, ...)); static long parse_dma_addr_autocount (); -static void inline_dmadata PARAMS ((int, DVP_INSN *)); +static void inline_dma_data PARAMS ((int, DVP_INSN *)); static void setup_autocount PARAMS ((const char *, DVP_INSN *)); static void insert_operand @@ -76,14 +76,21 @@ const char FLT_CHARS[] = "dD"; be provided. (e.g. mpg is followed by vu insns until a .EndMpg is seen). */ typedef enum { - ASM_INIT, ASM_MPG, ASM_DIRECT, ASM_UNPACK, ASM_VU + ASM_INIT, ASM_MPG, ASM_DIRECT, ASM_UNPACK, ASM_VU, ASM_GIF } asm_state; static asm_state cur_asm_state = ASM_INIT; /* Nonzero if inside .DmaData. */ -static int dmadata_state = 0; +static int dma_data_state = 0; /* Label of .DmaData (internally generated for inline data). */ -static const char *dmadata_name; +static const char *dma_data_name; + +/* Type of gif tag. */ +static gif_type gif_insn_type; +/* Name of label of current gif<foo> insn's data. */ +static const char *gif_data_name; +/* Pointer to current gif insn in fragment. */ +static char *gif_insn_frag; /* For variable length instructions, pointer to the initial frag and pointer into that frag. These only hold valid values if @@ -154,6 +161,7 @@ static void s_dmadata PARAMS ((int)); static void s_enddmadata PARAMS ((int)); static void s_dmapackvif PARAMS ((int)); static void s_enddirect PARAMS ((int)); +static void s_endgif PARAMS ((int)); static void s_endmpg PARAMS ((int)); static void s_endunpack PARAMS ((int)); static void s_state PARAMS ((int)); @@ -166,6 +174,7 @@ const pseudo_typeS md_pseudo_table[] = { "dmapackvif", s_dmapackvif, 0 }, { "enddirect", s_enddirect, 0 }, { "enddmadata", s_enddmadata, 0 }, + { "endgif", s_endgif, 0 }, { "endmpg", s_endmpg, 0 }, { "endunpack", s_endunpack, 0 }, /* .vu added to simplify debugging and creation of input files */ @@ -243,6 +252,13 @@ md_assemble (str) while (isspace (*str)) str++; + /* After a gif tag, no insns can appear until a .endgif is seen. */ + if (cur_asm_state == ASM_GIF) + { + as_bad ("missing .endgif"); + cur_asm_state = ASM_INIT; + } + if (cur_asm_state == ASM_INIT) { if (strncasecmp (str, "dma", 3) == 0) @@ -446,12 +462,40 @@ assemble_gif (str) { DVP_INSN insn_buf[4]; const dvp_opcode *opcode; + char *f; + int i; + + insn_buf[0] = insn_buf[1] = insn_buf[2] = insn_buf[3] = 0; opcode = assemble_one_insn (DVP_GIF, gif_opcode_lookup_asm (str), gif_operands, &str, insn_buf); if (opcode == NULL) return; + + /* Do an implicit alignment to a 16 byte boundary. */ + frag_align (4, 0, 0); + record_alignment (now_seg, 4); + + gif_insn_frag = f = frag_more (16); + for (i = 0; i < 4; ++i) + md_number_to_chars (f + i * 4, insn_buf[i], 4); + + /* Insert a label so we can compute the number of quadwords when the + .endgif is seen. */ + gif_data_name = S_GET_NAME (create_colon_label ("", unique_name ())); + + /* Record the type of the gif tag so we know how to compute nloop + in s_endgif. */ + if (strcmp (opcode->mnemonic, "gifpacked") == 0) + gif_insn_type = GIF_PACKED; + else if (strcmp (opcode->mnemonic, "gifreglist") == 0) + gif_insn_type = GIF_REGLIST; + else if (strcmp (opcode->mnemonic, "gifimage") == 0) + gif_insn_type = GIF_IMAGE; + else + abort (); + cur_asm_state = ASM_GIF; } /* Subroutine of md_assemble to assemble VU instructions. */ @@ -636,7 +680,7 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf) if (operand->flags & DVP_OPERAND_DMA_INLINE) { - inline_dmadata ((mods & DVP_OPERAND_AUTOCOUNT) != 0, + inline_dma_data ((mods & DVP_OPERAND_AUTOCOUNT) != 0, insn_buf); ++syn; continue; @@ -1196,7 +1240,9 @@ scan_symbol (sym) /* Evaluate an expression. The result is the value of the expression if it can be evaluated, or 0 if it cannot (say because some symbols haven't been defined yet) - in which case a fixup is queued. */ + in which case a fixup is queued. + + If OPINDEX is 0, don't queue any fixups, just return 0. */ static long #ifdef USE_STDARG @@ -1230,10 +1276,13 @@ eval_expr (opindex, offset, fmt, va_alist) value = exp.X_add_number; else { - fixups[fixup_count].exp = exp; - fixups[fixup_count].opindex = opindex; - fixups[fixup_count].offset = offset; - ++fixup_count; + if (opindex != 0) + { + fixups[fixup_count].exp = exp; + fixups[fixup_count].opindex = opindex; + fixups[fixup_count].offset = offset; + ++fixup_count; + } value = 0; } return value; @@ -1315,25 +1364,25 @@ setup_autocount (name, insn_buf) /* Record that inline data follows. */ static void -inline_dmadata (autocount_p, insn_buf) +inline_dma_data (autocount_p, insn_buf) int autocount_p; DVP_INSN *insn_buf; { - if (dmadata_state != 0 ) + if (dma_data_state != 0 ) { as_bad ("DmaData blocks cannot be nested."); return; } - dmadata_state = 1; + dma_data_state = 1; if (autocount_p) { - dmadata_name = S_GET_NAME (create_colon_label ("", unique_name ())); - setup_autocount (dmadata_name, insn_buf); + dma_data_name = S_GET_NAME (create_colon_label ("", unique_name ())); + setup_autocount (dma_data_name, insn_buf); } else - dmadata_name = 0; + dma_data_name = 0; } /* Compute the auto-count value for a DMA tag with out-of-line data. */ @@ -1514,26 +1563,30 @@ insert_operand (cpu, opcode, operand, mods, insn_buf, val, errmsg) int shift = ((mods & DVP_MOD_THIS_WORD) ? (operand->shift & 31) : operand->shift); - int word = (mods & DVP_MOD_THIS_WORD) ? 0 : operand->word; -#if 0 /* FIXME: revisit */ - DVP_INSN *p = insn_buf + (shift / 32); - if (operand->bits == 32) - *p = val; - else + /* FIXME: revisit */ + if (operand->word == 0) { - shift = shift % 32; - *p |= ((long) val & ((1 << operand->bits) - 1)) << shift; + int word = (mods & DVP_MOD_THIS_WORD) ? 0 : (shift / 32); + if (operand->bits == 32) + insn_buf[word] = val; + else + { + shift = shift % 32; + insn_buf[word] |= ((long) val & ((1 << operand->bits) - 1)) << shift; + } } -#else - if (operand->bits == 32) - insn_buf[word] = val; else { - long temp = (long) val & ((1 << operand->bits) - 1); - insn_buf[word] |= temp << operand->shift; + int word = (mods & DVP_MOD_THIS_WORD) ? 0 : operand->word; + if (operand->bits == 32) + insn_buf[word] = val; + else + { + long temp = (long) val & ((1 << operand->bits) - 1); + insn_buf[word] |= temp << operand->shift; + } } } -#endif } /* Insert an operand's final value into an instruction. @@ -1614,15 +1667,15 @@ s_dmadata (ignore) { char *name, c; - dmadata_name = 0; + dma_data_name = 0; - if (dmadata_state != 0) + if (dma_data_state != 0) { as_bad ("DmaData blocks cannot be nested."); ignore_rest_of_line (); return; } - dmadata_state = 1; + dma_data_state = 1; SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */ name = input_line_pointer; @@ -1636,7 +1689,7 @@ s_dmadata (ignore) c = get_symbol_end (); line_label = colon (name); /* user-defined label */ - dmadata_name = S_GET_NAME (line_label); + dma_data_name = S_GET_NAME (line_label); *input_line_pointer = c; demand_empty_rest_of_line (); @@ -1646,23 +1699,23 @@ static void s_enddmadata (ignore) int ignore; { - if (dmadata_state != 1) + if (dma_data_state != 1) { as_warn (".EndDmaData encountered outside a DmaData block -- ignored."); ignore_rest_of_line (); - dmadata_name = 0; + dma_data_name = 0; } - dmadata_state = 0; + dma_data_state = 0; demand_empty_rest_of_line (); /* "label" points to beginning of block. Create a name for the final label like _$<name>. */ - if (dmadata_name) + if (dma_data_name) { /* Fill the data out to a multiple of 16 bytes. */ /* FIXME: Does the fill contents matter? */ frag_align (4, 0, 0); - create_colon_label (END_LABEL_PREFIX, dmadata_name); + create_colon_label (END_LABEL_PREFIX, dma_data_name); } } @@ -1720,6 +1773,70 @@ s_enddirect (ignore) } static void +s_endgif (ignore) + int ignore; +{ + long count; + int nloop = gif_nloop (); + + if (cur_asm_state != ASM_GIF) + { + as_bad (".endgif doesn't follow a gif tag"); + return; + } + cur_asm_state = ASM_INIT; + + if (gif_insn_type == GIF_PACKED) + count = eval_expr (0, 0, "(. - %s) >> 4", gif_data_name); + else + count = eval_expr (0, 0, "(. - %s) >> 3", gif_data_name); + + if (count < 0 + || fixup_count != 0) + { + as_bad ("bad data count"); + return; + } + + /* Validate nloop if specified. Otherwise write the computed value into + the insn. */ + if (nloop != -1) + { + int ok_p; + + switch (gif_insn_type) + { + case GIF_PACKED : + case GIF_REGLIST : + ok_p = count == nloop * gif_nregs (); + break; + case GIF_IMAGE : + ok_p = count == nloop; + break; + } + if (! ok_p) + { + as_bad ("nloop value does not match size of data"); + return; + } + } + else + { + DVP_INSN insn = bfd_getl32 (gif_insn_frag + 12); + char *file; + unsigned int line; + as_where (&file, &line); + insert_operand_final (DVP_GIF, &gif_operands[gif_operand_nloop], + DVP_MOD_THIS_WORD, &insn, + (offsetT) nloop, file, line); + bfd_putl32 ((bfd_vma) insn, gif_insn_frag + 12); + } + + gif_data_name = NULL; + demand_empty_rest_of_line (); +} + +static void s_endmpg (ignore) int ignore; { |