diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2010-12-18 11:14:14 +0000 |
---|---|---|
committer | Richard Sandiford <rdsandiford@googlemail.com> | 2010-12-18 11:14:14 +0000 |
commit | 986754024085408d77fabdc6e1e94fa2b8221b7f (patch) | |
tree | 4f6313245d69122a6630ea1137dc24ab934f5e52 /gas/config | |
parent | e6a3fb4b5cc97668b0822c98d7896a5fca165360 (diff) | |
download | gdb-986754024085408d77fabdc6e1e94fa2b8221b7f.zip gdb-986754024085408d77fabdc6e1e94fa2b8221b7f.tar.gz gdb-986754024085408d77fabdc6e1e94fa2b8221b7f.tar.bz2 |
include/opcode/
2010-12-14 Mingjie Xing <mingjie.xing@gmail.com>
* mips.h (OP_*_OFFSET_A, OP_*_OFFSET_B, OP_*_OFFSET_C)
(OP_*_RZ, OP_*_FZ, INSN2_M_FP_D, INSN2_WRITE_GPR_Z, INSN2_WRITE_FPR_Z)
(INSN2_READ_GPR_Z, INSN2_READ_FPR_Z, INSN2_READ_GPR_D): Define.
opcodes/
2010-12-14 Mingjie Xing <mingjie.xing@gmail.com>
* mips-opc.c (WR_z, WR_Z, RD_z, RD_Z, RD_d): Define.
(mips_builtin_opcodes): Add loongson3a specific instructions.
* mips-dis.c (print_insn_args): Handle the new arguments +a|b|c|z|Z.
gas/
2010-12-14 Mingjie Xing <mingjie.xing@gmail.com>
* config/tc-mips.c (insn_uses_reg): Handle the new flags
INSN2_READ_FPR_Z, INSN2_READ_GPR_D and INSN2_READ_GPR_Z.
(append_insn): Handle delay-slot filling for the new flags.
(validate_mips_insn): Handle the new arguments +a|b|c|z|Z.
(mips_ip): Handle the new arguments +a|b|c|z|Z.
gas/testsuite/
2010-12-14 Mingjie Xing <mingjie.xing@gmail.com>
* gas/mips/loongson-3a-2.s, gas/mips/loongson-3a-2.d,
gas/mips/loongson-3a-3.s, gas/mips/loongson-3a-3.d: New tests.
* gas/mips/mips.exp: Run them.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-mips.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 65d1989..20bf431 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -2275,6 +2275,10 @@ insn_uses_reg (const struct mips_cl_insn *ip, unsigned int reg, && ((EXTRACT_OPERAND (FT, *ip) & ~(unsigned) 1) == (reg &~ (unsigned) 1))) return 1; + if ((ip->insn_mo->pinfo2 & INSN2_READ_FPR_Z) + && ((EXTRACT_OPERAND (FZ, *ip) & ~(unsigned) 1) + == (reg &~ (unsigned) 1))) + return 1; } else if (! mips_opts.mips16) { @@ -2284,6 +2288,12 @@ insn_uses_reg (const struct mips_cl_insn *ip, unsigned int reg, if ((ip->insn_mo->pinfo & INSN_READ_GPR_T) && EXTRACT_OPERAND (RT, *ip) == reg) return 1; + if ((ip->insn_mo->pinfo2 & INSN2_READ_GPR_D) + && EXTRACT_OPERAND (RD, *ip) == reg) + return 1; + if ((ip->insn_mo->pinfo2 & INSN2_READ_GPR_Z) + && EXTRACT_OPERAND (RZ, *ip) == reg) + return 1; } else { @@ -2809,6 +2819,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, bfd_reloc_code_real_type *reloc_type) { unsigned long prev_pinfo, pinfo; + unsigned long prev_pinfo2, pinfo2; relax_stateT prev_insn_frag_type = 0; bfd_boolean relaxed_branch = FALSE; segment_info_type *si = seg_info (now_seg); @@ -2822,7 +2833,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, file_ase_mips16 |= mips_opts.mips16; prev_pinfo = history[0].insn_mo->pinfo; + prev_pinfo2 = history[0].insn_mo->pinfo2; pinfo = ip->insn_mo->pinfo; + pinfo2 = ip->insn_mo->pinfo2; if (mips_relax.sequence != 2 && !mips_opts.noreorder) { @@ -3162,7 +3175,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, /* Update the register mask information. */ if (! mips_opts.mips16) { - if (pinfo & INSN_WRITE_GPR_D) + if ((pinfo & INSN_WRITE_GPR_D) || (pinfo2 & INSN2_READ_GPR_D)) mips_gprmask |= 1 << EXTRACT_OPERAND (RD, *ip); if ((pinfo & (INSN_WRITE_GPR_T | INSN_READ_GPR_T)) != 0) mips_gprmask |= 1 << EXTRACT_OPERAND (RT, *ip); @@ -3170,6 +3183,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, mips_gprmask |= 1 << EXTRACT_OPERAND (RS, *ip); if (pinfo & INSN_WRITE_GPR_31) mips_gprmask |= 1 << RA; + if (pinfo2 & (INSN2_WRITE_GPR_Z | INSN2_READ_GPR_Z)) + mips_gprmask |= 1 << EXTRACT_OPERAND (RZ, *ip); if (pinfo & INSN_WRITE_FPR_D) mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FD, *ip); if ((pinfo & (INSN_WRITE_FPR_S | INSN_READ_FPR_S)) != 0) @@ -3178,6 +3193,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FT, *ip); if ((pinfo & INSN_READ_FPR_R) != 0) mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FR, *ip); + if (pinfo2 & (INSN2_WRITE_FPR_Z | INSN2_READ_FPR_Z)) + mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FZ, *ip); if (pinfo & INSN_COP) { /* We don't keep enough information to sort these cases out. @@ -3272,6 +3289,10 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, && (prev_pinfo & INSN_WRITE_GPR_D) && insn_uses_reg (ip, EXTRACT_OPERAND (RD, history[0]), MIPS_GR_REG)) + || (! mips_opts.mips16 + && (prev_pinfo2 & INSN2_WRITE_GPR_Z) + && insn_uses_reg (ip, EXTRACT_OPERAND (RZ, history[0]), + MIPS_GR_REG)) || (mips_opts.mips16 && (((prev_pinfo & MIPS16_INSN_WRITE_X) && (insn_uses_reg @@ -8479,6 +8500,11 @@ validate_mips_insn (const struct mips_opcode *opc) case 'Q': USE_BITS (OP_MASK_SEQI, OP_SH_SEQI); break; case 's': USE_BITS (OP_MASK_CINSLM1, OP_SH_CINSLM1); break; case 'S': USE_BITS (OP_MASK_CINSLM1, OP_SH_CINSLM1); break; + case 'z': USE_BITS (OP_MASK_RZ, OP_SH_RZ); break; + case 'Z': USE_BITS (OP_MASK_FZ, OP_SH_FZ); break; + case 'a': USE_BITS (OP_MASK_OFFSET_A, OP_SH_OFFSET_A); break; + case 'b': USE_BITS (OP_MASK_OFFSET_B, OP_SH_OFFSET_B); break; + case 'c': USE_BITS (OP_MASK_OFFSET_C, OP_SH_OFFSET_C); break; default: as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"), @@ -9290,6 +9316,77 @@ mips_ip (char *str, struct mips_cl_insn *ip) s = expr_end; continue; + case 'a': /* 8-bit signed offset in bit 6 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_OFFSET_A + 1) >> 1); + max_range = ((OP_MASK_OFFSET_A + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range + || imm_expr.X_add_number > max_range) + { + as_bad (_("immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + INSERT_OPERAND (OFFSET_A, *ip, imm_expr.X_add_number); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case 'b': /* 8-bit signed offset in bit 3 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_OFFSET_B + 1) >> 1); + max_range = ((OP_MASK_OFFSET_B + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range + || imm_expr.X_add_number > max_range) + { + as_bad (_("immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + INSERT_OPERAND (OFFSET_B, *ip, imm_expr.X_add_number); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case 'c': /* 9-bit signed offset in bit 6 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_OFFSET_C + 1) >> 1); + max_range = ((OP_MASK_OFFSET_C + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range + || imm_expr.X_add_number > max_range) + { + as_bad (_("immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + INSERT_OPERAND (OFFSET_C, *ip, imm_expr.X_add_number); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case 'z': + if (!reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no)) + break; + if (regno == AT && mips_opts.at) + { + if (mips_opts.at == ATREG) + as_warn (_("used $at without \".set noat\"")); + else + as_warn (_("used $%u with \".set at=$%u\""), + regno, mips_opts.at); + } + INSERT_OPERAND (RZ, *ip, regno); + continue; + + case 'Z': + if (!reg_lookup (&s, RTYPE_FPU, ®no)) + break; + INSERT_OPERAND (FZ, *ip, regno); + continue; + default: as_bad (_("Internal error: bad mips opcode " "(unknown extension operand type `+%c'): %s %s"), |