xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/h8300/testcompare.md (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1;; ----------------------------------------------------------------------
2;; TEST INSTRUCTIONS
3;; ----------------------------------------------------------------------
4
5;; (define_insn_and_split "*tst_extzv_1_n"
6;;   [(set (cc0)
7;; 	(compare (zero_extract:SI (match_operand:QI 0 "general_operand_src" "r,U,mn>")
8;; 				  (const_int 1)
9;; 				  (match_operand 1 "const_int_operand" "n,n,n"))
10;; 		 (const_int 0)))
11;;   (clobber (match_scratch:QI 2 "=X,X,&r"))]
12;;  "!CONSTANT_P (operands[0])"
13;;  "@
14;;   btst\\t%Z1,%Y0
15;;   btst\\t%Z1,%Y0
16;;   #"
17;;  "&& reload_completed
18;;   && !satisfies_constraint_U (operands[0])"
19;;  [(set (match_dup 2)
20;;	(match_dup 0))
21;;   (parallel [(set (cc0) (compare (zero_extract:SI (match_dup 2)
22;;						   (const_int 1)
23;;						   (match_dup 1))
24;;				  (const_int 0)))
25;;	      (clobber (scratch:QI))])]
26;;  ""
27;;  [(set_attr "length" "2,8,10")])
28;;
29(define_insn ""
30  [(set (reg:CCZ CC_REG)
31	(eq (zero_extract:HSI (match_operand:HSI 0 "register_operand" "r")
32			      (const_int 1)
33			      (match_operand 1 "const_int_operand" "n"))
34	    (const_int 0)))]
35  "INTVAL (operands[1]) < 16"
36  "btst	%Z1,%Y0"
37  [(set_attr "length" "2")])
38
39(define_insn "*tst<mode>"
40  [(set (reg:CCZN CC_REG)
41	(compare:CCZN (match_operand:QHSI 0 "register_operand" "r")
42		      (const_int 0)))]
43  ""
44  {
45    if (<MODE>mode == QImode)
46      return "mov.b	%X0,%X0";
47    else if (<MODE>mode == HImode)
48      return "mov.w	%T0,%T0";
49    else if (<MODE>mode == SImode)
50      return "mov.l	%S0,%S0";
51    gcc_unreachable ();
52  }
53  [(set_attr "length" "2")])
54
55(define_insn "*tsthi_upper"
56  [(set (reg:CCZN CC_REG)
57	(compare (and:HI (match_operand:HI 0 "register_operand" "r")
58			 (const_int -256))
59		 (const_int 0)))]
60  "reload_completed"
61  "mov.b	%t0,%t0"
62  [(set_attr "length" "2")])
63
64(define_insn "*tstsi_upper"
65  [(set (reg:CCZN CC_REG)
66	(compare (and:SI (match_operand:SI 0 "register_operand" "r")
67			 (const_int -65536))
68		 (const_int 0)))]
69  "reload_completed"
70  "mov.w	%e0,%e0"
71  [(set_attr "length" "2")])
72
73(define_insn "*cmp<mode>_c"
74  [(set (reg:CCC CC_REG)
75	(ltu (match_operand:QHSI 0 "h8300_dst_operand" "rQ")
76	     (match_operand:QHSI 1 "h8300_src_operand" "rQi")))]
77  "reload_completed"
78  {
79    if (<MODE>mode == QImode)
80      return "cmp.b	%X1,%X0";
81    else if (<MODE>mode == HImode)
82      return "cmp.w	%T1,%T0";
83    else if (<MODE>mode == SImode)
84      return "cmp.l	%S1,%S0";
85    gcc_unreachable ();
86  }
87  [(set_attr "length_table" "add")])
88
89(define_insn "*cmpqi"
90  [(set (reg:CC CC_REG)
91	(compare (match_operand:QI 0 "h8300_dst_operand" "rQ")
92		 (match_operand:QI 1 "h8300_src_operand" "rQi")))]
93  "reload_completed"
94  "cmp.b	%X1,%X0"
95  [(set_attr "length_table" "add")])
96
97(define_insn "*cmphi"
98  [(set (reg:CC CC_REG)
99	(compare (match_operand:HI 0 "h8300_dst_operand" "rU,rQ")
100		 (match_operand:HI 1 "h8300_src_operand" "P3>X,rQi")))]
101  "reload_completed"
102{
103  switch (which_alternative)
104    {
105    case 0:
106      if (!TARGET_H8300SX)
107	return "cmp.w	%T1,%T0";
108      else
109	return "cmp.w	%T1:3,%T0";
110    case 1:
111      return "cmp.w	%T1,%T0";
112    default:
113      gcc_unreachable ();
114      }
115}
116  [(set_attr "length_table" "short_immediate,add")])
117
118(define_insn "cmpsi"
119  [(set (reg:CC CC_REG)
120	(compare (match_operand:SI 0 "h8300_dst_operand" "r,rQ")
121		 (match_operand:SI 1 "h8300_src_operand" "P3>X,rQi")))]
122  "reload_completed"
123{
124  switch (which_alternative)
125    {
126    case 0:
127      if (!TARGET_H8300SX)
128	return "cmp.l	%S1,%S0";
129      else
130	return "cmp.l	%S1:3,%S0";
131    case 1:
132      return "cmp.l	%S1,%S0";
133    default:
134      gcc_unreachable ();
135    }
136}
137  [(set_attr "length" "2,*")
138   (set_attr "length_table" "*,add")])
139
140;; Convert a memory comparison to a move if there is a scratch register.
141
142(define_peephole2
143  [(match_scratch:QHSI 1 "r")
144   (set (reg:CC CC_REG)
145	(compare (match_operand:QHSI 0 "memory_operand" "")
146		 (const_int 0)))]
147  ""
148  [(parallel [(set (match_dup 1) (match_dup 0)) (clobber (reg:CC CC_REG))])
149   (set (reg:CC CC_REG) (compare:CC (match_dup 1) (const_int 0)))])
150
151;; The compare-elimination pass does not handle memory reference.  So this
152;; little peephole helps fill the gap and avoid code quality regressions.
153(define_peephole2
154  [(parallel [(set (match_operand:QHSI 0 "register_operand" "")
155		   (match_operand:QHSI 1 "simple_memory_operand" ""))
156	      (clobber (reg:CC CC_REG))])
157   (set (reg:CCZN CC_REG)
158	(compare:CCZN (match_dup 0) (const_int 0)))]
159  ""
160  [(parallel [(set (reg:CCZN CC_REG) (compare:CCZN (match_dup 1) (const_int 0)))
161	      (set (match_dup 0) (match_dup 1))])])
162
163;; This exists solely to convince ifcvt to try some store-flag sequences.
164;;
165;; Essentially we don't want to expose a general store-flag capability.
166;; The only generally useful/profitable case is when we want to test the
167;; C bit.  In that case we can use addx, subx, bst, or bist to get the bit
168;; into a GPR.
169;;
170;; Others could be handled with stc, shifts and masking, but it likely isn't
171;; profitable.
172;;
173(define_expand "cstore<mode>4"
174  [(use (match_operator 1 "eqne_operator"
175         [(match_operand:QHSI 2 "h8300_dst_operand" "")
176          (match_operand:QHSI 3 "h8300_src_operand" "")]))
177   (clobber (match_operand:QHSI 0 "register_operand"))]
178  ""
179  {
180    FAIL;
181  })
182
183;; Storing the C bit is pretty simple since there are many ways to
184;; introduce it into a GPR.  addx, subx and a variety of bit manipulation
185;; instructions
186;;
187(define_insn "*store_c_<mode>"
188  [(set (match_operand:QHSI 0 "register_operand" "=r")
189	(eqne:QHSI (reg:CCC CC_REG) (const_int 0)))]
190  "reload_completed"
191  {
192    if (<CODE> == NE)
193      {
194	if (<MODE>mode == QImode)
195	  return "xor.b\t%X0,%X0\;bst\t#0,%X0";
196	else if (<MODE>mode == HImode)
197	  return "xor.w\t%T0,%T0\;bst\t#0,%s0";
198	else if (<MODE>mode == SImode)
199	  return "xor.l\t%S0,%S0\;bst\t#0,%w0";
200	gcc_unreachable ();
201      }
202    else if (<CODE> == EQ)
203      {
204	if (<MODE>mode == QImode)
205	  return "xor.b\t%X0,%X0\;bist\t#0,%X0";
206	else if (<MODE>mode == HImode)
207	  return "xor.w\t%T0,%T0\;bist\t#0,%s0";
208	else if (<MODE>mode == SImode)
209	  return "xor.l\t%S0,%S0\;bist\t#0,%w0";
210	gcc_unreachable ();
211      }
212  }
213  [(set (attr "length") (symbol_ref "<MODE>mode == SImode ? 6 : 4"))])
214
215;; Similarly, but with a negated result
216(define_insn "*store_neg_c_<mode>"
217  [(set (match_operand:QHSI 0 "register_operand" "=r")
218	(neg:QHSI (ne:QHSI (reg:CCC CC_REG) (const_int 0))))]
219  "reload_completed"
220  {
221    if (<MODE>mode == QImode)
222      return "subx\t%X0,%X0";
223    else if (<MODE>mode == HImode)
224      return "subx\t%X0,%X0\;exts.w\t%T0";
225    else if (<MODE>mode == SImode)
226      return "subx\t%X0,%X0\;exts.w\t%T0\;exts.l\t%S0";
227    gcc_unreachable ();
228  }
229  [(set
230     (attr "length")
231     (symbol_ref "(<MODE>mode == SImode ? 6 : <MODE>mode == HImode ? 4 : 2)"))])
232
233;; Using b[i]st we can store the C bit into any of the low 16 bits of
234;; a destination.  We can also rotate it up into the high bit of a 32 bit
235;; destination.
236(define_insn "*store_shifted_c<mode>"
237  [(set (match_operand:QHSI 0 "register_operand" "=r")
238	(ashift:QHSI (eqne:QHSI (reg:CCC CC_REG) (const_int 0))
239		     (match_operand 1 "immediate_operand" "n")))]
240  "(reload_completed
241    && (INTVAL (operands[1]) == 31 || INTVAL (operands[1]) <= 15))"
242  {
243    if (<CODE> == NE)
244      {
245	if (<MODE>mode == QImode)
246	  return "xor.b\t%X0,%X0\;bst\t%1,%X0";
247	else if (<MODE>mode == HImode && INTVAL (operands[1]) < 8)
248	  return "xor.w\t%T0,%T0\;bst\t%1,%X0";
249	else if (<MODE>mode == HImode)
250	  {
251	    operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
252	    output_asm_insn ("xor.w\t%T0,%T0\;bst\t%1,%t0", operands);
253	    return "";
254	  }
255	else if (<MODE>mode == SImode && INTVAL (operands[1]) == 31)
256	  return "xor.l\t%S0,%S0\;rotxr.l\t%S0";
257	else if (<MODE>mode == SImode && INTVAL (operands[1]) < 8)
258	  return "xor.l\t%S0,%S0\;bst\t%1,%X0";
259	else if (<MODE>mode == SImode)
260	  {
261	    operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
262	    output_asm_insn ("xor.l\t%S0,%S0\;bst\t%1,%t0", operands);
263	    return "";
264	  }
265	gcc_unreachable ();
266      }
267    else if (<CODE> == EQ)
268      {
269	if (<MODE>mode == QImode)
270	  return "xor.b\t%X0,%X0\;bist\t%1,%X0";
271	else if (<MODE>mode == HImode && INTVAL (operands[1]) < 8)
272	  return "xor.w\t%T0,%T0\;bist\t%1,%X0";
273	else if (<MODE>mode == HImode)
274	  {
275	    operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
276	    output_asm_insn ("xor.w\t%T0,%T0\;bist\t%1,%t0", operands);
277	    return "";
278	  }
279	else if (<MODE>mode == SImode && INTVAL (operands[1]) == 31)
280	  return "xor.l\t%S0,%S0\;bixor\t#0,%X0\;rotxr.l\t%S0";
281	else if (<MODE>mode == SImode && INTVAL (operands[1]) < 8)
282	  return "xor.l\t%S0,%S0\;bist\t%1,%X0";
283	else if (<MODE>mode == SImode)
284	  {
285	    operands[1] = GEN_INT (INTVAL (operands[1]) - 8);
286	    output_asm_insn ("xor.l\t%S0,%S0\;bist\t%1,%t0", operands);
287	    return "";
288	  }
289	gcc_unreachable ();
290      }
291    gcc_unreachable ();
292  }
293  [(set
294     (attr "length")
295     (symbol_ref "(<MODE>mode == QImode ? 4
296		   : <MODE>mode == HImode ? 4
297		   : <CODE> == NE ? 6
298		   : INTVAL (operands[1]) == 31 ? 8 : 6)"))])
299
300;; Recognize this scc and generate code we can match
301(define_insn_and_split "*store_c"
302  [(set (match_operand:QHSI 0 "register_operand" "=r")
303	(geultu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
304		     (match_operand:QHSI2 2 "register_operand" "r")))]
305  ""
306  "#"
307  "&& reload_completed"
308  [(set (reg:CCC CC_REG)
309	(ltu:CCC (match_dup 1) (match_dup 2)))
310   (set (match_dup 0)
311	(<geultu_to_c>:QHSI (reg:CCC CC_REG) (const_int 0)))])
312
313;; We can fold in negation of the result and generate better code than
314;; what the generic bits would do when testing for C == 1
315(define_insn_and_split "*store_neg_c"
316  [(set (match_operand:QHSI 0 "register_operand" "=r")
317	(neg:QHSI
318	  (ltu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
319		    (match_operand:QHSI2 2 "register_operand" "r"))))]
320  ""
321  "#"
322  "&& reload_completed"
323  [(set (reg:CCC CC_REG)
324	(ltu:CCC (match_dup 1) (match_dup 2)))
325   (set (match_dup 0)
326	(neg:QHSI (ne:QHSI (reg:CCC CC_REG) (const_int 0))))])
327
328;; We can use rotates and bst/bist to put the C bit into various places
329;; in the destination.
330(define_insn_and_split "*store_shifted_c"
331  [(set (match_operand:QHSI 0 "register_operand" "=r")
332       (ashift:QHSI (geultu:QHSI (match_operand:QHSI2 1 "register_operand" "r")
333                                 (match_operand:QHSI2 2 "register_operand" "r"))
334		    (match_operand 3 "immediate_operand" "n")))]
335  "INTVAL (operands[3]) == 31 || INTVAL (operands[3]) <= 15"
336  "#"
337  "&& reload_completed"
338  [(set (reg:CCC CC_REG) (ltu:CCC (match_dup 1) (match_dup 2)))
339   (set (match_dup 0)
340	(ashift:QHSI (<geultu_to_c>:QHSI (reg:CCC CC_REG) (const_int 0))
341		     (match_dup 3)))])
342
343