diff options
-rw-r--r-- | gas/ChangeLog | 19 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 219 |
2 files changed, 236 insertions, 2 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index c35328a..c3fc297 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,22 @@ +2005-08-25 Chao-ying Fu <fu@mips.com> + + * config/tc-mips.c (mips_set_options): Add ase_dsp for DSP instructions. + (mips_opts): Add -1 to initialize ase_dsp. + (file_ase_dsp): New variable for -mdsp. + (CPU_HAS_DSP): New define. + (validate_mips_insn): Add supports for 3, 4, 5, 6, 7, 8, 9, 0, ', :, @ + operand formats. + (mips_ip): Add min_range and max_range for checking singed numbers. + Check ase_dsp to enable DSP instructions. + Handle 3, 4, 5, 6, 7, 8, 9, 0, ', :, @ operand formats. + (OPTION_DSP, OPTION_NO_DSP): New define. + (OPTION_COMPAT_ARCH_BASE): Change because of inserting DSP define. + (md_parse_option): Parse OPTION_DSP and OPTION_NO_DSP. + (mips_after_parse_args): Set ase_dsp based on CPU. + (s_mipsset): Handle ".set dsp" and ".set nodsp". + (mips_elf_final_processing): Remind of adding new flag for DSP ASE. + (md_show_usage): Show usage of -mdsp and -mno-dsp. + 2005-08-23 David Ung <davidu@mips.com> * config/tc-mips.c (mips_cpu_info_table): Add 5kf to the table of diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 2be54ba..37d2613 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -193,6 +193,7 @@ struct mips_set_options command line options, and based on the default architecture. */ int ase_mips3d; int ase_mdmx; + int ase_dsp; /* Whether we are assembling for the mips16 processor. 0 if we are not, 1 if we are, and -1 if the value has not been initialized. Changed by `.set mips16' and `.set nomips16', and the -mips16 and @@ -243,7 +244,7 @@ static int file_mips_fp32 = -1; static struct mips_set_options mips_opts = { - ISA_UNKNOWN, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN, FALSE + ISA_UNKNOWN, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN, FALSE }; /* These variables are filled in with the masks of registers used. @@ -267,6 +268,10 @@ static int file_ase_mips3d; command line (e.g., by -march). */ static int file_ase_mdmx; +/* True if -mdsp was passed or implied by arguments passed on the + command line (e.g., by -march). */ +static int file_ase_dsp; + /* The argument of the -march= flag. The architecture we are assembling. */ static int file_mips_arch = CPU_UNKNOWN; static const char *mips_arch_string; @@ -365,6 +370,10 @@ static int mips_32bitmode = 0; #define CPU_HAS_MDMX(cpu) (FALSE \ ) +/* Return true if the given CPU supports the DSP ASE. */ +#define CPU_HAS_DSP(cpu) (FALSE \ + ) + /* True if CPU has a dror instruction. */ #define CPU_HAS_DROR(CPU) ((CPU) == CPU_VR5400 || (CPU) == CPU_VR5500) @@ -7817,6 +7826,17 @@ validate_mips_insn (const struct mips_opcode *opc) case '%': USE_BITS (OP_MASK_VECALIGN, OP_SH_VECALIGN); break; case '[': break; case ']': break; + case '3': USE_BITS (OP_MASK_SA3, OP_SH_SA3); break; + case '4': USE_BITS (OP_MASK_SA4, OP_SH_SA4); break; + case '5': USE_BITS (OP_MASK_IMM8, OP_SH_IMM8); break; + case '6': USE_BITS (OP_MASK_RS, OP_SH_RS); break; + case '7': USE_BITS (OP_MASK_DSPACC, OP_SH_DSPACC); break; + case '8': USE_BITS (OP_MASK_WRDSP, OP_SH_WRDSP); break; + case '9': USE_BITS (OP_MASK_DSPACC_S, OP_SH_DSPACC_S);break; + case '0': USE_BITS (OP_MASK_DSPSFT, OP_SH_DSPSFT); break; + case '\'': USE_BITS (OP_MASK_RDDSP, OP_SH_RDDSP); break; + case ':': USE_BITS (OP_MASK_DSPSFT_7, OP_SH_DSPSFT_7);break; + case '@': USE_BITS (OP_MASK_IMM10, OP_SH_IMM10); break; default: as_bad (_("internal: bad mips opcode (unknown operand type `%c'): %s %s"), c, opc->name, opc->args); @@ -7851,6 +7871,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) unsigned int limlo, limhi; char *s_reset; char save_c = 0; + offsetT min_range, max_range; insn_error = NULL; @@ -7913,6 +7934,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) (mips_opts.isa | (file_ase_mips16 ? INSN_MIPS16 : 0) | (mips_opts.ase_mdmx ? INSN_MDMX : 0) + | (mips_opts.ase_dsp ? INSN_DSP : 0) | (mips_opts.ase_mips3d ? INSN_MIPS3D : 0)), mips_opts.arch)) ok = TRUE; @@ -7965,6 +7987,175 @@ mips_ip (char *str, struct mips_cl_insn *ip) return; break; + case '3': /* dsp 3-bit unsigned immediate in bit 21 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_SA3) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_SA3, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_SA3; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_SA3; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '4': /* dsp 4-bit unsigned immediate in bit 21 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_SA4) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_SA4, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_SA4; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_SA4; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '5': /* dsp 8-bit unsigned immediate in bit 16 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_IMM8) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_IMM8, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_IMM8; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_IMM8; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '6': /* dsp 5-bit unsigned immediate in bit 21 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_RS) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_RS, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_RS; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_RS; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '7': /* four dsp accumulators in bits 11,12 */ + if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && + s[3] >= '0' && s[3] <= '3') + { + regno = s[3] - '0'; + s += 4; + ip->insn_opcode |= regno << OP_SH_DSPACC; + continue; + } + else + as_bad (_("Invalid dsp acc register")); + break; + + case '8': /* dsp 6-bit unsigned immediate in bit 11 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_WRDSP) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_WRDSP, + (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_WRDSP; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_WRDSP; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '9': /* four dsp accumulators in bits 21,22 */ + if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && + s[3] >= '0' && s[3] <= '3') + { + regno = s[3] - '0'; + s += 4; + ip->insn_opcode |= regno << OP_SH_DSPACC_S; + continue; + } + else + as_bad (_("Invalid dsp acc register")); + break; + + case '0': /* dsp 6-bit signed immediate in bit 20 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_DSPSFT + 1) >> 1); + max_range = ((OP_MASK_DSPSFT + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range || + imm_expr.X_add_number > max_range) + { + as_warn (_("DSP immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + imm_expr.X_add_number &= OP_MASK_DSPSFT; + ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number + << OP_SH_DSPSFT); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '\'': /* dsp 6-bit unsigned immediate in bit 16 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_RDDSP) + { + as_warn (_("DSP immediate not in range 0..%d (%lu)"), + OP_MASK_RDDSP, + (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_RDDSP; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_RDDSP; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case ':': /* dsp 7-bit signed immediate in bit 19 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_DSPSFT_7 + 1) >> 1); + max_range = ((OP_MASK_DSPSFT_7 + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range || + imm_expr.X_add_number > max_range) + { + as_warn (_("DSP immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + imm_expr.X_add_number &= OP_MASK_DSPSFT_7; + ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number + << OP_SH_DSPSFT_7); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '@': /* dsp 10-bit signed immediate in bit 16 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + min_range = -((OP_MASK_IMM10 + 1) >> 1); + max_range = ((OP_MASK_IMM10 + 1) >> 1) - 1; + if (imm_expr.X_add_number < min_range || + imm_expr.X_add_number > max_range) + { + as_warn (_("DSP immediate not in range %ld..%ld (%ld)"), + (long) min_range, (long) max_range, + (long) imm_expr.X_add_number); + } + imm_expr.X_add_number &= OP_MASK_IMM10; + ip->insn_opcode |= ((unsigned long) imm_expr.X_add_number + << OP_SH_IMM10); + imm_expr.X_op = O_absent; + s = expr_end; + continue; + case ',': if (*s++ == *args) continue; @@ -10027,9 +10218,13 @@ struct option md_longopts[] = {"mdmx", no_argument, NULL, OPTION_MDMX}, #define OPTION_NO_MDMX (OPTION_ASE_BASE + 5) {"no-mdmx", no_argument, NULL, OPTION_NO_MDMX}, +#define OPTION_DSP (OPTION_ASE_BASE + 6) + {"mdsp", no_argument, NULL, OPTION_DSP}, +#define OPTION_NO_DSP (OPTION_ASE_BASE + 7) + {"mno-dsp", no_argument, NULL, OPTION_NO_DSP}, /* Old-style architecture options. Don't add more of these. */ -#define OPTION_COMPAT_ARCH_BASE (OPTION_ASE_BASE + 6) +#define OPTION_COMPAT_ARCH_BASE (OPTION_ASE_BASE + 8) #define OPTION_M4650 (OPTION_COMPAT_ARCH_BASE + 0) {"m4650", no_argument, NULL, OPTION_M4650}, #define OPTION_NO_M4650 (OPTION_COMPAT_ARCH_BASE + 1) @@ -10281,6 +10476,14 @@ md_parse_option (int c, char *arg) mips_opts.ase_mdmx = 0; break; + case OPTION_DSP: + mips_opts.ase_dsp = 1; + break; + + case OPTION_NO_DSP: + mips_opts.ase_dsp = 0; + break; + case OPTION_MIPS16: mips_opts.mips16 = 1; mips_no_prev_insn (); @@ -10635,11 +10838,14 @@ mips_after_parse_args (void) mips_opts.ase_mips3d = (CPU_HAS_MIPS3D (file_mips_arch)) ? 1 : 0; if (mips_opts.ase_mdmx == -1) mips_opts.ase_mdmx = (CPU_HAS_MDMX (file_mips_arch)) ? 1 : 0; + if (mips_opts.ase_dsp == -1) + mips_opts.ase_dsp = (CPU_HAS_DSP (file_mips_arch)) ? 1 : 0; file_mips_isa = mips_opts.isa; file_ase_mips16 = mips_opts.mips16; file_ase_mips3d = mips_opts.ase_mips3d; file_ase_mdmx = mips_opts.ase_mdmx; + file_ase_dsp = mips_opts.ase_dsp; mips_opts.gp32 = file_mips_gp32; mips_opts.fp32 = file_mips_fp32; @@ -11577,6 +11783,10 @@ s_mipsset (int x ATTRIBUTE_UNUSED) mips_opts.ase_mdmx = 1; else if (strcmp (name, "nomdmx") == 0) mips_opts.ase_mdmx = 0; + else if (strcmp (name, "dsp") == 0) + mips_opts.ase_dsp = 1; + else if (strcmp (name, "nodsp") == 0) + mips_opts.ase_dsp = 0; else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0) { int reset = 0; @@ -13311,6 +13521,8 @@ mips_elf_final_processing (void) elf_elfheader (stdoutput)->e_flags |= EF_MIPS_CPIC; /* Set MIPS ELF flags for ASEs. */ + /* We may need to define a new flag for DSP ASE, and set this flag when + file_ase_dsp is true. */ if (file_ase_mips16) elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_M16; #if 0 /* XXX FIXME */ @@ -14015,6 +14227,9 @@ MIPS options:\n\ -mips16 generate mips16 instructions\n\ -no-mips16 do not generate mips16 instructions\n")); fprintf (stream, _("\ +-mdsp generate DSP instructions\n\ +-mno-dsp do not generate DSP instructions\n")); + fprintf (stream, _("\ -mfix-vr4120 work around certain VR4120 errata\n\ -mfix-vr4130 work around VR4130 mflo/mfhi errata\n\ -mgp32 use 32-bit GPRs, regardless of the chosen ISA\n\ |