* config/tc-dvp.c (LOCAL_LABEL_PREFIX,END_LABEL_PREFIX): New macros.

(inline_dmadata): Renamed from s_dmadata_implied.
	(assemble_one_insn): Rewrite dma operand processing.
	(md_apply_fix3): Handle DVP_OPERAND_DMA_NEXT.
	(unique_name,setup_autocount): New functions.
This commit is contained in:
Doug Evans
1998-02-19 22:51:08 +00:00
parent 6370553445
commit 915729414d
2 changed files with 216 additions and 191 deletions

View File

@ -1,3 +1,25 @@
start-sanitize-sky
Thu Feb 19 02:17:03 1998 Doug Evans <devans@charmed.cygnus.com>
* config/tc-dvp.c (LOCAL_LABEL_PREFIX,END_LABEL_PREFIX): New macros.
(inline_dmadata): Renamed from s_dmadata_implied.
(assemble_one_insn): Rewrite dma operand processing.
(md_apply_fix3): Handle DVP_OPERAND_DMA_NEXT.
(unique_name,setup_autocount): New functions.
* config/tc-dvp.c: Include stdarg.h/varargs.h.
(md_pseudo_table): Add .word.
(assemble_dma): Set alignment to 16 bytes. Enable code that records
fixups.
(assemble_one_insn): Handle DVP_OPERAND_DMA_{ADDR,AUTOCOUNT}.
(md_apply_fix3): Handle DVP_OPERAND_DMA_ADDR.
(parse_dma_addr_autocount): Renamed from parse_dma_ptr_autocount.
Rewrite.
(eval_expr): New function.
(create_label,create_colon_label): New function.
(s_enddmadata): Rewrite.
end-sanitize-sky
Wed Feb 18 23:39:46 1998 Richard Henderson <rth@cygnus.com> Wed Feb 18 23:39:46 1998 Richard Henderson <rth@cygnus.com>
* Makefile.am (install-exec-local): Install properly when ln * Makefile.am (install-exec-local): Install properly when ln

View File

@ -38,12 +38,19 @@
/* Compute DMA operand index number of OP. */ /* Compute DMA operand index number of OP. */
#define DMA_OPERAND_INDEX(op) ((op) - dma_operands) #define DMA_OPERAND_INDEX(op) ((op) - dma_operands)
/* Our local label prefix. */
#define LOCAL_LABEL_PREFIX ".L"
/* Label prefix for end markers used in autocounts. */
#define END_LABEL_PREFIX ".L.end."
static long parse_float PARAMS ((char **, const char **)); static long parse_float PARAMS ((char **, const char **));
static struct symbol * create_label PARAMS ((const char *, const char *)); static struct symbol * create_label PARAMS ((const char *, const char *));
static struct symbol * create_colon_label PARAMS ((const char *, const char *)); 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 eval_expr PARAMS ((int, int, const char *, ...));
static long parse_dma_ild_autocount ();
static long parse_dma_addr_autocount (); static long parse_dma_addr_autocount ();
static void inline_dmadata PARAMS ((int, DVP_INSN *));
static void setup_autocount PARAMS ((const char *, DVP_INSN *));
static void insert_operand static void insert_operand
PARAMS ((dvp_cpu, const dvp_opcode *, const dvp_operand *, int, PARAMS ((dvp_cpu, const dvp_opcode *, const dvp_operand *, int,
@ -73,6 +80,11 @@ typedef enum {
} asm_state; } asm_state;
static asm_state cur_asm_state = ASM_INIT; static asm_state cur_asm_state = ASM_INIT;
/* Nonzero if inside .DmaData. */
static int dmadata_state = 0;
/* Label of .DmaData (internally generated for inline data). */
static const char *dmadata_name;
/* For variable length instructions, pointer to the initial frag /* For variable length instructions, pointer to the initial frag
and pointer into that frag. These only hold valid values if and pointer into that frag. These only hold valid values if
cur_asm_state is one of ASM_MPG, ASM_DIRECT, ASM_UNPACK. */ cur_asm_state is one of ASM_MPG, ASM_DIRECT, ASM_UNPACK. */
@ -139,7 +151,6 @@ static subsegT prev_subseg;
static segT prev_seg; static segT prev_seg;
static void s_dmadata PARAMS ((int)); static void s_dmadata PARAMS ((int));
static void s_dmadata_implied PARAMS ((int));
static void s_enddmadata PARAMS ((int)); static void s_enddmadata PARAMS ((int));
static void s_dmapackvif PARAMS ((int)); static void s_dmapackvif PARAMS ((int));
static void s_enddirect PARAMS ((int)); static void s_enddirect PARAMS ((int));
@ -565,7 +576,7 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
start = str = *pstr; start = str = *pstr;
for ( ; opcode != NULL; opcode = DVP_OPCODE_NEXT_ASM (opcode)) for ( ; opcode != NULL; opcode = DVP_OPCODE_NEXT_ASM (opcode))
{ {
int past_opcode_p, num_suffixes, num_operands; int past_opcode_p, num_suffixes;
const unsigned char *syn; const unsigned char *syn;
/* Ensure the mnemonic part matches. */ /* Ensure the mnemonic part matches. */
@ -578,11 +589,10 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
/* Scan the syntax string. If it doesn't match, try the next one. */ /* Scan the syntax string. If it doesn't match, try the next one. */
dvp_opcode_init_parse (); dvp_opcode_init_parse ();
insn_buf[ opcode->opcode_word] = opcode->value; insn_buf[opcode->opcode_word] = opcode->value;
fixup_count = 0; fixup_count = 0;
past_opcode_p = 0; past_opcode_p = 0;
num_suffixes = 0; num_suffixes = 0;
num_operands = 0;
/* We don't check for (*str != '\0') here because we want to parse /* We don't check for (*str != '\0') here because we want to parse
any trailing fake arguments in the syntax string. */ any trailing fake arguments in the syntax string. */
@ -623,6 +633,15 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
if (operand->flags & DVP_OPERAND_FAKE) if (operand->flags & DVP_OPERAND_FAKE)
{ {
long value = 0; long value = 0;
if (operand->flags & DVP_OPERAND_DMA_INLINE)
{
inline_dmadata ((mods & DVP_OPERAND_AUTOCOUNT) != 0,
insn_buf);
++syn;
continue;
}
if (operand->parse) if (operand->parse)
{ {
errmsg = NULL; errmsg = NULL;
@ -690,23 +709,6 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
if (operand->flags & DVP_OPERAND_SUFFIX) if (operand->flags & DVP_OPERAND_SUFFIX)
as_fatal ("bad opcode table, suffix wrong"); as_fatal ("bad opcode table, suffix wrong");
#if 0 /* commas are in the syntax string now */
/* If this is not the first, there must be a comma. */
if (num_operands > 0)
{
if (*str != ',')
break;
++str;
}
#endif
if (operand->flags & DVP_OPERAND_DMA_ILD)
{
s_dmadata_implied (0);
++syn;
break;
}
/* Is there anything left to parse? /* Is there anything left to parse?
We don't check for this at the top because we want to parse We don't check for this at the top because we want to parse
any trailing fake arguments in the syntax string. */ any trailing fake arguments in the syntax string. */
@ -722,16 +724,8 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
if (errmsg) if (errmsg)
break; break;
} }
else if (operand->flags & DVP_OPERAND_DMA_ILD_AUTOCOUNT) else if ((operand->flags & DVP_OPERAND_DMA_ADDR)
{ && (mods & DVP_OPERAND_AUTOCOUNT))
errmsg = 0;
value = parse_dma_ild_autocount (opcode, operand, mods,
insn_buf, &str, &errmsg);
if (errmsg)
break;
}
else if ((operand->flags & (DVP_OPERAND_DMA_ADDR | DVP_OPERAND_DMA_AUTOCOUNT))
== (DVP_OPERAND_DMA_ADDR | DVP_OPERAND_DMA_AUTOCOUNT))
{ {
errmsg = 0; errmsg = 0;
value = parse_dma_addr_autocount (opcode, operand, mods, value = parse_dma_addr_autocount (opcode, operand, mods,
@ -791,7 +785,6 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
break; break;
++syn; ++syn;
++num_operands;
} }
} }
@ -1017,7 +1010,8 @@ md_apply_fix3 (fixP, valueP, seg)
&& operand->shift == 0); && operand->shift == 0);
fixP->fx_r_type = BFD_RELOC_MIPS_DVP_11_PCREL; fixP->fx_r_type = BFD_RELOC_MIPS_DVP_11_PCREL;
} }
else if ((operand->flags & DVP_OPERAND_DMA_ADDR) != 0) else if ((operand->flags & DVP_OPERAND_DMA_ADDR) != 0
|| (operand->flags & DVP_OPERAND_DMA_NEXT) != 0)
{ {
assert (operand->bits == 27 assert (operand->bits == 27
&& operand->shift == 4); && operand->shift == 4);
@ -1166,6 +1160,8 @@ md_atof (type, litP, sizeP)
return 0; return 0;
} }
/* Miscellaneous utilities. */
/* Parse a 32 bit floating point number. /* Parse a 32 bit floating point number.
The result is those 32 bits as an integer. */ The result is those 32 bits as an integer. */
@ -1181,34 +1177,9 @@ parse_float (pstr, errmsg)
*pstr = p; *pstr = p;
return (words[0] << 16) | words[1]; return (words[0] << 16) | words[1];
} }
/* Compute the auto-count value for a DMA tag with inline data. */
static long
parse_dma_ild_autocount (opcode, operand, mods, insn_buf, pstr, errmsg)
const dvp_opcode *opcode;
const dvp_operand *operand;
int mods;
DVP_INSN *insn_buf;
char **pstr;
const char **errmsg;
{
char *start = *pstr;
char *end = start;
long retval;
#if 0
/* FIXME: unfinished */
evaluate the operand as an expression
store the value to the count field
compute the length as _$EndDma-.
#endif
*pstr = end;
return 0;
}
/* Scan a symbol and return a pointer to one past the end. */ /* Scan a symbol and return a pointer to one past the end. */
#define issymchar(ch) (isalnum(ch) || ch == '_') #define issymchar(ch) (isalnum(ch) || ch == '_')
static char * static char *
scan_symbol (sym) scan_symbol (sym)
@ -1219,60 +1190,6 @@ scan_symbol (sym)
return sym; return sym;
} }
/* Compute the auto-count value for a DMA tag with out-of-line data. */
static long
parse_dma_addr_autocount (opcode, operand, mods, insn_buf, pstr, errmsg)
const dvp_opcode *opcode;
const dvp_operand *operand;
int mods;
DVP_INSN *insn_buf;
char **pstr;
const char **errmsg;
{
char *start = *pstr;
char *end = start;
long retval;
/* Data reference must be a .DmaData label. */
struct symbol *label, *label2, *endlabel;
const char *name;
char *name2;
int len;
long count;
char c;
label = label2 = 0;
if (! is_name_beginner (*start))
{
*errmsg = "invalid .DmaData label";
return 0;
}
name = start;
end = scan_symbol (name);
c = *end;
*end = 0;
label = symbol_find_or_make (name);
*end = c;
label2 = create_label ("_$", name);
/* FIXME: revisit .L. */
endlabel = create_label (".L.end.", name);
retval = eval_expr (dma_operand_addr, operand->word * 4, name);
count = eval_expr (dma_operand_count, (operand->word + 1) * 4,
".L.end.%s - %s", name, name);
/* count is in quadwords */
count /= 16;
/* Store the count field. */
insn_buf[3] &= 0xffff0000;
insn_buf[3] |= count & 0x0000ffff;
*pstr = end;
return retval;
}
/* Evaluate an expression. /* Evaluate an expression.
The result is the value of the expression if it can be evaluated, 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) or 0 if it cannot (say because some symbols haven't been defined yet)
@ -1357,6 +1274,166 @@ create_colon_label (prefix, name)
free (fullname); free (fullname);
return result; return result;
} }
/* Return a malloc'd string useful in creating unique labels. */
/* ??? Presumably such a routine already exists somewhere
[but a first pass at finding it didn't turn up anything]. */
static char *
unique_name ()
{
static int counter;
char *result;
asprintf (&result, "dvptmp%d", counter);
++counter;
return result;
}
/* Compute the auto-count value for a DMA tag. */
static void
setup_autocount (name, insn_buf)
const char *name;
DVP_INSN *insn_buf;
{
long count;
count = eval_expr (dma_operand_count, 12,
"(%s%s - %s) >> 4", END_LABEL_PREFIX, name, name);
/* count is in quadwords */
count /= 16;
/* Store the count field. */
insn_buf[3] &= 0xffff0000;
insn_buf[3] |= count & 0x0000ffff;
}
/* Record that inline data follows. */
static void
inline_dmadata (autocount_p, insn_buf)
int autocount_p;
DVP_INSN *insn_buf;
{
if (dmadata_state != 0 )
{
as_bad ("DmaData blocks cannot be nested.");
return;
}
dmadata_state = 1;
if (autocount_p)
{
dmadata_name = S_GET_NAME (create_colon_label ("", unique_name ()));
setup_autocount (dmadata_name, insn_buf);
}
else
dmadata_name = 0;
}
/* Compute the auto-count value for a DMA tag with out-of-line data. */
static long
parse_dma_addr_autocount (opcode, operand, mods, insn_buf, pstr, errmsg)
const dvp_opcode *opcode;
const dvp_operand *operand;
int mods;
DVP_INSN *insn_buf;
char **pstr;
const char **errmsg;
{
char *start = *pstr;
char *end = start;
long retval;
/* Data reference must be a .DmaData label. */
struct symbol *label, *label2, *endlabel;
const char *name;
char c;
label = label2 = 0;
if (! is_name_beginner (*start))
{
*errmsg = "invalid .DmaData label";
return 0;
}
name = start;
end = scan_symbol (name);
c = *end;
*end = 0;
label = symbol_find_or_make (name);
*end = c;
label2 = create_label ("_$", name);
endlabel = create_label (END_LABEL_PREFIX, name);
retval = eval_expr (dma_operand_addr, 8, name);
setup_autocount (name, insn_buf);
*pstr = end;
return retval;
}
/* Parse a DMA data spec which can be either of '*' or a quad word count. */
static int
parse_dma_count (pstr, errmsg)
char **pstr;
const char **errmsg;
{
char *str = *pstr;
long count, value;
expressionS exp;
if (*str == '*')
{
++*pstr;
/* -1 is a special marker to caller to tell it the count is to be
computed from the data. */
return -1;
}
expression (&exp);
if (exp.X_op == O_illegal
|| exp.X_op == O_absent)
;
else if (exp.X_op == O_constant)
value = exp.X_add_number;
else if (exp.X_op == O_register)
as_fatal ("got O_register");
else
{
/* We need to generate a fixup for this expression. */
if (fixup_count >= MAX_FIXUPS )
as_fatal ("too many fixups");
fixups[fixup_count].exp = exp;
fixups[fixup_count].opindex = 0 /*FIXME*/;
fixups[fixup_count].offset = 0 /*FIXME*/;
++fixup_count;
value = 0;
}
if (isdigit( *str)) /* ????????needs to accept an expression*/
{
char *start = str;
while (*str && *str != ',')
++str;
if (*str != ',')
{
*errmsg = "invalid dma count";
return 0;
}
count = atoi (start);
*pstr = str;
return (count);
}
*errmsg = "invalid dma count";
return 0;
}
/* Return length in bytes of the variable length VIF insn /* Return length in bytes of the variable length VIF insn
currently being assembled. */ currently being assembled. */
@ -1584,23 +1661,7 @@ insert_operand_final (cpu, operand, mods, insn_buf, val, file, line)
} }
} }
static short dmadata_state = 0; /* DVP pseudo ops. */
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_implied (ignore)
int ignore;
{
if (dmadata_state != 0 )
{
as_bad ("DmaData blocks cannot be nested.");
}
dmadata_state = 1;
dmadata_name = 0;
}
static void static void
s_dmadata (ignore) s_dmadata (ignore)
@ -1656,10 +1717,10 @@ s_enddmadata (ignore)
/* Fill the data out to a multiple of 16 bytes. */ /* Fill the data out to a multiple of 16 bytes. */
/* FIXME: Does the fill contents matter? */ /* FIXME: Does the fill contents matter? */
frag_align (4, 0, 0); frag_align (4, 0, 0);
create_colon_label (".L.end.", dmadata_name); create_colon_label (END_LABEL_PREFIX, dmadata_name);
} }
} }
static void static void
s_dmapackvif (ignore) s_dmapackvif (ignore)
int ignore; int ignore;
@ -1784,61 +1845,3 @@ s_endgif (ignore)
int ignore; int ignore;
{ {
} }
/* Parse a DMA data spec which can be either of '*' or a quad word count. */
static int
parse_dma_count (pstr, errmsg)
char **pstr;
const char **errmsg;
{
char *str = *pstr;
long count, value;
expressionS exp;
if (*str == '*')
{
++*pstr;
/* -1 is a special marker to caller to tell it the count is to be
computed from the data. */
return -1;
}
expression (&exp);
if (exp.X_op == O_illegal
|| exp.X_op == O_absent)
;
else if (exp.X_op == O_constant)
value = exp.X_add_number;
else if (exp.X_op == O_register)
as_fatal ("got O_register");
else
{
/* We need to generate a fixup for this expression. */
if (fixup_count >= MAX_FIXUPS )
as_fatal ("too many fixups");
fixups[fixup_count].exp = exp;
fixups[fixup_count].opindex = 0 /*FIXME*/;
fixups[fixup_count].offset = 0 /*FIXME*/;
++fixup_count;
value = 0;
}
if (isdigit( *str)) /* ????????needs to accept an expression*/
{
char *start = str;
while (*str && *str != ',')
++str;
if (*str != ',')
{
*errmsg = "invalid dma count";
return 0;
}
count = atoi (start);
*pstr = str;
return (count);
}
*errmsg = "invalid dma count";
return 0;
}