mirror of
https://github.com/Stichting-MINIX-Research-Foundation/pkgsrc-ng.git
synced 2025-09-13 14:25:12 -04:00
245 lines
7.9 KiB
C
245 lines
7.9 KiB
C
$NetBSD$
|
||
|
||
--- gas/config/tc-mips.c.orig Tue Sep 4 14:21:03 2012
|
||
+++ gas/config/tc-mips.c
|
||
@@ -909,6 +909,9 @@ enum fix_vr4120_class
|
||
NUM_FIX_VR4120_CLASSES
|
||
};
|
||
|
||
+/* ...likewise -mtrap-zero-jump. */
|
||
+static bfd_boolean mips_trap_zero_jump;
|
||
+
|
||
/* ...likewise -mfix-loongson2f-jump. */
|
||
static bfd_boolean mips_fix_loongson2f_jump;
|
||
|
||
@@ -941,6 +944,8 @@ static bfd_boolean mips_fix_cn63xxp1;
|
||
efficient expansion. */
|
||
|
||
static int mips_relax_branch;
|
||
+
|
||
+static int mips_fix_loongson2f_btb;
|
||
|
||
/* The expansion of many macros depends on the type of symbol that
|
||
they refer to. For example, when generating position-dependent code,
|
||
@@ -1316,6 +1321,7 @@ static void macro_build (expressionS *, const char *,
|
||
static void mips16_macro_build
|
||
(expressionS *, const char *, const char *, va_list *);
|
||
static void load_register (int, expressionS *, int);
|
||
+static void macro_build (expressionS *, const char *, const char *, ...);
|
||
static void macro_start (void);
|
||
static void macro_end (void);
|
||
static void macro (struct mips_cl_insn * ip);
|
||
@@ -3626,6 +3632,35 @@ nops_for_insn_or_target (int ignore, const struct mips
|
||
return nops;
|
||
}
|
||
|
||
+static void
|
||
+trap_zero_jump (struct mips_cl_insn * ip)
|
||
+{
|
||
+ if (strcmp (ip->insn_mo->name, "j") == 0
|
||
+ || strcmp (ip->insn_mo->name, "jr") == 0
|
||
+ || strcmp (ip->insn_mo->name, "jalr") == 0)
|
||
+ {
|
||
+ int sreg;
|
||
+
|
||
+ if (mips_opts.warn_about_macros)
|
||
+ return;
|
||
+
|
||
+ sreg = EXTRACT_OPERAND (0, RS, *ip);
|
||
+ if (mips_opts.isa == ISA_MIPS32
|
||
+ || mips_opts.isa == ISA_MIPS32R2
|
||
+ || mips_opts.isa == ISA_MIPS64
|
||
+ || mips_opts.isa == ISA_MIPS64R2)
|
||
+ {
|
||
+ expressionS ep;
|
||
+ ep.X_op = O_constant;
|
||
+ ep.X_add_number = 4096;
|
||
+ macro_build (&ep, "tltiu", "s,j", sreg, BFD_RELOC_LO16);
|
||
+ }
|
||
+ else if (mips_opts.isa != ISA_UNKNOWN
|
||
+ && mips_opts.isa != ISA_MIPS1)
|
||
+ macro_build (NULL, "teq", "s,t", sreg, 0);
|
||
+ }
|
||
+}
|
||
+
|
||
/* Fix NOP issue: Replace nops by "or at,at,zero". */
|
||
|
||
static void
|
||
@@ -3663,6 +3698,16 @@ fix_loongson2f_jump (struct mips_cl_insn * ip)
|
||
ep.X_add_number = 0xffff;
|
||
macro_build (&ep, "ori", "t,r,i", ATREG, ATREG, BFD_RELOC_LO16);
|
||
macro_build (NULL, "and", "d,v,t", sreg, sreg, ATREG);
|
||
+ /* Hide these three instructions to avoid getting a ``macro expanded into
|
||
+ multiple instructions'' warning. */
|
||
+ if (mips_relax.sequence != 2) {
|
||
+ mips_macro_warning.sizes[0] -= 3 * 4;
|
||
+ mips_macro_warning.insns[0] -= 3;
|
||
+ }
|
||
+ if (mips_relax.sequence != 1) {
|
||
+ mips_macro_warning.sizes[1] -= 3 * 4;
|
||
+ mips_macro_warning.insns[1] -= 3;
|
||
+ }
|
||
}
|
||
}
|
||
|
||
@@ -3718,6 +3763,11 @@ can_swap_branch_p (struct mips_cl_insn *ip)
|
||
if (mips_opts.mips16 && history[0].fixp[0])
|
||
return FALSE;
|
||
|
||
+ if (mips_fix_loongson2f)
|
||
+ fix_loongson2f (ip);
|
||
+ if (mips_trap_zero_jump)
|
||
+ trap_zero_jump (ip);
|
||
+
|
||
/* If the branch is itself the target of a branch, we can not swap.
|
||
We cheat on this; all we check for is whether there is a label on
|
||
this instruction. If there are any branches to anything other than
|
||
@@ -4764,6 +4814,45 @@ macro_read_relocs (va_list *args, bfd_reloc_code_real_
|
||
r[i] = (bfd_reloc_code_real_type) va_arg (*args, int);
|
||
}
|
||
|
||
+/* Fix jump through register issue on loongson2f processor for kernel code:
|
||
+ force a BTB clear before the jump to prevent it from being incorrectly
|
||
+ prefetched by the branch prediction engine. */
|
||
+
|
||
+static void
|
||
+macro_build_jrpatch (expressionS *ep, unsigned int sreg)
|
||
+{
|
||
+ if (!mips_fix_loongson2f_btb)
|
||
+ return;
|
||
+
|
||
+ if (sreg == ZERO || sreg == KT0 || sreg == KT1 || sreg == AT)
|
||
+ return;
|
||
+
|
||
+ if (!mips_opts.at)
|
||
+ {
|
||
+ as_warn (_("unable to apply loongson2f BTB workaround when .set noat"));
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* li $at, COP_0_BTB_CLEAR | COP_0_RAS_DISABLE */
|
||
+ ep->X_op = O_constant;
|
||
+ ep->X_add_number = 3;
|
||
+ macro_build (ep, "ori", "t,r,i", AT, ZERO, BFD_RELOC_LO16);
|
||
+
|
||
+ /* dmtc0 $at, COP_0_DIAG */
|
||
+ macro_build (NULL, "dmtc0", "t,G", AT, 22);
|
||
+
|
||
+ /* Hide these two instructions to avoid getting a ``macro expanded into
|
||
+ multiple instructions'' warning. */
|
||
+ if (mips_relax.sequence != 2) {
|
||
+ mips_macro_warning.sizes[0] -= 2 * 4;
|
||
+ mips_macro_warning.insns[0] -= 2;
|
||
+ }
|
||
+ if (mips_relax.sequence != 1) {
|
||
+ mips_macro_warning.sizes[1] -= 2 * 4;
|
||
+ mips_macro_warning.insns[0] -= 2;
|
||
+ }
|
||
+}
|
||
+
|
||
/* Build an instruction created by a macro expansion. This is passed
|
||
a pointer to the count of instructions created so far, an
|
||
expression, the name of the instruction to build, an operand format
|
||
@@ -7637,6 +7726,26 @@ macro (struct mips_cl_insn *ip)
|
||
macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", treg, tempreg, breg);
|
||
break;
|
||
|
||
+ case M_JR_S:
|
||
+ macro_build_jrpatch (&expr1, sreg);
|
||
+ macro_build (NULL, "jr", "s", sreg);
|
||
+ return; /* didn't modify $at */
|
||
+
|
||
+ case M_J_S:
|
||
+ macro_build_jrpatch (&expr1, sreg);
|
||
+ macro_build (NULL, "j", "s", sreg);
|
||
+ return; /* didn't modify $at */
|
||
+
|
||
+ case M_JALR_S:
|
||
+ macro_build_jrpatch (&expr1, sreg);
|
||
+ macro_build (NULL, "jalr", "s", sreg);
|
||
+ return; /* didn't modify $at */
|
||
+
|
||
+ case M_JALR_DS:
|
||
+ macro_build_jrpatch (&expr1, sreg);
|
||
+ macro_build (NULL, "jalr", "d,s", dreg, sreg);
|
||
+ return; /* didn't modify $at */
|
||
+
|
||
case M_MSGSND:
|
||
gas_assert (!mips_opts.micromips);
|
||
{
|
||
@@ -14350,6 +14459,8 @@ enum options
|
||
OPTION_SINGLE_FLOAT,
|
||
OPTION_DOUBLE_FLOAT,
|
||
OPTION_32,
|
||
+ OPTION_TRAP_ZERO_JUMP,
|
||
+ OPTION_NO_TRAP_ZERO_JUMP,
|
||
#ifdef OBJ_ELF
|
||
OPTION_CALL_SHARED,
|
||
OPTION_CALL_NONPIC,
|
||
@@ -14364,6 +14475,8 @@ enum options
|
||
OPTION_NO_PDR,
|
||
OPTION_MVXWORKS_PIC,
|
||
#endif /* OBJ_ELF */
|
||
+ OPTION_FIX_LOONGSON2F_BTB,
|
||
+ OPTION_NO_FIX_LOONGSON2F_BTB,
|
||
OPTION_END_OF_ENUM
|
||
};
|
||
|
||
@@ -14421,6 +14534,8 @@ struct option md_longopts[] =
|
||
{"mno-fix-loongson2f-jump", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_JUMP},
|
||
{"mfix-loongson2f-nop", no_argument, NULL, OPTION_FIX_LOONGSON2F_NOP},
|
||
{"mno-fix-loongson2f-nop", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_NOP},
|
||
+ {"mfix-loongson2f-btb", no_argument, NULL, OPTION_FIX_LOONGSON2F_BTB},
|
||
+ {"mno-fix-loongson2f-btb", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_BTB},
|
||
{"mfix-vr4120", no_argument, NULL, OPTION_FIX_VR4120},
|
||
{"mno-fix-vr4120", no_argument, NULL, OPTION_NO_FIX_VR4120},
|
||
{"mfix-vr4130", no_argument, NULL, OPTION_FIX_VR4130},
|
||
@@ -14459,6 +14574,9 @@ struct option md_longopts[] =
|
||
make testing easier. */
|
||
{"32", no_argument, NULL, OPTION_32},
|
||
|
||
+ {"mtrap-zero-jump", no_argument, NULL, OPTION_TRAP_ZERO_JUMP},
|
||
+ {"mno-trap-zero-jump", no_argument, NULL, OPTION_NO_TRAP_ZERO_JUMP},
|
||
+
|
||
/* ELF-specific options. */
|
||
#ifdef OBJ_ELF
|
||
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
|
||
@@ -14750,6 +14868,14 @@ md_parse_option (int c, char *arg)
|
||
mips_fix_vr4130 = 0;
|
||
break;
|
||
|
||
+ case OPTION_FIX_LOONGSON2F_BTB:
|
||
+ mips_fix_loongson2f_btb = 1;
|
||
+ break;
|
||
+
|
||
+ case OPTION_NO_FIX_LOONGSON2F_BTB:
|
||
+ mips_fix_loongson2f_btb = 0;
|
||
+ break;
|
||
+
|
||
case OPTION_FIX_CN63XXP1:
|
||
mips_fix_cn63xxp1 = TRUE;
|
||
break;
|
||
@@ -14782,6 +14908,14 @@ md_parse_option (int c, char *arg)
|
||
mips_opts.sym32 = FALSE;
|
||
break;
|
||
|
||
+ case OPTION_TRAP_ZERO_JUMP:
|
||
+ mips_trap_zero_jump = TRUE;
|
||
+ break;
|
||
+
|
||
+ case OPTION_NO_TRAP_ZERO_JUMP:
|
||
+ mips_trap_zero_jump = FALSE;
|
||
+ 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
|
||
@@ -19411,6 +19545,7 @@ MIPS options:\n\
|
||
fprintf (stream, _("\
|
||
-mfix-loongson2f-jump work around Loongson2F JUMP instructions\n\
|
||
-mfix-loongson2f-nop work around Loongson2F NOP errata\n\
|
||
+-mfix-loongson2f-btb work around Loongson2F BTB errata\n\
|
||
-mfix-vr4120 work around certain VR4120 errata\n\
|
||
-mfix-vr4130 work around VR4130 mflo/mfhi errata\n\
|
||
-mfix-24k insert a nop after ERET and DERET instructions\n\
|