checkpoint
This commit is contained in:
parent
8dddf63f16
commit
e1b747c4f2
1 changed files with 135 additions and 41 deletions
|
@ -40,6 +40,7 @@ static void insert_operand_final
|
||||||
|
|
||||||
static int insert_file PARAMS ((const char *));
|
static int insert_file PARAMS ((const char *));
|
||||||
|
|
||||||
|
static int cur_pke_insn_length PARAMS ((void));
|
||||||
static void install_pke_length PARAMS ((char *, int));
|
static void install_pke_length PARAMS ((char *, int));
|
||||||
|
|
||||||
const char comment_chars[] = ";";
|
const char comment_chars[] = ";";
|
||||||
|
@ -51,11 +52,16 @@ const char FLT_CHARS[] = "dD";
|
||||||
/* Current assembler state.
|
/* Current assembler state.
|
||||||
Instructions like mpg and direct are followed by a restricted set of
|
Instructions like mpg and direct are followed by a restricted set of
|
||||||
instructions until an end marker (e.g. mpg is followed by vu insns). */
|
instructions until an end marker (e.g. mpg is followed by vu insns). */
|
||||||
typedef enum { ASM_INIT, ASM_MPG, ASM_GPUIF, ASM_VU } asm_state;
|
typedef enum {
|
||||||
|
ASM_INIT, ASM_MPG, ASM_DIRECT, ASM_UNPACK, ASM_GPUIF, ASM_VU
|
||||||
|
} asm_state;
|
||||||
static asm_state cur_asm_state = ASM_INIT;
|
static asm_state cur_asm_state = ASM_INIT;
|
||||||
|
|
||||||
/* Pointer to pke insn currently being assembled or NULL if none. */
|
/* For variable length instructions, pointer to the initial frag
|
||||||
static char *cur_pke_insn;
|
and pointer into that frag. These only hold valid values if
|
||||||
|
cur_asm_state is one of ASM_MPG, ASM_DIRECT, ASM_UNPACK. */
|
||||||
|
static fragS *cur_varlen_frag;
|
||||||
|
static char *cur_varlen_insn;
|
||||||
|
|
||||||
/* Non-zero if packing pke instructions in dma tags. */
|
/* Non-zero if packing pke instructions in dma tags. */
|
||||||
static int dma_pack_pke_p;
|
static int dma_pack_pke_p;
|
||||||
|
@ -83,7 +89,7 @@ md_show_usage (stream)
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
fprintf (stream, "TX VU options:\n");
|
fprintf (stream, "DVP options:\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,17 +108,17 @@ static void s_state PARAMS ((int));
|
||||||
/* The target specific pseudo-ops which we support. */
|
/* The target specific pseudo-ops which we support. */
|
||||||
const pseudo_typeS md_pseudo_table[] =
|
const pseudo_typeS md_pseudo_table[] =
|
||||||
{
|
{
|
||||||
{ "dmadata", s_dmadata, 1 },
|
{ "dmadata", s_dmadata, 1 },
|
||||||
{ "dmapackpke", s_dmapackpke, 0 },
|
{ "dmapackpke", s_dmapackpke, 0 },
|
||||||
{ "enddirect", s_enddirect, 0 },
|
{ "enddirect", s_enddirect, 0 },
|
||||||
{ "enddmadata", s_dmadata, 0 },
|
{ "enddmadata", s_dmadata, 0 },
|
||||||
{ "endgpuif", s_endgpuif, 0 },
|
{ "endgpuif", s_endgpuif, 0 },
|
||||||
{ "endmpg", s_endmpg, 0 },
|
{ "endmpg", s_endmpg, 0 },
|
||||||
{ "endunpack", s_endunpack, 0 },
|
{ "endunpack", s_endunpack, 0 },
|
||||||
/* .vu,.gpuif added to simplify debugging */
|
/* .vu,.gpuif added to simplify debugging */
|
||||||
{ "vu", s_state, ASM_VU },
|
{ "vu", s_state, ASM_VU },
|
||||||
{ "gpuif", s_state, ASM_GPUIF },
|
{ "gpuif", s_state, ASM_GPUIF },
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -249,12 +255,12 @@ assemble_pke (str)
|
||||||
else
|
else
|
||||||
len = 1;
|
len = 1;
|
||||||
|
|
||||||
f = frag_more (len * 4);
|
/* Reminder: it is important to fetch enough space in one call to
|
||||||
|
|
||||||
/* Write out the instruction.
|
|
||||||
Reminder: it is important to fetch enough space in one call to
|
|
||||||
`frag_more'. We use (f - frag_now->fr_literal) to compute where
|
`frag_more'. We use (f - frag_now->fr_literal) to compute where
|
||||||
we are and we don't want frag_now to change between calls. */
|
we are and we don't want frag_now to change between calls. */
|
||||||
|
f = frag_more (len * 4);
|
||||||
|
|
||||||
|
/* Write out the instruction. */
|
||||||
for (i = 0; i < len; ++i)
|
for (i = 0; i < len; ++i)
|
||||||
md_number_to_chars (f + i * 4, insn_buf[i], 4);
|
md_number_to_chars (f + i * 4, insn_buf[i], 4);
|
||||||
|
|
||||||
|
@ -283,14 +289,15 @@ assemble_pke (str)
|
||||||
(bfd_reloc_code_real_type) reloc_type);
|
(bfd_reloc_code_real_type) reloc_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle variable length insns. */
|
||||||
|
|
||||||
if (opcode->flags & PKE_OPCODE_LENVAR)
|
if (opcode->flags & PKE_OPCODE_LENVAR)
|
||||||
{
|
{
|
||||||
/* Name of file to read data from. */
|
/* Name of file to read data from. */
|
||||||
char *file;
|
char *file;
|
||||||
/* In 32 bit words. */
|
/* Length in 32 bit words. */
|
||||||
int data_len;
|
int data_len;
|
||||||
|
|
||||||
cur_pke_insn = NULL;
|
|
||||||
file = NULL;
|
file = NULL;
|
||||||
data_len = 0;
|
data_len = 0;
|
||||||
pke_get_var_data (&file, &data_len);
|
pke_get_var_data (&file, &data_len);
|
||||||
|
@ -308,11 +315,22 @@ assemble_pke (str)
|
||||||
if (data_len == 0 || data_len < -2)
|
if (data_len == 0 || data_len < -2)
|
||||||
as_bad ("invalid data length");
|
as_bad ("invalid data length");
|
||||||
else if (data_len == -1)
|
else if (data_len == -1)
|
||||||
cur_pke_insn = f;
|
{
|
||||||
|
cur_varlen_frag = frag_now;
|
||||||
|
cur_varlen_insn = f;
|
||||||
|
if (opcode->flags & PKE_OPCODE_MPG)
|
||||||
|
cur_asm_state = ASM_MPG;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
install_pke_length (f, data_len * 4);
|
{
|
||||||
if (opcode->flags & PKE_OPCODE_MPG)
|
install_pke_length (f, data_len * 4);
|
||||||
cur_asm_state = ASM_VU;
|
/* Switch to VU state. We don't use MPG state as that is
|
||||||
|
used to indicate we're expecting to see a .endmpg. */
|
||||||
|
if (opcode->flags & PKE_OPCODE_MPG)
|
||||||
|
cur_asm_state = ASM_VU;
|
||||||
|
/* FIXME: We assume there is exactly the right amount of
|
||||||
|
data. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -734,6 +752,20 @@ md_undefined_symbol (name)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called after parsing the file via md_after_pass_hook. */
|
||||||
|
|
||||||
|
void
|
||||||
|
dvp_parse_done ()
|
||||||
|
{
|
||||||
|
/* Check for missing .EndMpg, and supply one if necessary. */
|
||||||
|
if (cur_asm_state == ASM_MPG)
|
||||||
|
s_endmpg (0);
|
||||||
|
else if (cur_asm_state == ASM_DIRECT)
|
||||||
|
s_enddirect (0);
|
||||||
|
else if (cur_asm_state == ASM_UNPACK)
|
||||||
|
s_endunpack (0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Functions concerning relocs. */
|
/* Functions concerning relocs. */
|
||||||
|
|
||||||
|
@ -795,8 +827,9 @@ md_pcrel_from_section (fixP, sec)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: `& -16L'? */
|
/* We assume this is a vu branch.
|
||||||
return (fixP->fx_frag->fr_address + fixP->fx_where) & -8L;
|
Offsets are calculated based on the address of the next insn. */
|
||||||
|
return ((fixP->fx_frag->fr_address + fixP->fx_where) & -8L) + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply a fixup to the object code. This is called for all the
|
/* Apply a fixup to the object code. This is called for all the
|
||||||
|
@ -1084,7 +1117,8 @@ parse_dma_ptr_autocount( opcode, operand, mods, insn_buf, pstr, errmsg)
|
||||||
|
|
||||||
/* Data reference must be a .DmaData label. */
|
/* Data reference must be a .DmaData label. */
|
||||||
struct symbol *label, *label2;
|
struct symbol *label, *label2;
|
||||||
char *name, *name2;
|
const char *name;
|
||||||
|
char *name2;
|
||||||
int len;
|
int len;
|
||||||
long count;
|
long count;
|
||||||
|
|
||||||
|
@ -1131,6 +1165,29 @@ parse_dma_ptr_autocount( opcode, operand, mods, insn_buf, pstr, errmsg)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return length in bytes of the variable length PKE insn
|
||||||
|
currently being assembled. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
cur_pke_insn_length ()
|
||||||
|
{
|
||||||
|
int byte_len;
|
||||||
|
fragS *f;
|
||||||
|
|
||||||
|
if (cur_varlen_frag == frag_now)
|
||||||
|
byte_len = frag_more (0) - cur_varlen_insn - 4; /* -4 for mpg itself */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte_len = (cur_varlen_frag->fr_fix + cur_varlen_frag->fr_offset -
|
||||||
|
(cur_varlen_insn - cur_varlen_frag->fr_literal)) - 4;
|
||||||
|
for (f = cur_varlen_frag->fr_next; f != frag_now; f = f->fr_next)
|
||||||
|
byte_len += f->fr_fix + f->fr_offset;
|
||||||
|
byte_len += frag_now_fix ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return byte_len;
|
||||||
|
}
|
||||||
|
|
||||||
/* Install length LEN, in bytes, in the pke insn at BUF.
|
/* Install length LEN, in bytes, in the pke insn at BUF.
|
||||||
The bytes in BUF are in target order. */
|
The bytes in BUF are in target order. */
|
||||||
|
|
||||||
|
@ -1400,35 +1457,66 @@ static void
|
||||||
s_enddirect (ignore)
|
s_enddirect (ignore)
|
||||||
int ignore;
|
int ignore;
|
||||||
{
|
{
|
||||||
}
|
int byte_len;
|
||||||
|
|
||||||
static void
|
if (cur_asm_state != ASM_DIRECT)
|
||||||
s_endgpuif (ignore)
|
{
|
||||||
int ignore;
|
as_bad ("`.enddirect' has no matching `direct' instruction");
|
||||||
{
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_len = cur_pke_insn_length ();
|
||||||
|
install_pke_length (cur_varlen_insn, byte_len);
|
||||||
|
|
||||||
|
cur_asm_state = ASM_INIT;
|
||||||
|
cur_varlen_frag = NULL;
|
||||||
|
cur_varlen_insn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
s_endmpg (ignore)
|
s_endmpg (ignore)
|
||||||
int ignore;
|
int ignore;
|
||||||
{
|
{
|
||||||
if (cur_asm_state != ASM_MPG || cur_pke_insn == NULL)
|
int byte_len;
|
||||||
as_bad ("`.endmpg' has no matching `mpg' instruction");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Compute the length and install it in the instruction. */
|
|
||||||
/*FIXME*/
|
|
||||||
|
|
||||||
cur_asm_state = ASM_INIT;
|
if (cur_asm_state != ASM_MPG)
|
||||||
cur_pke_insn = NULL;
|
{
|
||||||
|
as_bad ("`.endmpg' has no matching `mpg' instruction");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte_len = cur_pke_insn_length ();
|
||||||
|
install_pke_length (cur_varlen_insn, byte_len);
|
||||||
|
|
||||||
|
cur_asm_state = ASM_INIT;
|
||||||
|
cur_varlen_frag = NULL;
|
||||||
|
cur_varlen_insn = NULL;
|
||||||
|
|
||||||
|
/* Update $.MpgLoc. */
|
||||||
|
pke_set_mpgloc (pke_get_mpgloc () + byte_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
s_endunpack (ignore)
|
s_endunpack (ignore)
|
||||||
int ignore;
|
int ignore;
|
||||||
{
|
{
|
||||||
|
int byte_len;
|
||||||
|
|
||||||
|
if (cur_asm_state != ASM_UNPACK)
|
||||||
|
{
|
||||||
|
as_bad ("`.endunpack' has no matching `unpack' instruction");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_len = cur_pke_insn_length ();
|
||||||
|
install_pke_length (cur_varlen_insn, byte_len);
|
||||||
|
|
||||||
cur_asm_state = ASM_INIT;
|
cur_asm_state = ASM_INIT;
|
||||||
|
cur_varlen_frag = NULL;
|
||||||
|
cur_varlen_insn = NULL;
|
||||||
|
|
||||||
|
/* Update $.UnpackLoc. */
|
||||||
|
pke_set_unpackloc (pke_get_unpackloc () + byte_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1438,6 +1526,12 @@ s_state (state)
|
||||||
cur_asm_state = state;
|
cur_asm_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
s_endgpuif (ignore)
|
||||||
|
int ignore;
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse a DMA data spec which can be either of '*' or a quad word count. */
|
/* Parse a DMA data spec which can be either of '*' or a quad word count. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in a new issue