checkpoint

This commit is contained in:
Doug Evans 1998-01-21 00:30:46 +00:00
parent d707219dc9
commit 020ba60b39
2 changed files with 224 additions and 24 deletions

View file

@ -27,6 +27,10 @@
#include "opcode/txvu.h"
#include "elf/txvu.h"
static TXVU_INSN txvu_insert_operand
PARAMS ((TXVU_INSN, const struct txvu_operand *, int, offsetT,
char *, unsigned int));
const char comment_chars[] = ";";
const char line_comment_chars[] = "#";
const char line_separator_chars[] = "!";
@ -103,12 +107,17 @@ struct txvu_fixup
#define MAX_FIXUPS 5
static char * assemble_insn PARAMS ((char *, int));
static char * assemble_insn PARAMS ((char *, int, char *));
void
md_assemble (str)
char *str;
{
/* The lower instruction has the lower address.
Handle this by grabbing 8 bytes now, and then filling each word
as appropriate. */
char *f = frag_more (8);
#ifdef VERTICAL_BAR_SEPARATOR
char *p = strchr (str, '|');
@ -119,27 +128,29 @@ md_assemble (str)
}
*p = 0;
assemble_insn (str, 0);
assemble_insn (str, 0, f + 4);
*p = '|';
assemble_insn (p + 1, 1);
assemble_insn (p + 1, 1, f);
#else
str = assemble_insn (str, 0);
str = assemble_insn (str, 0, f + 4);
/* Don't assemble next one if we couldn't assemble the first. */
if (str)
assemble_insn (str, 1);
assemble_insn (str, 1, f);
#endif
}
/* Assemble one instruction.
LOWER_P is non-zero if assembling in the lower insn slot.
The result is a pointer to beyond the end of the scanned insn.
The result is a pointer to beyond the end of the scanned insn
or NULL if an error occured.
If this is the upper insn, the caller can pass back to result to us
parse the lower insn. */
static char *
assemble_insn (str, lower_p)
assemble_insn (str, lower_p, buf)
char *str;
int lower_p;
char *buf;
{
const struct txvu_opcode *opcode;
char *start;
@ -368,7 +379,6 @@ assemble_insn (str, lower_p)
if (*syn == '\0')
{
int i;
char *f;
/* For the moment we assume a valid `str' can only contain blanks
now. IE: We needn't try again with a longer version of the
@ -386,11 +396,10 @@ assemble_insn (str, lower_p)
as_bad ("junk at end of line: `%s'", str);
/* Write out the instruction.
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. */
f = frag_more (4);
md_number_to_chars (f, insn, 4);
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. */
md_number_to_chars (buf, insn, 4);
/* Create any fixups. */
for (i = 0; i < fc; ++i)
@ -408,9 +417,7 @@ assemble_insn (str, lower_p)
op_type = fixups[i].opindex;
reloc_type = op_type + (int) BFD_RELOC_UNUSED;
operand = &txvu_operands[op_type];
fix_new_exp (frag_now,
((f - frag_now->fr_literal)
+ (operand->flags & TXVU_OPERAND_LIMM ? 4 : 0)), 4,
fix_new_exp (frag_now, buf - frag_now->fr_literal, 4,
&fixups[i].exp,
(operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0,
(bfd_reloc_code_real_type) reloc_type);
@ -469,7 +476,7 @@ md_pcrel_from_section (fixP, sec)
}
/* FIXME: `& -16L'? */
return (fixP->fx_frag->fr_address + fixP->fx_where) & -4L;
return (fixP->fx_frag->fr_address + fixP->fx_where) & -8L;
}
/* Apply a fixup to the object code. This is called for all the
@ -487,19 +494,137 @@ md_apply_fix3 (fixP, valueP, seg)
char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
valueT value;
as_fatal ("txvu md_apply_fix3\n");
/* FIXME FIXME FIXME: The value we are passed in *valueP includes
the symbol values. Since we are using BFD_ASSEMBLER, if we are
doing this relocation the code in write.c is going to call
bfd_perform_relocation, which is also going to use the symbol
value. That means that if the reloc is fully resolved we want to
use *valueP since bfd_perform_relocation is not being used.
However, if the reloc is not fully resolved we do not want to use
*valueP, and must use fx_offset instead. However, if the reloc
is PC relative, we do want to use *valueP since it includes the
result of md_pcrel_from. This is confusing. */
if (fixP->fx_addsy == (symbolS *) NULL)
{
value = *valueP;
fixP->fx_done = 1;
}
else if (fixP->fx_pcrel)
{
value = *valueP;
}
else
{
value = fixP->fx_offset;
if (fixP->fx_subsy != (symbolS *) NULL)
{
if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
value -= S_GET_VALUE (fixP->fx_subsy);
else
{
/* We can't actually support subtracting a symbol. */
as_bad_where (fixP->fx_file, fixP->fx_line,
"expression too complex");
}
}
}
/* Check for txvu_operand's. These are indicated with a reloc value
>= BFD_RELOC_UNUSED. */
if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
{
int opindex;
const struct txvu_operand *operand;
TXVU_INSN insn;
opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
operand = &txvu_operands[opindex];
/* Fetch the instruction, insert the fully resolved operand
value, and stuff the instruction back again. */
insn = bfd_getl32 ((unsigned char *) where);
insn = txvu_insert_operand (insn, operand, -1, (offsetT) value,
fixP->fx_file, fixP->fx_line);
bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
if (fixP->fx_done)
{
/* Nothing else to do here. */
return 1;
}
/* Determine a BFD reloc value based on the operand information.
We are only prepared to turn a few of the operands into relocs. */
/* FIXME: This test is a hack. */
if ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0)
{
assert ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0
&& operand->bits == 11
&& operand->shift == 0);
fixP->fx_r_type = BFD_RELOC_TXVU_11_PCREL;
}
else
{
as_bad_where (fixP->fx_file, fixP->fx_line,
"unresolved expression that must be resolved");
fixP->fx_done = 1;
return 1;
}
}
else
{
switch (fixP->fx_r_type)
{
case BFD_RELOC_8:
md_number_to_chars (where, value, 1);
break;
case BFD_RELOC_16:
md_number_to_chars (where, value, 2);
break;
case BFD_RELOC_32:
md_number_to_chars (where, value, 4);
break;
default:
abort ();
}
}
fixP->fx_addnumber = value;
return 1;
}
/* Translate internal representation of relocation info to BFD target
format. */
arelent *
tc_gen_reloc (section, fixp)
tc_gen_reloc (section, fixP)
asection *section;
fixS *fixp;
fixS *fixP;
{
/* relocs not handled yet */
as_fatal ("txvu tc_gen_reloc\n");
arelent *reloc;
reloc = (arelent *) xmalloc (sizeof (arelent));
reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
if (reloc->howto == (reloc_howto_type *) NULL)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
"internal error: can't export reloc type %d (`%s')",
fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
return NULL;
}
assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
reloc->addend = fixP->fx_addnumber;
return reloc;
}
/* Write a value out to the object file, using the appropriate endianness. */
@ -583,3 +708,80 @@ md_atof (type, litP, sizeP)
return 0;
}
/* Insert an operand value into an instruction. */
static TXVU_INSN
txvu_insert_operand (insn, operand, mods, val, file, line)
TXVU_INSN insn;
const struct txvu_operand *operand;
int mods;
offsetT val;
char *file;
unsigned int line;
{
if (operand->bits != 32)
{
long min, max;
offsetT test;
if ((operand->flags & TXVU_OPERAND_RELATIVE_BRANCH) != 0)
{
if ((val & 7) != 0)
{
if (file == (char *) NULL)
as_warn ("branch to misaligned address");
else
as_warn_where (file, line, "branch to misaligned address");
}
val >>= 3;
}
if ((operand->flags & TXVU_OPERAND_SIGNED) != 0)
{
if ((operand->flags & TXVU_OPERAND_SIGNOPT) != 0)
max = (1 << operand->bits) - 1;
else
max = (1 << (operand->bits - 1)) - 1;
min = - (1 << (operand->bits - 1));
}
else
{
max = (1 << operand->bits) - 1;
min = 0;
}
if ((operand->flags & TXVU_OPERAND_NEGATIVE) != 0)
test = - val;
else
test = val;
if (test < (offsetT) min || test > (offsetT) max)
{
const char *err =
"operand out of range (%s not between %ld and %ld)";
char buf[100];
sprint_value (buf, test);
if (file == (char *) NULL)
as_warn (err, buf, min, max);
else
as_warn_where (file, line, err, buf, min, max);
}
}
if (operand->insert)
{
const char *errmsg;
errmsg = NULL;
insn = (*operand->insert) (insn, operand, mods, (long) val, &errmsg);
if (errmsg != (const char *) NULL)
as_warn (errmsg);
}
else
insn |= (((long) val & ((1 << operand->bits) - 1))
<< operand->shift);
return insn;
}

View file

@ -50,7 +50,5 @@
(as_fatal("estimate_size_before_relax called"),1)
#define MD_APPLY_FIX3
extern int txvu_md_apply_fix3 ();
#define md_apply_fix3 txvu_md_apply_fix3
#define TC_HANDLES_FX_DONE