mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-01 13:26:47 +08:00
checkpoint
This commit is contained in:
parent
7caebec6f6
commit
e033023fb2
@ -20,6 +20,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "sysdep.h"
|
||||
#include "as.h"
|
||||
#include "subsegs.h"
|
||||
/* Needed by opcode/dvp.h. */
|
||||
@ -34,14 +35,24 @@ static void insert_operand_final
|
||||
PARAMS ((dvp_cpu, const dvp_operand *, int,
|
||||
DVP_INSN *, offsetT, char *, unsigned int));
|
||||
|
||||
static int insert_file PARAMS ((const char *));
|
||||
|
||||
static void install_pke_length PARAMS ((char *, int));
|
||||
|
||||
const char comment_chars[] = ";";
|
||||
const char line_comment_chars[] = "#";
|
||||
const char line_separator_chars[] = "!";
|
||||
const char EXP_CHARS[] = "eE";
|
||||
const char FLT_CHARS[] = "dD";
|
||||
|
||||
/* Non-zero if in vu-mode. */
|
||||
static int vu_mode_p;
|
||||
/* Current assembler state.
|
||||
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). */
|
||||
typedef enum { ASM_INIT, ASM_MPG, ASM_GPUIF, ASM_VU } asm_state;
|
||||
static asm_state cur_asm_state = ASM_INIT;
|
||||
|
||||
/* Pointer to pke insn currently being assembled or NULL if none. */
|
||||
static char *cur_pke_insn;
|
||||
|
||||
/* Non-zero if packing pke instructions in dma tags. */
|
||||
static int dma_pack_pke_p;
|
||||
@ -83,7 +94,7 @@ static void s_enddirect PARAMS ((int));
|
||||
static void s_endgpuif PARAMS ((int));
|
||||
static void s_endmpg PARAMS ((int));
|
||||
static void s_endunpack PARAMS ((int));
|
||||
static void s_vu PARAMS ((int));
|
||||
static void s_state PARAMS ((int));
|
||||
|
||||
/* The target specific pseudo-ops which we support. */
|
||||
const pseudo_typeS md_pseudo_table[] =
|
||||
@ -95,9 +106,9 @@ const pseudo_typeS md_pseudo_table[] =
|
||||
{ "endgpuif", s_endgpuif, 0 },
|
||||
{ "endmpg", s_endmpg, 0 },
|
||||
{ "endunpack", s_endunpack, 0 },
|
||||
/* .vu,.endvu added to simplify debugging */
|
||||
{ "vu", s_vu, 1 },
|
||||
{ "endvu", s_vu, 0 },
|
||||
/* .vu,.gpuif added to simplify debugging */
|
||||
{ "vu", s_state, ASM_VU },
|
||||
{ "gpuif", s_state, ASM_GPUIF },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -119,7 +130,7 @@ md_begin ()
|
||||
This involves computing the hash chains. */
|
||||
dvp_opcode_init_tables (0);
|
||||
|
||||
vu_mode_p = 0;
|
||||
cur_asm_state = ASM_INIT;
|
||||
dma_pack_pke_p = 0;
|
||||
}
|
||||
|
||||
@ -131,6 +142,8 @@ struct dvp_fixup
|
||||
{
|
||||
/* index into `dvp_operands' */
|
||||
int opindex;
|
||||
/* byte offset from beginning of instruction */
|
||||
int offset;
|
||||
expressionS exp;
|
||||
};
|
||||
|
||||
@ -169,17 +182,20 @@ md_assemble (str)
|
||||
while (isspace (*str))
|
||||
str++;
|
||||
|
||||
if (! vu_mode_p)
|
||||
if (cur_asm_state == ASM_INIT)
|
||||
{
|
||||
if (strncasecmp (str, "dma", 3) == 0)
|
||||
assemble_dma (str);
|
||||
else if (strncasecmp (str, "gpuif", 5) == 0)
|
||||
assemble_gpuif (str);
|
||||
else
|
||||
assemble_pke (str);
|
||||
}
|
||||
else
|
||||
else if (cur_asm_state == ASM_GPUIF)
|
||||
assemble_gpuif (str);
|
||||
else if (cur_asm_state == ASM_VU
|
||||
|| cur_asm_state == ASM_MPG)
|
||||
assemble_vu (str);
|
||||
else
|
||||
as_fatal ("unknown parse state");
|
||||
}
|
||||
|
||||
/* Subroutine of md_assemble to assemble DMA instructions. */
|
||||
@ -222,13 +238,7 @@ assemble_pke (str)
|
||||
return;
|
||||
|
||||
if (opcode->flags & PKE_OPCODE_LENVAR)
|
||||
{
|
||||
/* Call back into the parser's state to get the insn's length.
|
||||
This is just the length of the insn, not of any following data.
|
||||
The result 0 if the length is unknown. */
|
||||
len = pke_len ();
|
||||
/* FIXME: not done yet */
|
||||
}
|
||||
len = 1; /* actual data follows later */
|
||||
else if (opcode->flags & PKE_OPCODE_LEN2)
|
||||
len = 2;
|
||||
else if (opcode->flags & PKE_OPCODE_LEN5)
|
||||
@ -250,7 +260,7 @@ assemble_pke (str)
|
||||
copies of this bit of code. */
|
||||
for (i = 0; i < fixup_count; ++i)
|
||||
{
|
||||
int op_type, reloc_type;
|
||||
int op_type, reloc_type, offset;
|
||||
const dvp_operand *operand;
|
||||
|
||||
/* Create a fixup for this operand.
|
||||
@ -261,13 +271,47 @@ assemble_pke (str)
|
||||
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 - frag_now->fr_literal, 4,
|
||||
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);
|
||||
}
|
||||
|
||||
if (opcode->flags & PKE_OPCODE_LENVAR)
|
||||
{
|
||||
/* Name of file to read data from. */
|
||||
char *file;
|
||||
/* In 32 bit words. */
|
||||
int data_len;
|
||||
|
||||
cur_pke_insn = NULL;
|
||||
file = NULL;
|
||||
data_len = 0;
|
||||
pke_get_var_data (&file, &data_len);
|
||||
if (file)
|
||||
{
|
||||
int byte_len = insert_file (file);
|
||||
install_pke_length (f, byte_len);
|
||||
/* Update $.MpgLoc. */
|
||||
pke_set_mpgloc (pke_get_mpgloc () + byte_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* data_len == -1 means the value must be computed from
|
||||
the data. */
|
||||
if (data_len == 0 || data_len < -2)
|
||||
as_bad ("invalid data length");
|
||||
else if (data_len == -1)
|
||||
cur_pke_insn = f;
|
||||
else
|
||||
install_pke_length (f, data_len * 4);
|
||||
if (opcode->flags & PKE_OPCODE_MPG)
|
||||
cur_asm_state = ASM_VU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Subroutine of md_assemble to assemble GPUIF instructions. */
|
||||
@ -599,6 +643,7 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
|
||||
as_fatal ("too many fixups");
|
||||
fixups[fixup_count].exp = exp;
|
||||
fixups[fixup_count].opindex = index;
|
||||
fixups[fixup_count].offset = (operand->shift / 32) * 4;
|
||||
++fixup_count;
|
||||
value = 0;
|
||||
}
|
||||
@ -964,6 +1009,70 @@ md_atof (type, litP, sizeP)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Install length LEN, in bytes, in the pke insn at BUF.
|
||||
The bytes in BUF are in target order. */
|
||||
|
||||
static void
|
||||
install_pke_length (buf, len)
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
char cmd = buf[3];
|
||||
|
||||
if ((cmd & 0x70) == 0x40)
|
||||
{
|
||||
/* mpg */
|
||||
len /= 4;
|
||||
if (len > 256)
|
||||
as_bad ("mpg data length must be between 1 and 256");
|
||||
buf[2] = len;
|
||||
}
|
||||
else if ((cmd & 0x70) == 0x50)
|
||||
{
|
||||
/* direct/directhl */
|
||||
}
|
||||
else if ((cmd & 0x60) == 0x60)
|
||||
{
|
||||
/* unpack */
|
||||
}
|
||||
else
|
||||
as_fatal ("bad call to install_pke_length");
|
||||
}
|
||||
|
||||
/* Insert a file into the output.
|
||||
The result is the number of bytes inserted.
|
||||
If an error occurs an error message is printed and zero is returned. */
|
||||
|
||||
static int
|
||||
insert_file (file)
|
||||
const char *file;
|
||||
{
|
||||
FILE *f;
|
||||
char buf[256];
|
||||
int n, total;
|
||||
|
||||
f = fopen (file, FOPEN_RB);
|
||||
if (f == NULL)
|
||||
{
|
||||
as_bad ("unable to read file `%s'", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
total = 0;
|
||||
do {
|
||||
n = fread (buf, 1, sizeof (buf), f);
|
||||
if (n > 0)
|
||||
{
|
||||
char *fr = frag_more (n);
|
||||
memcpy (fr, buf, n);
|
||||
total += n;
|
||||
}
|
||||
} while (n > 0);
|
||||
|
||||
fclose (f);
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Insert an operand value into an instruction. */
|
||||
|
||||
static void
|
||||
@ -1181,21 +1290,30 @@ static void
|
||||
s_endmpg (ignore)
|
||||
int ignore;
|
||||
{
|
||||
vu_mode_p = 0;
|
||||
if (cur_asm_state != ASM_MPG || cur_pke_insn == NULL)
|
||||
as_bad ("`.endmpg' has no matching `mpg' instruction");
|
||||
else
|
||||
{
|
||||
/* Compute the length and install it in the instruction. */
|
||||
/*FIXME*/
|
||||
|
||||
cur_asm_state = ASM_INIT;
|
||||
cur_pke_insn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
s_endunpack (ignore)
|
||||
int ignore;
|
||||
{
|
||||
vu_mode_p = 0;
|
||||
cur_asm_state = ASM_INIT;
|
||||
}
|
||||
|
||||
static void
|
||||
s_vu (enable_p)
|
||||
int enable_p;
|
||||
s_state (state)
|
||||
int state;
|
||||
{
|
||||
vu_mode_p = enable_p;
|
||||
cur_asm_state = state;
|
||||
}
|
||||
|
||||
/* Parse a DMA data spec which can be either of '*' or a quad word count. */
|
||||
@ -1232,6 +1350,7 @@ parse_dma_count( pstr, errmsg)
|
||||
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;
|
||||
}
|
||||
@ -1254,4 +1373,3 @@ parse_dma_count( pstr, errmsg)
|
||||
*errmsg = "invalid dma count";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user