aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-mips.c
diff options
context:
space:
mode:
authorChris Demetriou <cgd@google.com>2002-12-31 07:29:29 +0000
committerChris Demetriou <cgd@google.com>2002-12-31 07:29:29 +0000
commitaf7ee8bfa91b92e0357687808979175f511bacc3 (patch)
tree000d9febdd65ea93f23a9b7dab88550b14678f49 /gas/config/tc-mips.c
parent7ee21aad7db971f20f2dce387d56b72a5fd889e2 (diff)
downloadgdb-af7ee8bfa91b92e0357687808979175f511bacc3.zip
gdb-af7ee8bfa91b92e0357687808979175f511bacc3.tar.gz
gdb-af7ee8bfa91b92e0357687808979175f511bacc3.tar.bz2
[ bfd/ChangeLog ]
2002-12-30 Chris Demetriou <cgd@broadcom.com> * aoutx.h (NAME(aout,machine_type)): Add bfd_mach_mipsisa32r2 case. * archures.c (bfd_mach_mipsisa32r2): New define. * bfd-in2.h: Regenerate. * cpu-mips.c (I_mipsisa32r2): New enum value. (arch_info_struct): Add entry for I_mipsisa32r2. * elfxx-mips.c (elf_mips_isa, _bfd_elf_mips_mach) (_bfd_mips_elf_print_private_bfd_data): Handle E_MIPS_ARCH_32R2. (_bfd_mips_elf_final_write_processing): Add bfd_mach_mipsisa32r2 case. (_bfd_mips_elf_merge_private_bfd_data): Handle merging of binaries marked as using MIPS32 Release 2. [ binutils/ChangeLog ] 2002-12-30 Chris Demetriou <cgd@broadcom.com> * doc/binutils.texi (objdump): Note MIPS HWR (Hardware Register) changes in MIPS -M options. [ gas/ChangeLog ] 2002-12-30 Chris Demetriou <cgd@broadcom.com> * configure.in: Recognize mipsisa32r2, mipsisa32r2el, and CPU variants. * configure: Regenerate. * config/tc-mips.c (ISA_HAS_DROR, ISA_HAS_ROR): New defines. (macro_build): Handle "K" operand. (macro2): Use ISA_HAS_DROR and ISA_HAS_ROR in the places where CPU_HAS_DROR and CPU_HAS_ROR are currently used. (mips_ip): New variable "lastpos", and implement "+A", "+B", and "+C" operands for MIPS32 Release 2 ins/ext instructions. Implement "K" operand for MIPS32 Release 2 rdhwr instruction. (validate_mips_insn): Implement "+" as a way to extend the allowed operands, and implement "K", "+A", "+B", and "+C" operands. (OPTION_MIPS32R2): New define. (md_longopts): Add entry for OPTION_MIPS32R2. (OPTION_ELF_BASE): Adjust to accomodate OPTIONS_MIPS32R2. (md_parse_option): Handle OPTION_MIPS32R2. (s_mipsset): Reimplement handling of ".set mipsN" options and add support for ".set mips32r2". (mips_cpu_info_table): Add entry for "mips32r2" (MIPS32 Release 2). (md_show_usage): Document "-mips32r2" option. * doc/as.texinfo: Document "-mips32r2" option. * doc/c-mips.texi: Likewise. [ gas/testsuite/ChangeLog ] 2002-12-30 Chris Demetriou <cgd@broadcom.com> * gas/mips/cp0-names-mips32r2.d: New test. * gas/mips/hwr-names-mips32r2.d: New test. * gas/mips/hwr-names-numeric.d: New test. * gas/mips/hwr-names.s: New test source file. * gas/mips/mips32r2.d: New test. * gas/mips/mips32r2.s: New test source file. * gas/mips/mips32r2-ill.l: New test. * gas/mips/mips32r2-ill.s: New test source file. * gas/mips/mips.exp: Add mips32r2 architecture data array entry. Run new tests mentioned above. [ include/elf/ChangeLog ] 2002-12-30 Chris Demetriou <cgd@broadcom.com> * mips.h (E_MIPS_ARCH_32R2): New define. [ include/opcode/ChangeLog ] 2002-12-30 Chris Demetriou <cgd@broadcom.com> * mips.h: Document "+" as the start of two-character operand type names, and add new "K", "+A", "+B", and "+C" operand types. (OP_MASK_INSMSB, OP_SH_INSMSB, OP_MASK_EXTMSB) (OP_SH_EXTMSB, INSN_ISA32R2, ISA_MIPS32R2, CPU_MIPS32R2): New defines. [ opcodes/ChangeLog ] 2002-12-30 Chris Demetriou <cgd@broadcom.com> * mips-dis.c (mips_cp0_names_mips3264r2, mips_hwr_names_numeric) (mips_hwr_names_mips3264r2): New arrays. (mips_arch_choice): New "hwr_names" member. (mips_arch_choices): Adjust for structure change, and add a new entry for "mips32r2" ISA. (mips_hwr_names): New variable. (set_default_mips_dis_options): Set mips_hwr_names. (parse_mips_dis_option): New "hwr-names" option which sets mips_hwr_names, and adjust "reg-names=ARCH" to set mips_hwr_names. (print_insn_arg): Change return type to "int" and use that to indicate number of characters consumed. Add support for "+" operand extension character, "+A", "+B", "+C", and "K" operands. (print_insn_mips): Adjust for changes to print_insn_arg. (print_mips_disassembler_options): Adjust for "hwr-names" addition and "reg-names" change. * mips-opc (I33): New define (shorthand for INSN_ISA32R2). (mips_builtin_opcodes): Note that "nop" and "ssnop" are special forms of "sll". Add new MIPS32 Release 2 instructions: ehb, di, ei, ext, ins, jr.hb, jalr.hb, mfhc1, mfhc2, mthc1, mthc2, rdhwr, rdpgpr, seb, seh, synci, wrpgpr, wsbh. Note that hardware rotate instructions (ror, rorv) can be used on MIPS32 Release 2, and add the official mnemonics for them (rotr, rotrv) and the similar "rotl" mnemonic for left-rotate.
Diffstat (limited to 'gas/config/tc-mips.c')
-rw-r--r--gas/config/tc-mips.c184
1 files changed, 150 insertions, 34 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 2a2f11c..b501c19 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -260,6 +260,18 @@ static int mips_32bitmode = 0;
|| (ISA) == ISA_MIPS64 \
)
+/* Return true if ISA supports 64-bit right rotate (dror et al.)
+ instructions. */
+#define ISA_HAS_DROR(ISA) ( \
+ 0 \
+ )
+
+/* Return true if ISA supports 32-bit right rotate (ror et al.)
+ instructions. */
+#define ISA_HAS_ROR(ISA) ( \
+ (ISA) == ISA_MIPS32R2 \
+ )
+
#define HAVE_32BIT_GPRS \
(mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
@@ -3010,6 +3022,7 @@ macro_build (place, counter, ep, name, fmt, va_alist)
case 'd':
case 'G':
+ case 'K':
insn.insn_opcode |= va_arg (args, int) << OP_SH_RD;
continue;
@@ -6940,7 +6953,7 @@ macro2 (ip)
break;
case M_DROL:
- if (CPU_HAS_DROR (mips_arch))
+ if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
{
if (dreg == sreg)
{
@@ -6971,7 +6984,7 @@ macro2 (ip)
break;
case M_ROL:
- if (CPU_HAS_ROR (mips_arch))
+ if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
{
if (dreg == sreg)
{
@@ -7009,7 +7022,7 @@ macro2 (ip)
if (imm_expr.X_op != O_constant)
as_bad (_("Improper rotate count"));
rot = imm_expr.X_add_number & 0x3f;
- if (CPU_HAS_DROR (mips_arch))
+ if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
{
rot = (64 - rot) & 0x3f;
if (rot >= 32)
@@ -7045,7 +7058,7 @@ macro2 (ip)
if (imm_expr.X_op != O_constant)
as_bad (_("Improper rotate count"));
rot = imm_expr.X_add_number & 0x1f;
- if (CPU_HAS_ROR (mips_arch))
+ if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
{
macro_build ((char *) NULL, &icnt, NULL, "ror",
"d,w,<", dreg, sreg, (32 - rot) & 0x1f);
@@ -7067,7 +7080,7 @@ macro2 (ip)
break;
case M_DROR:
- if (CPU_HAS_DROR (mips_arch))
+ if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
{
macro_build ((char *) NULL, &icnt, NULL, "drorv",
"d,t,s", dreg, sreg, treg);
@@ -7084,7 +7097,7 @@ macro2 (ip)
break;
case M_ROR:
- if (CPU_HAS_ROR (mips_arch))
+ if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
{
macro_build ((char *) NULL, &icnt, NULL, "rorv",
"d,t,s", dreg, sreg, treg);
@@ -7108,7 +7121,7 @@ macro2 (ip)
if (imm_expr.X_op != O_constant)
as_bad (_("Improper rotate count"));
rot = imm_expr.X_add_number & 0x3f;
- if (CPU_HAS_DROR (mips_arch))
+ if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
{
if (rot >= 32)
macro_build ((char *) NULL, &icnt, NULL, "dror32",
@@ -7143,7 +7156,7 @@ macro2 (ip)
if (imm_expr.X_op != O_constant)
as_bad (_("Improper rotate count"));
rot = imm_expr.X_add_number & 0x1f;
- if (CPU_HAS_ROR (mips_arch))
+ if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
{
macro_build ((char *) NULL, &icnt, NULL, "ror",
"d,w,<", dreg, sreg, rot);
@@ -8003,6 +8016,18 @@ validate_mips_insn (opc)
case ',': break;
case '(': break;
case ')': break;
+ case '+':
+ switch (c = *p++)
+ {
+ case 'A': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
+ case 'B': USE_BITS (OP_MASK_INSMSB, OP_SH_INSMSB); break;
+ case 'C': USE_BITS (OP_MASK_EXTMSBD, OP_SH_EXTMSBD); break;
+ default:
+ as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"),
+ c, opc->name, opc->args);
+ return 0;
+ }
+ break;
case '<': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
case '>': USE_BITS (OP_MASK_SHAMT, OP_SH_SHAMT); break;
case 'A': break;
@@ -8015,6 +8040,7 @@ validate_mips_insn (opc)
case 'H': USE_BITS (OP_MASK_SEL, OP_SH_SEL); break;
case 'I': break;
case 'J': USE_BITS (OP_MASK_CODE19, OP_SH_CODE19); break;
+ case 'K': USE_BITS (OP_MASK_RD, OP_SH_RD); break;
case 'L': break;
case 'M': USE_BITS (OP_MASK_CCC, OP_SH_CCC); break;
case 'N': USE_BITS (OP_MASK_BCC, OP_SH_BCC); break;
@@ -8089,6 +8115,7 @@ mips_ip (str, ip)
char *argsStart;
unsigned int regno;
unsigned int lastregno = 0;
+ unsigned int lastpos = 0;
char *s_reset;
char save_c = 0;
@@ -8254,6 +8281,70 @@ mips_ip (str, ip)
continue;
break;
+ case '+': /* Opcode extension character. */
+ switch (*++args)
+ {
+ case 'A': /* ins/ext "pos". */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if ((unsigned long) imm_expr.X_add_number > 31)
+ {
+ as_bad (_("Improper position (%lu)"),
+ (unsigned long) imm_expr.X_add_number);
+ imm_expr.X_add_number = 0;
+ }
+ lastpos = imm_expr.X_add_number;
+ ip->insn_opcode |= lastpos << OP_SH_SHAMT;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'B': /* "ins" size spec (becomes MSB). */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if (imm_expr.X_add_number == 0
+ || (unsigned long) imm_expr.X_add_number > 32
+ || ((unsigned long) imm_expr.X_add_number
+ + lastpos) > 32)
+ {
+ as_bad (_("Improper insert size (%lu, position %lu)"),
+ (unsigned long) imm_expr.X_add_number,
+ (unsigned long) lastpos);
+ imm_expr.X_add_number &= OP_MASK_INSMSB;
+ }
+ ip->insn_opcode |= (lastpos + imm_expr.X_add_number
+ - 1) << OP_SH_INSMSB;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case 'C': /* "ext" size spec (becomes MSBD). */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+ if (imm_expr.X_add_number == 0
+ || (unsigned long) imm_expr.X_add_number > 32
+ || ((unsigned long) imm_expr.X_add_number
+ + lastpos) > 32)
+ {
+ as_bad (_("Improper extract size (%lu, position %lu)"),
+ (unsigned long) imm_expr.X_add_number,
+ (unsigned long) lastpos);
+ imm_expr.X_add_number &= OP_MASK_EXTMSBD;
+ }
+ ip->insn_opcode |= (imm_expr.X_add_number
+ - 1) << OP_SH_EXTMSBD;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ default:
+ as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"),
+ *args, insn->name, insn->args);
+ /* Further processing is fruitless. */
+ return;
+ }
+ break;
+
case '<': /* must be at least one digit */
/*
* According to the manual, if the shift amount is greater
@@ -8391,6 +8482,7 @@ mips_ip (str, ip)
case 'w': /* both dest and target */
case 'E': /* coprocessor target register */
case 'G': /* coprocessor destination register */
+ case 'K': /* 'rdhwr' destination register */
case 'x': /* ignore register name */
case 'z': /* must be zero register */
case 'U': /* destination register (clo/clz). */
@@ -8412,7 +8504,7 @@ mips_ip (str, ip)
if (regno > 31)
as_bad (_("Invalid register number (%d)"), regno);
}
- else if (*args == 'E' || *args == 'G')
+ else if (*args == 'E' || *args == 'G' || *args == 'K')
goto notreg;
else
{
@@ -8486,7 +8578,8 @@ mips_ip (str, ip)
if (regno == AT
&& ! mips_opts.noat
&& *args != 'E'
- && *args != 'G')
+ && *args != 'G'
+ && *args != 'K')
as_warn (_("Used $at without \".set noat\""));
c = *args;
if (*s == ' ')
@@ -8516,6 +8609,7 @@ mips_ip (str, ip)
break;
case 'd':
case 'G':
+ case 'K':
ip->insn_opcode |= regno << OP_SH_RD;
break;
case 'U':
@@ -10377,8 +10471,10 @@ struct option md_longopts[] =
#define OPTION_NO_RELAX_BRANCH (OPTION_MD_BASE + 40)
{"relax-branch", no_argument, NULL, OPTION_RELAX_BRANCH},
{"no-relax-branch", no_argument, NULL, OPTION_NO_RELAX_BRANCH},
+#define OPTION_MIPS32R2 (OPTION_MD_BASE + 41)
+ {"mips32r2", no_argument, NULL, OPTION_MIPS32R2},
#ifdef OBJ_ELF
-#define OPTION_ELF_BASE (OPTION_MD_BASE + 41)
+#define OPTION_ELF_BASE (OPTION_MD_BASE + 42)
#define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
@@ -10499,6 +10595,10 @@ md_parse_option (c, arg)
file_mips_isa = ISA_MIPS32;
break;
+ case OPTION_MIPS32R2:
+ file_mips_isa = ISA_MIPS32R2;
+ break;
+
case OPTION_MIPS64:
file_mips_isa = ISA_MIPS64;
break;
@@ -12019,27 +12119,49 @@ s_mipsset (x)
mips_opts.ase_mdmx = 0;
else if (strncmp (name, "mips", 4) == 0)
{
- int isa;
+ int reset = 0;
/* Permit the user to change the ISA on the fly. Needless to
say, misuse can cause serious problems. */
- isa = atoi (name + 4);
- switch (isa)
+ if (strcmp (name, "mips0") == 0)
+ {
+ reset = 1;
+ mips_opts.isa = file_mips_isa;
+ }
+ else if (strcmp (name, "mips1") == 0)
+ mips_opts.isa = ISA_MIPS1;
+ else if (strcmp (name, "mips2") == 0)
+ mips_opts.isa = ISA_MIPS2;
+ else if (strcmp (name, "mips3") == 0)
+ mips_opts.isa = ISA_MIPS3;
+ else if (strcmp (name, "mips4") == 0)
+ mips_opts.isa = ISA_MIPS4;
+ else if (strcmp (name, "mips5") == 0)
+ mips_opts.isa = ISA_MIPS5;
+ else if (strcmp (name, "mips32") == 0)
+ mips_opts.isa = ISA_MIPS32;
+ else if (strcmp (name, "mips32r2") == 0)
+ mips_opts.isa = ISA_MIPS32R2;
+ else if (strcmp (name, "mips64") == 0)
+ mips_opts.isa = ISA_MIPS64;
+ else
+ as_bad (_("unknown ISA level %s"), name + 4);
+
+ switch (mips_opts.isa)
{
case 0:
- mips_opts.gp32 = file_mips_gp32;
- mips_opts.fp32 = file_mips_fp32;
break;
- case 1:
- case 2:
- case 32:
+ case ISA_MIPS1:
+ case ISA_MIPS2:
+ case ISA_MIPS32:
+ case ISA_MIPS32R2:
mips_opts.gp32 = 1;
mips_opts.fp32 = 1;
break;
- case 3:
- case 4:
- case 5:
- case 64:
+ case ISA_MIPS3:
+ case ISA_MIPS4:
+ case ISA_MIPS5:
+ case ISA_MIPS64:
mips_opts.gp32 = 0;
mips_opts.fp32 = 0;
break;
@@ -12047,18 +12169,10 @@ s_mipsset (x)
as_bad (_("unknown ISA level %s"), name + 4);
break;
}
-
- switch (isa)
+ if (reset)
{
- case 0: mips_opts.isa = file_mips_isa; break;
- case 1: mips_opts.isa = ISA_MIPS1; break;
- case 2: mips_opts.isa = ISA_MIPS2; break;
- case 3: mips_opts.isa = ISA_MIPS3; break;
- case 4: mips_opts.isa = ISA_MIPS4; break;
- case 5: mips_opts.isa = ISA_MIPS5; break;
- case 32: mips_opts.isa = ISA_MIPS32; break;
- case 64: mips_opts.isa = ISA_MIPS64; break;
- default: as_bad (_("unknown ISA level %s"), name + 4); break;
+ mips_opts.gp32 = file_mips_gp32;
+ mips_opts.fp32 = file_mips_fp32;
}
}
else if (strcmp (name, "autoextend") == 0)
@@ -14360,6 +14474,7 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
{ "mips4", 1, ISA_MIPS4, CPU_R8000 },
{ "mips5", 1, ISA_MIPS5, CPU_MIPS5 },
{ "mips32", 1, ISA_MIPS32, CPU_MIPS32 },
+ { "mips32r2", 1, ISA_MIPS32R2, CPU_MIPS32R2 },
{ "mips64", 1, ISA_MIPS64, CPU_MIPS64 },
/* MIPS I */
@@ -14586,6 +14701,7 @@ MIPS options:\n\
-mips4 generate MIPS ISA IV instructions\n\
-mips5 generate MIPS ISA V instructions\n\
-mips32 generate MIPS32 ISA instructions\n\
+-mips32r2 generate MIPS32 release 2 ISA instructions\n\
-mips64 generate MIPS64 ISA instructions\n\
-march=CPU/-mtune=CPU generate code/schedule for CPU, where CPU is one of:\n"));