diff options
author | Ian Lance Taylor <ian@airs.com> | 1996-12-09 23:26:15 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1996-12-09 23:26:15 +0000 |
commit | 8728fa92639a428e7b02fc7693879665a8337c6f (patch) | |
tree | 81bc69a8a829cca280dca266cbbf2e14c9d66f7a /gas/config | |
parent | 102633cecf8dbea9ce842d5604e1a2dd52de4c0e (diff) | |
download | gdb-8728fa92639a428e7b02fc7693879665a8337c6f.zip gdb-8728fa92639a428e7b02fc7693879665a8337c6f.tar.gz gdb-8728fa92639a428e7b02fc7693879665a8337c6f.tar.bz2 |
* 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.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-mips.c | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 9842c1e..c1a348e 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -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) |