-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathgcc-vr4300.patch
205 lines (191 loc) · 7.13 KB
/
gcc-vr4300.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index e64928f4113..7aee85ac65d 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -13811,6 +13811,7 @@ mips_adjust_insn_length (rtx_insn *insn, int length)
case HAZARD_DELAY:
case HAZARD_FORBIDDEN_SLOT:
+ case HAZARD_MUL:
length += NOP_INSN_LENGTH;
break;
@@ -18972,6 +18973,32 @@ mips_classify_branch_p6600 (rtx_insn *insn)
return UC_UNDEFINED;
}
+/* Subroutine of mips_reorg_process_insns. Early revisions of the VR4300 have
+ an issue where a floating point multiply may corrupt the result of a
+ following integer or floating point multiply if one or more of the operands
+ is infinity, 0, or sNaN.
+
+ This can also happen if the instruction is in a delay slot and the jump target
+ is a multiply instruction, so this detects both a multiply or a branch slot. */
+
+static bool
+mips_needs_nop_after_fmul (rtx_insn *insn)
+{
+ if (!insn)
+ return false;
+
+ if (!TARGET_4300_MUL_FIX)
+ return false;
+
+ if (!INSN_P (insn) || recog_memoized (insn) < 0)
+ return false;
+
+ return INSN_ANNULLED_BRANCH_P (insn) /* branch with unfilled delay slot */
+ || get_attr_type (insn) == TYPE_FMUL /* MUL.S, MUL.D */
+ || get_attr_type (insn) == TYPE_IMUL; /* MULT, MULTU */
+}
+
+
/* Subroutine of mips_reorg_process_insns. If there is a hazard between
INSN and a previous instruction, avoid it by inserting nops after
instruction AFTER.
@@ -18989,7 +19016,7 @@ mips_classify_branch_p6600 (rtx_insn *insn)
static void
mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
- rtx *delayed_reg, rtx lo_reg, bool *fs_delay)
+ rtx *delayed_reg, rtx lo_reg, bool *fs_delay, bool *fmul_delay)
{
rtx pattern, set;
int nops, ninsns;
@@ -19039,6 +19066,8 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
|| (mips_classify_branch_p6600 (insn) == UC_BALC
&& mips_classify_branch_p6600 (after) == UC_OTHER)))
nops = 1;
+ else if (*fmul_delay && mips_needs_nop_after_fmul (insn))
+ nops = 1;
else
nops = 0;
@@ -19063,6 +19092,7 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
*hilo_delay += ninsns;
*delayed_reg = 0;
*fs_delay = false;
+ *fmul_delay = false;
if (INSN_CODE (insn) >= 0)
switch (get_attr_hazard (insn))
{
@@ -19092,6 +19122,10 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay,
gcc_assert (set);
*delayed_reg = SET_DEST (set);
break;
+
+ case HAZARD_MUL:
+ *fmul_delay = true;
+ break;
}
}
@@ -19135,6 +19169,7 @@ mips_reorg_process_insns (void)
rtx lo_reg, delayed_reg;
int hilo_delay;
bool fs_delay;
+ bool fmul_delay;
/* Force all instructions to be split into their final form. */
split_all_insns_noflow ();
@@ -19204,6 +19239,7 @@ mips_reorg_process_insns (void)
delayed_reg = 0;
lo_reg = gen_rtx_REG (SImode, LO_REGNUM);
fs_delay = false;
+ fmul_delay = false;
/* Make a second pass over the instructions. Delete orphaned
high-part relocations or turn them into NOPs. Avoid hazards
@@ -19288,7 +19324,7 @@ mips_reorg_process_insns (void)
INSN_CODE (subinsn) = CODE_FOR_nop;
}
mips_avoid_hazard (last_insn, subinsn, &hilo_delay,
- &delayed_reg, lo_reg, &fs_delay);
+ &delayed_reg, lo_reg, &fs_delay, &fmul_delay);
}
last_insn = insn;
}
@@ -19309,7 +19345,7 @@ mips_reorg_process_insns (void)
else
{
mips_avoid_hazard (last_insn, insn, &hilo_delay,
- &delayed_reg, lo_reg, &fs_delay);
+ &delayed_reg, lo_reg, &fs_delay, &fmul_delay);
/* When a compact branch introduces a forbidden slot hazard
and the next useful instruction is a SEQUENCE of a jump
and a non-nop instruction in the delay slot, remove the
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 02562d3b644..28687325a88 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -294,6 +294,7 @@ struct mips_cpu_info {
#define TARGET_MIPS4000 (mips_arch == PROCESSOR_R4000)
#define TARGET_MIPS4120 (mips_arch == PROCESSOR_R4120)
#define TARGET_MIPS4130 (mips_arch == PROCESSOR_R4130)
+#define TARGET_MIPS4300 (mips_arch == PROCESSOR_R4300)
#define TARGET_MIPS5400 (mips_arch == PROCESSOR_R5400)
#define TARGET_MIPS5500 (mips_arch == PROCESSOR_R5500)
#define TARGET_MIPS5900 (mips_arch == PROCESSOR_R5900)
@@ -1294,11 +1295,13 @@ struct mips_cpu_info {
/* Likewise mtc1 and mfc1. */
#define ISA_HAS_XFER_DELAY (mips_isa <= MIPS_ISA_MIPS3 \
+ && !TARGET_MIPS4300 \
&& !TARGET_MIPS5900 \
&& !TARGET_LOONGSON_2EF)
/* Likewise floating-point comparisons. */
#define ISA_HAS_FCMP_DELAY (mips_isa <= MIPS_ISA_MIPS3 \
+ && !TARGET_MIPS4300 \
&& !TARGET_MIPS5900 \
&& !TARGET_LOONGSON_2EF)
@@ -1433,6 +1436,7 @@ struct mips_cpu_info {
%{mfix-r5900} %{mno-fix-r5900} \
%{mfix-rm7000} %{mno-fix-rm7000} \
%{mfix-vr4120} %{mfix-vr4130} \
+%{mfix4300} %{mno-fix4300} \
%{mfix-24k} \
%{noasmopt:-O0; O0|fno-delayed-branch:-O1; O*:-O2; :-O1} \
%(subtarget_asm_debugging_spec) \
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index e0f0a582732..4301a0a9eff 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -740,7 +740,7 @@
;; DELAY means that the next instruction cannot read the result
;; of this one. HILO means that the next two instructions cannot
;; write to HI or LO.
-(define_attr "hazard" "none,delay,hilo,forbidden_slot"
+(define_attr "hazard" "none,delay,hilo,forbidden_slot,mul"
(cond [(and (eq_attr "type" "load,fpload,fpidxload")
(match_test "ISA_HAS_LOAD_DELAY"))
(const_string "delay")
@@ -760,8 +760,12 @@
(and (eq_attr "type" "mfhi,mflo")
(not (match_test "ISA_HAS_HILO_INTERLOCKS")))
- (const_string "hilo")]
- (const_string "none")))
+ (const_string "hilo")
+
+ (and (eq_attr "type" "fmul")
+ (match_test "TARGET_4300_MUL_FIX"))
+ (const_string "mul")]
+ (const_string "none")))
;; Can the instruction be put into a delay slot?
(define_attr "can_delay" "no,yes"
@@ -1527,25 +1531,11 @@
[(set (match_operand:SCALARF 0 "register_operand" "=f")
(mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
(match_operand:SCALARF 2 "register_operand" "f")))]
- "!TARGET_4300_MUL_FIX"
+ ""
"mul.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmul")
(set_attr "mode" "<MODE>")])
-;; Early VR4300 silicon has a CPU bug where multiplies with certain
-;; operands may corrupt immediately following multiplies. This is a
-;; simple fix to insert NOPs.
-
-(define_insn "*mul<mode>3_r4300"
- [(set (match_operand:SCALARF 0 "register_operand" "=f")
- (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
- (match_operand:SCALARF 2 "register_operand" "f")))]
- "TARGET_4300_MUL_FIX"
- "mul.<fmt>\t%0,%1,%2\;nop"
- [(set_attr "type" "fmul")
- (set_attr "mode" "<MODE>")
- (set_attr "insn_count" "2")])
-
(define_insn "mulv2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=f")
(mult:V2SF (match_operand:V2SF 1 "register_operand" "f")