* tc-txvu.c (*): Update to use handle new arguments for

parse/insert/extract/print handlers.
	({encode,decode}_fixup_reloc_type): New function.
	(assemble_pke): Write out insn after parsing it.
This commit is contained in:
Doug Evans
1998-01-27 22:17:11 +00:00
parent f006120d1d
commit 95bfad6d10
2 changed files with 167 additions and 45 deletions

View File

@ -1,3 +1,12 @@
start-sanitize-sky
Tue Jan 27 14:13:37 1998 Doug Evans <devans@seba.cygnus.com>
* config/tc-txvu.c (*): Update to use handle new arguments for
parse/insert/extract/print handlers.
({encode,decode}_fixup_reloc_type): New function.
(assemble_pke): Write out insn after parsing it.
end-sanitize-sky
Tue Jan 27 13:32:01 1998 Robert Lipe <robertl@dgii.com> Tue Jan 27 13:32:01 1998 Robert Lipe <robertl@dgii.com>
* configure.in (i386-*-sco3.2v5*): Defaults to ELF now. * configure.in (i386-*-sco3.2v5*): Defaults to ELF now.
@ -48,7 +57,7 @@ Tue Jan 27 05:32:05 1998 Richard Henderson <rth@cygnus.com>
start-sanitize-sky start-sanitize-sky
Mon Jan 26 16:29:49 1998 Doug Evans <devans@seba.cygnus.com> Mon Jan 26 16:29:49 1998 Doug Evans <devans@seba.cygnus.com>
* tc-txvu.c: First pass at dma/pke/gpuif support. * config/tc-txvu.c: First pass at dma/pke/gpuif support.
(assemble_one_insn): Renamed from assemble_insn. (assemble_one_insn): Renamed from assemble_insn.
Initialize errmsg = NULL before calling parse fn. Initialize errmsg = NULL before calling parse fn.
Allow [] in suffix operand. Allow [] in suffix operand.

View File

@ -27,9 +27,11 @@
#include "opcode/txvu.h" #include "opcode/txvu.h"
#include "elf/txvu.h" #include "elf/txvu.h"
enum cputype { CPU_VUUP, CPU_VULO, CPU_DMA, CPU_PKE, CPU_GPUIF };
static TXVU_INSN txvu_insert_operand static TXVU_INSN txvu_insert_operand
PARAMS ((TXVU_INSN, const struct txvu_operand *, int, offsetT, PARAMS ((TXVU_INSN, enum cputype, const txvu_operand *,
char *, unsigned int)); int, offsetT, char *, unsigned int));
const char comment_chars[] = ";"; const char comment_chars[] = ";";
const char line_comment_chars[] = "#"; const char line_comment_chars[] = "#";
@ -120,8 +122,6 @@ md_begin ()
dma_pack_pke_p = 0; dma_pack_pke_p = 0;
} }
enum cputype { CPU_VUUP, CPU_VULO, CPU_DMA, CPU_PKE, CPU_GPUIF };
/* We need to keep a list of fixups. We can't simply generate them as /* We need to keep a list of fixups. We can't simply generate them as
we go, because that would require us to first create the frag, and we go, because that would require us to first create the frag, and
that would screw up references to ``.''. */ that would screw up references to ``.''. */
@ -138,17 +138,24 @@ struct txvu_fixup
static int fixup_count; static int fixup_count;
static struct txvu_fixup fixups[MAX_FIXUPS]; static struct txvu_fixup fixups[MAX_FIXUPS];
/* Given a cpu type and operand number, return a temporary reloc type
for use in generating the fixup that encodes the cpu type and operand. */
static int encode_fixup_reloc_type PARAMS ((enum cputype, int));
/* Given an encoded fixup reloc type, decode it into cpu and operand. */
static void decode_fixup_reloc_type PARAMS ((int, enum cputype *,
const txvu_operand **));
static void assemble_dma PARAMS ((char *)); static void assemble_dma PARAMS ((char *));
static void assemble_gpuif PARAMS ((char *)); static void assemble_gpuif PARAMS ((char *));
static void assemble_pke PARAMS ((char *)); static void assemble_pke PARAMS ((char *));
static void assemble_vu PARAMS ((char *)); static void assemble_vu PARAMS ((char *));
static char * assemble_vu_insn PARAMS ((enum cputype, static char * assemble_vu_insn PARAMS ((enum cputype,
const struct txvu_opcode *, const txvu_opcode *,
const struct txvu_operand *, const txvu_operand *,
char *, char *)); char *, char *));
static char * assemble_one_insn PARAMS ((enum cputype, static char * assemble_one_insn PARAMS ((enum cputype,
const struct txvu_opcode *, const txvu_opcode *,
const struct txvu_operand *, const txvu_operand *,
char *, TXVU_INSN *)); char *, TXVU_INSN *));
void void
@ -178,11 +185,13 @@ static void
assemble_dma (str) assemble_dma (str)
char *str; char *str;
{ {
TXVU_INSN buf[4]; TXVU_INSN insn_buf[4];
assemble_one_insn (CPU_DMA, str = assemble_one_insn (CPU_DMA,
dma_opcode_lookup_asm (str), dma_operands, dma_opcode_lookup_asm (str), dma_operands,
str, buf); str, insn_buf);
if (str == NULL)
return;
} }
/* Subroutine of md_assemble to assemble PKE instructions. */ /* Subroutine of md_assemble to assemble PKE instructions. */
@ -191,11 +200,69 @@ static void
assemble_pke (str) assemble_pke (str)
char *str; char *str;
{ {
TXVU_INSN buf[4]; /* Space for the instruction.
The variable length insns can require much more space than this.
It is allocated later, when we know we have such an insn. */
TXVU_INSN insn_buf[5];
/* Insn's length, in 32 bit words. */
int len;
/* Non-zero if this is a variable length insn. */
int varlen_p;
/* Pointer to allocated frag. */
char *f;
int i;
assemble_one_insn (CPU_PKE, str = assemble_one_insn (CPU_PKE,
pke_opcode_lookup_asm (str), pke_operands, pke_opcode_lookup_asm (str), pke_operands,
str, buf); str, insn_buf);
if (str == NULL)
return;
/* 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. */
varlen_p = pke_varlen_p ();
len = pke_len ();
if (varlen_p)
{
/* FIXME: not done yet */
}
else
{
f = frag_more (len * 4);
}
/* 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
we are and we don't want frag_now to change between calls. */
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;
const txvu_operand *operand;
/* 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;
reloc_type = encode_fixup_reloc_type (CPU_PKE, op_type);
operand = &pke_operands[op_type];
fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
&fixups[i].exp,
(operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0,
(bfd_reloc_code_real_type) reloc_type);
}
} }
/* Subroutine of md_assemble to assemble GPUIF instructions. */ /* Subroutine of md_assemble to assemble GPUIF instructions. */
@ -204,11 +271,13 @@ static void
assemble_gpuif (str) assemble_gpuif (str)
char *str; char *str;
{ {
TXVU_INSN buf[4]; TXVU_INSN insn_buf[4];
assemble_one_insn (CPU_GPUIF, str = assemble_one_insn (CPU_GPUIF,
gpuif_opcode_lookup_asm (str), gpuif_operands, gpuif_opcode_lookup_asm (str), gpuif_operands,
str, buf); str, insn_buf);
if (str == NULL)
return;
} }
/* Subroutine of md_assemble to assemble VU instructions. */ /* Subroutine of md_assemble to assemble VU instructions. */
@ -254,8 +323,8 @@ assemble_vu (str)
static char * static char *
assemble_vu_insn (cpu, opcode, operand_table, str, buf) assemble_vu_insn (cpu, opcode, operand_table, str, buf)
enum cputype cpu; enum cputype cpu;
const struct txvu_opcode *opcode; const txvu_opcode *opcode;
const struct txvu_operand *operand_table; const txvu_operand *operand_table;
char *str; char *str;
char *buf; char *buf;
{ {
@ -276,7 +345,7 @@ assemble_vu_insn (cpu, opcode, operand_table, str, buf)
for (i = 0; i < fixup_count; ++i) for (i = 0; i < fixup_count; ++i)
{ {
int op_type, reloc_type; int op_type, reloc_type;
const struct txvu_operand *operand; const txvu_operand *operand;
/* Create a fixup for this operand. /* Create a fixup for this operand.
At this point we do not use a bfd_reloc_code_real_type for At this point we do not use a bfd_reloc_code_real_type for
@ -286,7 +355,7 @@ assemble_vu_insn (cpu, opcode, operand_table, str, buf)
feature. We pick a BFD reloc type in md_apply_fix. */ feature. We pick a BFD reloc type in md_apply_fix. */
op_type = fixups[i].opindex; op_type = fixups[i].opindex;
reloc_type = op_type + (int) BFD_RELOC_UNUSED; reloc_type = encode_fixup_reloc_type (cpu, op_type);
operand = &txvu_operands[op_type]; operand = &txvu_operands[op_type];
fix_new_exp (frag_now, buf - frag_now->fr_literal, 4, fix_new_exp (frag_now, buf - frag_now->fr_literal, 4,
&fixups[i].exp, &fixups[i].exp,
@ -310,8 +379,8 @@ assemble_vu_insn (cpu, opcode, operand_table, str, buf)
static char * static char *
assemble_one_insn (cpu, opcode, operand_table, str, insn_buf) assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
enum cputype cpu; enum cputype cpu;
const struct txvu_opcode *opcode; const txvu_opcode *opcode;
const struct txvu_operand *operand_table; const txvu_operand *operand_table;
char *str; char *str;
TXVU_INSN *insn_buf; TXVU_INSN *insn_buf;
{ {
@ -346,7 +415,7 @@ assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; ) for (/*str = start, */ syn = opcode->syntax; *syn != '\0'; )
{ {
int mods,index; int mods,index;
const struct txvu_operand *operand; const txvu_operand *operand;
const char *errmsg; const char *errmsg;
/* Non operand chars must match exactly. /* Non operand chars must match exactly.
@ -382,7 +451,8 @@ assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
if (operand->insert) if (operand->insert)
{ {
errmsg = NULL; errmsg = NULL;
(*operand->insert) (insn_buf, operand, mods, 0, &errmsg); (*operand->insert) (opcode, operand, mods, insn_buf, 0,
&errmsg);
/* If we get an error, go on to try the next insn. */ /* If we get an error, go on to try the next insn. */
if (errmsg) if (errmsg)
break; break;
@ -421,7 +491,8 @@ assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
c = *t; c = *t;
*t = '\0'; *t = '\0';
errmsg = NULL; errmsg = NULL;
suf_value = (*operand->parse) (&s, &errmsg); suf_value = (*operand->parse) (opcode, operand, mods, &s,
&errmsg);
*t = c; *t = c;
if (errmsg) if (errmsg)
{ {
@ -433,8 +504,8 @@ assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
} }
/* Insert the suffix's value into the insn. */ /* Insert the suffix's value into the insn. */
if (operand->insert) if (operand->insert)
(*operand->insert) (insn_buf, operand, (*operand->insert) (opcode, operand, mods,
mods, suf_value, NULL); insn_buf, suf_value, NULL);
else else
*insn_buf |= suf_value << operand->shift; *insn_buf |= suf_value << operand->shift;
@ -474,7 +545,8 @@ assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
if (operand->parse) if (operand->parse)
{ {
errmsg = NULL; errmsg = NULL;
value = (*operand->parse) (&str, &errmsg); value = (*operand->parse) (opcode, operand, mods,
&str, &errmsg);
if (errmsg) if (errmsg)
break; break;
} }
@ -509,8 +581,8 @@ assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
if (operand->insert) if (operand->insert)
{ {
const char *errmsg = NULL; const char *errmsg = NULL;
(*operand->insert) (insn_buf, operand, mods, (*operand->insert) (opcode, operand, mods,
value, &errmsg); insn_buf, value, &errmsg);
if (errmsg != (const char *) NULL) if (errmsg != (const char *) NULL)
break; break;
} }
@ -579,6 +651,47 @@ md_undefined_symbol (name)
/* Functions concerning relocs. */ /* Functions concerning relocs. */
/* Spacing between each cpu type's operand numbers.
Should be at least as bit as any operand table. */
#define RELOC_SPACING 256
/* Given a cpu type and operand number, return a temporary reloc type
for use in generating the fixup that encodes the cpu type and operand
number. */
static int
encode_fixup_reloc_type (cpu, opnum)
enum cputype cpu;
int opnum;
{
return (int) BFD_RELOC_UNUSED + ((int) cpu * RELOC_SPACING) + opnum;
}
/* Given a fixup reloc type, decode it into cpu type and operand. */
static void
decode_fixup_reloc_type (fixup_reloc, cpuP, operandP)
int fixup_reloc;
enum cputype *cpuP;
const txvu_operand **operandP;
{
enum cputype cpu = (fixup_reloc - (int) BFD_RELOC_UNUSED) / RELOC_SPACING;
int opnum = (fixup_reloc - (int) BFD_RELOC_UNUSED) % RELOC_SPACING;
*cpuP = cpu;
switch (cpu)
{
case CPU_VUUP : *operandP = &txvu_operands[opnum]; break;
case CPU_VULO : *operandP = &txvu_operands[opnum]; break;
case CPU_DMA : *operandP = &dma_operands[opnum]; break;
case CPU_PKE : *operandP = &pke_operands[opnum]; break;
case CPU_GPUIF : *operandP = &gpuif_operands[opnum]; break;
default : as_fatal ("bad fixup encoding");
}
}
/* Given a fixup reloc type, return a pointer to the operand
/* The location from which a PC relative jump should be calculated, /* The location from which a PC relative jump should be calculated,
given a PC relative reloc. */ given a PC relative reloc. */
@ -651,23 +764,22 @@ md_apply_fix3 (fixP, valueP, seg)
} }
} }
/* Check for txvu_operand's. These are indicated with a reloc value /* Check for dvp operand's. These are indicated with a reloc value
>= BFD_RELOC_UNUSED. */ >= BFD_RELOC_UNUSED. */
if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
{ {
int opindex; enum cputype cpu;
const struct txvu_operand *operand; const txvu_operand *operand;
TXVU_INSN insn; TXVU_INSN insn;
opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; decode_fixup_reloc_type ((int) fixP->fx_r_type,
& cpu, & operand);
operand = &txvu_operands[opindex];
/* Fetch the instruction, insert the fully resolved operand /* Fetch the instruction, insert the fully resolved operand
value, and stuff the instruction back again. */ value, and stuff the instruction back again. */
insn = bfd_getl32 ((unsigned char *) where); insn = bfd_getl32 ((unsigned char *) where);
insn = txvu_insert_operand (insn, operand, -1, (offsetT) value, insn = txvu_insert_operand (insn, cpu, operand, -1, (offsetT) value,
fixP->fx_file, fixP->fx_line); fixP->fx_file, fixP->fx_line);
bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
@ -833,9 +945,10 @@ md_atof (type, litP, sizeP)
/* Insert an operand value into an instruction. */ /* Insert an operand value into an instruction. */
static TXVU_INSN static TXVU_INSN
txvu_insert_operand (insn, operand, mods, val, file, line) txvu_insert_operand (insn, cpu, operand, mods, val, file, line)
TXVU_INSN insn; TXVU_INSN insn;
const struct txvu_operand *operand; enum cputype cpu;
const txvu_operand *operand;
int mods; int mods;
offsetT val; offsetT val;
char *file; char *file;
@ -894,7 +1007,7 @@ txvu_insert_operand (insn, operand, mods, val, file, line)
if (operand->insert) if (operand->insert)
{ {
const char *errmsg = NULL; const char *errmsg = NULL;
(*operand->insert) (&insn, operand, mods, (long) val, &errmsg); (*operand->insert) (NULL, operand, mods, &insn, (long) val, &errmsg);
if (errmsg != (const char *) NULL) if (errmsg != (const char *) NULL)
as_warn (errmsg); as_warn (errmsg);
} }