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