xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/m32c/mov.md (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1;; Machine Descriptions for R8C/M16C/M32C
2;; Copyright (C) 2005, 2007, 2008
3;; Free Software Foundation, Inc.
4;; Contributed by Red Hat.
5;;
6;; This file is part of GCC.
7;;
8;; GCC is free software; you can redistribute it and/or modify it
9;; under the terms of the GNU General Public License as published
10;; by the Free Software Foundation; either version 3, or (at your
11;; option) any later version.
12;;
13;; GCC is distributed in the hope that it will be useful, but WITHOUT
14;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16;; License for more details.
17;;
18;; You should have received a copy of the GNU General Public License
19;; along with GCC; see the file COPYING3.  If not see
20;; <http://www.gnu.org/licenses/>.
21
22;; move, push, extend, etc.
23
24;; Be careful to never create an alternative that has memory as both
25;; src and dest, as that makes gcc think that mem-mem moves in general
26;; are supported.  While the chip does support this, it only has two
27;; address registers and sometimes gcc requires more than that.  One
28;; example is code like this: a = *b where both a and b are spilled to
29;; the stack.
30
31;; Match push/pop before mov.b for passing char as arg,
32;; e.g. stdlib/efgcvt.c.
33(define_insn "movqi_op"
34  [(set (match_operand:QI 0 "m32c_nonimmediate_operand"
35			  "=Rqi*Rmm, <,          RqiSd*Rmm, SdSs,    Rqi*Rmm, Sd")
36	(match_operand:QI 1 "m32c_any_operand"
37			  "iRqi*Rmm, iRqiSd*Rmm, >,         Rqi*Rmm, SdSs,    i"))]
38  "m32c_mov_ok (operands, QImode)"
39  "@
40    mov.b\t%1,%0
41    push.b\t%1
42    pop.b\t%0
43    mov.b\t%1,%0
44    mov.b\t%1,%0
45    mov.b\t%1,%0"
46  [(set_attr "flags" "sz,*,*,sz,sz,sz")]
47  )
48
49(define_expand "movqi"
50  [(set (match_operand:QI 0 "nonimmediate_operand" "=RqiSd*Rmm")
51	(match_operand:QI 1 "general_operand" "iRqiSd*Rmm"))]
52  ""
53  "if (m32c_prepare_move (operands, QImode)) DONE;"
54  )
55
56
57(define_insn "movhi_op"
58  [(set (match_operand:HI 0 "m32c_nonimmediate_operand"
59			  "=Rhi*Rmm,     Sd, SdSs,   *Rcr, RhiSd*Rmm, <, RhiSd*Rmm, <, *Rcr")
60	(match_operand:HI 1 "m32c_any_operand"
61			  "iRhi*RmmSdSs, i, Rhi*Rmm, RhiSd*Rmm, *Rcr, iRhiSd*Rmm, >, *Rcr, >"))]
62  "m32c_mov_ok (operands, HImode)"
63  "@
64   mov.w\t%1,%0
65   mov.w\t%1,%0
66   mov.w\t%1,%0
67   ldc\t%1,%0
68   stc\t%1,%0
69   push.w\t%1
70   pop.w\t%0
71   pushc\t%1
72   popc\t%0"
73  [(set_attr "flags" "sz,sz,sz,n,n,n,n,n,n")]
74  )
75
76(define_expand "movhi"
77  [(set (match_operand:HI 0 "m32c_nonimmediate_operand" "=RhiSd*Rmm")
78	(match_operand:HI 1 "m32c_any_operand" "iRhiSd*Rmm"))]
79  ""
80  "if (m32c_prepare_move (operands, HImode)) DONE;"
81  )
82
83
84(define_insn "movpsi_op"
85  [(set (match_operand:PSI 0 "m32c_nonimmediate_operand"
86			   "=Raa, SdRmmRpi,  Rcl,  RpiSd*Rmm, <,       <, Rcl, RpiRaa*Rmm")
87	(match_operand:PSI 1 "m32c_any_operand"
88			   "sIU3, iSdRmmRpi, iRpiSd*Rmm, Rcl, Rpi*Rmm, Rcl, >, >"))]
89  "TARGET_A24 && m32c_mov_ok (operands, PSImode)"
90  "@
91   mov.l:s\t%1,%0
92   mov.l\t%1,%0
93   ldc\t%1,%0
94   stc\t%1,%0
95   push.l\t%1
96   pushc\t%1
97   popc\t%0
98   #"
99  [(set_attr "flags" "sz,sz,n,n,n,n,n,*")]
100  )
101
102
103;; The intention here is to combine the add with the move to create an
104;; indexed move.  GCC doesn't always figure this out itself.
105
106(define_peephole2
107  [(set (match_operand:HPSI 0 "register_operand" "")
108	(plus:HPSI (match_operand:HPSI 1 "register_operand" "")
109		   (match_operand:HPSI 2 "immediate_operand" "")))
110   (set (match_operand:QHSI 3 "nonimmediate_operand" "")
111	(mem:QHSI (match_operand:HPSI 4 "register_operand" "")))]
112  "REGNO (operands[0]) == REGNO (operands[1])
113   && REGNO (operands[0]) == REGNO (operands[4])
114   && (rtx_equal_p (operands[0], operands[3])
115       || (dead_or_set_p (peep2_next_insn (1), operands[4])
116          && ! reg_mentioned_p (operands[0], operands[3])))"
117  [(set (match_dup 3)
118	(mem:QHSI (plus:HPSI (match_dup 1)
119			     (match_dup 2))))]
120  "")
121
122(define_peephole2
123  [(set (match_operand:HPSI 0 "register_operand" "")
124	(plus:HPSI (match_operand:HPSI 1 "register_operand" "")
125		   (match_operand:HPSI 2 "immediate_operand" "")))
126   (set (mem:QHSI (match_operand:HPSI 4 "register_operand" ""))
127	(match_operand:QHSI 3 "m32c_any_operand" ""))]
128  "REGNO (operands[0]) == REGNO (operands[1])
129   && REGNO (operands[0]) == REGNO (operands[4])
130   && dead_or_set_p (peep2_next_insn (1), operands[4])
131   && ! reg_mentioned_p (operands[0], operands[3])"
132  [(set (mem:QHSI (plus:HPSI (match_dup 1)
133			     (match_dup 2)))
134	(match_dup 3))]
135  "")
136
137; Peephole to generate SImode mov instructions for storing an
138; immediate double data to a memory location.
139(define_peephole2
140  [(set (match_operand:HI 0 "memory_operand" "")
141        (match_operand 1 "const_int_operand" ""))
142   (set (match_operand:HI 2 "memory_operand" "")
143        (match_operand 3 "const_int_operand" ""))]
144   "TARGET_A24 && m32c_immd_dbl_mov (operands, HImode)"
145   [(set (match_dup 4) (match_dup 5))]
146   ""
147)
148
149; Some PSI moves must be split.
150(define_split
151  [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "")
152	(match_operand:PSI 1 "m32c_any_operand" ""))]
153  "reload_completed && m32c_split_psi_p (operands)"
154  [(set (match_dup 2)
155	(match_dup 3))
156   (set (match_dup 4)
157	(match_dup 5))]
158  "m32c_split_move (operands, PSImode, 3);"
159  )
160
161(define_expand "movpsi"
162  [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "")
163	(match_operand:PSI 1 "m32c_any_operand" ""))]
164  ""
165  "if (m32c_prepare_move (operands, PSImode)) DONE;"
166  )
167
168
169
170(define_expand "movsi"
171  [(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=RsiSd*Rmm")
172	(match_operand:SI 1 "m32c_any_operand" "iRsiSd*Rmm"))]
173  ""
174  "if (m32c_split_move (operands, SImode, 0)) DONE;"
175  )
176
177; All SI moves are split if TARGET_A16
178(define_insn_and_split "movsi_splittable"
179  [(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=Rsi<*Rmm,RsiSd*Rmm,Ss")
180	(match_operand:SI 1 "m32c_any_operand" "iRsiSd*Rmm,iRsi>*Rmm,Rsi*Rmm"))]
181  "TARGET_A16"
182  "#"
183  "TARGET_A16 && reload_completed"
184  [(pc)]
185  "m32c_split_move (operands, SImode, 1); DONE;"
186  )
187
188; The movsi pattern doesn't always match because sometimes the modes
189; don't match.
190(define_insn "push_a01_l"
191  [(set (mem:SI (pre_dec:PSI (reg:PSI SP_REGNO)))
192	(match_operand 0 "a_operand" "Raa"))]
193  ""
194  "push.l\t%0"
195  [(set_attr "flags" "n")]
196  )
197
198(define_insn "movsi_24"
199  [(set (match_operand:SI 0 "m32c_nonimmediate_operand"  "=Rsi*Rmm,   Sd,       RsiSd*Rmm,     <")
200	(match_operand:SI 1 "m32c_any_operand" "iRsiSd*Rmm, iRsi*Rmm, >, iRsiRaaSd*Rmm"))]
201  "TARGET_A24"
202  "@
203   mov.l\t%1,%0
204   mov.l\t%1,%0
205   #
206   push.l\t%1"
207  [(set_attr "flags" "sz,sz,*,n")]
208  )
209
210(define_expand "movdi"
211  [(set (match_operand:DI 0 "m32c_nonimmediate_operand" "=RdiSd*Rmm")
212	(match_operand:DI 1 "m32c_any_operand" "iRdiSd*Rmm"))]
213  ""
214  "if (m32c_split_move (operands, DImode, 0)) DONE;"
215  )
216
217(define_insn_and_split "movdi_splittable"
218  [(set (match_operand:DI 0 "m32c_nonimmediate_operand" "=Rdi<*Rmm,RdiSd*Rmm")
219	(match_operand:DI 1 "m32c_any_operand" "iRdiSd*Rmm,iRdi>*Rmm"))]
220  ""
221  "#"
222  "reload_completed"
223  [(pc)]
224  "m32c_split_move (operands, DImode, 1); DONE;"
225  )
226
227
228
229
230(define_insn "pushqi"
231  [(set (mem:QI (pre_dec:PSI (reg:PSI SP_REGNO)))
232        (match_operand:QI 0 "mrai_operand" "iRqiSd*Rmm"))]
233  ""
234  "push.b\t%0"
235  [(set_attr "flags" "n")]
236  )
237
238(define_expand "pushhi"
239  [(set (mem:HI (pre_dec:PSI (reg:PSI SP_REGNO)))
240        (match_operand:HI 0 "" ""))]
241  ""
242  "if (TARGET_A16)
243     gen_pushhi_16 (operands[0]);
244   else
245     gen_pushhi_24 (operands[0]);
246   DONE;"
247  )
248
249(define_insn "pushhi_16"
250  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNO)))
251        (match_operand:HI 0 "mrai_operand" "iRhiSd*Rmm,Rcr"))]
252  "TARGET_A16"
253  "@
254   push.w\t%0
255   pushc\t%0"
256  [(set_attr "flags" "n,n")]
257  )
258
259(define_insn "pushhi_24"
260  [(set (mem:HI (pre_dec:PSI (reg:PSI SP_REGNO)))
261        (match_operand:HI 0 "mrai_operand" "iRhiSd*Rmm"))]
262  "TARGET_A24"
263  "push.w\t%0"
264  [(set_attr "flags" "n")]
265  )
266
267;(define_insn "pushpi"
268;  [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO)))
269;        (match_operand:PI 0 "mrai_operand" "iRaa,Rcr"))]
270;  "TARGET_A24"
271;  "@
272;   push.l\t%0
273;   pushc\t%0"
274;  )
275
276(define_insn "pushsi"
277  [(set (mem:SI (pre_dec:PSI (reg:PSI SP_REGNO)))
278        (match_operand:SI 0 "mrai_operand" "iRsiSd*Rmm"))]
279  "TARGET_A24"
280  "push.l\t%0"
281  [(set_attr "flags" "n")]
282  )
283
284(define_expand "pophi"
285  [(set (match_operand:HI 0 "mra_operand" "=RhiSd*Rmm,Rcr")
286        (mem:HI (post_inc:HI (reg:HI SP_REGNO))))]
287  ""
288  "if (TARGET_A16)
289     gen_pophi_16 (operands[0]);
290   else
291     gen_pophi_24 (operands[0]);
292   DONE;"
293  )
294
295(define_insn "pophi_16"
296  [(set (match_operand:HI 0 "mra_operand" "=RhiSd*Rmm,Rcr")
297        (mem:HI (post_inc:HI (reg:HI SP_REGNO))))]
298  "TARGET_A16"
299  "@
300   pop.w\t%0
301   popc\t%0"
302  [(set_attr "flags" "n,n")]
303  )
304
305(define_insn "pophi_24"
306  [(set (match_operand:HI 0 "mra_operand" "=RhiSd*Rmm")
307        (mem:HI (post_inc:PSI (reg:PSI SP_REGNO))))]
308  "TARGET_A24"
309  "pop.w\t%0"
310  [(set_attr "flags" "n")]
311  )
312
313(define_insn "poppsi"
314  [(set (match_operand:PSI 0 "cr_operand" "=Rcl")
315        (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))]
316  "TARGET_A24"
317  "popc\t%0"
318  [(set_attr "flags" "n")]
319  )
320
321
322;; Rhl used here as an HI-mode Rxl
323(define_insn "extendqihi2"
324[(set (match_operand:HI 0 "m32c_nonimmediate_operand" "=RhlSd*Rmm")
325	(sign_extend:HI (match_operand:QI 1 "mra_operand" "0")))]
326  ""
327  "exts.b\t%1"
328  [(set_attr "flags" "sz")]
329  )
330
331(define_insn "extendhisi2"
332  [(set (match_operand:SI 0 "register_operand" "=R03")
333	(sign_extend:SI (match_operand:HI 1 "r0123_operand" "0")))]
334  ""
335  "*
336   if (REGNO(operands[0]) == 0) return \"exts.w\t%1\";
337   else return \"mov.w r1,r3 | sha.w #-8,r3 | sha.w #-7,r3\";"
338  [(set_attr "flags" "x")]
339  )
340
341(define_insn "extendhipsi2"
342  [(set (match_operand:PSI 0 "register_operand" "=R03")
343	(sign_extend:PSI (match_operand:HI 1 "register_operand" "0")))]
344  ""
345  "*
346   if (REGNO(operands[0]) == 0) return \"exts.w\t%1\";
347   else return \"mov.w r1,r3 | sha.w #-8,r3 | sha.w #-7,r3\";"
348  [(set_attr "flags" "x")]
349  )
350
351(define_insn "extendpsisi2"
352  [(set (match_operand:SI 0 "mr_operand" "=R03Sd*Rmm")
353	(sign_extend:SI (match_operand:PSI 1 "mr_operand" "0")))]
354  ""
355  "; expand psi %1 to si %0"
356  [(set_attr "flags" "n")]
357  )
358
359(define_insn "zero_extendpsisi2"
360  [(set (match_operand:SI 0 "mr_operand" "=R03Sd*Rmm")
361	(zero_extend:SI (match_operand:PSI 1 "mr_operand" "0")))]
362  ""
363  "; expand psi %1 to si %0"
364  [(set_attr "flags" "n")]
365  )
366
367(define_insn "zero_extendhipsi2"
368  [(set (match_operand:PSI 0 "register_operand" "=Raa")
369	(truncate:PSI (zero_extend:SI (match_operand:HI 1 "register_operand" "R03"))))]
370  ""
371  "mov.w\t%1,%0"
372  [(set_attr "flags" "sz")]
373  )
374
375(define_insn "zero_extendhisi2"
376  [(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=RsiSd")
377	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")))]
378  ""
379  "mov.w\t#0,%H0"
380  [(set_attr "flags" "x")]
381  )
382
383(define_insn "zero_extendqihi2"
384  [(set (match_operand:HI 0 "m32c_nonimmediate_operand" "=?Rhl,RhiSd*Rmm")
385	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,0")))]
386  ""
387  "@
388   mov.b\t#0,%H0
389   and.w\t#255,%0"
390  [(set_attr "flags" "x,x")]
391  )
392
393(define_insn "truncsipsi2_16"
394  [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "=RsiRadSd*Rmm,Raa,Rcr,RsiSd*Rmm")
395	(truncate:PSI (match_operand:SI 1 "nonimmediate_operand" "0,RsiSd*Rmm,RsiSd*Rmm,Rcr")))]
396  "TARGET_A16"
397  "@
398   ; no-op trunc si %1 to psi %0
399   #
400   ldc\t%1,%0
401   stc\t%1,%0"
402  [(set_attr "flags" "n,*,n,n")]
403  )
404
405(define_insn "trunchiqi2"
406  [(set (match_operand:QI 0 "m32c_nonimmediate_operand" "=RqiRmmSd")
407	(truncate:QI (match_operand:HI 1 "mra_qi_operand" "0")))]
408  ""
409  "; no-op trunc hi %1 to qi %0"
410  [(set_attr "flags" "n")]
411  )
412
413(define_insn "truncsipsi2_24"
414  [(set (match_operand:PSI 0              "m32c_nonimmediate_operand" "=RsiSd*Rmm,Raa,!Rcl,RsiSd*Rmm")
415	(truncate:PSI (match_operand:SI 1 "m32c_nonimmediate_operand" "0,RsiSd*Rmm,RsiSd*Rmm,!Rcl")))]
416  "TARGET_A24"
417  "@
418   ; no-op trunc si %1 to psi %0
419   mov.l\t%1,%0
420   ldc\t%1,%0
421   stc\t%1,%0"
422  [(set_attr "flags" "n,sz,n,n")]
423  )
424
425(define_expand "truncsipsi2"
426  [(set (match_operand:PSI 0 "m32c_nonimmediate_operand" "=RsiRadSd*Rmm,Raa,Rcr,RsiSd*Rmm")
427	(truncate:PSI (match_operand:SI 1 "m32c_nonimmediate_operand" "0,RsiSd*Rmm,RsiSd*Rmm,Rcr")))]
428  ""
429  ""
430  )
431
432(define_expand "reload_inqi"
433  [(set (match_operand:QI 2 "" "=&Rqi")
434	(match_operand:QI 1 "" ""))
435   (set (match_operand:QI 0 "" "")
436	(match_dup 2))
437   ]
438  ""
439  "")
440
441(define_expand "reload_outqi"
442  [(set (match_operand:QI 2 "" "=&Rqi")
443	(match_operand:QI 1 "" ""))
444   (set (match_operand:QI 0 "" "")
445	(match_dup 2))
446   ]
447  ""
448  "")
449
450(define_expand "reload_inhi"
451  [(set (match_operand:HI 2 "" "=&Rhi")
452	(match_operand:HI 1 "" ""))
453   (set (match_operand:HI 0 "" "")
454	(match_dup 2))
455   ]
456  ""
457  "")
458
459(define_expand "reload_outhi"
460  [(set (match_operand:HI 2 "" "=&Rhi")
461	(match_operand:HI 1 "" ""))
462   (set (match_operand:HI 0 "" "")
463	(match_dup 2))
464   ]
465  ""
466  "")
467