* config/tc-mips.c (RELAX_MIPS16_ENCODE): Add small and ext

arguments, and store them.  Adjust other RELAX_MIPS16 macros.
	(RELAX_MIPS16_USER_SMALL): Define.
	(RELAX_MIPS16_USER_EXT): Define.
	(mips16_small, mips16_ext): New static variables.
	(append_insn): Pass mips16_small and mips16_ext to
	RELAX_MIPS16_ENCODE.
	(mips16_ip): Set mips16_small and mips16_ext.
	(mips16_immed): Don't check mips16_autoextend.
	(mips16_extended_frag): Check USER_SMALL and USER_EXT.
This commit is contained in:
Ian Lance Taylor 1996-12-09 23:26:15 +00:00
parent 102633cecf
commit 8728fa9263
2 changed files with 53 additions and 22 deletions

View File

@ -1,5 +1,16 @@
Mon Dec 9 17:09:42 1996 Ian Lance Taylor <ian@cygnus.com>
* config/tc-mips.c (RELAX_MIPS16_ENCODE): Add small and ext
arguments, and store them. Adjust other RELAX_MIPS16 macros.
(RELAX_MIPS16_USER_SMALL): Define.
(RELAX_MIPS16_USER_EXT): Define.
(mips16_small, mips16_ext): New static variables.
(append_insn): Pass mips16_small and mips16_ext to
RELAX_MIPS16_ENCODE.
(mips16_ip): Set mips16_small and mips16_ext.
(mips16_immed): Don't check mips16_autoextend.
(mips16_extended_frag): Check USER_SMALL and USER_EXT.
* write.c (write_relocs): Print an error for an out of range
fixup, rather than calling abort.

View File

@ -453,23 +453,29 @@ static const int mips16_to_32_reg_map[] =
use the high bit of the subtype field to distinguish these cases.
The information we store for this type of relaxation is simply the
argument code found in the opcode file for this relocation. That
tells us the size of the value, and how it should be stored. We
also store whether the fragment is considered to be extended or
argument code found in the opcode file for this relocation, and
whether the user explicitly requested a small or extended form.
That tells us the size of the value, and how it should be stored.
We also store whether the fragment is considered to be extended or
not. We also store whether this is known to be a branch to a
different section, whether we have tried to relax this frag yet,
and whether we have ever extended a PC relative fragment because of
a shift count. */
#define RELAX_MIPS16_ENCODE(type) \
(0x80000000 | ((type) & 0xff))
#define RELAX_MIPS16_ENCODE(type, small, ext) \
(0x80000000 \
| ((type) & 0xff) \
| ((small) ? 0x100 : 0) \
| ((ext) ? 0x200 : 0))
#define RELAX_MIPS16_P(i) (((i) & 0x80000000) != 0)
#define RELAX_MIPS16_TYPE(i) ((i) & 0xff)
#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x100) != 0)
#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x100)
#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) &~ 0x100)
#define RELAX_MIPS16_LONG_BRANCH(i) (((i) & 0x200) != 0)
#define RELAX_MIPS16_MARK_LONG_BRANCH(i) ((i) | 0x200)
#define RELAX_MIPS16_CLEAR_LONG_BRANCH(i) ((i) &~ 0x200)
#define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x100) != 0)
#define RELAX_MIPS16_USER_EXT(i) (((i) & 0x200) != 0)
#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x400) != 0)
#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x400)
#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) &~ 0x400)
#define RELAX_MIPS16_LONG_BRANCH(i) (((i) & 0x800) != 0)
#define RELAX_MIPS16_MARK_LONG_BRANCH(i) ((i) | 0x800)
#define RELAX_MIPS16_CLEAR_LONG_BRANCH(i) ((i) &~ 0x800)
/* Prototypes for static functions. */
@ -648,6 +654,10 @@ static bfd_reloc_code_real_type offset_reloc;
static boolean imm_unmatched_hi;
/* These are set by mips16_ip if an explicit extension is used. */
static boolean mips16_small, mips16_ext;
/*
* This function is called once, at assembler startup time. It should
* set up all the tables, etc. that the MD part of the assembler will need.
@ -1356,7 +1366,8 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
/* We need to set up a variant frag. */
assert (mips16 && address_expr != NULL);
f = frag_var (rs_machine_dependent, 4, 0,
RELAX_MIPS16_ENCODE (reloc_type - BFD_RELOC_UNUSED),
RELAX_MIPS16_ENCODE (reloc_type - BFD_RELOC_UNUSED,
mips16_small, mips16_ext),
make_expr_symbol (address_expr), (long) 0,
(char *) NULL);
}
@ -6628,7 +6639,9 @@ mips_ip (str, ip)
/* This routine assembles an instruction into its binary format when
assembling for the mips16. As a side effect, it sets one of the
global variables imm_reloc or offset_reloc to the type of
relocation to do if one of the operands is an address expression. */
relocation to do if one of the operands is an address expression.
It also sets mips16_small and mips16_ext if the user explicitly
requested a small or extended instruction. */
static void
mips16_ip (str, ip)
@ -6636,7 +6649,6 @@ mips16_ip (str, ip)
struct mips_cl_insn *ip;
{
char *s;
boolean small, ext;
const char *args;
struct mips_opcode *insn;
char *argsstart;
@ -6646,8 +6658,8 @@ mips16_ip (str, ip)
insn_error = NULL;
small = false;
ext = false;
mips16_small = false;
mips16_ext = false;
for (s = str; islower (*s); ++s)
;
@ -6664,14 +6676,14 @@ mips16_ip (str, ip)
if (s[1] == 't' && s[2] == ' ')
{
*s = '\0';
small = true;
mips16_small = true;
s += 3;
break;
}
else if (s[1] == 'e' && s[2] == ' ')
{
*s = '\0';
ext = true;
mips16_ext = true;
s += 3;
break;
}
@ -6681,6 +6693,9 @@ mips16_ip (str, ip)
return;
}
if (! mips16_autoextend && ! mips16_ext)
mips16_small = true;
if ((insn = (struct mips_opcode *) hash_find (mips16_op_hash, str)) == NULL)
{
insn_error = "unrecognized opcode";
@ -6723,9 +6738,9 @@ mips16_ip (str, ip)
{
mips16_immed ((char *) NULL, 0,
imm_reloc - BFD_RELOC_UNUSED,
imm_expr.X_add_number, true, small, ext,
&ip->insn_opcode, &ip->use_extend,
&ip->extend);
imm_expr.X_add_number, true, mips16_small,
mips16_ext, &ip->insn_opcode,
&ip->use_extend, &ip->extend);
imm_expr.X_op = O_absent;
imm_reloc = BFD_RELOC_UNUSED;
}
@ -7196,7 +7211,7 @@ mips16_immed (file, line, type, val, warn, small, ext, insn, use_extend,
if (warn && ext && ! needext)
as_warn_where (file, line, "extended operand requested but not required");
if ((small || ! mips16_autoextend) && needext)
if (small && needext)
as_bad_where (file, line, "invalid unextended operand value");
if (small || (! ext && ! needext))
@ -9011,6 +9026,11 @@ mips16_extended_frag (fragp, sec, stretch)
int mintiny, maxtiny;
segT symsec;
if (RELAX_MIPS16_USER_SMALL (fragp->fr_subtype))
return 0;
if (RELAX_MIPS16_USER_EXT (fragp->fr_subtype))
return 1;
type = RELAX_MIPS16_TYPE (fragp->fr_subtype);
op = mips16_immed_operands;
while (op->type != type)