/* tc-i860.c -- Assembler for the Intel i860 architecture.
- Copyright (C) 1989, 1992, 1993, 1994, 1995, 1998, 1999, 2000
+ Copyright 1989, 1992, 1993, 1994, 1995, 1998, 1999, 2000
Free Software Foundation, Inc.
Brought back from the dead and completely reworked
#include "opcode/i860.h"
#include "elf/i860.h"
-
/* Defined by default since this is primarily a SVR4/860 assembler.
However, I'm trying to leave the door open for Intel syntax. Of course,
if full support for anything other than SVR4 is done, then we should
select this based on a command-line flag. */
#define SYNTAX_SVR4
-
/* The opcode hash table. */
static struct hash_control *op_hash = NULL;
As in 0f12.456 or 0d1.2345e12. */
const char FLT_CHARS[] = "rRsSfFdDxXpP";
-
/* Register prefix. */
#ifdef SYNTAX_SVR4
static const char reg_prefix = '%';
static const char reg_prefix = 0;
#endif
-
struct i860_it
{
char *error;
/* If true, then warn if any pseudo operations were expanded. */
static int target_warn_expand = 0;
-
/* Prototypes. */
static void i860_process_insn PARAMS ((char *));
static void s_dual PARAMS ((int));
static void print_insn PARAMS ((struct i860_it *));
#endif
-
const pseudo_typeS md_pseudo_table[] =
{
#ifdef OBJ_ELF
{NULL, 0, 0},
};
-
/* Dual-instruction mode handling. */
enum dual
{
};
static enum dual dual_mode = DUAL_OFF;
-
/* Handle ".dual" directive. */
static void
s_dual (ignore)
dual_mode = DUAL_ON;
}
-
/* Handle ".enddual" directive. */
static void
s_enddual (ignore)
dual_mode = DUAL_OFF;
}
-
/* Temporary register used when expanding assembler pseudo operations. */
static int atmp = 31;
demand_empty_rest_of_line ();
}
-
/* This function is called once, at assembler startup time. It should
set up all the tables and data structures that the MD part of the
assembler will need. */
as_fatal (_("Defective assembler. No assembly attempted."));
}
-
/* This is the core of the machine-dependent assembler. STR points to a
machine dependent instruction. This function emits the frags/bytes
it assembles to. */
the_insn.reloc);
/* Despite the odd name, this is a scratch field. We use
- it to encode operand type information. */
+ it to encode operand type information. */
fix->fx_addnumber = the_insn.fup;
}
the_insn = pseudo[++i];
}
-
/* Assemble the instruction pointed to by STR. */
static void
i860_process_insn (str)
the_insn.opcode = opcode;
}
-
static int
i860_get_expression (str)
char *str;
return 0;
}
-
/* Turn a string in input_line_pointer into a floating point constant of
type TYPE, and store the appropriate bytes in *LITP. The number of
LITTLENUMS emitted is stored in *SIZEP. An error message is returned,
return 0;
}
-
/* Write out in current endian mode. */
void
md_number_to_chars (buf, val, n)
number_to_chars_littleendian (buf, val, n);
}
-
/* This should never be called for i860. */
void
md_number_to_disp (buf, val, n)
as_fatal (_("md_number_to_disp\n"));
}
-
/* This should never be called for i860. */
void
md_number_to_field (buf, val, fix)
as_fatal (_("i860_number_to_field\n"));
}
-
/* This should never be called for i860. */
int
md_estimate_size_before_relax (fragP, segtype)
as_fatal (_("i860_estimate_size_before_relax\n"));
}
-
#ifdef DEBUG_I860
static void
print_insn (insn)
}
#endif /* DEBUG_I860 */
-
\f
#ifdef OBJ_ELF
CONST char *md_shortopts = "VQ:";
CONST char *md_shortopts = "";
#endif
-
#define OPTION_EB (OPTION_MD_BASE + 0)
#define OPTION_EL (OPTION_MD_BASE + 1)
#define OPTION_WARN_EXPAND (OPTION_MD_BASE + 2)
};
size_t md_longopts_size = sizeof (md_longopts);
-
int
md_parse_option (c, arg)
int c;
return 1;
}
-
void
md_show_usage (stream)
FILE *stream;
return 0;
}
-
/* The i860 denotes auto-increment with '++'. */
void
md_operand (exp)
{
char *s;
- for (s = input_line_pointer; s; s++)
+ for (s = input_line_pointer; *s; s++)
{
if (s[0] == '+' && s[1] == '+')
{
}
}
-
/* Round up a section size to the appropriate boundary. */
valueT
md_section_align (segment, size)
return size;
}
-
/* On the i860, a PC-relative offset is relative to the address of the
of the offset plus its size. */
long
return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
}
-
/* Determine the relocation needed for non PC-relative 16-bit immediates.
Also adjust the given immediate as necessary. Finally, check that
all constraints (such as alignment) are satisfied. */
long *val;
{
valueT fup = fix->fx_addnumber;
- bfd_reloc_code_real_type reloc;
+ bfd_reloc_code_real_type reloc;
if (fix->fx_pcrel)
abort ();
return reloc;
}
-
/* Attempt to simplify or eliminate a fixup. To indicate that a fixup
has been eliminated, set fix->fx_done. If fix->fx_addsy is non-NULL,
we will have to generate a reloc entry. */
{
char *buf;
- long val = (long)(*valuep);
+ long val = (long) (*valuep);
unsigned long insn;
valueT fup;
fix->fx_r_type = obtain_reloc_for_imm16 (fix, &val);
/* Insert the immediate. */
- insn |= val & 0xffff;
- bfd_putl32 (insn, buf);
-
- fix->fx_done = (fix->fx_addsy == 0);
+ if (fix->fx_addsy)
+ fix->fx_done = 0;
+ else
+ {
+ insn |= val & 0xffff;
+ bfd_putl32 (insn, buf);
+ fix->fx_r_type = BFD_RELOC_NONE;
+ fix->fx_done = 1;
+ }
}
else if (fup & OP_IMM_U16)
{
fix->fx_r_type = obtain_reloc_for_imm16 (fix, &val);
/* Insert the immediate. */
- insn |= val & 0x7ff;
- insn |= (val & 0xf800) << 5;
- bfd_putl32 (insn, buf);
-
- fix->fx_done = (fix->fx_addsy == 0);
- }
+ if (fix->fx_addsy)
+ fix->fx_done = 0;
+ else
+ {
+ insn |= val & 0x7ff;
+ insn |= (val & 0xf800) << 5;
+ bfd_putl32 (insn, buf);
+ fix->fx_r_type = BFD_RELOC_NONE;
+ fix->fx_done = 1;
+ }
+ }
else if (fup & OP_IMM_BR16)
{
if (val & 0x3)
val = val >> 2;
/* Insert the immediate. */
- insn |= (val & 0x7ff);
- insn |= ((val & 0xf800) << 5);
- bfd_putl32 (insn, buf);
-
- fix->fx_r_type = BFD_RELOC_860_PC16;
- fix->fx_done = (fix->fx_addsy == 0);
+ if (fix->fx_addsy)
+ {
+ fix->fx_done = 0;
+ fix->fx_r_type = BFD_RELOC_860_PC16;
+ }
+ else
+ {
+ insn |= (val & 0x7ff);
+ insn |= ((val & 0xf800) << 5);
+ bfd_putl32 (insn, buf);
+ fix->fx_r_type = BFD_RELOC_NONE;
+ fix->fx_done = 1;
+ }
}
else if (fup & OP_IMM_BR26)
{
val >>= 2;
/* Insert the immediate. */
- insn |= (val & 0x3ffffff);
- bfd_putl32 (insn, buf);
-
- fix->fx_r_type = BFD_RELOC_860_PC26;
- fix->fx_done = (fix->fx_addsy == 0);
+ if (fix->fx_addsy)
+ {
+ fix->fx_r_type = BFD_RELOC_860_PC26;
+ fix->fx_done = 0;
+ }
+ else
+ {
+ insn |= (val & 0x3ffffff);
+ bfd_putl32 (insn, buf);
+ fix->fx_r_type = BFD_RELOC_NONE;
+ fix->fx_done = 1;
+ }
}
else if (fup != OP_NONE)
{
- as_bad_where (fix->fx_file, fix->fx_line,
+ as_bad_where (fix->fx_file, fix->fx_line,
_("Unrecognized fix-up (0x%08x)"), fup);
abort ();
}
{
/* I believe only fix-ups such as ".long .ep.main-main+0xc8000000"
reach here (???). */
- insn |= (val & 0xffffffff);
- bfd_putl32 (insn, buf);
- fix->fx_r_type = BFD_RELOC_32;
- fix->fx_done = (fix->fx_addsy == 0);
+ if (fix->fx_addsy)
+ {
+ fix->fx_r_type = BFD_RELOC_32;
+ fix->fx_done = 0;
+ }
+ else
+ {
+ insn |= (val & 0xffffffff);
+ bfd_putl32 (insn, buf);
+ fix->fx_r_type = BFD_RELOC_NONE;
+ fix->fx_done = 1;
+ }
}
/* Return value ignored. */
return 0;
}
-
/* Generate a machine dependent reloc from a fixup. */
arelent*
tc_gen_reloc (section, fixp)
}
return reloc;
}
-