static segT prev_seg;
static void s_dmadata PARAMS ((int));
+static void s_dmadata_implied PARAMS ((int));
+static void s_enddmadata PARAMS ((int));
static void s_dmapackpke PARAMS ((int));
static void s_enddirect PARAMS ((int));
static void s_endgpuif PARAMS ((int));
/* The target specific pseudo-ops which we support. */
const pseudo_typeS md_pseudo_table[] =
{
- { "dmadata", s_dmadata, 1 },
- { "dmapackpke", s_dmapackpke, 0 },
- { "enddirect", s_enddirect, 0 },
- { "enddmadata", s_dmadata, 0 },
- { "endgpuif", s_endgpuif, 0 },
- { "endmpg", s_endmpg, 0 },
- { "endunpack", s_endunpack, 0 },
- /* .vu,.gpuif added to simplify debugging */
- { "vu", s_state, ASM_VU },
- { "gpuif", s_state, ASM_GPUIF },
- { NULL, NULL, 0 }
+ { "dmadata", s_dmadata, 0 },
+ { "dmapackpke", s_dmapackpke, 0 },
+ { "enddirect", s_enddirect, 0 },
+ { "enddmadata", s_enddmadata, 0 },
+ { "endgpuif", s_endgpuif, 0 },
+ { "endmpg", s_endmpg, 0 },
+ { "endunpack", s_endunpack, 0 },
+ /* .vu,.gpuif added to simplify debugging */
+ { "vu", s_state, ASM_VU },
+ { "gpuif", s_state, ASM_GPUIF },
+ { NULL, NULL, 0 }
};
\f
void
assemble_dma (str)
char *str;
{
- DVP_INSN insn_buf[4];
- const dvp_opcode *opcode;
+ DVP_INSN insn_buf[4];
+ int len; /* Insn's length, in 32 bit words. */
+ char *f; /* Pointer to allocated frag. */
+ int i;
+ const dvp_opcode *opcode;
- opcode = assemble_one_insn (DVP_DMA,
- dma_opcode_lookup_asm (str), dma_operands,
- &str, insn_buf);
- if (opcode == NULL)
- return;
- if (! output_dma)
- return;
+ /*
+ Fill the first two words with PKE NOPs.
+ They may be over-written later if DmaPackPke is on.
+ initialize the remainder with zeros.
+ */
+ insn_buf[ 0] = 0;
+ insn_buf[ 1] = 0;
+ insn_buf[ 2] = 0;
+ insn_buf[ 3] = 0;
+
+ opcode = assemble_one_insn (DVP_DMA,
+ dma_opcode_lookup_asm (str), dma_operands,
+ &str, insn_buf);
+ if( opcode == NULL) return;
+ if( !output_dma) return;
+
+ len = 4;
+ f = frag_more( len * 4);
+
+ /* Write out the PKE / DMA instructions. */
+ for( i = 0; i < len; ++i)
+ md_number_to_chars( f + i * 4, insn_buf[i], 4);
+
+ /* Create any fixups. */
+ /* FIXME: It might eventually be possible to combine all the various
+ copies of this bit of code. */
+ for( i = 0; i < fixup_count; ++i)
+ {
+ int op_type, reloc_type, offset;
+ const dvp_operand *operand;
+
+#if 0
+ /*
+ Create a fixup for this operand.
+ At this point we do not use a bfd_reloc_code_real_type for
+ operands residing in the insn, but instead just use the
+ operand index. This lets us easily handle fixups for any
+ operand type, although that is admittedly not a very exciting
+ feature. We pick a BFD reloc type in md_apply_fix.
+ */
+
+ op_type = fixups[i].opindex;
+ offset = fixups[i].offset;
+ reloc_type = encode_fixup_reloc_type (DVP_PKE, op_type);
+ operand = &pke_operands[op_type];
+ fix_new_exp (frag_now, f + offset - frag_now->fr_literal, 4,
+ &fixups[i].exp,
+ (operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0,
+ (bfd_reloc_code_real_type) reloc_type);
+#endif
+ }
}
/* Subroutine of md_assemble to assemble PKE instructions. */
/* Scan the syntax string. If it doesn't match, try the next one. */
dvp_opcode_init_parse ();
- *insn_buf = opcode->value;
+ insn_buf[ opcode->opcode_word] = opcode->value;
fixup_count = 0;
past_opcode_p = 0;
num_suffixes = 0;
}
#endif
+ if( operand->flags & DVP_OPERAND_DMA_ILD)
+ {
+ s_dmadata_implied( 0);
+ ++syn;
+ break;
+ }
+
/* Is there anything left to parse?
We don't check for this at the top because we want to parse
any trailing fake arguments in the syntax string. */
if (*str == '\0')
break;
-#if 0
- /* Is this the special DMA count operand? */
- if( operand->flags & DVP_OPERAND_DMA_COUNT)
- dvp_dma_operand_autocount( 0);
- if( (operand->flags & DVP_OPERAND_DMA_COUNT) && *str == '*')
- {
- /* Yes, it is!
- Remember that we must compute the length later
- when the dma-block label (second operand) is known. */
- ++str;
- dvp_dma_operand_autocount( 1);
- }
-#endif
-
+ /* Parse the operand. */
if( operand->flags & DVP_OPERAND_DMA_ILD_AUTOCOUNT)
{
errmsg = 0;
value = parse_dma_ild_autocount( opcode, operand, mods, insn_buf, &str, &errmsg);
if( errmsg) break;
}
-
- if( operand->flags & DVP_OPERAND_DMA_PTR_AUTOCOUNT)
+ else if( operand->flags & DVP_OPERAND_DMA_PTR_AUTOCOUNT)
{
errmsg = 0;
value = parse_dma_ptr_autocount( opcode, operand, mods, insn_buf, &str, &errmsg);
if( errmsg) break;
}
-
- /* Parse the operand. */
else if (operand->parse)
{
errmsg = NULL;
else
{
/* We currently assume a field does not cross a word boundary. */
- int shift = ((mods & DVP_MOD_THIS_WORD)
- ? (operand->shift & 31)
- : operand->shift);
- DVP_INSN *p = insn_buf + (shift / 32);
if (operand->bits == 32)
- *p = val;
+ insn_buf[ operand->word] = val;
else
{
- shift = shift % 32;
- *p |= ((long) val & ((1 << operand->bits) - 1)) << shift;
+ long temp = (long) val & ((1 << operand->bits) - 1);
+ insn_buf[ operand->word] |= temp << operand->shift;
}
}
}
}
}
\f
+static short dmadata_state = 0;
+static const char *dmadata_name;
+
+/* Non-zero if .DmaData was implied by a real (non-pseudo) opcode. */
+static int implied_dmadata_p = 0;
+
static void
-s_dmadata( type)
- int type;
+s_dmadata_implied( ignore)
+ int ignore;
{
- static short state = 0;
- static symbolS *label; /* Points to symbol */
- char *name;
- const char *prevName;
- int temp;
+ if( dmadata_state != 0 )
+ {
+ as_bad( "DmaData blocks cannot be nested.");
+ }
+ dmadata_state = 1;
+ dmadata_name = 0;
+}
+
+static void
+s_dmadata( ignore)
+ int ignore;
+{
+ char *name, c;
- switch( type )
+ dmadata_name = 0;
+
+ if( dmadata_state != 0 )
{
- case 1: /* .DmaData */
- if( state != 0 )
- {
- as_bad( "DmaData blocks cannot be nested.");
- ignore_rest_of_line();
- state = 1;
- break;
- }
- state = 1;
+ as_bad( "DmaData blocks cannot be nested.");
+ ignore_rest_of_line();
+ return;
+ }
+ dmadata_state = 1;
- SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
- name = input_line_pointer;
+ SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
+ name = input_line_pointer;
- if( !is_name_beginner( *name) )
- {
- as_bad( "invalid identifier for \".DmaData\"");
- obstack_1grow( &cond_obstack, 0);
- ignore_rest_of_line();
- break;
- }
- else
- {
- char c;
+ if( !is_name_beginner( *name) )
+ {
+ as_bad( "invalid identifier for \".DmaData\"");
+ obstack_1grow( &cond_obstack, 0); /*FIXME what is this for?*/
+ ignore_rest_of_line();
+ return;
+ }
- c = get_symbol_end();
- line_label = label = colon( name); /* user-defined label */
- *input_line_pointer = c;
+ c = get_symbol_end();
+ line_label = colon( name); /* user-defined label */
+ dmadata_name = line_label->bsym->name;
+ *input_line_pointer = c;
- demand_empty_rest_of_line();
- } /* if a valid identifyer name */
- break;
+ demand_empty_rest_of_line();
+}
- case 0: /* .EndDmaData */
- if( state != 1 )
- {
- as_warn( ".EndDmaData encountered outside a DmaData block -- ignored.");
- ignore_rest_of_line();
- state = 0;
- break;
- }
- state = 0;
- demand_empty_rest_of_line();
+static void
+s_enddmadata( ignore)
+ int ignore;
+{
+ if( dmadata_state != 1)
+ {
+ as_warn( ".EndDmaData encountered outside a DmaData block -- ignored.");
+ ignore_rest_of_line();
+ dmadata_name = 0;
+ }
+ dmadata_state = 0;
+ demand_empty_rest_of_line();
- /*
- * "label" points to beginning of block
- * Create a name for the final label like _$<name>
- */
- prevName = label->bsym->name;
- temp = strlen( prevName) + 1;
+ /*
+ * "label" points to beginning of block
+ * Create a name for the final label like _$<name>
+ */
+ if( dmadata_name) {
+ int temp;
+ char *name;
+
+ temp = strlen( dmadata_name) + 1;
name = xmalloc( temp + 2);
name[ 0] = '_';
name[ 1] = '$';
- memcpy( name+2, prevName, temp); /* copy original name & \0 */
+ memcpy( name+2, dmadata_name, temp); /* copy original name & \0 */
colon( name);
free( name);
- break;
-
- default:
- as_assert( __FILE__, __LINE__, 0);
}
}
-
+\f
static void
s_dmapackpke( ignore)
int ignore;
SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
switch( *input_line_pointer++ )
{
- case 0:
+ case '0':
dma_pack_pke_p = 0;
break;
- case 1:
+ case '1':
dma_pack_pke_p = 1;
break;
default: