diff options
author | Thiemo Seufer <ths@networkno.de> | 2006-05-19 13:03:06 +0000 |
---|---|---|
committer | Thiemo Seufer <ths@networkno.de> | 2006-05-19 13:03:06 +0000 |
commit | 7455baf866b0aff03f256a1ee89c858d52bae90e (patch) | |
tree | c85ce491b32d3adf59fe15b8819952d1e39354a0 /gas/config | |
parent | 707bfff6e63692596905aacc2a0e1d04b2aec5cc (diff) | |
download | gdb-7455baf866b0aff03f256a1ee89c858d52bae90e.zip gdb-7455baf866b0aff03f256a1ee89c858d52bae90e.tar.gz gdb-7455baf866b0aff03f256a1ee89c858d52bae90e.tar.bz2 |
* config/tc-mipc.c (ISA_HAS_ODD_SINGLE_FPR): New define.
(mips_oddfpreg_ok): New function.
(mips_ip): Use it.
-------------------------------------------------------------------
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-mips.c | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index c33b4ff..ba2a790 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -326,6 +326,12 @@ static int mips_32bitmode = 0; || (ISA) == ISA_MIPS64R2 \ || mips_opts.ase_smartmips) +/* Return true if ISA supports single-precision floats in odd registers. */ +#define ISA_HAS_ODD_SINGLE_FPR(ISA) \ + ((ISA) == ISA_MIPS32 \ + || (ISA) == ISA_MIPS32R2 \ + || (ISA) == ISA_MIPS64 \ + || (ISA) == ISA_MIPS64R2) #define HAVE_32BIT_GPRS \ (mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa)) @@ -8209,6 +8215,46 @@ static const struct mips_immed mips_immed[] = { { 0,0,0,0 } }; +/* Check whether an odd floating-point register is allowed. */ +static int +mips_oddfpreg_ok (const struct mips_opcode *insn, int argnum) +{ + const char *s = insn->name; + + if (insn->pinfo == INSN_MACRO) + /* Let a macro pass, we'll catch it later when it is expanded. */ + return 1; + + if (ISA_HAS_ODD_SINGLE_FPR (mips_opts.isa)) + { + /* Allow odd registers for single-precision ops. */ + switch (insn->pinfo & (FP_S | FP_D)) + { + case FP_S: + case 0: + return 1; /* both single precision - ok */ + case FP_D: + return 0; /* both double precision - fail */ + default: + break; + } + + /* Cvt.w.x and cvt.x.w allow an odd register for a 'w' or 's' operand. */ + s = strchr (insn->name, '.'); + if (argnum == 2) + s = s != NULL ? strchr (s + 1, '.') : NULL; + return (s != NULL && (s[1] == 'w' || s[1] == 's')); + } + + /* Single-precision coprocessor loads and moves are OK too. */ + if ((insn->pinfo & FP_S) + && (insn->pinfo & (INSN_COPROC_MEMORY_DELAY | INSN_STORE_MEMORY + | INSN_LOAD_COPROC_DELAY | INSN_COPROC_MOVE_DELAY))) + return 1; + + return 0; +} + /* This routine assembles an instruction into its binary format. 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 @@ -9074,18 +9120,7 @@ do_msbd: { if ((regno & 1) != 0 && HAVE_32BIT_FPRS - && ! (strcmp (str, "mtc1") == 0 - || strcmp (str, "mfc1") == 0 - || strcmp (str, "lwc1") == 0 - || strcmp (str, "swc1") == 0 - || strcmp (str, "l.s") == 0 - || strcmp (str, "s.s") == 0 - || strcmp (str, "mftc1") == 0 - || strcmp (str, "mfthc1") == 0 - || strcmp (str, "cftc1") == 0 - || strcmp (str, "mttc1") == 0 - || strcmp (str, "mtthc1") == 0 - || strcmp (str, "cttc1") == 0)) + && ! mips_oddfpreg_ok (ip->insn_mo, argnum)) as_warn (_("Float register should be even, was %d"), regno); |