aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2002-09-30 12:04:54 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2002-09-30 12:04:54 +0000
commit60b63b728f8bd4156ee67f70183fa01b425c2cba (patch)
tree3cb3153bd6ad9d55ff9db92ff4d2c27dd7e7d565 /gas/config
parent9752cf1b67871d71ba4ccaf358e7550979bb4a3c (diff)
downloadgdb-60b63b728f8bd4156ee67f70183fa01b425c2cba.zip
gdb-60b63b728f8bd4156ee67f70183fa01b425c2cba.tar.gz
gdb-60b63b728f8bd4156ee67f70183fa01b425c2cba.tar.bz2
[gas/]
* doc/c-mips.texi: Add entries for -march=vr4120,vr4130,vr4181, vr5400 and vr5500. Add entry for -mfix-vr4122-bugs. * config/tc-mips.c (CPU_HAS_DROR, CPU_HAS_ROR): New macros. (hilo_interlocks): True for CPU_VR5500. (gpr_interlocks, cop_interlocks): True for CPU_VR5400 and CPU_VR5500. (mips_fix_vr4122_bugs): New. (append_insn): Work around 4122 errors if mips_fix_vr4122_bugs. (mips_emit_delays): Likewise. (macro2) [M_DROLI]: Use dror or dror32 if CPU_HAS_DROR. [M_ROLI]: Likewise ror if CPU_HAS_ROR. (validate_mips_insn, mips_ip): Handle '[', ']', 'e' and '%'. (OPTION_FIX_VR4122, OPTION_NO_FIX_VR4122): New options. (md_longopts): Add -mfix-vr4122-bugs and -no-mfix-vr4122-bugs. (OPTION_ELF_BASE): Bump. (md_parse_option): Handle the new options. (mips_cpu_info_table): Add entries for vr4120, vr4130, vr4181, vr5400 and vr5500. [gas/testsuite/] * gas/mips/mips4100.[sd]: Move dmadd16 and madd16 checks to... * gas/mips/vr4111.[sd]: ...this new test. * gas/mips/vr4120.[sd], * gas/mips/vr4122.[sd], * gas/mips/vr5400.[sd], * gas/mips/vr5500.[sd]: New tests. * mips.exp: Run them.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-mips.c148
1 files changed, 147 insertions, 1 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 7c8be07..d88c925 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -296,11 +296,18 @@ static int mips_32bitmode = 0;
#define CPU_HAS_MDMX(cpu) (false \
)
+/* True if CPU has a dror instruction. */
+#define CPU_HAS_DROR(CPU) ((CPU) == CPU_VR5400 || (CPU) == CPU_VR5500)
+
+/* True if CPU has a ror instruction. */
+#define CPU_HAS_ROR(CPU) CPU_HAS_DROR (CPU)
+
/* Whether the processor uses hardware interlocks to protect
reads from the HI and LO registers, and thus does not
require nops to be inserted. */
#define hilo_interlocks (mips_arch == CPU_R4010 \
+ || mips_arch == CPU_VR5500 \
|| mips_arch == CPU_SB1 \
)
@@ -308,12 +315,16 @@ static int mips_32bitmode = 0;
from the GPRs, and thus does not require nops to be inserted. */
#define gpr_interlocks \
(mips_opts.isa != ISA_MIPS1 \
+ || mips_arch == CPU_VR5400 \
+ || mips_arch == CPU_VR5500 \
|| mips_arch == CPU_R3900)
/* As with other "interlocks" this is used by hardware that has FP
(co-processor) interlocks. */
/* Itbl support may require additional care here. */
#define cop_interlocks (mips_arch == CPU_R4300 \
+ || mips_arch == CPU_VR5400 \
+ || mips_arch == CPU_VR5500 \
|| mips_arch == CPU_SB1 \
)
@@ -550,6 +561,8 @@ static const unsigned int mips16_to_32_reg_map[] =
{
16, 17, 2, 3, 4, 5, 6, 7
};
+
+static int mips_fix_4122_bugs;
/* Since the MIPS does not have multiple forms of PC relative
instructions, we do not have to do relaxing as is done on other
@@ -1689,6 +1702,50 @@ append_insn (place, ip, address_expr, reloc_type, unmatched_hi)
if (prev_prev_nop && nops == 0)
++nops;
+ if (mips_fix_4122_bugs && prev_insn.insn_mo->name)
+ {
+ /* We're out of bits in pinfo, so we must resort to string
+ ops here. Shortcuts are selected based on opcodes being
+ limited to the VR4122 instruction set. */
+ int min_nops = 0;
+ const char *pn = prev_insn.insn_mo->name;
+ const char *tn = ip->insn_mo->name;
+ if (strncmp(pn, "macc", 4) == 0
+ || strncmp(pn, "dmacc", 5) == 0)
+ {
+ /* Errata 21 - [D]DIV[U] after [D]MACC */
+ if (strstr (tn, "div"))
+ {
+ min_nops = 1;
+ }
+
+ /* Errata 23 - Continuous DMULT[U]/DMACC instructions */
+ if (pn[0] == 'd' /* dmacc */
+ && (strncmp(tn, "dmult", 5) == 0
+ || strncmp(tn, "dmacc", 5) == 0))
+ {
+ min_nops = 1;
+ }
+
+ /* Errata 24 - MT{LO,HI} after [D]MACC */
+ if (strcmp (tn, "mtlo") == 0
+ || strcmp (tn, "mthi") == 0)
+ {
+ min_nops = 1;
+ }
+
+ }
+ else if (strncmp(pn, "dmult", 5) == 0
+ && (strncmp(tn, "dmult", 5) == 0
+ || strncmp(tn, "dmacc", 5) == 0))
+ {
+ /* Here is the rest of errata 23. */
+ min_nops = 1;
+ }
+ if (nops < min_nops)
+ nops = min_nops;
+ }
+
/* If we are being given a nop instruction, don't bother with
one of the nops we would otherwise output. This will only
happen when a nop instruction is used with mips_optimize set
@@ -2586,6 +2643,20 @@ mips_emit_delays (insns)
++nops;
}
+ if (mips_fix_4122_bugs && prev_insn.insn_mo->name)
+ {
+ int min_nops = 0;
+ const char *pn = prev_insn.insn_mo->name;
+ if (strncmp(pn, "macc", 4) == 0
+ || strncmp(pn, "dmacc", 5) == 0
+ || strncmp(pn, "dmult", 5) == 0)
+ {
+ min_nops = 1;
+ }
+ if (nops < min_nops)
+ nops = min_nops;
+ }
+
if (nops > 0)
{
struct insn_label_list *l;
@@ -6714,6 +6785,17 @@ macro2 (ip)
if (imm_expr.X_op != O_constant)
as_bad (_("rotate count too large"));
rot = imm_expr.X_add_number & 0x3f;
+ if (CPU_HAS_DROR (mips_arch))
+ {
+ rot = (64 - rot) & 0x3f;
+ if (rot >= 32)
+ macro_build ((char *) NULL, &icnt, NULL, "dror32",
+ "d,w,<", dreg, sreg, rot - 32);
+ else
+ macro_build ((char *) NULL, &icnt, NULL, "dror",
+ "d,w,<", dreg, sreg, rot);
+ break;
+ }
if (rot == 0)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "dsrl",
"d,w,<", dreg, sreg, 0);
@@ -6741,6 +6823,12 @@ macro2 (ip)
if (imm_expr.X_op != O_constant)
as_bad (_("rotate count too large"));
rot = imm_expr.X_add_number & 0x1f;
+ if (CPU_HAS_ROR (mips_arch))
+ {
+ macro_build ((char *) NULL, &icnt, NULL, "ror",
+ "d,w,<", dreg, sreg, (32 - rot) & 0x1f);
+ break;
+ }
if (rot == 0)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "srl",
"d,w,<", dreg, sreg, 0);
@@ -7716,6 +7804,10 @@ validate_mips_insn (opc)
case 'P': USE_BITS (OP_MASK_PERFREG, OP_SH_PERFREG); break;
case 'U': USE_BITS (OP_MASK_RD, OP_SH_RD);
USE_BITS (OP_MASK_RT, OP_SH_RT); break;
+ case 'e': USE_BITS (OP_MASK_VECBYTE, OP_SH_VECBYTE); break;
+ case '%': USE_BITS (OP_MASK_VECALIGN, OP_SH_VECALIGN); break;
+ case '[': break;
+ case ']': break;
default:
as_bad (_("internal: bad mips opcode (unknown operand type `%c'): %s %s"),
c, opc->name, opc->args);
@@ -7907,6 +7999,8 @@ mips_ip (str, ip)
return;
case ')': /* these must match exactly */
+ case '[':
+ case ']':
if (*s++ == *args)
continue;
break;
@@ -8828,6 +8922,41 @@ mips_ip (str, ip)
ip->insn_opcode |= c;
continue;
+ case 'e':
+ /* Must be at least one digit. */
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+
+ if ((unsigned long) imm_expr.X_add_number
+ > (unsigned long) OP_MASK_VECBYTE)
+ {
+ as_bad (_("bad byte vector index (%ld)"),
+ (long) imm_expr.X_add_number);
+ imm_expr.X_add_number = 0;
+ }
+
+ ip->insn_opcode |= imm_expr.X_add_number << OP_SH_VECBYTE;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
+ case '%':
+ my_getExpression (&imm_expr, s);
+ check_absolute_expr (ip, &imm_expr);
+
+ if ((unsigned long) imm_expr.X_add_number
+ > (unsigned long) OP_MASK_VECALIGN)
+ {
+ as_bad (_("bad byte vector index (%ld)"),
+ (long) imm_expr.X_add_number);
+ imm_expr.X_add_number = 0;
+ }
+
+ ip->insn_opcode |= imm_expr.X_add_number << OP_SH_VECALIGN;
+ imm_expr.X_op = O_absent;
+ s = expr_end;
+ continue;
+
default:
as_bad (_("bad char = '%c'\n"), *args);
internalError ();
@@ -9992,8 +10121,12 @@ struct option md_longopts[] =
{"mdmx", no_argument, NULL, OPTION_MDMX},
#define OPTION_NO_MDMX (OPTION_MD_BASE + 36)
{"no-mdmx", no_argument, NULL, OPTION_NO_MDMX},
+#define OPTION_FIX_VR4122 (OPTION_MD_BASE + 37)
+#define OPTION_NO_FIX_VR4122 (OPTION_MD_BASE + 38)
+ {"mfix-vr4122-bugs", no_argument, NULL, OPTION_FIX_VR4122},
+ {"no-mfix-vr4122-bugs", no_argument, NULL, OPTION_NO_FIX_VR4122},
#ifdef OBJ_ELF
-#define OPTION_ELF_BASE (OPTION_MD_BASE + 37)
+#define OPTION_ELF_BASE (OPTION_MD_BASE + 39)
#define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
@@ -10194,6 +10327,14 @@ md_parse_option (c, arg)
g_switch_value = 0x7fffffff;
break;
+ case OPTION_FIX_VR4122:
+ mips_fix_4122_bugs = 1;
+ break;
+
+ case OPTION_NO_FIX_VR4122:
+ mips_fix_4122_bugs = 0;
+ break;
+
#ifdef OBJ_ELF
/* When generating ELF code, we permit -KPIC and -call_shared to
select SVR4_PIC, and -non_shared to select no PIC. This is
@@ -13644,6 +13785,9 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
{ "r4010", 0, ISA_MIPS2, CPU_R4010 },
{ "vr4100", 0, ISA_MIPS3, CPU_VR4100 },
{ "vr4111", 0, ISA_MIPS3, CPU_R4111 },
+ { "vr4120", 0, ISA_MIPS3, CPU_VR4120 },
+ { "vr4130", 0, ISA_MIPS3, CPU_VR4120 },
+ { "vr4181", 0, ISA_MIPS3, CPU_R4111 },
{ "vr4300", 0, ISA_MIPS3, CPU_R4300 },
{ "r4400", 0, ISA_MIPS3, CPU_R4400 },
{ "r4600", 0, ISA_MIPS3, CPU_R4600 },
@@ -13655,6 +13799,8 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
{ "r10000", 0, ISA_MIPS4, CPU_R10000 },
{ "r12000", 0, ISA_MIPS4, CPU_R12000 },
{ "vr5000", 0, ISA_MIPS4, CPU_R5000 },
+ { "vr5400", 0, ISA_MIPS4, CPU_VR5400 },
+ { "vr5500", 0, ISA_MIPS4, CPU_VR5500 },
{ "rm5200", 0, ISA_MIPS4, CPU_R5000 },
{ "rm5230", 0, ISA_MIPS4, CPU_R5000 },
{ "rm5231", 0, ISA_MIPS4, CPU_R5000 },