1;; ----------------------------------------------------------------------
2;; SHIFTS
3;; ----------------------------------------------------------------------
4;;
5;; We make some attempt to provide real efficient shifting.  One example is
6;; doing an 8-bit shift of a 16-bit value by moving a byte reg into the other
7;; reg and moving 0 into the former reg.
8;;
9;; We also try to achieve this in a uniform way.  IE: We don't try to achieve
10;; this in both rtl and at insn emit time.  Ideally, we'd use rtl as that would
11;; give the optimizer more cracks at the code.  However, we wish to do things
12;; like optimizing shifting the sign bit to bit 0 by rotating the other way.
13;; There is rtl to handle this (rotate + and), but the H8/300 doesn't handle
14;; 16-bit rotates.  Also, if we emit complicated rtl, combine may not be able
15;; to detect cases it can optimize.
16;;
17;; For these and other fuzzy reasons, I've decided to go the less pretty but
18;; easier "do it at insn emit time" route.
19
20
21(define_expand "ashl<mode>3"
22  [(set (match_operand:QHSI 0 "register_operand" "")
23	(ashift:QHSI (match_operand:QHSI 1 "register_operand" "")
24		     (match_operand:QI 2 "nonmemory_operand" "")))]
25  ""
26  {
27    if (expand_a_shift (<MODE>mode, ASHIFT, operands))
28    DONE;
29  })
30
31(define_expand "ashr<mode>3"
32  [(set (match_operand:QHSI 0 "register_operand" "")
33	(ashiftrt:QHSI (match_operand:QHSI 1 "register_operand" "")
34		       (match_operand:QI 2 "nonmemory_operand" "")))]
35  ""
36  {
37    if (expand_a_shift (<MODE>mode, ASHIFTRT, operands))
38    DONE;
39  })
40
41(define_expand "lshr<mode>3"
42  [(set (match_operand:QHSI 0 "register_operand" "")
43	(lshiftrt:QHSI (match_operand:QHSI 1 "register_operand" "")
44		       (match_operand:QI 2 "nonmemory_operand" "")))]
45  ""
46  {
47    if (expand_a_shift (<MODE>mode, LSHIFTRT, operands))
48    DONE;
49  })
50
51;; QI/HI/SI BIT SHIFTS
52
53(define_insn_and_split ""
54  [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
55	(match_operator:QHSI 3 "h8sx_unary_shift_operator"
56	 [(match_operand:QHSI 1 "h8300_dst_operand" "0")
57	  (match_operand:QI 2 "const_int_operand" "")]))]
58  "h8300_operands_match_p (operands)"
59  "#"
60  "&& reload_completed"
61  [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
62	      (clobber (reg:CC CC_REG))])])
63
64(define_insn ""
65  [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
66	(match_operator:QHSI 3 "h8sx_unary_shift_operator"
67	 [(match_operand:QHSI 1 "h8300_dst_operand" "0")
68	  (match_operand:QI 2 "const_int_operand" "")]))
69   (clobber (reg:CC CC_REG))]
70  "h8300_operands_match_p (operands)"
71{
72  if (<MODE>mode == E_QImode)
73    return output_h8sx_shift (operands, 'b', 'X');
74  if (<MODE>mode == E_HImode)
75    return output_h8sx_shift (operands, 'w', 'T');
76  if (<MODE>mode == E_SImode)
77    return output_h8sx_shift (operands, 'l', 'S');
78  gcc_unreachable ();
79}
80  [(set_attr "length_table" "unary")])
81
82(define_insn ""
83  [(set (reg:CCZN CC_REG)
84	(compare:CCZN
85	  (match_operator:QHSI 3 "h8sx_unary_shift_operator"
86	    [(match_operand:QHSI 1 "h8300_dst_operand" "0")
87	     (match_operand:QI 2 "const_int_operand" "")])
88	  (const_int 0)))
89   (set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
90	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
91  "h8300_operands_match_p (operands)"
92{
93  if (<MODE>mode == E_QImode)
94    return output_h8sx_shift (operands, 'b', 'X');
95  if (<MODE>mode == E_HImode)
96    return output_h8sx_shift (operands, 'w', 'T');
97  if (<MODE>mode == E_SImode)
98    return output_h8sx_shift (operands, 'l', 'S');
99  gcc_unreachable ();
100}
101  [(set_attr "length_table" "unary")])
102
103(define_insn_and_split ""
104  [(set (match_operand:QHSI 0 "register_operand" "=r")
105	(match_operator:QHSI 3 "h8sx_binary_shift_operator"
106	 [(match_operand:QHSI 1 "register_operand" "0")
107	  (match_operand:QI 2 "nonmemory_operand" "r P5>X")]))]
108  ""
109  "#"
110  "&& reload_completed"
111  [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
112	      (clobber (reg:CC CC_REG))])])
113
114(define_insn ""
115  [(set (match_operand:QHSI 0 "register_operand" "=r")
116	(match_operator:QHSI 3 "h8sx_binary_shift_operator"
117	 [(match_operand:QHSI 1 "register_operand" "0")
118	  (match_operand:QI 2 "nonmemory_operand" "r P5>X")]))
119   (clobber (reg:CC CC_REG))]
120  ""
121{
122  if (<MODE>mode == QImode)
123    return output_h8sx_shift (operands, 'b', 'X');
124  if (<MODE>mode == HImode)
125    return output_h8sx_shift (operands, 'w', 'T');
126  if (<MODE>mode == SImode)
127    return output_h8sx_shift (operands, 'l', 'S');
128  gcc_unreachable ();
129}
130  [(set_attr "length" "4")])
131
132(define_insn ""
133  [(set (reg:CCZN CC_REG)
134	(compare:CCZN
135	  (match_operator:QHSI 3 "h8sx_binary_shift_operator"
136	   [(match_operand:QHSI 1 "register_operand" "0")
137	    (match_operand:QI 2 "nonmemory_operand" "r P5>X")])
138	  (const_int 0)))
139   (set (match_operand:QHSI 0 "register_operand" "=r")
140	(match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
141  ""
142{
143  if (<MODE>mode == QImode)
144    return output_h8sx_shift (operands, 'b', 'X');
145  if (<MODE>mode == HImode)
146    return output_h8sx_shift (operands, 'w', 'T');
147  if (<MODE>mode == SImode)
148    return output_h8sx_shift (operands, 'l', 'S');
149  gcc_unreachable ();
150}
151  [(set_attr "length" "4")])
152
153(define_insn_and_split "*shiftqi_noscratch"
154  [(set (match_operand:QI 0 "register_operand" "=r,r")
155	(shifts:QI
156	  (match_operand:QI 1 "register_operand" "0,0")
157	  (match_operand:QI 2 "nonmemory_operand" "R,rn")))]
158  "(GET_CODE (operands[2]) == CONST_INT
159    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode,
160				     <CODE>))"
161  "#"
162  "&& reload_completed"
163  [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2)))
164	      (clobber (reg:CC CC_REG))])])
165
166(define_insn "*shiftqi_noscratch_clobber_flags"
167  [(set (match_operand:QI 0 "register_operand" "=r,r")
168	(shifts:QI
169	  (match_operand:QI 1 "register_operand" "0,0")
170	  (match_operand:QI 2 "nonmemory_operand" "R,rn")))
171   (clobber (reg:CC CC_REG))]
172  "(GET_CODE (operands[2]) == CONST_INT
173    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, <CODE>))"
174{
175  return output_a_shift (operands, <CODE>);
176}
177  [(set (attr "length")
178	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
179
180(define_insn "*shiftqi_noscratch_set_flags"
181  [(set (reg:CCZN CC_REG)
182	(compare:CCZN
183	  (shifts:QI
184	    (match_operand:QI 1 "register_operand" "0,0")
185	    (match_operand:QI 2 "nonmemory_operand" "R,rn"))
186	  (const_int 0)))
187   (set (match_operand:QI 0 "register_operand" "=r,r")
188	(shifts:QI (match_dup 1) (match_dup 2)))]
189  "(GET_CODE (operands[2]) == CONST_INT
190    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, <CODE>)
191    && compute_a_shift_cc (operands, <CODE>))"
192{
193  return output_a_shift (operands, <CODE>);
194}
195  [(set (attr "length")
196	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
197
198
199(define_insn_and_split "*shiftqi"
200  [(set (match_operand:QI 0 "register_operand" "=r,r")
201	(shifts:QI
202	  (match_operand:QI 1 "register_operand" "0,0")
203	  (match_operand:QI 2 "nonmemory_operand" "R,rn")))
204   (clobber (match_scratch:QI 3 "=X,&r"))]
205  ""
206  "#"
207  "&& reload_completed"
208  [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2)))
209	      (clobber (match_dup 3))
210	      (clobber (reg:CC CC_REG))])])
211
212(define_insn "*shiftqi_clobber_flags"
213  [(set (match_operand:QI 0 "register_operand" "=r,r")
214	(shifts:QI
215	  (match_operand:QI 1 "register_operand" "0,0")
216	  (match_operand:QI 2 "nonmemory_operand" "R,rn")))
217   (clobber (match_scratch:QI 3 "=X,&r"))
218   (clobber (reg:CC CC_REG))]
219  ""
220{
221  return output_a_shift (operands, <CODE>);
222}
223  [(set (attr "length")
224	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
225
226(define_insn_and_split "*shifthi_noscratch"
227  [(set (match_operand:HI 0 "register_operand" "=r,r")
228	(shifts:HI
229	  (match_operand:HI 1 "register_operand" "0,0")
230	  (match_operand:HI 2 "nonmemory_operand" "S,rn")))]
231  "(GET_CODE (operands[2]) == CONST_INT
232    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>))"
233  "#"
234  "&& reload_completed"
235  [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2)))
236	      (clobber (reg:CC CC_REG))])])
237
238(define_insn "*shifthi_noscratch_clobber_flags"
239  [(set (match_operand:HI 0 "register_operand" "=r,r")
240	(shifts:HI
241	  (match_operand:HI 1 "register_operand" "0,0")
242	  (match_operand:HI 2 "nonmemory_operand" "S,rn")))
243   (clobber (reg:CC CC_REG))]
244  "(GET_CODE (operands[2]) == CONST_INT
245    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>))"
246{
247  return output_a_shift (operands, <CODE>);
248}
249  [(set (attr "length")
250	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
251
252(define_insn "*shifthi_noscratch_setzn"
253  [(set (reg:CCZN CC_REG)
254	(compare:CCZN
255	  (shifts:HI (match_operand:HI 1 "register_operand" "0,0")
256		     (match_operand:HI 2 "nonmemory_operand" "S,rn"))
257	  (const_int 0)))
258   (set (match_operand:HI 0 "register_operand" "=r,r")
259	(shifts:HI (match_dup 1) (match_dup 2)))]
260  "(GET_CODE (operands[2]) == CONST_INT
261    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>)
262    && compute_a_shift_cc (operands, <CODE>))"
263{
264  return output_a_shift (operands, <CODE>);
265}
266  [(set (attr "length")
267	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
268
269(define_insn_and_split "*shifthi"
270  [(set (match_operand:HI 0 "register_operand" "=r,r")
271	(shifts:HI
272	  (match_operand:HI 1 "register_operand" "0,0")
273	  (match_operand:QI 2 "nonmemory_operand" "S,rn")))
274   (clobber (match_scratch:QI 3 "=X,&r"))]
275  ""
276  "#"
277  "&& reload_completed"
278  [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2)))
279	      (clobber (match_dup 3))
280	      (clobber (reg:CC CC_REG))])])
281
282(define_insn "*shifthi_clobber_flags"
283  [(set (match_operand:HI 0 "register_operand" "=r,r")
284	(shifts:HI
285	  (match_operand:HI 1 "register_operand" "0,0")
286	  (match_operand:QI 2 "nonmemory_operand" "S,rn")))
287   (clobber (match_scratch:QI 3 "=X,&r"))
288   (clobber (reg:CC CC_REG))]
289  ""
290{
291  return output_a_shift (operands, <CODE>);
292}
293  [(set (attr "length")
294	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
295
296(define_insn_and_split "*shiftsi_noscratch"
297  [(set (match_operand:SI 0 "register_operand" "=r,r")
298	(shifts:SI
299	  (match_operand:SI 1 "register_operand" "0,0")
300	  (match_operand:QI 2 "nonmemory_operand" "T,rn")))]
301  "(GET_CODE (operands[2]) == CONST_INT
302    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>))"
303  "#"
304  "&& reload_completed"
305  [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2)))
306	      (clobber (reg:CC CC_REG))])])
307
308(define_insn "*shiftsi_noscratch_clobber_flags"
309  [(set (match_operand:SI 0 "register_operand" "=r,r")
310	(shifts:SI
311	  (match_operand:SI 1 "register_operand" "0,0")
312	  (match_operand:SI 2 "nonmemory_operand" "T,rn")))
313   (clobber (reg:CC CC_REG))]
314  "(GET_CODE (operands[2]) == CONST_INT
315    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>))"
316{
317  return output_a_shift (operands, <CODE>);
318}
319  [(set (attr "length")
320	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
321
322(define_insn "*shiftsi_noscratch_cczn"
323  [(set (reg:CCZN CC_REG)
324	(compare:CCZN
325	  (shifts:SI
326	    (match_operand:SI 1 "register_operand" "0,0")
327	    (match_operand:SI 2 "nonmemory_operand" "T,rn"))
328	  (const_int 0)))
329   (set (match_operand:SI 0 "register_operand" "=r,r")
330	(shifts:SI (match_dup 1) (match_dup 2)))]
331  "(GET_CODE (operands[2]) == CONST_INT
332    && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>)
333    && compute_a_shift_cc (operands, <CODE>))"
334{
335  return output_a_shift (operands, <CODE>);
336}
337  [(set (attr "length")
338	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
339
340;; Split a variable shift into a loop.  If the register containing
341;; the shift count dies, then we just use that register.
342
343
344(define_insn_and_split "*shiftsi"
345  [(set (match_operand:SI 0 "register_operand" "=r,r")
346	(shifts:SI
347	  (match_operand:SI 1 "register_operand" "0,0")
348	  (match_operand:QI 2 "nonmemory_operand" "T,rn")))
349   (clobber (match_scratch:QI 3 "=X,&r"))]
350  ""
351  "#"
352  "&& reload_completed"
353  [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2)))
354	      (clobber (match_dup 3))
355	      (clobber (reg:CC CC_REG))])])
356
357(define_insn "*shiftsi_clobber_flags"
358  [(set (match_operand:SI 0 "register_operand" "=r,r")
359	(shifts:SI
360	  (match_operand:SI 1 "register_operand" "0,0")
361	  (match_operand:QI 2 "nonmemory_operand" "T,rn")))
362   (clobber (match_scratch:QI 3 "=X,&r"))
363   (clobber (reg:CC CC_REG))]
364  ""
365{
366  return output_a_shift (operands, <CODE>);
367}
368  [(set (attr "length")
369	(symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
370
371(define_split
372  [(set (match_operand 0 "register_operand" "")
373	(match_operator 2 "nshift_operator"
374	 [(match_dup 0)
375	  (match_operand:QI 1 "register_operand" "")]))
376   (clobber (match_operand:QI 3 "register_operand" ""))
377   (clobber (reg:CC CC_REG))]
378  "epilogue_completed
379   && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
380  [(set (reg:CCZN CC_REG)
381        (compare:CCZN (match_dup 1) (const_int 0)))
382   (set (pc)
383        (if_then_else (le (reg:CCZN CC_REG)  (const_int 0))
384		      (label_ref (match_dup 5))
385		      (pc)))
386   (match_dup 4)
387   (parallel
388     [(set (match_dup 0)
389	   (match_op_dup 2 [(match_dup 0) (const_int 1)]))
390      (clobber (reg:CC CC_REG))])
391   (parallel
392     [(set (reg:CCZN CC_REG)
393	   (compare:CCZN
394	     (plus:QI (match_dup 1) (const_int -1))
395	     (const_int 0)))
396      (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))])
397   (set (pc)
398        (if_then_else (ne (reg:CCZN CC_REG) (const_int 0))
399		      (label_ref (match_dup 4))
400		      (pc)))
401   (match_dup 5)]
402  {
403    operands[4] = gen_label_rtx ();
404    operands[5] = gen_label_rtx ();
405  })
406
407(define_split
408  [(set (match_operand 0 "register_operand" "")
409	(match_operator 2 "nshift_operator"
410	 [(match_dup 0)
411	  (match_operand:QI 1 "register_operand" "")]))
412   (clobber (match_operand:QI 3 "register_operand" ""))
413   (clobber (reg:CC CC_REG))]
414  "epilogue_completed
415   && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
416  [(parallel
417     [(set (reg:CCZN CC_REG)
418	   (compare:CCZN (match_dup 1) (const_int 0)))
419      (set (match_dup 3) (match_dup 1))])
420   (set (pc)
421        (if_then_else (le (reg:CCZN CC_REG) (const_int 0))
422		      (label_ref (match_dup 5))
423		      (pc)))
424   (match_dup 4)
425   (parallel
426     [(set (match_dup 0)
427	   (match_op_dup 2 [(match_dup 0) (const_int 1)]))
428      (clobber (reg:CC CC_REG))])
429   (parallel
430     [(set (reg:CCZN CC_REG)
431	   (compare:CCZN
432	     (plus:QI (match_dup 3) (const_int -1))
433	     (const_int 0)))
434      (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1)))])
435   (set (pc)
436        (if_then_else (ne (reg:CCZN CC_REG) (const_int 0))
437		      (label_ref (match_dup 4))
438		      (pc)))
439   (match_dup 5)]
440  {
441    operands[4] = gen_label_rtx ();
442    operands[5] = gen_label_rtx ();
443  })
444
445(define_split
446  [(set (match_operand:SI 0 "register_operand")
447	(match_operator:SI 3 "nshift_operator"
448	 [(match_operand:SI 1 "register_operand")
449	  (match_operand:QI 2 "nonmemory_operand")]))
450   (clobber (match_scratch:QI 4))]
451  "reload_completed"
452  [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
453	      (clobber (match_dup 4))
454	      (clobber (reg:CC CC_REG))])])
455
456
457;; ----------------------------------------------------------------------
458;; ROTATIONS
459;; ----------------------------------------------------------------------
460
461(define_expand "rotl<mode>3"
462  [(set (match_operand:QHSI 0 "register_operand" "")
463	(rotate:QHSI (match_operand:QHSI 1 "register_operand" "")
464		     (match_operand:QI 2 "nonmemory_operand" "")))]
465  ""
466  {
467    if (expand_a_rotate (operands))
468    DONE;
469  })
470
471(define_insn_and_split "rotl<mode>3_1"
472  [(set (match_operand:QHSI 0 "register_operand" "=r")
473	(rotate:QHSI (match_operand:QHSI 1 "register_operand" "0")
474		     (match_operand:QI 2 "immediate_operand" "")))]
475  ""
476  "#"
477  "&& reload_completed"
478  [(parallel [(set (match_dup 0) (rotate:QHSI (match_dup 1) (match_dup 2)))
479	      (clobber (reg:CC CC_REG))])])
480
481(define_insn "rotl<mode>3_1_clobber_flags"
482  [(set (match_operand:QHSI 0 "register_operand" "=r")
483	(rotate:QHSI (match_operand:QHSI 1 "register_operand" "0")
484		     (match_operand:QI 2 "immediate_operand" "")))
485   (clobber (reg:CC CC_REG))]
486  ""
487{
488  return output_a_rotate (ROTATE, operands);
489}
490  [(set (attr "length")
491	(symbol_ref "compute_a_rotate_length (operands)"))])
492