2008-05-30 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / config / m68hc11 / m68hc11.md
blob8a7a5d0a0bf96c8f7950a1469edd33be5b6d4ec2
1 ;;- Machine description file for Motorola 68HC11 and 68HC12.
2 ;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
3 ;;- Free Software Foundation, Inc.
4 ;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
11 ;; any later version.
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
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/>.
22 ;; Note:
23 ;;   A first 68HC11 port was made by Otto Lind (otto@coactive.com)
24 ;;   on gcc 2.6.3.  I have used it as a starting point for this port.
25 ;;   However, this new port is a complete re-write.  Its internal
26 ;;   design is completely different.  The generated code is not
27 ;;   compatible with the gcc 2.6.3 port.
29 ;;   The gcc 2.6.3 port is available at:
31 ;;   ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
34 ;;- Instruction patterns.  When multiple patterns apply,
35 ;;- the first one in the file is chosen.
36 ;;-
37 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
38 ;;-
39 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
40 ;;- updates for most instructions.
43 ;; The following constraints are used:
45 ;; Single pair registers:
46 ;; a    register 'a'                     8-bit
47 ;; b    register 'b'                     8-bit
48 ;; d    register 'd'                    16-bit
49 ;; t    pseudo soft register 'TMP'      16-bit
50 ;; v    register 'd' for 68hc11,        16-bit
51 ;;      NO_REG for 68hc12
52 ;;      (used for scratch register)
53 ;; w    register 'sp'                   16-bit 
54 ;; x    register 'x'                    16-bit
55 ;; y    register 'y'                    16-bit
56 ;; z    register 'z'                    16-bit  (fake r for 68HC11 and 68HC12)
57 ;; D    register 'd+x'                  32-bit 
59 ;; Group of registers:
60 ;; q    register 'a' or 'b' or 'd'       8-bit
61 ;; u    pseudo soft register            16-bit
62 ;; A    register 'x', 'y', 'z'          16-bit
63 ;; B    register 'x', 'y'               16-bit
64 ;; h    register 'd', 'x', 'y', 'z'     16-bit
66 ;; Other constraints:
68 ;; Q    an operand which is in memory but whose address is constant
69 ;;      (i.e., a (MEM (SYMBOL_REF x))).  This constraint is used by
70 ;;      bset/bclr instructions together with linker relaxation.  The
71 ;;      operand can be translated to a page0 addressing mode if the
72 ;;      symbol address is in page0 (0..255).
74 ;; R    an operand which is in memory and whose address is expressed
75 ;;      with 68HC11/68HC12 indexed addressing mode.  In general this
76 ;;      is any valid (MEM) except a (MEM (SYMBOL_REF x)).
78 ;; U    an operand which is in memory and if it uses the 68HC12 indexed
79 ;;      addressing mode, the offset is in the range -16..+15.  This is
80 ;;      used by 68HC12 movb/movw instructions since they do not accept
81 ;;      the full 16-bit offset range (as other insn do).
84 ;; Immediate integer operand constraints:
85 ;;   `L' is for range -65536 to 65536
86 ;;   `M' is for values whose 16-bit low part is 0
87 ;;   'N' is for +1 or -1.
88 ;;   'O' is for 16 (for rotate using swap).
89 ;;   'P' is for range -8 to 2 (used by addhi_sp)
91 ;; In many cases, it's not possible to use the 'g' or 'r' constraints.
93 ;; Operands modifiers:
95 ;;     %b       Get the low part of the operand (to obtain a QImode)
96 ;;              This modifier must always be used for QImode operations
97 ;;              because a correction must be applied when the operand
98 ;;              is a soft register (ex: *ZD1). Otherwise, we generate
99 ;;              *ZD1 and this is the high part of the register. For other
100 ;;              kinds of operands, if the operand is already QImode, no
101 ;;              additional correction is made.
102 ;;     %h       Get the high part of the operand (to obtain a QImode)
103 ;;     %t       Represents the temporary/scratch register *_.tmp
104 ;;              The scratch register is used in some cases when GCC puts
105 ;;              some values in bad registers. 
107 ;; 32/64-bit Patterns:
108 ;;     The 68HC11 does not support 32/64-bit operations.  Most of the
109 ;;     32/64-bit patterns are defined to split the instruction in
110 ;;     16-bits patterns.  Providing split patterns generates better code
111 ;;     than letting GCC implement the 32/64-bit operation itself.
114 ;; Notes:
116 ;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
117 ;;   otherwise some insn are not satisfied.
119 ;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
120 ;;   be valid only when z_replacement_completed == 2 because once these
121 ;;   swap instructions are generated, a flow/cse pass fails to handle
122 ;;   them correctly (it would treat the X, Y or D register as dead sometimes).
124 ;; o Some split pattern generate instructions that operate on 'a' or 'b'
125 ;;   register directly (high part and low part of D respectively).
126 ;;   Such split pattern must also be valid when z_replacement_completed == 2
127 ;;   because flow/cse is not aware that D is composed of {a, b}.
129 ;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
130 ;;   the high part of a soft register must be expanded after z_replacement
131 ;;   pass.
133 ;;---------------------------------------------------------------------------
134 ;; Constants
136 (define_constants [
137    ;; Register numbers
138    (X_REGNUM        0)          ; Index X register
139    (D_REGNUM        1)          ; Data register
140    (Y_REGNUM        2)          ; Index Y register
141    (SP_REGNUM       3)          ; Stack pointer
142    (PC_REGNUM       4)          ; Program counter
143    (A_REGNUM        5)          ; A (high part of D)
144    (B_REGNUM        6)          ; B (low part of D)
145    (CC_REGNUM       7)          ; Condition code register
146    (SOFT_TMP_REGNUM 10)         ; TMP soft register
147    (SOFT_Z_REGNUM   11)         ; Z soft register
148    (SOFT_XY_REGNUM  12)         ; XY soft register
151 (include "predicates.md")
153 ;;--------------------------------------------------------------------
154 ;;-  Test
155 ;;--------------------------------------------------------------------
157 ;; The test and compare insn must not accept a memory operand with
158 ;; an auto-inc mode.  If we do this, the reload can emit move insns
159 ;; after the test or compare.  Such move will set the flags and therefore
160 ;; break the comparison.  This can happen if the auto-inc register
161 ;; does not happen to be a hard register (i.e., reloading occurs).
162 ;; An offsetable memory operand should be ok.  The 'tst_operand' and
163 ;; 'cmp_operand' predicates take care of this rule.
165 (define_expand "tstsi"
166   [(set (cc0)
167         (match_operand:SI 0 "tst_operand" ""))]
168   ""
169   "
171   m68hc11_compare_op0 = operands[0];
172   m68hc11_compare_op1 = const0_rtx;
173   DONE;
176 (define_expand "tsthi"
177   [(set (cc0)
178         (match_operand:HI 0 "tst_operand" ""))]
179   ""
180   "
182   m68hc11_compare_op0 = operands[0];
183   m68hc11_compare_op1 = const0_rtx;
184   DONE;
187 (define_insn "tsthi_1"
188   [(set (cc0)
189         (match_operand:HI 0 "tst_operand" "dx,*y"))]
190   ""
191   "*
193    if (D_REG_P (operands[0]) && !TARGET_M6812)
194      return \"std\\t%t0\";
195    else
196      return \"cp%0\\t#0\";
199 (define_expand "tstqi"
200   [(set (cc0)
201         (match_operand:QI 0 "tst_operand" ""))]
202   ""
203   "
205   m68hc11_compare_op0 = operands[0];
206   m68hc11_compare_op1 = const0_rtx;
207   DONE;
211 ;; Split pattern for (tst:QI) on an address register.
213 (define_split
214   [(set (cc0)
215         (match_operand:QI 0 "hard_addr_reg_operand" ""))]
216   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
217   [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
218               (set (match_dup 1) (reg:HI D_REGNUM))])
219    (set (cc0) (reg:QI D_REGNUM))
220    (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
221               (set (match_dup 1) (reg:HI D_REGNUM))])]
222   "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
224 (define_insn "tstqi_1"
225   [(set (cc0)
226         (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
227   ""
228   "*
230   if (A_REG_P (operands[0]))
231     return \"#\";
233   else if (D_REG_P (operands[0]))
234     return \"tstb\";
236   else if (dead_register_here (insn, d_reg))
237     return \"ldab\\t%b0\";
239   else
240     return \"tst\\t%b0\";
244 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated 
245 ;; during the Z register replacement.  They are used when an operand
246 ;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
247 ;; In that case, we have to preserve the values of the replacement
248 ;; register (as well as the CC0 since the insns are compare insns).
249 ;; To do this, the replacement register is pushed on the stack and
250 ;; restored after the real compare.  A pattern+split is defined to
251 ;; avoid problems with the flow+cse register pass which are made
252 ;; after Z register replacement.
254 (define_insn_and_split "tstqi_z_used"
255   [(set (cc0)
256         (match_operand:QI 0 "tst_operand" "m"))
257    (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
258    (use (reg:HI SOFT_Z_REGNUM))]
259   ""
260   "#"
261   "z_replacement_completed == 2"
262   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
263    (set (match_dup 1) (match_dup 2))
264    (set (cc0) (match_dup 0))
265    (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
266   "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
269 ;;--------------------------------------------------------------------
270 ;;- Compare
271 ;;--------------------------------------------------------------------
273 (define_expand "cmpsi"
274   [(set (cc0)
275         (compare (match_operand:SI 0 "tst_operand" "")
276                  (match_operand:SI 1 "cmp_operand" "")))]
277   ""
278   "
280   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
281     operands[0] = force_reg (SImode, operands[0]);
283   m68hc11_compare_op0 = operands[0];
284   m68hc11_compare_op1 = operands[1];
285   DONE;
289 ;; Comparison of a hard register with another one is provided because
290 ;; it helps GCC to avoid to spill a pseudo hard register.
291 ;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
292 ;; (except that we loose the information that the value is saved in it).
294 ;; The split pattern transforms the comparison into a save of one hard
295 ;; register and a comparison with the temporary.
297 (define_split
298   [(set (cc0)
299         (compare (match_operand:HI 0 "hard_reg_operand" "")
300                  (match_operand:HI 1 "hard_reg_operand" "")))]
301   "TARGET_M6811
302    && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
303   [(set (match_dup 2) (match_dup 1))
304    (set (cc0)
305         (compare (match_dup 0) (match_dup 2)))]
306   "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
308 (define_split
309   [(set (cc0)
310         (compare (match_operand:HI 0 "hard_reg_operand" "")
311                  (match_operand:HI 1 "hard_reg_operand" "")))]
312   "0 && TARGET_M6812
313    && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
314   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
315    (set (cc0)
316         (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
317   "")
319 (define_expand "cmphi"
320   [(set (cc0)
321         (compare (match_operand:HI 0 "tst_operand" "")
322                  (match_operand:HI 1 "cmp_operand" "")))]
323   ""
324   "
326   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
327     operands[0] = force_reg (HImode, operands[0]);
329   m68hc11_compare_op0 = operands[0];
330   m68hc11_compare_op1 = operands[1];
331   DONE;
334 (define_insn "cmphi_1_hc12"
335   [(set (cc0)
336         (compare (match_operand:HI 0 "tst_operand" 
337                                 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
338                  (match_operand:HI 1 "general_operand"
339                                 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
340   "TARGET_M6812"
341   "*
343   if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
344     {
345       cc_status.flags |= CC_REVERSED;
346       return \"cp%1\\t%0\";
347     }
348   else if (SP_REG_P (operands[1]))
349     return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
350   else if (H_REG_P (operands[1]))
351     return \"psh%1\n\\tcp%0\\t2,sp+\";
352   else
353     return \"cp%0\\t%1\";
356 (define_insn "cmphi_1_hc11"
357   [(set (cc0)
358         (compare (match_operand:HI 0 "tst_operand" 
359                                 "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
360                  (match_operand:HI 1 "cmp_operand"
361                                 "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
362   "TARGET_M6811"
363   "*
365   if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
366     {
367       cc_status.flags |= CC_REVERSED;
368       return \"cp%1\\t%0\";
369     }
370   else if (H_REG_P (operands[1]))
371     return \"#\";
372   else
373     return \"cp%0\\t%1\";
376 (define_insn_and_split "cmphi_z_used"
377   [(set (cc0)
378         (compare (match_operand:HI 0 "tst_operand" "dxy,m")
379                  (match_operand:HI 1 "cmp_operand" "mi,dxy")))
380    (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
381    (use (reg:HI SOFT_Z_REGNUM))]
382   ""
383   "#"
384   "z_replacement_completed == 2"
385   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
386    (set (match_dup 2) (match_dup 3))
387    (set (cc0) (compare (match_dup 0) (match_dup 1)))
388    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
389   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
392 ;; 8-bit comparison with address register.
393 ;; There is no such comparison instruction, we have to temporarily switch
394 ;; the address register and the D register and do the comparison with D.
395 ;; The xgdx and xgdy instructions preserve the flags.
397 (define_split
398   [(set (cc0)
399         (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
400                  (match_operand:QI 1 "cmp_operand" "")))]
401   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
402   [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
403               (set (match_dup 3) (reg:HI D_REGNUM))])
404    (set (cc0)
405         (compare (reg:QI D_REGNUM) (match_dup 1)))
406    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
407               (set (match_dup 3) (reg:HI D_REGNUM))])]
408   "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
410 (define_split
411   [(set (cc0)
412         (compare (match_operand:QI 0 "hard_reg_operand" "")
413                  (match_operand:QI 1 "hard_reg_operand" "")))]
414   "reload_completed"
415   [(set (match_dup 3) (match_dup 4))
416    (set (cc0)
417         (compare (match_dup 0) (match_dup 2)))]
418   "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
419    operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
420    operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
422 (define_expand "cmpqi"
423   [(set (cc0)
424         (compare (match_operand:QI 0 "tst_operand" "")
425                  (match_operand:QI 1 "cmp_operand" "")))]
426   ""
427   "
429   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
430     operands[0] = force_reg (QImode, operands[0]);
432   m68hc11_compare_op0 = operands[0];
433   m68hc11_compare_op1 = operands[1];
434   DONE;
437 (define_insn "bitcmpqi"
438   [(set (cc0)
439         (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
440                 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
441   ""
442   "@
443    bitb\\t%b1
444    #
445    bitb\\t%b1
446    bitb\\t%b0
447    bitb\\t%b0")
449 (define_split /* "bitcmpqi" */
450   [(set (cc0)
451         (and:QI (match_operand:QI 0 "tst_operand" "")
452                 (match_operand:QI 1 "hard_addr_reg_operand" "")))]
453   "z_replacement_completed == 2"
454   [(set (match_dup 3) (match_dup 2))
455    (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
456   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
457    operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
458    operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
460 (define_insn_and_split "bitcmpqi_z_used"
461   [(set (cc0)
462         (and:QI (match_operand:QI 0 "tst_operand" "d,m")
463                 (match_operand:QI 1 "cmp_operand" "m,d")))
464    (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
465    (use (reg:HI SOFT_Z_REGNUM))]
466   ""
467   "#"
468   "z_replacement_completed == 2"
469   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
470    (set (match_dup 2) (match_dup 3))
471    (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
472    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
473   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
475 (define_insn "bitcmphi"
476   [(set (cc0)
477         (and:HI (match_operand:HI 0 "tst_operand" "d")
478                 (match_operand:HI 1 "const_int_operand" "i")))]
479   "(INTVAL (operands[1]) & 0x0ff) == 0
480    || (INTVAL (operands[1]) & 0x0ff00) == 0"
481   "*
483    if ((INTVAL (operands[1]) & 0x0ff) == 0)
484      return \"bita\\t%h1\";
485    else
486      return \"bitb\\t%1\";
489 (define_insn "bitcmpqi_12"
490   [(set (cc0)
491         (zero_extract (match_operand:HI 0 "tst_operand" "d")
492                       (match_operand:HI 1 "const_int_operand" "i")
493                       (match_operand:HI 2 "const_int_operand" "i")))]
494   "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
495    || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
496        && (unsigned) INTVAL (operands[2]) >= 8)"
497   "*
499    rtx ops[1];
500    int mask;
501    int startpos = INTVAL (operands[2]);
502    int bitsize = INTVAL (operands[1]);
504    if (startpos >= 8)
505      {
506        startpos -= 8;
507        mask = (1 << (startpos + bitsize)) - 1;
508        mask &= ~((1 << startpos) - 1);
510        ops[0] = GEN_INT (mask);
511        output_asm_insn (\"bita\\t%0\", ops);
512      }
513    else
514      {
515        mask = (1 << (startpos + bitsize)) - 1;
516        mask &= ~((1 << startpos) - 1);
518        ops[0] = GEN_INT (mask);
519        output_asm_insn (\"bitb\\t%0\", ops);
520      }
521    return \"\";
524 (define_insn "cmpqi_1"
525   [(set (cc0)
526         (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
527                  (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
528   ""
529   "*
531    if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
532      {
533         return \"#\";
534      }
535    else if (D_REG_P (operands[0]))
536      {
537         return \"cmpb\\t%b1\";
538      }
539    cc_status.flags |= CC_REVERSED;
540    return \"cmpb\\t%b0\";
543 (define_insn_and_split "cmpqi_z_used"
544   [(set (cc0)
545         (compare (match_operand:QI 0 "tst_operand" "dxy,m")
546                  (match_operand:QI 1 "cmp_operand" "m,dxy")))
547    (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
548    (use (reg:HI SOFT_Z_REGNUM))]
549   ""
550   "#"
551   "z_replacement_completed == 2"
552   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
553    (set (match_dup 2) (match_dup 3))
554    (set (cc0) (compare (match_dup 0) (match_dup 1)))
555    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
556   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
558 ;;--------------------------------------------------------------------
559 ;;-  Move strict_low_part
560 ;;--------------------------------------------------------------------
562 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
563 ;; The replacement must be made at the very end because we loose the
564 ;; (strict_low_part ...) information.  This is correct for our machine
565 ;; description but not for GCC optimization passes.
567 (define_insn_and_split "movstrictsi"
568   [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
569         (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
570   ""
571   "#"
572   "z_replacement_completed == 2"
573   [(set (match_dup 0) (match_dup 1))]
574   "")
576 (define_insn_and_split "movstricthi"
577   [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
578         (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
579   ""
580   "#"
581   "z_replacement_completed == 2"
582   [(set (match_dup 0) (match_dup 1))]
583   "")
585 (define_insn_and_split "movstrictqi"
586   [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
587         (match_operand:QI 1 "general_operand" "d,imudA"))]
588   ""
589   "#"
590   "z_replacement_completed == 2"
591   [(set (match_dup 0) (match_dup 1))]
592   "")
594 ;;--------------------------------------------------------------------
595 ;;- 64-bit Move Operations.
596 ;; The movdi and movdf patterns are identical except for the mode.
597 ;; They are also very similar to those for movsi and movsf.
599 ;; For 68HC11, we need a scratch register (either D, X, Y) 
600 ;; because there is no memory->memory moves.  It must be defined with
601 ;; earlyclobber (&) so that it does not appear in the source or destination 
602 ;; address.  Providing patterns for movdi/movdf allows GCC to generate
603 ;; better code.  [Until now, the scratch register is limited to D because
604 ;; otherwise we can run out of registers in the A_REGS class for reload].
606 ;; For 68HC12, the scratch register is not necessary.  To use the same
607 ;; pattern and same split, we use the 'v' constraint.  This tells the
608 ;; reload to use the _.tmp register (which is not used at all).
609 ;; The insn will be split in one or several memory moves (movw).
610 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
611 ;;--------------------------------------------------------------------
612 (define_expand "movdi"
613   [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
614                    (match_operand:DI 1 "general_operand" ""))
615               (clobber (match_scratch:HI 2 ""))])]
616   ""
617   "
618   /* For push/pop, emit a REG_INC note to make sure the reload
619      inheritance and reload CSE pass notice the change of the stack
620      pointer.  */
621   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
622     {
623       rtx insn;
625       insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
626       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
627                                           stack_pointer_rtx,
628                                           REG_NOTES (insn));
629       DONE;
630     }
633 ;; Separate push from normal moves to avoid reloading problems
634 ;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
635 ;; We can also accept more scratch registers.
636 (define_insn_and_split "*pushdi_internal"
637   [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
638         (match_operand:DI 1 "general_operand" "i,U,m,!u"))
639    (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
640   ""
641   "#"
642   "reload_completed"
643   [(const_int 0)]
644   "m68hc11_split_move (operands[0], operands[1], operands[2]);
645    DONE;")
647 (define_insn_and_split "movdi_internal"
648   [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
649         (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
650    (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
651   ""
652   "#"
653   "reload_completed"
654   [(const_int 0)]
655   "m68hc11_split_move (operands[0], operands[1], operands[2]);
656    DONE;")
658 (define_expand "movdf"
659   [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
660                    (match_operand:DF 1 "general_operand" ""))
661               (clobber (match_scratch:HI 2 ""))])]
662   ""
663   "/* For push/pop, emit a REG_INC note to make sure the reload
664       inheritance and reload CSE pass notice the change of the stack
665       pointer.  */
666   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
667     {
668       rtx insn;
670       insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
671       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
672                                           stack_pointer_rtx,
673                                           REG_NOTES (insn));
674       DONE;
675     }
678 ;; See pushdi_internal
679 (define_insn_and_split "*pushdf_internal"
680   [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
681         (match_operand:DF 1 "general_operand" "i,U,m,!u"))
682    (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
683   ""
684   "#"
685   "reload_completed"
686   [(const_int 0)]
687   "m68hc11_split_move (operands[0], operands[1], operands[2]);
688    DONE;")
690 (define_insn_and_split "movdf_internal"
691   [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
692         (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
693    (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
694   ""
695   "#"
696   "reload_completed"
697   [(const_int 0)]
698   "m68hc11_split_move (operands[0], operands[1], operands[2]);
699    DONE;")
701 ;;--------------------------------------------------------------------
702 ;;- 32-bit Move Operations.
703 ;; The movsi and movsf patterns are identical except for the mode.
704 ;; When we move to/from a hard register (d+x), we don't need a scratch.
705 ;; Otherwise, a scratch register is used as intermediate register for
706 ;; the move.  The '&' constraint is necessary to make sure the reload
707 ;; pass does not give us a register that dies in the insn and is used
708 ;; for input/output operands.
709 ;;--------------------------------------------------------------------
710 (define_expand "movsi"
711   [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
712                    (match_operand:SI 1 "general_operand" ""))
713               (clobber (match_scratch:HI 2 ""))])]
714   ""
715   "/* For push/pop, emit a REG_INC note to make sure the reload
716       inheritance and reload CSE pass notice the change of the stack
717       pointer.  */
718   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
719     {
720       rtx insn;
722       insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
723       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
724                                           stack_pointer_rtx,
725                                           REG_NOTES (insn));
726       DONE;
727     }
730 (define_insn_and_split "*pushsi_internal"
731   [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
732         (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
733    (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
734   ""
735   "#"
736   "reload_completed"
737   [(const_int 0)]
738   "m68hc11_split_move (operands[0], operands[1], operands[2]);
739    DONE;")
741 (define_insn_and_split "movsi_internal"
742   [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
743         (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
744    (clobber (match_scratch:HI 2               "=X,&d,X,X,X,X,&d,&d,X"))]
745   ""
746   "#"
747   "reload_completed"
748   [(const_int 0)]
749   "m68hc11_split_move (operands[0], operands[1], operands[2]);
750    DONE;")
752 (define_expand "movsf"
753   [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
754                    (match_operand:SF 1 "general_operand" ""))
755               (clobber (match_scratch:HI 2 ""))])]
756   ""
757   "/* For push/pop, emit a REG_INC note to make sure the reload
758       inheritance and reload CSE pass notice the change of the stack
759       pointer.  */
760   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
761     {
762       rtx insn;
764       insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
765       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
766                                           stack_pointer_rtx,
767                                           REG_NOTES (insn));
768       DONE;
769     }
772 (define_insn_and_split "*pushsf_internal"
773   [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
774         (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
775    (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
776   ""
777   "#"
778   "reload_completed"
779   [(const_int 0)]
780   "m68hc11_split_move (operands[0], operands[1], operands[2]);
781    DONE;")
783 (define_insn_and_split "movsf_internal"
784   [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
785         (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
786    (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
787   ""
788   "#"
789   "reload_completed"
790   [(const_int 0)]
791   "m68hc11_split_move (operands[0], operands[1], operands[2]);
792    DONE;")
795 ;;--------------------------------------------------------------------
796 ;;- 16-bit Move Operations.
797 ;; We don't need a scratch register.
798 ;;--------------------------------------------------------------------
800 (define_insn "*movhi2_push"
801   [(set (match_operand:HI 0 "push_operand" "=<,<,<")
802         (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
803   "TARGET_M6811 && !TARGET_M6812"
804   "*
806   cc_status = cc_prev_status;
807   if (D_REG_P (operands[1]))
808     {
809       output_asm_insn (\"pshb\", operands);
810       return \"psha\";
811     }
812   else if (X_REG_P (operands[1]))
813     {
814       return \"pshx\";
815     }
816   else if (Y_REG_P (operands[1]))
817     {
818       return \"pshy\";
819     }
820   fatal_insn (\"Invalid register in the instruction\", insn);
823 (define_insn "*movhi2_pop"
824   [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
825         (match_operand:HI 1 "pop_operand" ">,>"))]
826   "TARGET_M6811"
827   "*
829   cc_status = cc_prev_status;
830   if (D_REG_P (operands[0]))
831     {
832       output_asm_insn (\"pula\", operands);
833       return \"pulb\";
834     }
835   else if (X_REG_P (operands[0]))
836     {
837       return \"pulx\";
838     }
839   else if (Y_REG_P (operands[0]))
840     {
841       return \"puly\";
842     }
843   fatal_insn (\"Invalid register in the instruction\", insn);
846 (define_expand "movhi"
847   [(set (match_operand:HI 0 "nonimmediate_operand" "")
848         (match_operand:HI 1 "general_operand" ""))]
849   ""
850   "
852   if (reload_in_progress)
853     {
854       if (m68hc11_reload_operands (operands))
855         {
856           DONE;
857         }
858     }
859   if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
860     {
861       if (GET_CODE (operands[0]) == MEM &&
862           (GET_CODE (operands[1]) == MEM
863            || GET_CODE (operands[1]) == CONST_INT))
864         {
865           operands[1] = force_reg (HImode, operands[1]);
866         }
867       else if (IS_STACK_PUSH (operands[0])
868                && GET_CODE (operands[1]) != REG)
869         {
870           operands[1] = force_reg (HImode, operands[1]);
871         }
872     }
873   /* For push/pop, emit a REG_INC note to make sure the reload
874      inheritance and reload CSE pass notice the change of the stack
875      pointer.  */
876   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
877     {
878       rtx insn;
880       insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
881       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
882                                           stack_pointer_rtx,
883                                           REG_NOTES (insn));
884       DONE;
885     }
888 (define_insn "*movhi_68hc12"
889   [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
890         (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
891   "TARGET_M6812"
892   "*
894   m68hc11_gen_movhi (insn, operands);
895   return \"\";
898 (define_insn "movhi_const0"
899   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
900         (const_int 0))]
901   "TARGET_M6811"
902   "@
903    clra\\n\\tclrb
904    ld%0\\t#0
905    clr\\t%b0\\n\\tclr\\t%h0")
907 (define_insn "*movhi_m68hc11"
908   [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
909         (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
910   "TARGET_M6811"
911   "*
913   m68hc11_gen_movhi (insn, operands);
914   return \"\";
917 ;;--------------------------------------------------------------------
918 ;;- 8-bit Move Operations.
919 ;; We don't need a scratch register.
920 ;;--------------------------------------------------------------------
922 ;; The *a alternative also clears the high part of the register.
923 ;; This should be ok since this is not the (strict_low_part) set.
925 (define_insn "movqi_const0"
926   [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
927         (const_int 0))]
928   ""
929   "@
930    clrb
931    clr\\t%b0
932    clr\\t%b0
933    ld%0\\t#0
934    clr%0")
937 ;; 8-bit operations on address registers.
939 ;; Switch temporary to the D register and load the value in B.
940 ;; This is possible as long as the address register does not
941 ;; appear in the source operand.
943 (define_split
944   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
945         (match_operand:QI 1 "general_operand" ""))]
946   "z_replacement_completed == 2
947    && !reg_mentioned_p (operands[0], operands[1])
948    && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
949   [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
950               (set (match_dup 2) (reg:HI D_REGNUM))])
951    (set (reg:QI D_REGNUM) (match_dup 1))
952    (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
953               (set (match_dup 2) (reg:HI D_REGNUM))])]
954   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
957 ;; 8-bit operations on address registers.
959 (define_split
960   [(set (match_operand:QI 0 "nonimmediate_operand" "")
961         (match_operand:QI 1 "hard_addr_reg_operand" ""))]
962   "z_replacement_completed == 2
963    && !reg_mentioned_p (operands[1], operands[0])
964    && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
965   [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
966               (set (match_dup 2) (reg:HI D_REGNUM))])
967    (set (match_dup 0) (reg:QI D_REGNUM))
968    (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
969               (set (match_dup 2) (reg:HI D_REGNUM))])]
970   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
972 (define_insn "*movqi2_push"
973   [(set (match_operand:QI 0 "push_operand" "=<,<")
974         (match_operand:QI 1 "general_operand" "d,!*A"))]
975   ""
976   "*
978   if (A_REG_P (operands[1]))
979     return \"#\";
981   cc_status = cc_prev_status;
982   return \"pshb\";
986 (define_expand "movqi"
987   [(set (match_operand:QI 0 "nonimmediate_operand" "")
988         (match_operand:QI 1 "general_operand" ""))]
989   ""
990   "
992   if (reload_in_progress)
993     {
994       if (m68hc11_reload_operands (operands))
995         {
996           DONE;
997         }
998     }
999   if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
1000     {
1001       if (GET_CODE (operands[0]) == MEM
1002           && (GET_CODE (operands[1]) == MEM
1003               || GET_CODE (operands[1]) == CONST_INT))
1004         {
1005           operands[1] = force_reg (QImode, operands[1]);
1006         }
1007       else if (IS_STACK_PUSH (operands[0])
1008                && GET_CODE (operands[1]) != REG)
1009         {
1010           operands[1] = force_reg (QImode, operands[1]);
1011         }
1012     }
1013   /* For push/pop, emit a REG_INC note to make sure the reload
1014      inheritance and reload CSE pass notice the change of the stack
1015      pointer.  */
1016   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
1017     {
1018       rtx insn;
1020       insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
1021       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
1022                                           stack_pointer_rtx,
1023                                           REG_NOTES (insn));
1024       DONE;
1025     }
1028 (define_insn "*movqi_68hc12"
1029   [(set (match_operand:QI 0 "nonimmediate_operand" 
1030                                 "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
1031         (match_operand:QI 1 "general_operand" 
1032                                 "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
1033   "TARGET_M6812"
1034   "*
1036   m68hc11_gen_movqi (insn, operands);
1037   return \"\";
1040 (define_insn "*movqi_m68hc11"
1041   [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
1042         (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
1043   "TARGET_M6811"
1044   "*
1046   m68hc11_gen_movqi (insn, operands);
1047   return \"\";
1050 ;;--------------------------------------------------------------------
1051 ;;-  Swap registers
1052 ;;--------------------------------------------------------------------
1053 ;; Swapping registers is used for split patterns.
1054 (define_insn "swap_areg"
1055    [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1056          (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1057     (set (match_dup 1) (match_dup 0))]
1058    ""
1059    "*
1061   m68hc11_output_swap (insn, operands);
1062   return \"\";
1065 ;;--------------------------------------------------------------------
1066 ;;-  Truncation insns.
1067 ;;--------------------------------------------------------------------
1069 ;; Truncation are not necessary because GCC knows how to truncate,
1070 ;; specially when values lie in consecutive registers.
1073 (define_expand "floatunssisf2"
1074   [(set (match_operand:SF 0 "nonimmediate_operand" "")
1075         (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1076   ""
1077   "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT, 
1078                          SFmode, SImode, 2, operands);
1079    DONE;")
1081 (define_expand "floatunssidf2"
1082   [(set (match_operand:DF 0 "nonimmediate_operand" "")
1083         (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1084   ""
1085   "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT, 
1086                          DFmode, SImode, 2, operands);
1087    DONE;")
1089 ;;--------------------------------------------------------------------
1090 ;;-  Zero extension insns.
1091 ;;--------------------------------------------------------------------
1094 ;; 64-bit extend.  The insn will be split into 16-bit instructions just
1095 ;; before the final pass.  We need a scratch register for the split.
1096 ;; The final value can be generated on the stack directly.  This is more
1097 ;; efficient and useful for conversions made during parameter passing rules.
1099 (define_insn "zero_extendqidi2"
1100   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1101         (zero_extend:DI 
1102            (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1103    (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1104   ""
1105   "#")
1107 (define_split
1108   [(set (match_operand:DI 0 "push_operand" "")
1109         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1110    (clobber (match_scratch:HI 2 "=&dB"))]
1111   "z_replacement_completed == 2"
1112   [(const_int 0)]
1113   "
1115   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1116   rtx push = m68hc11_gen_lowpart (HImode, low);
1117   rtx src  = operands[1];
1119    /* Source operand must be in a hard register.  */
1120    if (!H_REG_P (src))
1121      {
1122        src = gen_rtx_REG (QImode, REGNO (operands[2]));
1123        emit_move_insn (src, operands[1]);
1124      }
1126    /* Source is in D, we can push B then one word of 0 and we do
1127       a correction on the stack pointer.  */
1128    if (D_REG_P (src))
1129      {
1130        emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1131        emit_move_insn (operands[2], const0_rtx);
1132        if (D_REG_P (operands[2]))
1133          {
1134            emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1135          }
1136        else
1137          {
1138            emit_move_insn (push, operands[2]);
1139            emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1140                                   gen_rtx_REG (HImode, HARD_SP_REGNUM),
1141                                   const1_rtx));
1142          }
1143      }
1144    else
1145      {
1146        /* Source is in X or Y.  It's better to push the 16-bit register
1147           and then to some stack adjustment.  */
1148        src = gen_rtx_REG (HImode, REGNO (src));
1149        emit_move_insn (push, src);
1150        emit_move_insn (operands[2], const0_rtx);
1151        emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1152                               gen_rtx_REG (HImode, HARD_SP_REGNUM),
1153                               const1_rtx));
1154        emit_move_insn (push, operands[2]);
1155        emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1156                               gen_rtx_REG (HImode, HARD_SP_REGNUM),
1157                               const1_rtx));
1158      }      
1159    emit_move_insn (push, operands[2]);
1160    emit_move_insn (push, operands[2]);
1161    emit_move_insn (push, operands[2]);
1162    DONE;
1165 (define_split
1166   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1167         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1168    (clobber (match_scratch:HI 2 "=&dB"))]
1169   "z_replacement_completed == 2"
1170   [(const_int 0)]
1171   "
1173   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1174   rtx low2 = m68hc11_gen_lowpart (HImode, low);
1175   rtx src  = operands[1];
1177    /* Source operand must be in a hard register.  */
1178    if (!H_REG_P (src))
1179      {
1180        src = gen_rtx_REG (QImode, REGNO (operands[2]));
1181        emit_move_insn (src, operands[1]);
1182      }
1184    emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1185    emit_move_insn (operands[2], const0_rtx);
1186    src = gen_rtx_REG (QImode, REGNO (operands[2]));
1187    emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1189    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1190    low = m68hc11_gen_highpart (SImode, operands[0]);
1191    emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1192    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1193    DONE;
1196 (define_insn "zero_extendhidi2"
1197   [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1198         (zero_extend:DI 
1199             (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1200    (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1201   ""
1202   "#")
1204 (define_split
1205   [(set (match_operand:DI 0 "non_push_operand" "")
1206         (zero_extend:DI 
1207             (match_operand:HI 1 "nonimmediate_operand" "")))
1208    (clobber (match_scratch:HI 2 ""))]
1209   "z_replacement_completed == 2"
1210   [(const_int 0)]
1211   "
1213    rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1214    rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1215    rtx src  = operands[1];
1217    /* Make sure the source is in a hard register.  */
1218    if (!H_REG_P (src))
1219      {
1220        src = operands[2];
1221        emit_move_insn (src, operands[1]);
1222      }
1224    /* Move the low part first for the push.  */
1225    emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1227    /* Now, use the scratch register to fill in the zeros.  */
1228    emit_move_insn (operands[2], const0_rtx);
1229    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1230    emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1231    emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1232    DONE;
1235 (define_insn "zero_extendsidi2"
1236   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1237         (zero_extend:DI 
1238             (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1239    (clobber (match_scratch:HI 2 "=d,d,d,d"))]
1240   ""
1241   "#")
1243 (define_split 
1244   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1245         (zero_extend:DI 
1246             (match_operand:SI 1 "nonimmediate_operand" "")))
1247    (clobber (match_scratch:HI 2 ""))]
1248   "z_replacement_completed == 2"
1249   [(const_int 0)]
1250   "
1252   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1253   rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1255   /* Move the low part first so that this is ok for a push.  */
1256   m68hc11_split_move (low, operands[1], operands[2]);
1258   /* Use the scratch register to clear the high part of the destination.  */
1259   emit_move_insn (operands[2], const0_rtx);
1260   emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1261   emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1262   DONE;
1266 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1267 ;; because it's less efficient.
1269 (define_insn "zero_extendhisi2"
1270   [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1271         (zero_extend:SI 
1272             (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1273    (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1274   ""
1275   "#")
1277 (define_split
1278   [(set (match_operand:SI 0 "non_push_operand" "")
1279         (zero_extend:SI 
1280             (match_operand:HI 1 "nonimmediate_operand" "")))
1281    (clobber (match_scratch:HI 2 ""))]
1282   "reload_completed"
1283   [(const_int 0)]
1284   "
1286   rtx src = operands[1];
1288   if (!H_REG_P (src) && !H_REG_P (operands[0]))
1289     {
1290       src = operands[2];
1291       emit_move_insn (src, operands[1]);
1292     }
1293   emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1294   emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1295   DONE;
1298 (define_insn "zero_extendqisi2"
1299   [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1300       (zero_extend:SI 
1301           (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1302   ""
1303   "#")
1305 (define_split 
1306   [(set (match_operand:SI 0 "non_push_operand" "")
1307         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1308   "reload_completed && !X_REG_P (operands[0])"
1309   [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1310    (set (match_dup 3) (const_int 0))]
1311   "
1312    operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1313    operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1315 (define_split 
1316   [(set (match_operand:SI 0 "hard_reg_operand" "")
1317         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1318   "z_replacement_completed == 2 && X_REG_P (operands[0])"
1319   [(set (match_dup 2) (match_dup 3))
1320    (set (match_dup 4) (const_int 0))
1321    (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1322   "
1323    if (X_REG_P (operands[1]))
1324      {
1325         emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
1326                                   gen_rtx_REG (HImode, HARD_X_REGNUM)));
1327         emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
1328                                          gen_rtx_REG (QImode, HARD_D_REGNUM)));
1329         emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
1330                         const0_rtx);
1331         DONE;
1332      }
1334    if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
1335      {
1336         emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1337                                                               operands[0]),
1338                                          operands[1]));
1339         emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
1340         DONE;
1341      }
1342    operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1343    operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1344    if (A_REG_P (operands[1]))
1345      {
1346        operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1347        operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
1348        operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
1349      }
1350    else
1351      {
1352        operands[5] = operands[2] =
1353        operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1354        operands[6] = operands[1];
1355      }
1358 (define_insn "zero_extendqihi2"
1359   [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
1360         (zero_extend:HI 
1361             (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1362   ""
1363  "*
1365   if (A_REG_P (operands[0]))
1366     return \"#\";
1368   if (H_REG_P (operands[0]))
1369     {
1370       output_asm_insn (\"clra\", operands);
1371       if (operands[0] != operands[1]
1372           && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1373         {
1374           if (X_REG_P (operands[1])
1375               || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1376             {
1377               output_asm_insn (\"stx\\t%t1\", operands);
1378               output_asm_insn (\"ldab\\t%T0\", operands);
1379             }
1380           else if (Y_REG_P (operands[1])
1381                    || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1382             {
1383               output_asm_insn (\"sty\\t%t1\", operands);
1384               output_asm_insn (\"ldab\\t%T0\", operands);
1385             }
1386           else
1387             {
1388               output_asm_insn (\"ldab\\t%b1\", operands);
1389             }
1390           cc_status.flags |= CC_NOT_NEGATIVE;
1391         }
1392       else
1393         {
1394           /* Status refers to the clra insn. Status is ok for others
1395            * since we have loaded the value in B.
1396            */
1397           CC_STATUS_INIT;
1398         }
1399       return \"\";
1400     }
1402   if (A_REG_P (operands[1]))
1403     {
1404       output_asm_insn (\"st%1\\t%0\", operands);
1405       output_asm_insn (\"clr\\t%h0\", operands);
1406       CC_STATUS_INIT;
1407     }
1408   else
1409     {
1410       output_asm_insn (\"clr\\t%h0\", operands);
1411       output_asm_insn (\"stab\\t%b0\", operands);
1412       cc_status.flags |= CC_NOT_NEGATIVE;
1413     }
1415   return \"\";
1419 ;;--------------------------------------------------------------------
1420 ;;-  Sign extension insns.
1421 ;;--------------------------------------------------------------------
1423 (define_insn "extendqisi2"
1424   [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1425         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1426   ""
1427   "*
1429   rtx ops[3];
1430   int need_tst = 0;
1432   /* The 68HC12 has a sign-extension instruction.  Use it when the
1433      destination is the register (X,D).  First sign-extend the low
1434      part and fill X with the sign-extension of the high part.  */
1435   if (TARGET_M6812 && X_REG_P (operands[0]))
1436     {
1437       if (!D_REG_P (operands[1]))
1438         {
1439           ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1440           ops[1] = operands[1];
1441           m68hc11_gen_movqi (insn, ops);
1442         }
1443       return \"sex\\tb,d\\n\\tsex\\ta,x\";
1444     }
1446   ops[2] = gen_label_rtx ();
1448   if (X_REG_P (operands[1]))
1449     {
1450       output_asm_insn (\"xgdx\", operands);
1451       need_tst = 1;
1452     }
1453   else if (X_REG_P (operands[0]))
1454     {
1455       /* X can be used as an indexed addressing in the source.
1456          Get the value before clearing it.  */
1457       if (reg_mentioned_p (ix_reg, operands[1]))
1458         {
1459           output_asm_insn (\"ldab\\t%b1\", operands);
1460           need_tst = 1;
1461         }
1462       output_asm_insn (\"ldx\\t#0\", operands);
1463     }
1465   output_asm_insn (\"clra\", operands);
1466   if (!X_REG_P (operands[0]))
1467     {
1468       ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1469       ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1471       if (IS_STACK_PUSH (operands[0]))
1472         {
1473           output_asm_insn (\"pshb\", ops);
1474           output_asm_insn (\"tstb\", ops);
1475         }
1476       else
1477         {
1478           output_asm_insn (\"stab\\t%b1\", ops);
1479         }
1480     }
1481   else if (D_REG_P (operands[1]) || need_tst)
1482     {
1483       output_asm_insn (\"tstb\", operands);
1484     }
1485   else
1486     {
1487       output_asm_insn (\"ldab\\t%b1\", operands);
1488     }
1489   output_asm_insn (\"bpl\\t%l2\", ops);
1490   output_asm_insn (\"deca\", operands);
1491   if (X_REG_P (operands[0]))
1492     output_asm_insn (\"dex\", operands);
1494   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1496   if (!X_REG_P (operands[0]))
1497     {
1498       if (IS_STACK_PUSH (operands[0]))
1499         {
1500           output_asm_insn (\"psha\", ops);
1501           output_asm_insn (\"psha\", ops);
1502           output_asm_insn (\"psha\", ops);
1503         }
1504       else
1505         {
1506           output_asm_insn (\"staa\\t%h0\", ops);
1508           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1509           if (dead_register_here (insn, d_reg))
1510             {
1511               output_asm_insn (\"tab\", ops);
1512               output_asm_insn (\"std\\t%0\", ops);
1513             }
1514           else
1515             {
1516               output_asm_insn (\"staa\\t%b0\", ops);
1517               output_asm_insn (\"staa\\t%h0\", ops);
1518             }
1519         }
1520     }
1522   CC_STATUS_INIT;
1523   return \"\";
1527 (define_insn "extendqihi2"
1528   [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1529         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1530   ""
1531   "*
1533   rtx ops[2];
1535   if (A_REG_P (operands[0]))
1536     return \"#\";
1538   ops[0] = gen_label_rtx ();
1539   if (D_REG_P (operands[0]))
1540     {
1541       if (TARGET_M6812)
1542         {
1543           if (!D_REG_P (operands[1]))
1544             {
1545               ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1546               ops[1] = operands[1];
1547               m68hc11_gen_movqi (insn, ops);
1548             }
1549           return \"sex\\tb,d\";
1550         }
1551       output_asm_insn (\"clra\", operands);
1552       if (H_REG_P (operands[1]))
1553         {
1554           output_asm_insn (\"tstb\", operands);
1555         }
1556       else
1557         {
1558           output_asm_insn (\"ldab\\t%b1\", operands);
1559         }
1560       output_asm_insn (\"bpl\\t%l0\", ops);
1561       output_asm_insn (\"deca\", operands);
1563       (*targetm.asm_out.internal_label) (asm_out_file, \"L\", 
1564                                  CODE_LABEL_NUMBER (ops[0]));
1565     }
1566    else
1567     {
1568       output_asm_insn (\"clr\\t%h0\", operands);
1569       if (m68hc11_register_indirect_p (operands[1], HImode))
1570         {
1571           ops[1] = operands[1];
1572           output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1573           CC_STATUS_INIT;
1574         }
1575       else
1576         {
1577           output_asm_insn (\"tst\\t%b1\", operands);
1578           output_asm_insn (\"bpl\\t%l0\", ops);
1579         }
1580       output_asm_insn (\"dec\\t%h0\", operands);
1581       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1582                                  CODE_LABEL_NUMBER (ops[0]));
1583     }
1585   return \"\";
1589 ;; Split the special case where the source of the sign extend is
1590 ;; either Y or Z. In that case, we can't move the source in the D
1591 ;; register directly. The movhi pattern handles this move by using
1592 ;; a temporary scratch memory location.
1594 (define_split
1595   [(set (match_operand:SI 0 "register_operand" "")
1596         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1597   "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1598   [(set (reg:HI D_REGNUM) (match_dup 1))
1599    (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1600   "")
1602 (define_insn "extendhisi2"
1603   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1604         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1605   ""
1606   "*
1608   rtx ops[2];
1609   int x_reg_used;
1611   if (Y_REG_P (operands[1]))
1612     return \"#\";
1614   if (X_REG_P (operands[1]))
1615     {
1616       output_asm_insn (\"xgdx\", operands);
1617       x_reg_used = 1;
1618     }
1619   else
1620     {
1621       /* X can be used as an indexed addressing in the source.
1622          Get the value before clearing it.  */
1623       x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1624       if (x_reg_used)
1625         {
1626           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1627           ops[1] = operands[1];
1628           m68hc11_gen_movhi (insn, ops);
1629         }
1630     }
1632   CC_STATUS_INIT;
1633   if (TARGET_M6812 && 0)
1634     {
1635       /* This sequence of code is larger than the one for 68HC11.
1636          Don't use it; keep it for documentation.  */
1637       if (!D_REG_P (operands[1]) && !x_reg_used)
1638         {
1639           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1640           ops[1] = operands[1];
1641           m68hc11_gen_movhi (insn, ops);
1642         }
1643       output_asm_insn (\"sex\\ta,x\", operands);
1644       output_asm_insn (\"xgdx\", operands);
1645       output_asm_insn (\"sex\\ta,d\", operands);
1646       return \"xgdx\";
1647     }
1649   output_asm_insn (\"ldx\\t#0\", operands);
1650   if (D_REG_P (operands[1]) || x_reg_used)
1651     {
1652       output_asm_insn (\"tsta\", operands);
1653     }
1654   else
1655     {
1656       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1657       ops[1] = operands[1];
1658       m68hc11_gen_movhi (insn, ops);
1659     }
1661   ops[0] = gen_label_rtx ();
1662   output_asm_insn (\"bpl\\t%l0\", ops);
1663   output_asm_insn (\"dex\", operands);
1664   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1666   return \"\";
1670 ;;--------------------------------------------------------------------
1671 ;;- Min and Max instructions (68HC12).
1672 ;;--------------------------------------------------------------------
1673 (define_insn "uminqi3"
1674   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1675         (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1676                  (match_operand:QI 2 "general_operand" "m,d")))]
1677   "TARGET_M6812 && TARGET_MIN_MAX"
1678   "*
1680   /* Flags are set according to (sub:QI (operand 1) (operand2)).
1681      The mina/minm use A as the source or destination.  This is the
1682      high part of D.  There is no way to express that in the pattern
1683      so we must use 'exg a,b' to put the operand in the good register.  */
1684   CC_STATUS_INIT;
1685   if (D_REG_P (operands[0]))
1686     {
1687       return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1688     }
1689   else
1690     {
1691       return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1692     }
1695 (define_insn "umaxqi3"
1696   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1697         (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1698                  (match_operand:QI 2 "general_operand" "m,d")))]
1699   "TARGET_M6812 && TARGET_MIN_MAX"
1700   "*
1702   /* Flags are set according to (sub:QI (operand 1) (operand2)).
1703      The maxa/maxm use A as the source or destination.  This is the
1704      high part of D.  There is no way to express that in the pattern
1705      so we must use 'exg a,b' to put the operand in the good register.  */
1706   CC_STATUS_INIT;
1707   if (D_REG_P (operands[0]))
1708     {
1709       return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1710     }
1711   else
1712     {
1713       return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1714     }
1717 (define_insn "uminhi3"
1718   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1719         (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1720                  (match_operand:HI 2 "general_operand" "m,d")))]
1721   "TARGET_M6812 && TARGET_MIN_MAX"
1722   "*
1724   /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
1725   CC_STATUS_INIT;
1726   if (D_REG_P (operands[0]))
1727     {
1728       return \"emind\\t%2\";
1729     }
1730   else
1731     {
1732       return \"eminm\\t%0\";
1733     }
1736 (define_insn "umaxhi3"
1737   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1738         (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1739                  (match_operand:HI 2 "general_operand" "m,d")))]
1740   "TARGET_M6812 && TARGET_MIN_MAX"
1741   "*
1743   /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
1744   CC_STATUS_INIT;
1745   if (D_REG_P (operands[0]))
1746     {
1747       return \"emaxd\\t%2\";
1748     }
1749   else
1750     {
1751       return \"emaxm\\t%0\";
1752     }
1756 ;;--------------------------------------------------------------------
1757 ;;- Add instructions.
1758 ;;--------------------------------------------------------------------
1759 ;; 64-bit: Use a library call because what GCC generates is huge.
1761 (define_expand "adddi3"
1762   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1763         (plus:DI (match_operand:DI 1 "general_operand" "")
1764                  (match_operand:DI 2 "general_operand" "")))]
1765   ""
1766   "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1767    DONE;")
1770 ;; - 32-bit Add.
1772 (define_expand "addsi3"
1773   [(parallel [(set (match_operand:SI 0 "register_operand" "")
1774                      (plus:SI (match_operand:SI 1 "general_operand" "")
1775                               (match_operand:SI 2 "general_operand" "")))
1776               (clobber (match_scratch:HI 3 ""))])]
1777   ""
1778   "")
1780 (define_insn "*addsi3_zero_extendhi"
1781   [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1782         (plus:SI (zero_extend:SI 
1783                  (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1784                  (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1785    (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1786   ""
1787   "*
1789   rtx ops[3];
1791   if (X_REG_P (operands[2]))
1792     {
1793       ops[0] = operands[1];
1794     }
1795   else
1796     {
1797       if (X_REG_P (operands[1]))
1798         {
1799           output_asm_insn (\"xgdx\", ops);
1800         }
1801       else if (!D_REG_P (operands[1]))
1802         {
1803           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1804           ops[1] = operands[1];
1805           m68hc11_gen_movhi (insn, ops);
1806         }
1807       ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1808       ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1809     }
1810   ops[2] = gen_label_rtx ();
1812   /* ldx preserves the carry, propagate it by incrementing X directly.  */
1813   output_asm_insn (\"addd\\t%0\", ops);
1814   if (!X_REG_P (operands[2]))
1815     output_asm_insn (\"ldx\\t%1\", ops);
1817   output_asm_insn (\"bcc\\t%l2\", ops);
1818   output_asm_insn (\"inx\", ops);
1820   CC_STATUS_INIT;
1821   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1822   return \"\";  
1826 (define_split /* "*addsi3_zero_extendqi" */
1827   [(set (match_operand:SI 0 "register_operand" "")
1828         (plus:SI (zero_extend:SI 
1829                    (match_operand:QI 1 "general_operand" ""))
1830                  (match_operand:SI 2 "memory_operand" "")))
1831    (clobber (match_scratch:HI 3 "=X,X"))]
1832   "reload_completed"
1833   [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1834    (parallel [(set (match_dup 0) 
1835                    (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1836               (clobber (match_dup 3))])]
1837   "")
1839 (define_insn "*addsi3_zero_extendqi"
1840   [(set (match_operand:SI 0 "register_operand" "=D,D")
1841         (plus:SI (zero_extend:SI 
1842                    (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1843                  (match_operand:SI 2 "general_operand" "miD,!muiD")))
1844    (clobber (match_scratch:HI 3 "=X,X"))]
1845   ""
1846   "*
1848   rtx ops[4];
1850   if (GET_CODE (operands[2]) == MEM)
1851     return \"#\";
1853   if (X_REG_P (operands[2]))
1854     {
1855       if (H_REG_P (operands[1]))
1856         {
1857           ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1858           ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1859           m68hc11_gen_movhi (insn, ops);
1860         }
1861       else
1862         {
1863           ops[0] = operands[1];
1864         }
1865       ops[1] = const0_rtx;
1866     }
1867   else
1868     {
1869       if (X_REG_P (operands[1]))
1870         {
1871           output_asm_insn (\"xgdx\", ops);
1872         }
1873       else if (!D_REG_P (operands[1]))
1874         {
1875           ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1876           ops[1] = operands[1];
1877           m68hc11_gen_movqi (insn, ops);
1878         }
1880       ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1881       ops[1] = ops[0];
1882       ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1883       output_asm_insn (\"clra\", ops);
1884     }
1886   /* ldx preserves the carry, propagate it by incrementing X directly.  */
1887   output_asm_insn (\"addb\\t%b0\", ops);
1888   output_asm_insn (\"adca\\t%h1\", ops);
1889   if (!X_REG_P (operands[2]))
1890     output_asm_insn (\"ldx\\t%2\", ops);
1892   /* If the above adca was adding some constant, we don't need to propagate
1893      the carry unless the constant was 0xff.  */
1894   if (X_REG_P (operands[2])
1895       || GET_CODE (ops[1]) != CONST_INT
1896       || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1897     {
1898       ops[3] = gen_label_rtx ();
1900       output_asm_insn (\"bcc\\t%l3\", ops);
1901       output_asm_insn (\"inx\", ops);
1903       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1904                                  CODE_LABEL_NUMBER (ops[3]));
1905     }
1906   CC_STATUS_INIT;
1907   return \"\";  
1910 (define_insn "*addsi3"
1911   [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
1912         (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1913                  (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
1914    (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1915   ""
1916   "*
1918   rtx   ops[3];
1919   const char* add_insn;
1920   const char* inc_insn;
1921   const char* incb_mem;
1922   const char* inch_mem;
1923   HOST_WIDE_INT val;
1925   if (which_alternative > 2)
1926     {
1927       return \"#\";
1928     }
1930   val = INTVAL (operands[2]);
1931   if ((val & 0x0ffffL) == 0)
1932     {
1933       if (!H_REG_P (operands[0]))
1934         {
1935           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1936           ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1937           output_asm_insn (\"ldd\\t%0\", ops);
1938           output_asm_insn (\"addd\\t%1\", ops);
1939           output_asm_insn (\"std\\t%0\", ops);
1940           return \"\";
1941         }
1942       else if (val == 1)
1943         {
1944           return \"inx\";
1945         }
1946       else
1947         {
1948           return \"#\";
1949         }
1950     }
1951   if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1952     {
1953       return \"#\";
1954     }
1956   if (val >= 0)
1957     {
1958       ops[1]   = operands[2];
1959       add_insn = \"addd\\t%1\";
1960       inc_insn = \"inx\\t\";
1961       incb_mem  = \"inc\\t%b1\";
1962       inch_mem  = \"inc\\t%h1\";
1963     }
1964   else
1965     {
1966       ops[1] = GEN_INT (- val);
1967       add_insn = \"subd\\t%1\";
1968       inc_insn = \"dex\";
1969       incb_mem  = \"dec\\t%b1\";
1970       inch_mem  = \"dec\\t%h1\";
1971     }
1972       
1973   ops[2] = gen_label_rtx ();
1974   if (!H_REG_P (operands[0]))
1975     {
1976       ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1977       output_asm_insn (\"ldd\\t%0\", ops);
1978     }
1979   output_asm_insn (add_insn, ops);
1980   if (!H_REG_P (operands[0]))
1981     {
1982       output_asm_insn (\"std\\t%0\", ops);
1983     }
1984   output_asm_insn (\"bcc\\t%l2\", ops);
1985   if (H_REG_P (operands[0]))
1986     {
1987       output_asm_insn (inc_insn, ops);
1988     }
1989   else
1990     {
1991       ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1992       ops[1] = ops[0];
1993       if (INTVAL (operands[2]) < 0)
1994         {
1995           output_asm_insn (\"ldd\\t%1\", ops);
1996           output_asm_insn (\"addd\\t#-1\", ops);
1997           output_asm_insn (\"std\\t%1\", ops);
1998         }
1999       else
2000         {
2001           output_asm_insn (incb_mem, ops);
2002           output_asm_insn (\"bne\\t%l2\", ops);
2003           output_asm_insn (inch_mem, ops);
2004         }
2005     }
2006   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
2008   CC_STATUS_INIT;
2009   return \"\";
2012 (define_split
2013   [(set (match_operand:SI 0 "register_operand" "")
2014         (plus:SI (match_operand:SI 1 "register_operand" "")
2015                  (match_operand:SI 2 "const_int_operand" "")))
2016    (clobber (match_scratch:HI 3 ""))]
2017   "reload_completed && z_replacement_completed == 2
2018    && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
2019   [(set (match_dup 5) (match_dup 6))
2020    (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
2021    (set (match_dup 6) (match_dup 5))]
2022   "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2023    if (X_REG_P (operands[0]))
2024      {
2025        operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
2026      }
2027    else
2028      {
2029        operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2030        operands[5] = operands[3];
2031      }
2032    ")
2034 (define_split
2035   [(set (match_operand:SI 0 "register_operand" "")
2036         (plus:SI (match_operand:SI 1 "register_operand" "")
2037                  (match_operand:SI 2 "general_operand" "")))
2038    (clobber (match_scratch:HI 3 "=X"))]
2039   "reload_completed && z_replacement_completed == 2
2040    && (GET_CODE (operands[2]) != CONST_INT || 
2041         (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
2042   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2043    (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2044               (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2045    (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2046    (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2047    (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2048               (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
2049   "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2050    operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2051    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2052    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2055 ;; Instruction generated to propagate the carry of a 16-bit add
2056 ;; to the upper 16-bit part (in register X).
2058 (define_insn "*addsi_carry"
2059   [(set (match_operand:HI 0 "register_operand" "=x")
2060            (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2061                              (const_int 0)) 
2062                     (reg:HI CC_REGNUM)))]
2063   ""
2064   "*
2066   rtx ops[2];
2068   ops[0] = gen_label_rtx ();
2069   output_asm_insn (\"bcc\\t%l0\", ops);
2070   output_asm_insn (\"in%0\", operands);
2071   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2072   CC_STATUS_INIT;
2073   return \"\";
2077 ;; - 16-bit Add.
2079 (define_expand "addhi3"
2080   [(set (match_operand:HI 0 "register_operand" "")
2081            (plus:HI (match_operand:HI 1 "register_operand" "")
2082                     (match_operand:HI 2 "general_operand" "")))]
2083   ""
2084   "
2086   if (TARGET_M6811 && SP_REG_P (operands[0]))
2087     {
2088       emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
2089                          gen_rtx_SET (VOIDmode,
2090                                   operand0,
2091                                   gen_rtx_PLUS (HImode,
2092                                            operand1, operand2)),
2093                         gen_rtx_CLOBBER (VOIDmode,
2094                                 gen_rtx_SCRATCH (HImode)))));
2095       DONE;
2096     }
2099 (define_insn "*addhi3_68hc12"
2100   [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
2101         (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
2102                  (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
2103   "TARGET_M6812"
2104   "*
2106   int val;
2107   const char* insn_code;
2109   if (which_alternative >= 4)
2110     {
2111       if (A_REG_P (operands[2]))
2112         {
2113           CC_STATUS_INIT;
2114           output_asm_insn (\"xgd%2\", operands);
2115           output_asm_insn (\"lea%0 d,%0\", operands);
2116           return \"xgd%2\";
2117         }
2118       return \"#\";
2119     }
2121   if (D_REG_P (operands[0]))
2122     {
2123       if (X_REG_P (operands[2]))
2124         {
2125           m68hc11_notice_keep_cc (operands[0]);
2126           output_asm_insn (\"xgdx\", operands);
2127           output_asm_insn (\"leax\\td,%2\", operands);
2128           return \"xgdx\";
2129         }
2130       else if (Y_REG_P (operands[2]))
2131         {
2132           m68hc11_notice_keep_cc (operands[0]);
2133           output_asm_insn (\"xgdy\", operands);
2134           output_asm_insn (\"leay\\td,%2\", operands);
2135           return \"xgdy\";
2136         }
2137       else if (SP_REG_P (operands[2]))
2138         {
2139           output_asm_insn (\"sts\\t%t0\", operands);
2140           return \"addd\\t%t0\";
2141         }
2142       return \"addd\\t%2\";
2143     }
2145   if (GET_CODE (operands[2]) == CONST_INT)
2146     val = INTVAL (operands[2]);
2147   else
2148     val = 1000;
2150   if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
2151     {
2152       m68hc11_notice_keep_cc (operands[0]);
2153       switch (REGNO (operands[0]))
2154         {
2155         case HARD_X_REGNUM:
2156           return \"leax\\t%i2,%1\";
2158         case HARD_Y_REGNUM:
2159           return \"leay\\t%i2,%1\";
2161         case HARD_SP_REGNUM:
2162           return \"leas\\t%i2,%1\";
2164         default:
2165           fatal_insn (\"Invalid operands in the instruction\", insn);
2166         }
2167     }
2168   if (val > 0)
2169     {
2170       insn_code = X_REG_P (operands[0]) ? \"inx\"
2171                 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2172     }
2173   else
2174     {
2175       val  = -val;
2176       insn_code = X_REG_P (operands[0]) ? \"dex\"
2177                 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2178     }
2180   /* For X and Y increment, the flags are not complete. Only the Z flag
2181      is updated. For SP increment, flags are not changed.  */
2182   if (SP_REG_P (operands[0]))
2183     {
2184       cc_status = cc_prev_status; 
2185       if (INTVAL (operands[2]) < 0)
2186         {
2187           while (val > 2)
2188             {
2189               output_asm_insn (\"pshx\", operands);
2190               val -= 2;
2191             }
2192           if (val == 0)
2193             return \"\";
2194         }     
2195     }
2196   else
2197     {
2198       CC_STATUS_INIT;
2199     }
2201   while (val)
2202     {
2203       output_asm_insn (insn_code, operands);
2204       val--;
2205     }
2206   return \"\";
2210 ;; Specific pattern to add to the stack pointer.
2211 ;; We also take care of the clobbering of the IY register.
2213 (define_insn "addhi_sp"
2214   [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2215           (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2216                    (match_operand:HI 2 "general_operand" "P,im,u,im")))
2217    (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2218   "!TARGET_M6812"
2219   "*
2221   HOST_WIDE_INT val;
2223   if (optimize && Y_REG_P (operands[3])
2224       && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
2225     operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
2227   if (GET_CODE (operands[2]) == CONST_INT
2228       && (val = INTVAL (operands[2])) != 0
2229       && (CONST_OK_FOR_LETTER_P (val, 'P')
2230           || (val > 0 && val <= 8)))
2231     {
2232       while (val > 1 || val < -1)
2233         {
2234           if (val > 0)
2235             {
2236               if (!H_REG_P (operands[3]))
2237                 break;
2239               output_asm_insn (\"pul%3\", operands);
2240               val -= 2;
2241             }
2242           else
2243             {
2244               output_asm_insn (\"pshx\", operands);
2245               val += 2;
2246             }
2247         }
2248       while (val != 0)
2249         {
2250           if (val > 0)
2251             {
2252               output_asm_insn (\"ins\", operands);
2253               val--;
2254             }
2255           else
2256             {
2257               output_asm_insn (\"des\", operands);
2258               val++;
2259             }
2260         }
2261       cc_status = cc_prev_status;
2262       return \"\";
2263     }
2265   /* Need to transfer to SP to X/Y and then to D register.
2266      Register X/Y is lost, this is specified by the (clobber) statement.  */
2267   output_asm_insn (\"ts%3\", operands);
2268   if (GET_CODE (operands[2]) == CONST_INT
2269       && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
2270       && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
2271     {
2272       output_asm_insn (\"ldab\\t%2\", operands);
2273       output_asm_insn (\"ab%3\", operands);
2274       CC_STATUS_INIT;
2275     }
2276   else
2277     {
2278       output_asm_insn (\"xgd%3\", operands);
2279       output_asm_insn (\"addd\\t%2\", operands);
2280       output_asm_insn (\"xgd%3\", operands);
2281     }
2283    /* The status flags correspond to the addd.  xgdy and tys do not
2284       modify the flags.  */
2285   return \"t%3s\";
2288 (define_insn "*addhi3"
2289   [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
2290         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
2291                  (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
2292   "TARGET_M6811"
2293   "*
2295   const char* insn_code;
2296   int val;
2298   if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2299     {
2300       output_asm_insn (\"sts\\t%t0\", operands);
2301       output_asm_insn (\"addd\\t%t0\", operands);
2302       return \"addd\\t#1\";
2303     }
2304   if (GET_CODE (operands[2]) != CONST_INT)
2305     {
2306       /* Adding to an address register or with another/same register
2307          is not possible. This must be replaced.  */
2308       if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2309         return \"#\";
2311       return \"addd\\t%2\";
2312     }
2313   val = INTVAL (operands[2]);
2314   if (!SP_REG_P (operands[0]))
2315     {
2316       if (D_REG_P (operands[0]))
2317         {
2318           if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2319             {
2320               CC_STATUS_INIT;
2321               return \"adda\\t%h2\";
2322             }
2323           else
2324             {
2325               return \"addd\\t%2\";
2326             }
2327         }
2328       else if (GET_CODE (operands[2]) != CONST_INT
2329                || INTVAL (operands[2]) < -4
2330                || INTVAL (operands[2]) > 4)
2331         return \"#\";
2332     }
2333   if (val > 0)
2334     {
2335       insn_code = X_REG_P (operands[0]) ? \"inx\"
2336                     : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2337     }
2338   else
2339     {
2340       val  = -val;
2341       insn_code = X_REG_P (operands[0]) ? \"dex\"
2342                     : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2343     }
2345   /* For X and Y increment, the flags are not complete.  Only the Z flag
2346      is updated.  For SP increment, flags are not changed.  */
2347   if (SP_REG_P (operands[0]))
2348     {
2349       cc_status = cc_prev_status; 
2350       if (INTVAL (operands[2]) < 0)
2351         {
2352           while (val >= 2)
2353             {
2354               output_asm_insn (\"pshx\", operands);
2355               val -= 2;
2356             }
2357         }
2358       else if (optimize && dead_register_here (insn, ix_reg))
2359         {
2360           while (val >= 2)
2361             {
2362               output_asm_insn (\"pulx\", operands);
2363               val -= 2;
2364             }
2365         }
2366     }
2367   else
2368     {
2369       CC_STATUS_INIT;
2370     }
2372   while (val)
2373     {
2374       output_asm_insn (insn_code, operands);
2375       val--;
2376     }
2377   return \"\";
2380 (define_insn "*addhi3_zext"
2381   [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2382         (plus:HI (zero_extend:HI 
2383                      (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2384                  (match_operand:HI 2 "general_operand" "0,0")))]
2385   ""
2386   "*
2388   CC_STATUS_INIT;
2389   if (A_REG_P (operands[0]))
2390     return \"ab%0\";
2391   else if (A_REG_P (operands[1]))
2392     return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2393   else 
2394     return \"addb\\t%b1\\n\\tadca\\t#0\";
2398 ;; Translate d = d + d into d = << 1
2399 ;; We have to do this because adding a register to itself is not possible.
2400 ;; ??? It's not clear whether this is really necessary.
2402 (define_split
2403   [(set (match_operand:QI 0 "hard_reg_operand" "")
2404         (plus:QI (match_dup 0)
2405                  (match_dup 0)))]
2406   "0 && reload_completed"
2407   [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2408   "")
2410 (define_insn "addqi3"
2411   [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2412         (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2413                  (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2414   ""
2415   "*
2417   if (GET_CODE (operands[2]) == CONST_INT)
2418     {
2419       if (INTVAL (operands[2]) == 1)
2420         {
2421           if (DA_REG_P (operands[0]))
2422             {
2423               return \"inca\";
2424             }
2425           else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2426            {
2427              return \"incb\";
2429            }
2430           else if (A_REG_P (operands[0]))
2431            {
2432              /* This applies on the 16-bit register.  This should be ok since
2433                 this is not a strict_low_part increment.  */
2434              return \"in%0\";
2435            }
2436           else
2437            {
2438              return \"inc\\t%b0\";
2439            }
2440         }
2441       else if (INTVAL (operands[2]) == -1)
2442         {
2443           if (DA_REG_P (operands[0]))
2444             {
2445               return \"deca\";
2446             }
2447           else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2448             {
2449               return \"decb\";
2450             }
2451           else if (A_REG_P (operands[0]))
2452             {
2453              /* This applies on the 16-bit register.  This should be ok since
2454                 this is not a strict_low_part decrement.  */
2455               return \"de%0\";
2456             }
2457           else
2458             {
2459               return \"dec\\t%b0\";
2460             }
2461         }
2462     }
2463   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2464     return \"#\";
2465   else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2466     return \"addb\\t%b2\";
2467   else
2468     return \"adda\\t%b2\";
2472 ;; add with carry is used for 32-bit add.
2474 (define_insn "*adcq"
2475   [(set (match_operand:QI 0 "register_operand" "=q")
2476         (plus:QI (plus:QI (reg:QI CC_REGNUM)
2477                           (match_operand:QI 1 "register_operand" "%0"))
2478                  (match_operand:QI 2 "general_operand" "ium")))]
2479   ""
2480   "adc%0\\t%b2")
2482 ;;--------------------------------------------------------------------
2483 ;;- Subtract instructions.
2484 ;;--------------------------------------------------------------------
2486 (define_expand "subdi3"
2487   [(set (match_operand:DI 0 "nonimmediate_operand" "")
2488         (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2489                   (match_operand:DI 2 "general_operand" "")))]
2490   ""
2491   "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2492    DONE;")
2495 ;; 32-bit Subtract (see addsi3)
2496 ;; Subtract with a constant are handled by addsi3.
2499 ;; - 32-bit Add.
2501 (define_expand "subsi3"
2502   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2503                      (minus:SI (match_operand:SI 1 "register_operand" "")
2504                               (match_operand:SI 2 "general_operand" "")))
2505               (clobber (match_scratch:HI 3 ""))])]
2506   ""
2507   "")
2509 (define_insn "*subsi3"
2510   [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
2511         (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2512                   (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
2513    (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
2514   ""
2515   "#")
2517 (define_insn "*subsi3_zero_extendhi"
2518   [(set (match_operand:SI 0 "register_operand" "=D")
2519         (minus:SI (match_operand:SI 1 "register_operand" "0")
2520             (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
2521    (clobber (match_scratch:HI 3 "=X"))]
2522   ""
2523   "*
2525   rtx ops[2];
2527   if (A_REG_P (operands[2]))
2528     {
2529       if (TARGET_M6812)
2530         ops[0] = gen_rtx_MEM (HImode,
2531                           gen_rtx_PRE_DEC (HImode,
2532                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2533       else
2534         ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2536       ops[1] = operands[2];
2537       m68hc11_gen_movhi (insn, ops);
2538       if (TARGET_M6812)
2539         operands[2] = gen_rtx_MEM (HImode,
2540                                gen_rtx_POST_INC (HImode,
2541                                         gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2542       else
2543         operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2544     }
2545   ops[0] = gen_label_rtx (); 
2546   output_asm_insn (\"subd\\t%2\", operands);
2547   output_asm_insn (\"bcc\\t%l0\", ops);
2548   output_asm_insn (\"dex\", ops);
2549   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2550   CC_STATUS_INIT;
2551   return \"\";
2554 (define_insn "*subsi3_zero_extendqi"
2555   [(set (match_operand:SI 0 "register_operand" "=D")
2556         (minus:SI (match_operand:SI 1 "register_operand" "0")
2557             (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
2558    (clobber (match_scratch:HI 3 "=X"))]
2559   ""
2560   "*
2562   rtx ops[2];
2564   if (A_REG_P (operands[2]))
2565     {
2566       ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2567       ops[1] = operands[2];
2568       m68hc11_gen_movhi (insn, ops);
2569       operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2570     }
2571   ops[0] = gen_label_rtx (); 
2572   output_asm_insn (\"subb\\t%b2\", operands);
2573   output_asm_insn (\"sbca\\t#0\", operands);
2574   output_asm_insn (\"bcc\\t%l0\", ops);
2575   output_asm_insn (\"dex\", ops);
2576   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2577   CC_STATUS_INIT;
2578   return \"\";
2582 ;; reg:HI 1 -> d        reg:QI 6 -> B
2583 ;; reg:QI 7 -> ccr      reg:QI 5 -> A
2585 (define_split /* "*subsi3" */
2586   [(set (match_operand:SI 0 "register_operand" "")
2587         (minus:SI (match_operand:SI 1 "register_operand" "")
2588                   (match_operand:SI 2 "general_operand" "")))
2589    (clobber (match_scratch:HI 3 "=X"))]
2590   "reload_completed && z_replacement_completed == 2
2591    && X_REG_P (operands[1])"
2592   [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2593    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2594               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2595    (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2596    (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2597    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2598               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2599   "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2600    operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2601    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2602    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2604 (define_split /* "*subsi3" */
2605   [(set (match_operand:SI 0 "register_operand" "")
2606         (minus:SI (match_operand:SI 1 "general_operand" "")
2607                   (match_operand:SI 2 "register_operand" "")))
2608    (clobber (match_scratch:HI 3 "=X"))]
2609   "reload_completed && z_replacement_completed == 2
2610    && X_REG_P (operands[2])"
2611   [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2612    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2613               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2614    (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2615    (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2616    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2617               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2618    (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2619   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2620    operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2621    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2622    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2624 (define_split /* "*subsi3" */
2625   [(set (match_operand:SI 0 "nonimmediate_operand" "")
2626         (minus:SI (match_operand:SI 1 "general_operand" "")
2627                   (match_operand:SI 2 "general_operand" "")))
2628    (clobber (match_scratch:HI 3 "=d"))]
2629   "reload_completed && z_replacement_completed == 2
2630    && !X_REG_P (operands[0])"
2631   [(set (match_dup 3) (match_dup 4))
2632    (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2633    (set (match_dup 4) (match_dup 3))
2634    (set (match_dup 3) (match_dup 6))
2635    (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2636    (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2637    (set (match_dup 6) (match_dup 3))]
2638   "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2639    operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2640    operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2641    operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2642    operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2643    operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2646 ;; - 16-bit Subtract.
2648 (define_expand "subhi3"
2649   [(set (match_operand:HI 0 "register_operand" "=r")
2650         (minus:HI (match_operand:HI 1 "register_operand" "0")
2651                   (match_operand:HI 2 "general_operand" "g")))]
2652   ""
2653   "")
2656 ;; Subtract from stack. This is better if we provide a pattern.
2658 (define_insn "*subhi3_sp"
2659   [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2660         (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2661                   (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2662    (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2663   ""
2664   "*
2666   if (X_REG_P (operands[2]))
2667     {
2668       operands[2] = m68hc11_soft_tmp_reg;
2669       output_asm_insn (\"stx\\t%2\", operands);
2670     }
2671   else if (Y_REG_P (operands[2]))
2672     {
2673       operands[2] = m68hc11_soft_tmp_reg;
2674       output_asm_insn (\"sty\\t%2\", operands);
2675     }
2676   else if (D_REG_P (operands[2]))
2677     {
2678       operands[2] = m68hc11_soft_tmp_reg;
2679       output_asm_insn (\"std\\t%2\", operands);
2680     }
2682   if (D_REG_P (operands[3]))
2683     {
2684       int save_x;
2686       save_x = !dead_register_here (insn, ix_reg);
2687       if (save_x)
2688         output_asm_insn (\"xgdx\", operands);
2689       output_asm_insn (\"tsx\", operands);
2690       output_asm_insn (\"xgdx\", operands);
2691       output_asm_insn (\"subd\\t%2\", operands);
2692       output_asm_insn (\"xgdx\", operands);
2694       /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2695          modify the flags.  */
2696       output_asm_insn (\"txs\", operands);
2697       if (save_x)
2698         return \"xgdx\";
2699       else
2700         return \"\";
2701     }
2703   /* Need to transfer to SP to X,Y and then to D register.
2704      Register X,Y is lost, this is specified by the (clobber) statement.  */
2705   output_asm_insn (\"ts%3\", operands);
2706   output_asm_insn (\"xgd%3\", operands);
2707   output_asm_insn (\"subd\\t%2\", operands);
2708   output_asm_insn (\"xgd%3\", operands);
2710    /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2711       modify the flags.  */
2712   return \"t%3s\";
2716 (define_insn "*subhi3"
2717   [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
2718         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
2719                   (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
2720   ""
2721   "*
2723   /* Adding to an address register or with another/same register
2724      is not possible.  This must be replaced.  */
2725   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2726     return \"#\";
2728   return \"subd\\t%2\";
2731 (define_insn "*subhi3_zext"
2732   [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2733         (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2734            (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2735   ""
2736   "*
2738   CC_STATUS_INIT;
2739   if (A_REG_P (operands[2]))
2740     {
2741       rtx ops[2];
2743       ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2744       ops[1] = operands[2];
2745       m68hc11_gen_movqi (insn, ops);
2746       return \"subb\\t%T0\\n\\tsbca\\t#0\";
2747     }
2748   return \"subb\\t%b2\\n\\tsbca\\t#0\";
2751 (define_insn "subqi3"
2752   [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2753         (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2754                   (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2755   ""
2756   "*
2758   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2759     return \"#\";
2760   else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2761     return \"subb\\t%b2\";
2762   else
2763     return \"suba\\t%b2\";
2767 ;; subtract with carry is used for 32-bit subtract.
2769 (define_insn "*subcq"
2770   [(set (match_operand:QI 0 "register_operand" "=q")
2771         (minus:QI (minus:QI (reg:QI CC_REGNUM)
2772                             (match_operand:QI 1 "register_operand" "0"))
2773                   (match_operand:QI 2 "general_operand" "ium")))]
2774   ""
2775   "sbc%0\\t%b2")
2777 ;;--------------------------------------------------------------------
2778 ;;- Multiply instructions.
2779 ;;--------------------------------------------------------------------
2781 ;; 32 and 64-bit multiply are handled by the library
2784 (define_expand "mulsi3"
2785   [(set (match_operand:SI 0 "nonimmediate_operand" "")
2786         (mult:SI (match_operand:SI 1 "general_operand" "")
2787                  (match_operand:SI 2 "general_operand" "")))]
2788   ""
2789   "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2790    DONE;")
2792 (define_expand "mulhi3"
2793   [(parallel [(set (match_operand:HI 0 "register_operand" "")
2794                        (mult:HI (match_operand:HI 1 "register_operand" "")
2795                                 (match_operand:HI 2 "register_operand" "")))
2796               (clobber (match_scratch:HI 3 ""))])]
2797   ""
2798   "")
2800 (define_insn "mulhi3_m68hc11"
2801   [(set (match_operand:HI 0 "register_operand" "=d")
2802         (mult:HI (match_operand:HI 1 "register_operand" "%0")
2803                  (match_operand:HI 2 "register_operand" "x")))
2804    (clobber (match_scratch:HI 3 "=X"))]
2805   "TARGET_M6811"
2806   "*
2808   CC_STATUS_INIT;
2809   /* D * X -> D  (X and Y are preserved by this function call).  */
2810   return \"jsr\\t___mulhi3\";
2813 (define_insn "mulhi3_m68hc12"
2814   [(set (match_operand:HI 0 "register_operand" "=d,d")
2815         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2816                  (match_operand:HI 2 "register_operand" "y,x")))
2817    (clobber (match_scratch:HI 3 "=2,2"))]
2818   "TARGET_M6812"
2819   "*
2821   CC_STATUS_INIT;
2822   if (X_REG_P (operands[2]))
2823     return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2824   else
2825     return \"emul\";
2828 (define_insn "umulhisi3"
2829   [(set (match_operand:SI 0 "register_operand" "=D,D")
2830         (mult:SI (zero_extend:SI
2831                      (match_operand:HI 1 "register_operand" "%d,d"))
2832                  (zero_extend:SI
2833                      (match_operand:HI 2 "register_operand" "y,x"))))
2834    (clobber (match_scratch:HI 3 "=2,X"))]
2835   "TARGET_M6812"
2836   "*
2838   if (X_REG_P (operands [2]))
2839     output_asm_insn (\"exg\\tx,y\", operands);
2841   /* Can't use the carry after that; other flags are ok when testing
2842      the 32-bit result.  */
2843   cc_status.flags |= CC_NO_OVERFLOW;
2844   return \"emul\\n\\texg\\tx,y\";
2847 (define_insn "mulhisi3"
2848   [(set (match_operand:SI 0 "register_operand" "=D,D")
2849         (mult:SI (sign_extend:SI
2850                      (match_operand:HI 1 "register_operand" "%d,d"))
2851                  (sign_extend:SI
2852                      (match_operand:HI 2 "register_operand" "y,x"))))
2853    (clobber (match_scratch:HI 3 "=2,X"))]
2854   "TARGET_M6812"
2855   "*
2857   if (X_REG_P (operands [2]))
2858     output_asm_insn (\"exg\\tx,y\", operands);
2860   /* Can't use the carry after that; other flags are ok when testing
2861      the 32-bit result.  */
2862   cc_status.flags |= CC_NO_OVERFLOW;
2863   return \"emuls\\n\\texg\\tx,y\";
2866 (define_insn "umulqihi3"
2867   [(set (match_operand:HI 0 "register_operand" "=d")
2868         (mult:HI (zero_extend:HI
2869                      (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2870                  (zero_extend:HI
2871                      (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2872   ""
2873   "*
2875   if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2876     {
2877       output_asm_insn (\"tba\", operands);
2878     }
2879   else
2880     {
2881       rtx ops[2];
2883       if (D_REG_P (operands[2]))
2884         {
2885           rtx temp = operands[2];
2886           operands[2] = operands[1];
2887           operands[1] = temp;
2888         }
2890       ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2891       ops[1] = operands[2];
2892       m68hc11_gen_movqi (insn, ops);
2894       if (!D_REG_P (operands[1]))
2895         {
2896           output_asm_insn (\"ldab\\t%b1\", operands);
2897         }
2898     }
2900   CC_STATUS_INIT;
2901   return \"mul\";
2904 (define_insn "mulqi3"
2905   [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
2906         (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
2907                  (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
2908   ""
2909   "*
2911   if (A_REG_P (operands[0]))
2912     return \"#\";
2914   if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2915     {
2916       output_asm_insn (\"tba\", operands);
2917     }
2918   else
2919     {
2920       if (D_REG_P (operands[2]))
2921         {
2922           rtx temp = operands[2];
2923           operands[2] = operands[1];
2924           operands[1] = temp;
2925         }
2926         
2927       output_asm_insn (\"ldaa\\t%b2\", operands);
2929       if (!D_REG_P (operands[1]))
2930         {
2931           output_asm_insn (\"ldab\\t%b1\", operands);
2932         }
2933     }
2935   CC_STATUS_INIT;
2936   return \"mul\";
2939 (define_split
2940   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
2941         (mult:QI (match_operand:QI 1 "general_operand" "")
2942                  (match_operand:QI 2 "general_operand" "")))]
2943   "z_replacement_completed == 2"
2944   [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2945               (set (match_dup 3) (reg:HI D_REGNUM))])
2946    (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
2947    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2948               (set (match_dup 3) (reg:HI D_REGNUM))])]
2949   "
2950    operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
2951    if (A_REG_P (operands[1]))
2952      operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2953    else
2954      operands[5] = operands[1];
2955    if (A_REG_P (operands[2]))
2956      operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2957    else
2958      operands[6] = operands[2];
2959   ")
2961 (define_insn "mulqihi3"
2962   [(set (match_operand:HI 0 "register_operand" "=d,d,d")
2963         (mult:HI (sign_extend:HI
2964                         (match_operand:QI 1 "register_operand" "%0,0,0"))
2965                  (sign_extend:HI
2966                         (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
2967   ""
2968   "*
2970   CC_STATUS_INIT;
2972   /* Special case when multiplying the register with itself.  */
2973   if (D_REG_P (operands[2]))
2974     {
2975       output_asm_insn (\"tba\", operands);
2976       return \"mul\";
2977     }
2979   if (!H_REG_P (operands[2]))
2980     {
2981       output_asm_insn (\"ldaa\\t%b2\", operands);
2982     }
2983   else
2984     {
2985       rtx ops[2];
2987       ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2988       ops[1] = operands[2];
2989       m68hc11_gen_movqi (insn, ops);
2990     }
2991   return \"jsr\\t___mulqi3\";
2994 ;;--------------------------------------------------------------------
2995 ;;- Divide instructions.
2996 ;;--------------------------------------------------------------------
2998 (define_insn "divmodhi4"
2999   [(set (match_operand:HI 0 "register_operand" "=d,d")
3000           (div:HI (match_operand:HI 1 "register_operand" "0,0")
3001                   (match_operand:HI 2 "general_operand" "A,ium")))
3002    (set (match_operand:HI 3 "register_operand" "=&x,&x")
3003         (mod:HI (match_dup 1) (match_dup 2)))]
3004   ""
3005   "*
3007   if (!X_REG_P (operands[2])) 
3008     {
3009       if (Y_REG_P (operands[2]))
3010         {
3011           output_asm_insn (\"sty\\t%t1\", operands);
3012           output_asm_insn (\"ldx\\t%t1\", operands);
3013         }
3014       else
3015         {
3016           output_asm_insn (\"ldx\\t%2\", operands);
3017         }
3018     }
3019   if (TARGET_M6812)
3020     {
3021       /* Flags are ok after that.  */
3022       return \"idivs\\n\\txgdx\";      
3023     }
3024   else
3025     {
3026       CC_STATUS_INIT;
3027       return \"bsr\\t__divmodhi4\";
3028     }
3031 (define_insn "udivmodhi4"
3032   [(set (match_operand:HI 0 "register_operand" "=d,d")
3033           (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
3034                    (match_operand:HI 2 "general_operand" "A,ium")))
3035    (set (match_operand:HI 3 "register_operand" "=x,x")
3036         (umod:HI (match_dup 1) (match_dup 2)))]
3037   ""
3038   "*
3040   if (!X_REG_P (operands[2])) 
3041     {
3042       if (Y_REG_P (operands[2]))
3043         {
3044           output_asm_insn (\"sty\\t%t1\", operands);
3045           output_asm_insn (\"ldx\\t%t1\", operands);
3046         }
3047       else
3048         {
3049           output_asm_insn (\"ldx\\t%2\", operands);
3050         }
3051     }
3053   /* Z V and C flags are set but N is unchanged.
3054      Since this is an unsigned divide, we can probably keep the flags
3055      and indicate this.  */
3056   cc_status.flags |= CC_NOT_NEGATIVE;
3057   return \"idiv\\n\\txgdx\";
3060 ;;--------------------------------------------------------------------
3061 ;;- and instructions.
3062 ;;--------------------------------------------------------------------
3064 (define_insn_and_split "anddi3"
3065   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3066         (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3067                 (match_operand:DI 2 "general_operand" "imu,imu")))
3068    (clobber (match_scratch:HI 3 "=d,d"))]
3069   ""
3070   "#"
3071   "reload_completed"
3072   [(const_int 0)]
3073   "m68hc11_split_logical (SImode, AND, operands);
3074    DONE;")
3076 (define_insn_and_split "andsi3"
3077   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3078         (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3079                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3080    (clobber (match_scratch:HI 3 "=X,d"))]
3081   ""
3082   "#"
3083   "reload_completed"
3084   [(const_int 0)]
3085   "m68hc11_split_logical (HImode, AND, operands);
3086    DONE;")
3088 (define_expand "andhi3"
3089   [(set (match_operand:HI 0 "register_operand" "")
3090         (and:HI (match_operand:HI 1 "register_operand" "")
3091                 (match_operand:HI 2 "general_operand" "")))]
3092   ""
3093   "")
3095 (define_insn "*andhi3_mem"
3096   [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3097         (and:HI (match_dup 0)
3098                 (match_operand:HI 1 "immediate_operand" "i,i")))
3099    (clobber (match_scratch:HI 2 "=X,xy"))]
3100   "TARGET_RELAX && !TARGET_M6812"
3101   "*
3103   int val = INTVAL (operands[1]) & 0x0FFFF;
3105   if (val == 0x0ffff)
3106     {
3107       cc_status = cc_prev_status;
3108       return \"\";
3109     }
3111   CC_STATUS_INIT;
3113   /* The bclr instruction uses an inverted mask.  */
3114   operands[1] = GEN_INT ((~val) & 0x0FFFF);
3116   /* When destination is a global variable, generate a .relax instruction
3117      and load the address in the clobber register.  That load can be
3118      eliminated by the linker if the address is in page0.  */
3119   if (which_alternative == 1)
3120     {
3121       rtx ops[3];
3123       ops[0] = operands[2];
3124       ops[1] = XEXP (operands[0], 0);
3125       ops[2] = gen_label_rtx ();
3126       output_asm_insn (\".relax\\t%l2\", ops);
3127       m68hc11_gen_movhi (insn, ops);
3128       if ((val & 0x0FF) != 0x0FF)
3129         output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
3131       if ((val & 0x0FF00) != 0x0FF00)
3132         output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
3134       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3135                                  CODE_LABEL_NUMBER (ops[2]));
3136       return \"\";
3137     }
3139   if ((val & 0x0FF) != 0x0FF)
3140     output_asm_insn (\"bclr\\t%b0, %b1\", operands);
3142   if ((val & 0x0FF00) != 0x0FF00)
3143     output_asm_insn (\"bclr\\t%h0, %h1\", operands);
3145   return \"\";
3148 (define_insn "*andhi3_const"
3149   [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3150         (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3151                 (match_operand:HI 2 "const_int_operand" "")))]
3152   ""
3153   "*
3155   int val = INTVAL (operands[2]) & 0x0FFFF;
3156   int lowpart_zero = 0;
3157   int highpart_zero = 0;
3158   int lowpart_unknown = 0;
3159   int highpart_unknown = 0;
3161   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3162     return \"#\";
3164   if (val == 0x0ffff)
3165     {
3166       cc_status = cc_prev_status;
3167       return \"\";
3168     }
3170   /* First, try to clear the low and high part.
3171      If that's possible, the second 'and' will give
3172      the good status flags and we can avoid a tsthi.  */
3173   if ((val & 0x0FF) == 0)
3174     {
3175       if (D_REG_P (operands[0]))
3176         output_asm_insn (\"clrb\", operands);
3177       else
3178         output_asm_insn (\"clr\\t%b0\", operands);
3179       lowpart_zero = 1;
3180     }
3181   if ((val & 0x0FF00) == 0)
3182     {
3183       if (D_REG_P (operands[0]))
3184         output_asm_insn (\"clra\", operands);
3185       else
3186         output_asm_insn (\"clr\\t%h0\", operands);
3187       highpart_zero = 1;
3188     }
3190   if ((val & 0x0FF) == 0x0FF)
3191     {
3192       lowpart_unknown = 1;
3193     }
3194   else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3195     {
3196       rtx ops[2];
3198       ops[0] = operands[0];
3199       ops[1] = GEN_INT ((~val) & 0x0FF);
3200       output_asm_insn (\"bclr\\t%b0, %1\", ops);
3201     }
3202   else if ((val & 0x0FF) != 0)
3203     {
3204       output_asm_insn (\"andb\\t%b2\", operands);
3205     }
3207   if ((val & 0x0FF00) == 0x0FF00)
3208     {
3209       highpart_unknown = 1;
3210     }
3211   else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3212     {
3213       rtx ops[2];
3215       ops[0] = operands[0];
3216       ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
3217       output_asm_insn (\"bclr\\t%h0, %1\", ops);
3218     }
3219   else if ((val & 0x0FF00) != 0)
3220     {
3221       output_asm_insn (\"anda\\t%h2\", operands);
3222     }
3224   if (highpart_unknown || lowpart_unknown)
3225      CC_STATUS_INIT;
3226   else if (highpart_zero == 0 && lowpart_zero == 0)
3227      CC_STATUS_INIT;
3229   return \"\";
3232 (define_insn "*andhi3_gen"
3233   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3234         (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3235                 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3236   ""
3237   "*
3239   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3240     return \"#\";
3242   CC_STATUS_INIT;
3243   return \"anda\\t%h2\\n\\tandb\\t%b2\";
3246 (define_expand "andqi3"
3247   [(set (match_operand:QI 0 "register_operand" "")
3248         (and:QI (match_operand:QI 1 "register_operand" "")
3249                 (match_operand:QI 2 "general_operand" "")))]
3250   ""
3251   "")
3253 (define_insn "*andqi3_mem"
3254   [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3255         (and:QI (match_dup 0)
3256                 (match_operand:QI 1 "const_int_operand" "i,i")))
3257    (clobber (match_scratch:HI 2 "=X,xy"))]
3258   "TARGET_RELAX && !TARGET_M6812"
3259   "*
3261   int val = INTVAL (operands[1]) & 0x0FF;
3263   if (val == 0x0ff)
3264     {
3265       cc_status = cc_prev_status;
3266       return \"\";
3267     }
3269   /* The bclr instruction uses an inverted mask.  */
3270   operands[1] = GEN_INT ((~val) & 0x0FF);
3272   /* When destination is a global variable, generate a .relax instruction
3273      and load the address in the clobber register.  That load can be
3274      eliminated by the linker if the address is in page0.  */
3275   if (which_alternative == 1)
3276     {
3277       rtx ops[3];
3279       ops[0] = operands[2];
3280       ops[1] = XEXP (operands[0], 0);
3281       ops[2] = gen_label_rtx ();
3282       output_asm_insn (\".relax\\t%l2\", ops);
3283       m68hc11_gen_movhi (insn, ops);
3284       output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3285       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3286                                  CODE_LABEL_NUMBER (ops[2]));
3287       return \"\";
3288     }
3289   return \"bclr\\t%b0, %1\";
3292 (define_insn "*andqi3_const"
3293   [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3294         (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3295                 (match_operand:QI 2 "const_int_operand" "")))]
3296   ""
3297   "*
3299   int val = INTVAL (operands[2]) & 0x0FF;
3301   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3302     return \"#\";
3304   if (val == 0x0ff)
3305     {
3306       cc_status = cc_prev_status;
3307       return \"\";
3308     }
3309   if (!H_REG_P (operands[0]))
3310     {
3311       rtx ops[2];
3313       ops[0] = operands[0];
3314       ops[1] = GEN_INT ((~val) & 0x0FF);
3315       output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3316       return \"\";
3317     }
3318   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3319     return \"andb\\t%b2\";
3320   else if (DA_REG_P (operands[0]))
3321     return \"anda\\t%b2\";
3322   else
3323     fatal_insn (\"Invalid operand in the instruction\", insn);
3326 (define_insn "*andqi3_gen"
3327   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3328         (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3329              (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
3330   ""
3331   "*
3333   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3334     return \"#\";
3336   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3337     return \"andb\\t%b2\";
3338   else if (DA_REG_P (operands[0]))
3339     return \"anda\\t%b2\";
3340   else
3341     fatal_insn (\"Invalid operand in the instruction\", insn);
3344 ;;--------------------------------------------------------------------
3345 ;;- Bit set or instructions.
3346 ;;--------------------------------------------------------------------
3348 (define_insn_and_split "iordi3"
3349   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3350         (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3351                 (match_operand:DI 2 "general_operand" "imu,imu")))
3352    (clobber (match_scratch:HI 3 "=d,d"))]
3353   ""
3354   "#"
3355   "reload_completed"
3356   [(const_int 0)]
3357   "m68hc11_split_logical (SImode, IOR, operands);
3358    DONE;")
3360 (define_insn_and_split "iorsi3"
3361   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3362         (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3363                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3364    (clobber (match_scratch:HI 3 "=X,d"))]
3365   ""
3366   "#"
3367   "reload_completed"
3368   [(const_int 0)]
3369   "m68hc11_split_logical (HImode, IOR, operands);
3370    DONE;")
3372 (define_expand "iorhi3"
3373   [(set (match_operand:HI 0 "register_operand" "")
3374         (ior:HI (match_operand:HI 1 "register_operand" "")
3375                 (match_operand:HI 2 "splitable_operand" "")))]
3376   ""
3377   "")
3379 (define_insn "*iorhi3_mem"
3380   [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3381         (ior:HI (match_dup 0)
3382                 (match_operand:HI 1 "const_int_operand" "")))
3383    (clobber (match_scratch:HI 2 "=X,xy"))]
3384   "TARGET_RELAX && !TARGET_M6812"
3385   "*
3387   int val = INTVAL (operands[1]) & 0x0FFFF;
3389   if (val == 0)
3390     {
3391       cc_status = cc_prev_status;
3392       return \"\";
3393     }
3394   CC_STATUS_INIT;
3395   if (which_alternative == 1)
3396     {
3397       rtx ops[3];
3399       ops[0] = operands[2];
3400       ops[1] = XEXP (operands[0], 0);
3401       ops[2] = gen_label_rtx ();
3402       output_asm_insn (\".relax\\t%l2\", ops);
3403       m68hc11_gen_movhi (insn, ops);
3404       if ((val & 0x0FF) != 0)
3405         output_asm_insn (\"bset\\t1,%2, %b1\", operands);
3407       if ((val & 0x0FF00) != 0)
3408         output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3409       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3410                                  CODE_LABEL_NUMBER (ops[2]));
3411       return \"\";
3412     }
3414   if ((val & 0x0FF) != 0)
3415     output_asm_insn (\"bset\\t%b0, %b1\", operands);
3417   if ((val & 0x0FF00) != 0)
3418     output_asm_insn (\"bset\\t%h0, %h1\", operands);
3420   return \"\";
3423 (define_insn "*iorhi3_const"
3424   [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3425         (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3426                 (match_operand:HI 2 "const_int_operand" "")))]
3427   ""
3428   "*
3430   int val = INTVAL (operands[2]) & 0x0FFFF;
3432   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3433     return \"#\";
3435   if (val == 0)
3436     {
3437       cc_status = cc_prev_status;
3438       return \"\";
3439     }
3441   if ((val & 0x0FF) != 0)
3442     {
3443       if (!H_REG_P (operands[0]))
3444         output_asm_insn (\"bset\\t%b0, %b2\", operands);
3445       else
3446         output_asm_insn (\"orab\\t%b2\", operands);
3447     }
3449   if ((val & 0x0FF00) != 0)
3450     {
3451       if (!H_REG_P (operands[0]))
3452          output_asm_insn (\"bset\\t%h0, %h2\", operands);
3453       else
3454          output_asm_insn (\"oraa\\t%h2\", operands);
3455     }
3457   CC_STATUS_INIT;
3458   return \"\";
3461 (define_insn "*iorhi3_gen"
3462   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3463         (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3464                 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3465   ""
3466   "*
3468   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3469     return \"#\";
3471   CC_STATUS_INIT;
3472   return \"oraa\\t%h2\\n\\torab\\t%b2\";
3475 (define_expand "iorqi3"
3476   [(set (match_operand:QI 0 "register_operand" "")
3477         (ior:QI (match_operand:QI 1 "register_operand" "")
3478                 (match_operand:QI 2 "general_operand" "")))]
3479   ""
3480   "")
3482 (define_insn "*iorqi3_mem"
3483   [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3484         (ior:QI (match_dup 0)
3485                 (match_operand:QI 1 "const_int_operand" "")))
3486    (clobber (match_scratch:HI 2 "=X,xy"))]
3487   "TARGET_RELAX && !TARGET_M6812"
3488   "*
3490   int val = INTVAL (operands[1]) & 0x0FF;
3492   if (val == 0)
3493     {
3494       cc_status = cc_prev_status;
3495       return \"\";
3496     }
3497   if (which_alternative == 1)
3498     {
3499       rtx ops[3];
3501       ops[0] = operands[2];
3502       ops[1] = XEXP (operands[0], 0);
3503       ops[2] = gen_label_rtx ();
3504       output_asm_insn (\".relax\\t%l2\", ops);
3505       m68hc11_gen_movhi (insn, ops);
3506       output_asm_insn (\"bset\\t0,%2, %1\", operands);
3507       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3508                                  CODE_LABEL_NUMBER (ops[2]));
3509       return \"\";
3510     }
3511   return \"bset\\t%b0, %1\";
3514 (define_insn "*iorqi3_const"
3515   [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3516         (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3517                 (match_operand:QI 2 "const_int_operand" "")))]
3518   ""
3519   "*
3521   int val = INTVAL (operands[2]) & 0x0FF;
3523   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3524     return \"#\";
3526   if (val == 0)
3527     {
3528       cc_status = cc_prev_status;
3529       return \"\";
3530     }
3531   if (!H_REG_P (operands[0]))
3532     {
3533       return \"bset\\t%b0, %2\";
3534     }
3536   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3537     return \"orab\\t%b2\";
3538   else if (DA_REG_P (operands[0]))
3539     return \"oraa\\t%b2\";
3540   else
3541     fatal_insn (\"Invalid operand in the instruction\", insn);
3544 (define_insn "*iorqi3_gen"
3545   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3546         (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3547              (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
3548   ""
3549   "*
3551   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3552     return \"#\";
3554   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3555     return \"orab\\t%b2\";
3556   else if (DA_REG_P (operands[0]))
3557     return \"oraa\\t%b2\";
3558   else
3559     fatal_insn (\"Invalid operand in the instruction\", insn);
3563 ;;--------------------------------------------------------------------
3564 ;;- xor instructions.
3565 ;;--------------------------------------------------------------------
3567 (define_insn_and_split "xordi3"
3568   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3569         (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3570                 (match_operand:DI 2 "general_operand" "imu,imu")))
3571    (clobber (match_scratch:HI 3 "=d,d"))]
3572   ""
3573   "#"
3574   "reload_completed"
3575   [(const_int 0)]
3576   "m68hc11_split_logical (SImode, XOR, operands);
3577    DONE;")
3579 (define_insn_and_split "xorsi3"
3580   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3581         (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3582                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3583    (clobber (match_scratch:HI 3 "=X,d"))]
3584   ""
3585   "#"
3586   "reload_completed"
3587   [(const_int 0)]
3588   "m68hc11_split_logical (HImode, XOR, operands);
3589    DONE;")
3591 (define_insn "xorhi3"
3592   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3593         (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3594                 (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
3595   ""
3596   "*
3598   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3599     return \"#\";
3601   if (GET_CODE (operands[2]) == CONST_INT)
3602     {
3603       int val = INTVAL (operands[2]) & 0x0FFFF;
3605       if (val == 0)
3606         {
3607           cc_status = cc_prev_status;
3608           return \"\";
3609         }
3610       if ((val & 0x0FF) != 0)
3611         {
3612           output_asm_insn (\"eorb\\t%b2\", operands);
3613         }
3614       else if ((val & 0x0FF) == 0x0FF)
3615         {
3616           output_asm_insn (\"comb\", operands);
3617         }
3619       if ((val & 0x0FF00) != 0)
3620         {
3621           output_asm_insn (\"eora\\t%h2\", operands);
3622         }
3623       else if ((val & 0x0FF00) == 0x0FF00)
3624         {
3625           output_asm_insn (\"coma\", operands);
3626         }
3628       CC_STATUS_INIT;
3629       return \"\";
3630     }
3632   CC_STATUS_INIT;
3633   return \"eora\\t%h2\\n\\teorb\\t%b2\";
3636 (define_insn "xorqi3"
3637   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3638         (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3639              (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
3640   ""
3641   "*
3643   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3644     return \"#\";
3646   if (GET_CODE (operands[2]) == CONST_INT)
3647     {
3648       int val = INTVAL (operands[2]) & 0x0FF;
3650       if (val == 0)
3651         {
3652           cc_status = cc_prev_status;
3653           return \"\";
3654         }
3655       if (val == 0x0FF)
3656         {
3657           if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3658             return \"comb\";
3659           else
3660             return \"coma\";
3661         }
3662     }
3663   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3664     return \"eorb\\t%b2\";
3665   else if (DA_REG_P (operands[0]))
3666     return \"eora\\t%b2\";
3667   else
3668     fatal_insn (\"Invalid operand in the instruction\", insn);
3671 ;;--------------------------------------------------------------------
3672 ;;- Bit set or instructions.
3673 ;;--------------------------------------------------------------------
3675 (define_insn_and_split "*logicalsi3_zexthi"
3676   [(set (match_operand:SI 0 "register_operand" "=D")
3677         (match_operator:SI 3 "m68hc11_logical_operator"
3678                 [(zero_extend:SI
3679                      (match_operand:HI 1 "general_operand" "imudA"))
3680                  (match_operand:SI 2 "general_operand" "Dimu")]))]
3681   ""
3682   "#"
3683   "reload_completed"
3684   [(set (reg:HI D_REGNUM) (match_dup 4))
3685    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3686    (set (reg:HI X_REGNUM) (match_dup 6))]
3687   "PUT_MODE (operands[3], HImode);
3688    if (X_REG_P (operands[2]))
3689      {
3690        operands[5] = operands[1];
3691        /* Make all the (set (REG:x) (REG:y)) a nop set.  */
3692        operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3693        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3694      }
3695    else
3696      {
3697        operands[4] = operands[1];
3698        operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3699        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3700      }
3701    /* For an AND, make sure the high 16-bit part is cleared.  */
3702    if (GET_CODE (operands[3]) == AND)
3703      {
3704        operands[6] = const0_rtx;
3705      }
3706    ")
3708 (define_insn_and_split "*logicalsi3_zextqi"
3709   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3710         (match_operator:SI 3 "m68hc11_logical_operator"
3711                 [(zero_extend:SI
3712                      (match_operand:QI 1 "general_operand" "d,*A,imu"))
3713                  (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3714   ""
3715   "#"
3716   "z_replacement_completed == 2"
3717   [(set (reg:QI A_REGNUM) (match_dup 4))
3718    (set (reg:QI D_REGNUM) (match_dup 7))
3719    (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3720    (set (reg:HI X_REGNUM) (match_dup 6))]
3721   "PUT_MODE (operands[3], QImode);
3722    if (X_REG_P (operands[2]))
3723      {
3724        operands[5] = operands[1];
3725        /* Make all the (set (REG:x) (REG:y)) a nop set.  */
3726        operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3727        operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
3728        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3729      }
3730    else
3731      {
3732        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3733        operands[7] = operands[1];
3734        operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3735        operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3736        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3737      }
3738    /* For an AND, make sure the high 24-bit part is cleared.  */
3739    if (GET_CODE (operands[3]) == AND)
3740      {
3741        operands[4] = const0_rtx;
3742        operands[6] = const0_rtx;
3743      }
3744    ")
3746 (define_insn_and_split "*logicalhi3_zexthi_ashift8"
3747   [(set (match_operand:HI 0 "register_operand" "=d")
3748         (match_operator:HI 3 "m68hc11_logical_operator"
3749                 [(zero_extend:HI
3750                      (match_operand:QI 1 "general_operand" "imud*A"))
3751                  (ashift:HI
3752                      (match_operand:HI 2 "general_operand" "imud*A")
3753                      (const_int 8))]))]
3754   ""
3755   "#"
3756   "z_replacement_completed == 2"
3757   [(set (reg:QI A_REGNUM) (match_dup 4))
3758    (set (reg:QI B_REGNUM) (match_dup 5))]
3759   "
3760    if (GET_CODE (operands[3]) == AND)
3761      {
3762        emit_insn (gen_movhi (operands[0], const0_rtx));
3763        DONE;
3764      }
3765    else
3766      {
3767        operands[5] = operands[1];
3768        if (D_REG_P (operands[2]))
3769          {
3770            operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3771          }
3772        else
3773          {
3774            operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3775          }
3776      }
3777   ")
3779 (define_insn_and_split "*logicalhi3_zexthi"
3780   [(set (match_operand:HI 0 "register_operand" "=d,d")
3781         (match_operator:HI 3 "m68hc11_logical_operator"
3782                 [(zero_extend:HI
3783                      (match_operand:QI 1 "general_operand" "imd*A,?u"))
3784                  (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3785   ""
3786   "#"
3787   "z_replacement_completed == 2"
3788   [(set (reg:QI B_REGNUM) (match_dup 6))
3789    (set (reg:QI A_REGNUM) (match_dup 4))
3790    (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3791   "
3792    PUT_MODE (operands[3], QImode);
3793    if (D_REG_P (operands[2]))
3794      {
3795        operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3796        operands[5] = operands[1];
3797        operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3798      }
3799    else
3800      {
3801        operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3802        operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3803        if (D_REG_P (operands[1]))
3804          operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3805        else
3806          operands[6] = operands[1];
3807      }
3808    /* For an AND, make sure the high 8-bit part is cleared.  */
3809    if (GET_CODE (operands[3]) == AND)
3810      {
3811        operands[4] = const0_rtx;
3812      }
3813   ")
3816 (define_insn_and_split "*logicalsi3_silshr16"
3817   [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
3818           (match_operator:SI 3 "m68hc11_logical_operator"
3819               [(lshiftrt:SI 
3820                    (match_operand:SI 1 "general_operand" "uim,uim,0,0")
3821                    (const_int 16))
3822                 (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
3823   ""
3824   "#"
3825   "reload_completed"
3826   [(set (reg:HI D_REGNUM) (match_dup 4))
3827    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3828    (set (reg:HI X_REGNUM) (match_dup 6))]
3829   "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3830    if (X_REG_P (operands[2]))
3831      {
3832        operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3833        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3834      }
3835    else
3836      {
3837        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3838        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3839      }
3840    PUT_MODE (operands[3], HImode);
3842    /* For an AND, make sure the high 16-bit part is cleared.  */
3843    if (GET_CODE (operands[3]) == AND)
3844      {
3845        operands[6] = const0_rtx;
3846      }
3849 (define_insn_and_split "*logicalsi3_silshl16"
3850   [(set (match_operand:SI 0 "register_operand" "=D,D")
3851           (match_operator:SI 3 "m68hc11_logical_operator"
3852               [(ashift:SI 
3853                    (match_operand:SI 1 "general_operand" "uim,?D")
3854                    (const_int 16))
3855                 (match_operand:SI 2 "general_operand" "0,0")]))]
3856   ""
3857   "#"
3858   "z_replacement_completed == 2"
3859   [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3860    (set (reg:HI D_REGNUM) (match_dup 5))]
3861   "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3862    PUT_MODE (operands[3], HImode);
3864    if (GET_CODE (operands[3]) == AND)
3865      operands[5] = const0_rtx;
3866    else
3867      operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3868    ")
3870 (define_insn_and_split "*logicalsi3_silshl16_zext"
3871   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3872           (match_operator:SI 3 "m68hc11_logical_operator"
3873               [(ashift:SI
3874                   (zero_extend:SI
3875                      (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
3876                   (const_int 16))
3877             (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
3878   ""
3879   "#"
3880   ;; Must split before z register replacement
3881   "reload_completed"
3882   [(set (match_dup 4) (match_dup 5))
3883    (set (match_dup 6) (match_dup 7))]
3884   "
3885     /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
3886    if (GET_CODE (operands[1]) == HARD_D_REGNUM
3887        && GET_CODE (operands[3]) != AND)
3888      {
3889        /* This particular case is too early to be split before
3890           Z register replacement because the cse-reg pass we do
3891           does not recognize the 'swap_areg'.  It is ok to handle
3892           this case after.  */
3893        if (z_replacement_completed != 2)
3894          {
3895            FAIL;
3896          }
3897        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
3898        emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
3899                                  gen_rtx_REG (HImode, HARD_X_REGNUM)));
3900      }
3901    operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3902    operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3903    operands[5] = operands[2];
3904    operands[7] = operands[1];
3906    if (GET_CODE (operands[3]) == AND)
3907      operands[5] = operands[7] = const0_rtx;
3908    ")
3910 ;;--------------------------------------------------------------------
3911 ;; 16-bit Arithmetic and logical operations on X and Y:
3913 ;;      PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3915 ;; Operations on X or Y registers are split here.  Instructions are
3916 ;; changed into:
3917 ;;   - xgdx/xgdy instruction pattern,
3918 ;;   - The same operation on register D,
3919 ;;   - xgdx/xgdy instruction pattern.
3920 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3921 ;; We also handle the case were the address register is used in both source
3922 ;; operands, such as:
3924 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3925 ;; or
3926 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3929 (define_split
3930   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3931         (match_operator:HI 3 "m68hc11_arith_operator"
3932             [(match_operand:HI 1 "hard_addr_reg_operand" "")
3933              (match_operand:HI 2 "general_operand" "")]))]
3934   "z_replacement_completed == 2
3935    /* If we are adding a small constant to X or Y, it's
3936      better to use one or several inx/iny instructions.  */
3937    && !(GET_CODE (operands[3]) == PLUS 
3938         && ((TARGET_M6812 
3939              && (immediate_operand (operands[2], HImode)
3940                  || hard_reg_operand (operands[2], HImode)))
3941             || (GET_CODE (operands[2]) == CONST_INT
3942                 && INTVAL (operands[2]) >= -4
3943                 && INTVAL (operands[2]) <= 4)))"
3944   [(set (match_dup 9) (match_dup 0))
3945    (set (match_dup 4) (match_dup 5))
3946    (set (match_dup 8) (match_dup 7))
3947    (set (match_dup 0) (match_dup 1))
3948    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3949               (set (match_dup 0) (reg:HI D_REGNUM))])
3950    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3951    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3952               (set (match_dup 0) (reg:HI D_REGNUM))])]
3953   "
3954    operands[9] = operands[0];
3955    /* For 68HC12, push the value on the stack and do the operation
3956       with a pop.  */
3957    if (TARGET_M6812
3958        && m68hc11_non_shift_operator (operands[3], HImode)
3959        && (H_REG_P (operands[2])
3960            || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3961                && reg_mentioned_p (operands[0], operands[2]))))
3962      {
3963        operands[4] = gen_rtx_MEM (HImode,
3964                               gen_rtx_PRE_DEC (HImode,
3965                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3966        operands[6] = gen_rtx_MEM (HImode,
3967                               gen_rtx_POST_INC (HImode,
3968                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3969        operands[5] = operands[2];
3970        operands[8] = operands[7] = operands[0];
3971      }
3972    /* Save the operand2 in a temporary location and use it.  */
3973    else if ((H_REG_P (operands[2])
3974              || reg_mentioned_p  (operands[0], operands[2]))
3975             && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3976      {
3977        if (GET_CODE (operands[3]) == MINUS
3978            && reg_mentioned_p (operands[0], operands[2]))
3979          {
3980            operands[9] = gen_rtx_MEM (HImode,
3981                               gen_rtx_PRE_DEC (HImode,
3982                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3983            operands[1] = gen_rtx_MEM (HImode,
3984                               gen_rtx_POST_INC (HImode,
3985                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3986            operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3987            operands[4] = operands[7] = operands[0];
3988            operands[6] = operands[8];
3989            operands[5] = operands[2];
3990          }
3991        else 
3992          {
3993        operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3994        operands[6] = operands[4];
3995        if (!H_REG_P (operands[2]))
3996          {
3997            operands[5] = operands[0];
3998            operands[7] = operands[2];
3999            operands[8] = operands[0];
4000          }
4001        else
4002          {
4003            operands[5] = operands[2];
4004            operands[8] = operands[7] = operands[0];
4005          }
4006          }
4007      }
4008    else
4009      {
4010        operands[4] = operands[5] = operands[0];
4011        operands[6] = operands[2];
4012        operands[8] = operands[7] = operands[0];
4013      }
4014    ")
4016 (define_split
4017   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4018         (match_operator:HI 3 "m68hc11_arith_operator"
4019             [(match_operand:HI 1 "general_operand" "")
4020              (match_operand:HI 2 "general_operand" "")]))]
4021   "z_replacement_completed == 2
4022    /* If we are adding a small constant to X or Y, it's
4023      better to use one or several inx/iny instructions.  */
4024    && !(GET_CODE (operands[3]) == PLUS 
4025         && ((TARGET_M6812 
4026             && (immediate_operand (operands[2], HImode)
4027                 || hard_reg_operand (operands[2], HImode)))
4028             || (GET_CODE (operands[2]) == CONST_INT
4029                 && INTVAL (operands[2]) >= -4
4030                 && INTVAL (operands[2]) <= 4)))"
4031   [(set (match_dup 0) (match_dup 1))
4032    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4033               (set (match_dup 0) (reg:HI D_REGNUM))])
4034    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
4035    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4036               (set (match_dup 0) (reg:HI D_REGNUM))])]
4037   "
4038    ")
4041 ;; Next split handles the logical operations on D register with
4042 ;; another hard register for the second operand.  For this, we
4043 ;; have to save the second operand in a scratch location and use
4044 ;; it instead.  This must be supported because in some (rare) cases
4045 ;; the second operand can come in a hard register and the reload
4046 ;; pass doesn't know how to reload it in a memory location.
4048 ;;      PLUS MINUS AND IOR XOR
4050 ;; The shift operators are special and must not appear here.
4052 (define_split
4053   [(set (match_operand:HI 0 "d_register_operand" "")
4054         (match_operator:HI 3 "m68hc11_non_shift_operator"
4055             [(match_operand:HI 1 "d_register_operand" "")
4056              (match_operand:HI 2 "hard_reg_operand" "")]))]
4057   "TARGET_M6811
4058    && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4059   [(set (match_dup 4) (match_dup 2))
4060    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4061   "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
4064 ;; For 68HC12, push the operand[2] value on the stack and do the
4065 ;; logical/arithmetic operation with a pop.
4067 (define_split
4068   [(set (match_operand:HI 0 "d_register_operand" "")
4069         (match_operator:HI 3 "m68hc11_non_shift_operator"
4070             [(match_operand:HI 1 "d_register_operand" "")
4071              (match_operand:HI 2 "hard_reg_operand" "")]))]
4072   "TARGET_M6812
4073    && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4074   [(set (match_dup 4) (match_dup 2))
4075    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4076   "operands[4] = gen_rtx_MEM (HImode,
4077                           gen_rtx_PRE_DEC (HImode,
4078                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4079    operands[5] = gen_rtx_MEM (HImode,
4080                           gen_rtx_POST_INC (HImode,
4081                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4082    ")
4084 ;;--------------------------------------------------------------------
4085 ;; 16-bit Unary operations on X and Y:
4087 ;;              NOT NEG
4089 ;; Operations on X or Y registers are split here.  Instructions are
4090 ;; changed into:
4091 ;;   - xgdx/xgdy instruction pattern,
4092 ;;   - The same operation on register D,
4093 ;;   - xgdx/xgdy instruction pattern.
4094 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4095 ;; We also handle the case were the address register is used in both source
4096 ;; operands, such as:
4098 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4099 ;; or
4100 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4102 (define_split
4103   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4104         (match_operator:HI 2 "m68hc11_unary_operator"
4105             [(match_operand 1 "general_operand" "")]))]
4106   "z_replacement_completed == 2"
4107   [(set (match_dup 4) (match_dup 5))
4108    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4109               (set (match_dup 0) (reg:HI D_REGNUM))])
4110    (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4111    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4112               (set (match_dup 0) (reg:HI D_REGNUM))])]
4113   "
4115   if ((H_REG_P (operands[1])
4116        && !rtx_equal_p (operands[0], operands[1]))
4117       || reg_mentioned_p (operands[0], operands[1]))
4118     {
4119       /* Move to the destination register, before the xgdx.  */
4120       operands[4] = gen_rtx_REG (GET_MODE (operands[1]), 
4121                              REGNO (operands[0]));
4122       operands[5] = operands[1];
4124       /* Apply the operation on D.  */
4125       operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
4126     }
4127   else
4128     {
4129       /* Generate a copy to same register (nop).  */
4130       operands[4] = operands[5] = operands[0];
4131       operands[3] = operands[1];
4132     }
4136 ;; 8-bit operations on address registers.
4138 ;; We have to take care that the address register is not used for the
4139 ;; source of operand2. If operand2 is the D register, we have to save
4140 ;; that register in a temporary location.
4142 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4144 (define_split
4145   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4146         (match_operator:QI 3 "m68hc11_arith_operator"
4147             [(match_operand:QI 1 "hard_addr_reg_operand" "")
4148              (match_operand:QI 2 "general_operand" "")]))]
4149   "z_replacement_completed == 2
4150    /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
4151       incqi pattern generates a better code.  */
4152    && !(GET_CODE (operands[3]) == PLUS
4153         && GET_CODE (operands[2]) == CONST_INT
4154         && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4155   [(set (match_dup 5) (match_dup 6))
4156    (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4157               (set (match_dup 4) (reg:HI D_REGNUM))])
4158    (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4159    (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4160               (set (match_dup 4) (reg:HI D_REGNUM))])]
4161   "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
4163    /* For the second operand is a hard register or if the address
4164       register appears in the source, we have to save the operand[2]
4165       value in a temporary location and then use that temp.
4166       Otherwise, it's ok and we generate a (set (D) (D)) that
4167       will result in a nop.  */
4168    if (H_REG_P (operands[2]))
4169      {
4170        operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4171        operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
4172        operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4173      }
4174    else if (reg_mentioned_p (operands[0], operands[2]))
4175      {
4176        operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4177        operands[6] = operands[2];
4178        operands[7] = operands[5];
4179      }
4180    else
4181      {
4182        operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4183        operands[7] = operands[2];
4184      }
4185   ")
4188 ;; Next split handles the logical operations on D register with
4189 ;; another hard register for the second operand.  For this, we
4190 ;; have to save the second operand in a scratch location and use
4191 ;; it instead.  This must be supported because in some (rare) cases
4192 ;; the second operand can come in a hard register and the reload
4193 ;; pass doesn't know how to reload it in a memory location.
4195 ;;      PLUS MINUS AND IOR XOR
4197 ;; The shift operators are special and must not appear here.
4199 (define_split
4200   [(set (match_operand:QI 0 "d_register_operand" "")
4201         (match_operator:QI 3 "m68hc11_non_shift_operator"
4202             [(match_operand:QI 1 "d_register_operand" "")
4203              (match_operand:QI 2 "hard_reg_operand" "")]))]
4204   "reload_completed"
4205   [(set (match_dup 5) (match_dup 6))
4206    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4207   "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4208    operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4209    operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
4211 ;;--------------------------------------------------------------------
4212 ;; 8-bit Unary operations on X and Y:
4214 ;;              NOT NEG
4216 ;; Operations on X or Y registers are split here.  Instructions are
4217 ;; changed into:
4218 ;;   - xgdx/xgdy instruction pattern,
4219 ;;   - The same operation on register D,
4220 ;;   - xgdx/xgdy instruction pattern.
4221 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4222 ;; We also handle the case were the address register is used in both source
4223 ;; operands, such as:
4225 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4226 ;; or
4227 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4229 (define_split
4230   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4231         (match_operator:QI 2 "m68hc11_unary_operator"
4232             [(match_operand:QI 1 "general_operand" "")]))]
4233   "z_replacement_completed == 2"
4234   [(set (match_dup 4) (match_dup 5))
4235    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4236               (set (match_dup 3) (reg:HI D_REGNUM))])
4237    (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4238    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4239               (set (match_dup 3) (reg:HI D_REGNUM))])]
4240   "
4242   operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4243   if ((H_REG_P (operands[1])
4244        && !rtx_equal_p (operands[0], operands[1]))
4245       || reg_mentioned_p (operands[0], operands[1]))
4246     {
4247       /* Move to the destination register, before the xgdx.  */
4248       operands[4] = operands[0];
4249       operands[5] = operands[1];
4251       /* Apply the operation on D.  */
4252       operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4253     }
4254   else
4255     {
4256       operands[4] = operands[5] = operands[0];
4257       operands[6] = operands[1];
4258     }
4262 ;;--------------------------------------------------------------------
4263 ;;-  Complements
4264 ;;--------------------------------------------------------------------
4266 (define_expand "negdi2"
4267   [(set (match_operand:DI 0 "nonimmediate_operand" "")
4268         (neg:DI (match_operand:DI 1 "general_operand" "")))]
4269   ""
4270   "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4271    DONE;")
4274 (define_insn "negsi2"
4275   [(set (match_operand:SI 0 "register_operand" "=D")
4276         (neg:SI (match_operand:SI 1 "general_operand" "0")))]
4277   ""
4278   "*
4280   rtx ops[1];
4282   CC_STATUS_INIT;
4284   /* With -Os or without -O, use a special library call.  */
4285   if (optimize_size || optimize == 0)
4286     return \"bsr\\t___negsi2\";
4288   ops[0] = gen_label_rtx ();
4290   /* 32-bit complement and add 1.  */
4291   output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4292   output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4293   output_asm_insn (\"bne\\t%l0\", ops);
4294   output_asm_insn (\"inx\", operands);
4295   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4296   return \"\";
4299 (define_insn "neghi2"
4300   [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
4301         (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4302   ""
4303   "@
4304    coma\\n\\tcomb\\n\\taddd\\t#1
4305    clra\\n\\tclrb\\n\\tsubd\\t%1
4306    xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4308 (define_insn "negqi2"
4309   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4310         (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
4311   ""
4312   "@
4313    negb
4314    neg\\t%b0
4315    neg\\t%b0
4316    #")
4319 ;; - 32-bit complement.  GCC knows how to translate them but providing a
4320 ;; pattern generates better/smaller code.
4322 (define_expand "one_cmpldi2"
4323   [(set (match_operand:DI 0 "nonimmediate_operand" "")
4324         (not:DI (match_operand:DI 1 "general_operand" "")))]
4325   ""
4326   "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4327    DONE;")
4329 (define_insn "one_cmplsi2"
4330   [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4331         (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4332    (clobber (match_scratch:HI 2 "=X,d,X"))]
4333   ""
4334   "@
4335    bsr\\t___one_cmplsi2
4336    #
4337    #")
4339 (define_insn "one_cmplhi2"
4340   [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
4341         (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
4342   ""
4343   "@
4344    comb\\n\\tcoma
4345    com\\t%b0\\n\\tcom\\t%h0
4346    #
4347    com\\t%b0\\n\\tcom\\t%h0")
4349 (define_insn "one_cmplqi2"
4350   [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
4351         (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
4352   ""
4353   "@
4354    comb
4355    com\\t%b0
4356    #
4357    com\\t%b0")
4359 (define_split /* "*one_cmplsi2" */
4360   [(set (match_operand:SI 0 "non_push_operand" "")
4361         (not:SI (match_dup 0)))
4362    (clobber (match_scratch:HI 1 ""))]
4363   "z_replacement_completed == 2
4364    && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4365   [(set (match_dup 2) (not:HI (match_dup 2)))
4366    (set (match_dup 3) (not:HI (match_dup 3)))]
4367   "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4368    operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
4370 (define_split /* "*one_cmplsi2" */
4371   [(set (match_operand:SI 0 "non_push_operand" "")
4372         (not:SI (match_operand:SI 1 "non_push_operand" "")))
4373    (clobber (match_operand:HI 2 "d_register_operand" ""))]
4374   "z_replacement_completed == 2
4375    && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4376   [(set (match_dup 2) (match_dup 3))
4377    (set (match_dup 2) (not:HI (match_dup 2)))
4378    (set (match_dup 4) (match_dup 2))
4379    (set (match_dup 2) (match_dup 5))
4380    (set (match_dup 2) (not:HI (match_dup 2)))
4381    (set (match_dup 6) (match_dup 2))]
4382   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4383    operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4384    operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4385    operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
4387 ;;--------------------------------------------------------------------
4388 ;;- arithmetic shifts
4389 ;;--------------------------------------------------------------------
4391 ;; Provide some 64-bit shift patterns. 
4392 (define_expand "ashldi3"
4393   [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4394                      (ashift:DI (match_operand:DI 1 "general_operand" "")
4395                                 (match_operand:HI 2 "general_operand" "")))
4396               (clobber (match_scratch:HI 3 ""))])]
4397    ""
4398    "
4400   if (GET_CODE (operands[2]) != CONST_INT 
4401       || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4402     {
4403       FAIL;
4404     }
4407 (define_insn_and_split "*ashldi3_const32"
4408   [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4409         (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4410                    (const_int 32)))
4411    (clobber (match_scratch:HI 2 "=&A,d,d"))]
4412    ""
4413    "#"
4414    "reload_completed"
4415    [(const_int 0)]
4416    "/* Move the lowpart in the highpart first in case the shift
4417        is applied on the source.  */
4418     if (IS_STACK_PUSH (operands[0]))
4419       {
4420          m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4421                              const0_rtx, operands[2]);
4423          /* Adjust first operand if it uses SP so that we take into
4424             account the above push.  Can occur only for 68HC12.  */
4425          if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
4426                               operands[1]))
4427            operands[1] = adjust_address (operands[1],
4428                                          GET_MODE (operands[0]), 4);
4429       }
4430     m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4431                         m68hc11_gen_lowpart (SImode, operands[1]),
4432                         operands[2]);
4433     if (!IS_STACK_PUSH (operands[0]))
4434       {
4435         m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4436                             const0_rtx, operands[2]);
4437       }
4438     DONE;")
4440 (define_insn_and_split "*ashldi3_const1"
4441   [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4442         (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4443                    (const_int 1)))
4444    (clobber (match_scratch:HI 2 "=d,d,d"))]
4445    ""
4446    "#"
4447    "z_replacement_completed == 2"
4448    [(set (match_dup 2) (match_dup 3))
4449     (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4450     (set (match_dup 4) (match_dup 2))
4452     (set (match_dup 2) (match_dup 5))
4453     (parallel [(set (match_dup 2)
4454                        (rotate:HI (match_dup 2) (const_int 1)))
4455                (clobber (reg:HI CC_REGNUM))])
4456     (set (match_dup 6) (match_dup 2))
4458     (set (match_dup 2) (match_dup 7))
4459     (parallel [(set (match_dup 2)
4460                        (rotate:HI (match_dup 2) (const_int 1)))
4461                (clobber (reg:HI CC_REGNUM))])
4462     (set (match_dup 8) (match_dup 2))
4464     (set (match_dup 2) (match_dup 9))
4465     (parallel [(set (match_dup 2)
4466                        (rotate:HI (match_dup 2) (const_int 1)))
4467                (clobber (reg:HI CC_REGNUM))])
4468     (set (match_dup 10) (match_dup 2))]
4469    "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4470     operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4471     operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4473     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4474     operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4475     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4477     operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4478     operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4479     operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4481     operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4482     operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4483     operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4485 (define_insn "addsi_silshr16"
4486   [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
4487           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
4488                                 (const_int 16))
4489                    (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
4490   ""
4491   "#")
4493 (define_split
4494   [(set (match_operand:SI 0 "register_operand" "")
4495           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4496                                 (const_int 16))
4497                    (match_operand:SI 2 "general_operand" "")))]
4498   "z_replacement_completed == 2 && !X_REG_P (operands[1])"
4499   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4500    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4501                                             (const_int 0))
4502                                    (reg:HI CC_REGNUM)))]
4503   "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4505 (define_split
4506   [(set (match_operand:SI 0 "register_operand" "")
4507           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4508                                 (const_int 16))
4509                    (match_operand:SI 2 "general_operand" "")))]
4510   "z_replacement_completed == 2 && X_REG_P (operands[1])"
4511   [(set (reg:HI D_REGNUM) (match_dup 5))
4512    (set (reg:HI X_REGNUM) (match_dup 3))
4513    (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4514    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4515                                             (const_int 0))
4516                                    (reg:HI CC_REGNUM)))]
4517   "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4518    if (X_REG_P (operands[2]))
4519      {
4520        operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4521        operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4522      }
4523    else
4524      {
4525        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4526        operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4527      }
4530 (define_insn "addsi_ashift16"
4531   [(set (match_operand:SI 0 "register_operand" "=D")
4532           (plus:SI 
4533                    (mult:SI (match_operand:SI 2 "general_operand" "uim")
4534                             (const_int 65536))
4535                 (match_operand:SI 1 "general_operand" "0")))
4536    (clobber (match_scratch:HI 3 "=X"))]
4537   "0"
4538   "#")
4540 (define_split
4541   [(set (match_operand:SI 0 "register_operand" "")
4542           (plus:SI 
4543                    (mult:SI (match_operand:SI 2 "general_operand" "")
4544                             (const_int 65536))
4545                    (match_operand:SI 1 "general_operand" "")))
4546    (clobber (match_scratch:HI 3 "=X"))]
4547   "0 && reload_completed && z_replacement_completed == 2"
4548   [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4549   "
4551   operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4554 (define_insn_and_split "addsi_andshr16"
4555   [(set (match_operand:SI 0 "register_operand" "=D")
4556           (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4557                            (const_int 65535))
4558                    (match_operand:SI 2 "general_operand" "0")))]
4559   ""
4560   "#"
4561   "z_replacement_completed == 2"
4562   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4563    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4564   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4567 ;; 32-bit shifts are made by a small library routine that uses
4568 ;; a specific passing convention for parameters (for efficiency reasons).
4570 ;; [D + X] -> Value to be shifted
4571 ;; Y       -> Shift count
4573 ;; The shift count is clobbered by the routine.
4575 (define_expand "ashlsi3"
4576   [(parallel
4577        [(set (match_operand:SI 0 "register_operand" "") 
4578              (match_operand:SI 1 "general_operand" ""))
4579         (clobber (scratch:HI))])
4580    (parallel
4581      [(set (match_dup 0) (ashift:SI (match_dup 0)
4582                          (match_operand:HI 2 "nonmemory_operand" "")))
4583       (clobber (scratch:HI))])]
4584    ""
4585    "")
4587 (define_split
4588   [(set (match_operand:SI 0 "nonimmediate_operand" "")
4589         (ashift:SI (match_operand:SI 1 "general_operand" "")
4590                    (const_int 16)))
4591    (clobber (match_scratch:HI 3 ""))]
4592    ""
4593   [(set (match_dup 2) (match_dup 3))
4594    (set (match_dup 4) (const_int 0))]
4595    "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4596     operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4597     operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4599 (define_insn "*ashlsi3_const16"
4600   [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4601         (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4602                    (const_int 16)))
4603    (clobber (match_scratch:HI 2 "=X,X,X"))]
4604    ""
4605    "#")
4607 (define_insn_and_split "*ashlsi3_const16_zexthi"
4608   [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4609         (ashift:SI (zero_extend:HI 
4610                         (match_operand:HI 1 "general_operand" "duim*A"))
4611                    (const_int 16)))
4612    (clobber (match_scratch:HI 2 "=X"))]
4613    ""
4614    "#"
4615    "reload_completed"
4616    [(set (reg:HI X_REGNUM) (match_dup 1))
4617     (set (reg:HI D_REGNUM) (const_int 0))]
4618    "")
4620 (define_insn "*ashlsi3_const1"
4621   [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
4622         (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
4623                    (const_int 1)))
4624    (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
4625    ""
4626    "*
4628   CC_STATUS_INIT;
4629   if (X_REG_P (operands[1]))
4630     {
4631       return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4632     }
4633   else
4634     {
4635       rtx ops[2];
4637       ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4638       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4639       m68hc11_gen_movhi (insn, ops);
4640       output_asm_insn (\"lsld\", ops);
4641       if (!X_REG_P (operands[0]))
4642         {
4643           ops[1] = ops[0];
4644           ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4645           m68hc11_gen_movhi (insn, ops);
4646           ops[0] = ops[1];
4647           ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4648           m68hc11_gen_movhi (insn, ops);
4649         }
4650       else
4651         {
4652           /* Load the high part in X in case the source operand
4653              uses X as a memory pointer.  */
4654           ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4655           ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4656           m68hc11_gen_movhi (insn, ops);
4657           output_asm_insn (\"xgdx\", ops);
4658         }
4659       output_asm_insn (\"rolb\", ops);
4660       output_asm_insn (\"rola\", ops);
4661       if (!X_REG_P (operands[0]))
4662         {
4663           ops[1] = ops[0];
4664           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4665           m68hc11_gen_movhi (insn, ops);
4666         }
4667       else
4668         {
4669           output_asm_insn (\"xgdx\", ops);
4670         }
4671       return \"\";
4672     }
4675 (define_insn "*ashlsi3_const"
4676   [(set (match_operand:SI 0 "register_operand" "+D")
4677         (ashift:SI (match_dup 0)
4678                    (match_operand:HI 1 "const_int_operand" "")))
4679    (clobber (match_scratch:HI 2 "=y"))]
4680    "TARGET_M6811 /* See *ashlsi3 note.  */"
4681    "*
4683   CC_STATUS_INIT;
4684   return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4687 (define_insn "*ashlsi3"
4688   [(set (match_operand:SI 0 "register_operand" "+D,D")
4689         (ashift:SI (match_dup 0)
4690                    (match_operand:HI 1 "general_operand" "y,mi")))
4691    (clobber (match_scratch:HI 2 "=1,X"))]
4692    ""
4693    "*
4695   CC_STATUS_INIT;
4697   /* There is a reload problem if we don't accept 'm' for the shift value.
4698      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4699      and this conflicts with all reloads.  Since X, Y, Z are used there
4700      is not enough register in class A_REGS.
4702      Assuming that 'operands[1]' does not refer to the stack (which 
4703      is true for 68hc11 only, we save temporary the value of Y.
4705      For 68HC12 we must also accept a constant because Z register is
4706      disabled when compiling with -fomit-frame-pointer.  We can come up
4707      with a reload problem and the *lshrsi3_const pattern was disabled
4708      for that reason.  */
4709   if (!Y_REG_P (operands[2]))
4710     {
4711       rtx ops[1];
4712       int y_dead = dead_register_here (insn, iy_reg);
4714       ops[0] = operands[1];
4715       if (y_dead == 0)
4716         {
4717           output_asm_insn (\"pshy\", operands);
4718           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4719             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4720         }
4721       output_asm_insn (\"ldy\\t%0\", ops);
4722       output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4723       return y_dead == 0 ? \"puly\" : \"\";
4724     }
4725   return \"bsr\\t___ashlsi3\";
4728 (define_expand "ashlhi3"
4729   [(set (match_operand:HI 0 "register_operand" "")
4730         (ashift:HI (match_operand:HI 1 "register_operand" "")
4731                    (match_operand:HI 2 "general_operand" "")))]
4732    ""
4733    "
4735   if (GET_CODE (operands[2]) != CONST_INT) 
4736     {
4737       rtx scratch = gen_reg_rtx (HImode);
4738       emit_move_insn (scratch, operands[2]);
4739       emit_insn (gen_rtx_PARALLEL (VOIDmode,
4740                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
4741                             operand0,
4742                             gen_rtx_ASHIFT (HImode,
4743                                         operand1, scratch)),
4744                               gen_rtx_CLOBBER (VOIDmode, scratch))));
4745       DONE;
4746     }
4749 (define_insn "*ashlhi3_const1"
4750   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4751         (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4752                    (const_int 1)))]
4753   ""
4754   "*
4756   if (A_REG_P (operands[0]))
4757     return \"#\";
4759   if (D_REG_P (operands[0]))
4760     {
4761       return \"asld\";
4762     }
4763   
4764   output_asm_insn (\"asl\\t%b0\", operands);
4765   output_asm_insn (\"rol\\t%h0\", operands);
4766   CC_STATUS_INIT;
4767   return \"\";
4771 (define_insn "*ashlhi3_2"
4772   [(set (match_operand:HI 0 "register_operand" "=d,*x")
4773         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4774                    (match_operand:HI 2 "register_operand" "+x,+d")))
4775    (clobber (match_dup 2))]
4776   ""
4777   "*
4779   if (A_REG_P (operands[0]))
4780     return \"#\";
4782   CC_STATUS_INIT;
4783   return \"bsr\\t___lshlhi3\";
4786 (define_insn "*ashlhi3"
4787   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4788         (ashift:HI (match_dup 0)
4789                    (match_operand:HI 1 "register_operand" "+x")))
4790    (clobber (match_dup 1))]
4791   ""
4792   "*
4794   CC_STATUS_INIT;
4795   return \"bsr\\t___lshlhi3\";
4798 (define_insn "*ashlhi3"
4799   [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4800         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4801                    (match_operand:HI 2 "const_int_operand" "")))]
4802   ""
4803   "*
4805   int   i;
4807   if (A_REG_P (operands[0]))
4808     return \"#\";
4810   i = INTVAL (operands[2]);
4811   if (i >= 8)
4812     {
4813       CC_STATUS_INIT;
4814       output_asm_insn (\"tba\", operands);
4815       if (i == 15)
4816         {
4817           output_asm_insn (\"rora\", operands);
4818           output_asm_insn (\"anda\\t#0\", operands);
4819           output_asm_insn (\"rora\", operands);
4820         }
4821       else
4822         while (i != 8 )
4823           {
4824             output_asm_insn (\"asla\", operands);
4825             i--;
4826           }
4827       return \"clrb\";
4828     }
4829   for (i = 0; i < INTVAL (operands[2]) - 1; i++) 
4830     {
4831       output_asm_insn (\"asld\", operands);
4832     }
4833   return \"asld\";
4836 (define_expand "ashlqi3"
4837   [(set (match_operand:QI 0 "register_operand" "")
4838         (ashift:QI (match_operand:QI 1 "register_operand" "")
4839                    (match_operand:QI 2 "general_operand" "")))]
4840    ""
4841    "")
4843 (define_insn "*ashlqi3_const1"
4844   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4845         (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4846                    (const_int 1)))]
4847   ""
4848   "@
4849    aslb
4850    asl\\t%b0
4851    asl\\t%b0
4852    asl%0
4853    #")
4855 (define_insn "*ashlqi3_const"
4856   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4857         (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4858                    (match_operand:QI 2 "const_int_operand" "")))]
4859   ""
4860   "*
4862   int i;
4863   const char* insn_code;
4865   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4866     insn_code = \"aslb\";
4867   else if (DA_REG_P (operands[0]))
4868     insn_code = \"asla\";
4869   else
4870     return \"#\";
4872   i = INTVAL (operands[2]);
4873   if (i >= 8)
4874     {
4875       if (DA_REG_P (operands[0]))
4876         return \"clra\";
4877       else
4878         return \"clrb\";
4879     }
4880   else if (i == 7)
4881     {
4882       if (DA_REG_P (operands[0]))
4883         {
4884           output_asm_insn (\"rora\", operands);
4885           output_asm_insn (\"ldaa\\t#0\", operands);
4886           return \"rora\";
4887         }
4888       else
4889         {
4890           output_asm_insn (\"rorb\", operands);
4891           output_asm_insn (\"ldab\\t#0\", operands);
4892           return \"rorb\";
4893         }
4894     }
4895   else if (i == 6)
4896     {
4897       if (DA_REG_P (operands[0]))
4898         {
4899           output_asm_insn (\"rora\", operands);
4900           output_asm_insn (\"rora\", operands);
4901           output_asm_insn (\"rora\", operands);
4902           return \"anda\\t#0xC0\";
4903         }
4904       else
4905         {
4906           output_asm_insn (\"rorb\", operands);
4907           output_asm_insn (\"rorb\", operands);
4908           output_asm_insn (\"rorb\", operands);
4909           return \"andb\\t#0xC0\";
4910         }
4911     }
4912   while (--i >= 0)
4913     {
4914       output_asm_insn (insn_code, operands);
4915     }
4916   return \"\";
4919 (define_insn "*ashlqi3"
4920   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4921         (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4922                      (match_operand:QI 2 "nonimmediate_operand" 
4923                                          "m*u*d*A,m*u*d*A,m*u")))]
4924   ""
4925   "*
4927   rtx ops[2];
4929   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4930     return \"#\";
4932   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
4933   ops[1] = operands[2];
4934   m68hc11_gen_movqi (insn, ops);
4936   CC_STATUS_INIT;
4937   return \"bsr\\t___lshlqi3\";
4940 (define_expand "ashrhi3"
4941   [(set (match_operand:HI 0 "register_operand" "")
4942         (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4943                      (match_operand:HI 2 "general_operand" "")))]
4944    ""
4945    "
4947   if (GET_CODE (operands[2]) != CONST_INT) 
4948     {
4949       rtx scratch = gen_reg_rtx (HImode);
4951       emit_move_insn (scratch, operands[2]);
4952       emit_insn (gen_rtx_PARALLEL (VOIDmode,
4953                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
4954                                 operand0,
4955                                 gen_rtx_ASHIFTRT (HImode,
4956                                         operand1, scratch)),
4957                               gen_rtx_CLOBBER (VOIDmode, scratch))));
4958        DONE;
4959     }
4962 (define_insn "*ashrhi3_const1"
4963   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4964         (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4965                      (const_int 1)))]
4966   ""
4967   "*
4969   if (A_REG_P (operands[0]))
4970     return \"#\";
4972   CC_STATUS_INIT;
4973   if (D_REG_P (operands[0]))
4974     {
4975       return \"asra\\n\\trorb\";
4976     }
4977   
4978   output_asm_insn (\"asr\\t%h0\", operands);
4979   output_asm_insn (\"ror\\t%b0\", operands);
4980   return \"\";
4984 (define_insn "*ashrhi3_const"
4985   [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4986         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4987                      (match_operand:HI 2 "const_int_operand" "")))]
4988   ""
4989   "*
4991   rtx ops[2];
4992   int val = INTVAL (operands[2]);
4994   if (A_REG_P (operands[0]))
4995     return \"#\";
4997   if (val >= 15)
4998     {
4999       ops[0] = gen_label_rtx ();
5001       output_asm_insn (\"clrb\", operands);
5002       output_asm_insn (\"rola\", operands);
5004         /* Clear A without clearing the carry flag.  */
5005       output_asm_insn (\"tba\", operands);
5006       output_asm_insn (\"bcc\\t%l0\", ops);
5007       output_asm_insn (\"coma\", operands);
5008       output_asm_insn (\"comb\", operands);
5010       CC_STATUS_INIT;
5011       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5012                                  CODE_LABEL_NUMBER (ops[0]));
5013       return \"\";
5014     }
5015   if (val >= 8)
5016     {
5017       ops[0] = gen_label_rtx ();
5019       output_asm_insn (\"tab\", operands);
5020       output_asm_insn (\"clra\", operands);
5021       output_asm_insn (\"tstb\", operands);
5022       output_asm_insn (\"bge\\t%l0\", ops);
5023       output_asm_insn (\"deca\", operands);
5025       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5026                                  CODE_LABEL_NUMBER (ops[0]));
5028       val -= 8;
5030       while (val > 0)
5031         {
5032           output_asm_insn (\"asrb\", operands);
5033           val--;
5034         }
5035         /* Status is ok.  */
5036       return \"\";
5037     }
5038   if (val == 7)
5039     {
5040       ops[0] = gen_label_rtx ();
5041       output_asm_insn (\"rolb\", operands);
5042       output_asm_insn (\"rola\", operands);
5043       output_asm_insn (\"tab\", operands);
5044       output_asm_insn (\"anda\\t#0\", operands);
5045       output_asm_insn (\"bcc\\t%l0\", ops);
5046       output_asm_insn (\"coma\", ops);
5048       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5049                                  CODE_LABEL_NUMBER (ops[0]));
5050       return \"\";
5051     }
5052   while (val > 0)
5053     {
5054       output_asm_insn (\"asra\", operands);
5055       output_asm_insn (\"rorb\", operands);
5056       val--;
5057     }
5058   CC_STATUS_INIT;
5060   return \"\";
5063 (define_insn "*ashrhi3"
5064   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5065         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5066                      (match_operand:HI 2 "register_operand" "+x,+d")))
5067    (clobber (match_dup 2))]
5068   ""
5069   "*
5071   if (A_REG_P (operands[0]))
5072     return \"#\";
5074   output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5075   return \"\"; 
5078 (define_expand "ashrsi3"
5079   [(parallel
5080        [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5081         (clobber (scratch:HI))])
5082    (parallel
5083        [(set (match_operand:SI 0 "register_operand" "")
5084                 (ashiftrt:SI (match_dup 0)
5085                              (match_operand:HI 2 "general_operand" "")))
5086         (clobber (scratch:HI))])]
5087    ""
5088    "")
5090 (define_insn "*ashrsi3_const"
5091   [(set (match_operand:SI 0 "register_operand" "+D")
5092         (ashiftrt:SI (match_dup 0)
5093                      (match_operand:HI 1 "const_int_operand" "")))
5094    (clobber (match_scratch:HI 2 "=y"))]
5095    "TARGET_M6811 /* See *ashrsi3 note.  */"
5096    "*
5098   CC_STATUS_INIT;
5099   return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
5102 (define_insn "*ashrsi3"
5103   [(set (match_operand:SI 0 "register_operand" "+D,D")
5104         (ashiftrt:SI (match_dup 0)
5105                      (match_operand:HI 1 "general_operand" "y,mi")))
5106    (clobber (match_scratch:HI 2 "=1,X"))]
5107    ""
5108    "*
5110   CC_STATUS_INIT;
5111   /* There is a reload problem if we don't accept 'm' for the shift value.
5112      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5113      and this conflicts with all reloads.  Since X, Y, Z are used there
5114      is not enough register in class A_REGS.
5116      Assuming that 'operands[1]' does not refer to the stack (which 
5117      is true for 68hc11 only, we save temporary the value of Y.
5119      For 68HC12 we must also accept a constant because Z register is
5120      disabled when compiling with -fomit-frame-pointer.  We can come up
5121      with a reload problem and the *lshrsi3_const pattern was disabled
5122      for that reason.  */
5123   if (!Y_REG_P (operands[2]))
5124     {
5125       rtx ops[1];
5126       int y_dead = dead_register_here (insn, iy_reg);
5128       ops[0] = operands[1];
5129       if (y_dead == 0)
5130         {
5131           output_asm_insn (\"pshy\", operands);
5132           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5133             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5134         }
5135       output_asm_insn (\"ldy\\t%0\", ops);
5136       output_asm_insn (\"bsr\\t___ashrsi3\", operands);
5137       return y_dead == 0 ? \"puly\" : \"\";
5138     }
5139   return \"bsr\\t___ashrsi3\";
5142 (define_expand "ashrqi3"
5143   [(set (match_operand:QI 0 "register_operand" "")
5144         (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5145                      (match_operand:QI 2 "general_operand" "")))]
5146    ""
5147    "")
5149 (define_insn "*ashrqi3_const1"
5150   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5151         (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5152                      (const_int 1)))]
5153   ""
5154   "@
5155    asrb
5156    asr\\t%b0
5157    asr\\t%b0
5158    asr%0
5159    #")
5161 (define_insn "*ashrqi3_const"
5162   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5163         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5164                      (match_operand:QI 2 "const_int_operand" "")))]
5165   ""
5166   "*
5168   int i;
5169   const char* insn_code;
5171   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5172     insn_code = \"asrb\";
5173   else if (DA_REG_P (operands[0]))
5174     insn_code = \"asra\";
5175   else
5176     return \"#\";
5178   i = INTVAL (operands[2]);
5179   if (i > 8)
5180     i = 8;
5181   while (--i >= 0)
5182     {
5183       output_asm_insn (insn_code, operands);
5184     }
5185   return \"\";
5188 (define_insn "*ashrqi3"
5189   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5190         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5191                      (match_operand:QI 2 "nonimmediate_operand" 
5192                                          "m*u*d*A,m*u*d*A,m*u")))]
5193   ""
5194   "*
5196   rtx ops[2];
5198   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5199     return \"#\";
5201   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5202   ops[1] = operands[2];
5203   m68hc11_gen_movqi (insn, ops);
5205   CC_STATUS_INIT;
5206   return \"bsr\\t___ashrqi3\";
5209 ;;--------------------------------------------------------------------
5210 ;; logical shift instructions
5211 ;;--------------------------------------------------------------------
5212 (define_expand "lshrdi3"
5213   [(parallel [(set (match_operand:DI 0 "general_operand" "")
5214                      (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5215                                   (match_operand:HI 2 "general_operand" "")))
5216               (clobber (match_scratch:HI 3 ""))])]
5217    ""
5218    "
5220   if (GET_CODE (operands[2]) != CONST_INT 
5221      || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5222          && INTVAL (operands[2]) != 1))
5223     {
5224       FAIL;
5225     }
5228 (define_insn_and_split "*lshrdi3_const32"
5229   [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5230         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
5231                      (const_int 32)))
5232    (clobber (match_scratch:HI 2 "=&A,d,d"))]
5233    ""
5234    "#"
5235    "reload_completed"
5236    [(const_int 0)]
5237    "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5238                         m68hc11_gen_highpart (SImode, operands[1]),
5239                         operands[2]);
5240     m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5241                         const0_rtx, operands[2]);
5242     DONE;")
5244 (define_insn "*lshrdi3_const63"
5245   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5246         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5247                      (match_operand:DI 2 "const_int_operand" "")))
5248    (clobber (match_scratch:HI 3 "=d,d"))]
5249    "INTVAL (operands[2]) >= 48"
5250    "#")
5252 (define_split
5253   [(set (match_operand:DI 0 "nonimmediate_operand" "")
5254         (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5255                      (match_operand:DI 2 "const_int_operand" "")))
5256    (clobber (match_scratch:HI 3 "=d"))]
5257    "z_replacement_completed && INTVAL (operands[2]) >= 56"
5258    [(set (reg:QI D_REGNUM) (match_dup 9))
5259     (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5260     (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5261     (set (match_dup 4) (reg:HI D_REGNUM))
5262     (set (reg:QI D_REGNUM) (const_int 0))
5263     (set (match_dup 5) (reg:HI D_REGNUM))
5264     (set (match_dup 6) (reg:HI D_REGNUM))
5265     (set (match_dup 7) (reg:HI D_REGNUM))]
5266    "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
5267     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5268     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5269     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5271     operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5272     operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5273     operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5275     operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5276     operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5277     operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5279 (define_split
5280   [(set (match_operand:DI 0 "nonimmediate_operand" "")
5281         (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5282                      (match_operand:DI 2 "const_int_operand" "")))
5283    (clobber (match_scratch:HI 3 "=d"))]
5284    "z_replacement_completed && INTVAL (operands[2]) >= 48 
5285     && INTVAL (operands[2]) < 56"
5286    [(set (reg:HI D_REGNUM) (match_dup 9))
5287     (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5288     (set (match_dup 4) (reg:HI D_REGNUM))
5289     (set (reg:HI D_REGNUM) (const_int 0))
5290     (set (match_dup 5) (reg:HI D_REGNUM))
5291     (set (match_dup 6) (reg:HI D_REGNUM))
5292     (set (match_dup 7) (reg:HI D_REGNUM))]
5293    "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
5294     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5295     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5296     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5298     operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5299     operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5300     operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5301     operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5302     operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5304 (define_insn_and_split "*lshrdi_const1"
5305   [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5306         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5307                      (const_int 1)))
5308    (clobber (match_scratch:HI 2 "=d,d"))]
5309    ""
5310    "#"
5311    "z_replacement_completed == 2"
5312    [(set (match_dup 2) (match_dup 3))
5313     (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5314     (set (match_dup 4) (match_dup 2))
5316     (set (match_dup 2) (match_dup 5))
5317     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5318                (clobber (reg:HI CC_REGNUM))])
5319     (set (match_dup 6) (match_dup 2))
5321     (set (match_dup 2) (match_dup 7))
5322     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5323                (clobber (reg:HI CC_REGNUM))])
5324     (set (match_dup 8) (match_dup 2))
5326     (set (match_dup 2) (match_dup 9))
5327     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5328                (clobber (reg:HI CC_REGNUM))])
5329     (set (match_dup 10) (match_dup 2))]
5330    "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5331     operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5332     operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5334     operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5335     operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5336     operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5338     operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5339     operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5340     operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5342     operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5343     operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5344     operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5346 (define_expand "lshrsi3"
5347   [(parallel
5348        [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5349         (clobber (scratch:HI))])
5350    (parallel
5351        [(set (match_operand:SI 0 "register_operand" "")
5352              (lshiftrt:SI (match_dup 0)
5353                           (match_operand:HI 2 "general_operand" "")))
5354         (clobber (scratch:HI))])]
5355    ""
5356    "")
5358 (define_split
5359   [(set (match_operand:SI 0 "non_push_operand" "")
5360         (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
5361                      (const_int 16)))
5362    (clobber (match_scratch:HI 3 ""))]
5363    "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5364   [(set (match_dup 2) (match_dup 3))
5365    (set (match_dup 4) (const_int 0))]
5366    "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5367     operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5368     operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5370 (define_insn "*lshrsi3_const16"
5371   [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5372         (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
5373                      (const_int 16)))
5374    (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5375    ""
5376    "@
5377     #
5378     xgdx\\n\\tldx\\t#0
5379     #
5380     #")
5382 (define_insn "*lshrsi3_const1"
5383   [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
5384         (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
5385                      (const_int 1)))
5386    (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
5387    ""
5388    "*
5390   CC_STATUS_INIT;
5391   if (X_REG_P (operands[1]))
5392     {
5393       return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5394     }
5395   else
5396     {
5397       rtx ops[2];
5399       ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5400       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
5401       m68hc11_gen_movhi (insn, ops);
5402       output_asm_insn (\"lsrd\", ops);
5403       if (!X_REG_P (operands[0]))
5404         {
5405           ops[1] = ops[0];
5406           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5407           m68hc11_gen_movhi (insn, ops);
5408           ops[0] = ops[1];
5409           ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5410           m68hc11_gen_movhi (insn, ops);
5411         }
5412       else
5413         {
5414           /* Load the lowpart in X in case the operands is some N,x.  */
5415           ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
5416           ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5417           m68hc11_gen_movhi (insn, ops);
5418           output_asm_insn (\"xgdx\", ops);
5419         }
5420       output_asm_insn (\"rora\", ops);
5421       output_asm_insn (\"rorb\", ops);
5422       if (!X_REG_P (operands[0]))
5423         {
5424           ops[1] = ops[0];
5425           ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5426           m68hc11_gen_movhi (insn, ops);
5427         }
5428       return \"\";
5429     }
5432 (define_insn "*lshrsi3_const"
5433   [(set (match_operand:SI 0 "register_operand" "+D")
5434         (lshiftrt:SI (match_dup 0)
5435                      (match_operand:HI 1 "const_int_operand" "")))
5436    (clobber (match_scratch:HI 2 "=y"))]
5437    "TARGET_M6811 /* See *lshrsi3 note.  */"
5438    "*
5440   CC_STATUS_INIT;
5441   return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5444 (define_insn "*lshrsi3"
5445   [(set (match_operand:SI 0 "register_operand" "+D,D")
5446         (lshiftrt:SI (match_dup 0)
5447                      (match_operand:HI 1 "general_operand" "y,mi")))
5448    (clobber (match_scratch:HI 2 "=1,X"))]
5449    ""
5450    "*
5452   CC_STATUS_INIT;
5453   /* There is a reload problem if we don't accept 'm' for the shift value.
5454      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5455      and this conflicts with all reloads.  Since X, Y, Z are used there
5456      is not enough register in class A_REGS.
5458      Assuming that 'operands[1]' does not refer to the stack (which 
5459      is true for 68hc11 only, we save temporary the value of Y.
5461      For 68HC12 we must also accept a constant because Z register is
5462      disabled when compiling with -fomit-frame-pointer.  We can come up
5463      with a reload problem and the *lshrsi3_const pattern was disabled
5464      for that reason.  */
5465   if (!Y_REG_P (operands[2]))
5466     {
5467       rtx ops[1];
5468       int y_dead = dead_register_here (insn, iy_reg);
5470       ops[0] = operands[1];
5471       if (y_dead == 0)
5472         {
5473           output_asm_insn (\"pshy\", operands);
5474           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5475             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5476         }
5477       output_asm_insn (\"ldy\\t%0\", ops);
5478       output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5479       return y_dead == 0 ? \"puly\" : \"\";
5480     }
5481   return \"bsr\\t___lshrsi3\";
5484 (define_expand "lshrhi3"
5485   [(set (match_operand:HI 0 "register_operand" "")
5486         (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5487                      (match_operand:HI 2 "general_operand" "")))]
5488    ""
5489    "
5491   if (GET_CODE (operands[2]) != CONST_INT)
5492     {
5493       rtx scratch = gen_reg_rtx (HImode);
5494       operand1 = force_reg (HImode, operand1);
5496       emit_move_insn (scratch, operands[2]);
5497       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5498                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5499                                         operand0,
5500                                         gen_rtx_LSHIFTRT (HImode,
5501                                                 operand1, scratch)),
5502                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5503      DONE;
5504   }
5507 (define_insn "lshrhi3_const1"
5508   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5509         (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5510                      (const_int 1)))]
5511   ""
5512   "*
5514   if (A_REG_P (operands[0]))
5515     return \"#\";
5517   if (D_REG_P (operands[0]))
5518     return \"lsrd\";
5520   CC_STATUS_INIT;
5521   return \"lsr\\t%h0\\n\\tror\\t%b0\";
5524 (define_insn "lshrhi3_const"
5525   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5526         (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5527                      (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5528   ""
5529   "*
5531   int val = INTVAL (operands[2]);
5533   if (A_REG_P (operands[0]))
5534     return \"#\";
5536   if (val >= 8)
5537     {
5538       if (val == 8)
5539         CC_STATUS_INIT;
5541       if (!H_REG_P (operands[1]))
5542         {
5543           output_asm_insn (\"clra\", operands);
5544           output_asm_insn (\"ldab\\t%h1\", operands);
5545         }
5546       else if (A_REG_P (operands[1]))
5547         {
5548           output_asm_insn (\"st%1\\t%t0\", operands);
5549           output_asm_insn (\"ldab\\t%t0\", operands);
5550           output_asm_insn (\"clra\", operands);
5551         }
5552       else
5553         {
5554           output_asm_insn (\"tab\", operands);
5555           output_asm_insn (\"clra\", operands);
5556         }
5557       val -= 8;
5558       switch (val) 
5559         {
5560         case 7:
5561           output_asm_insn (\"rolb\", operands);
5562           output_asm_insn (\"tab\", operands);
5563           output_asm_insn (\"rolb\", operands);
5564           break;
5566         case 6:
5567           output_asm_insn (\"rolb\", operands);
5568           output_asm_insn (\"rolb\", operands);
5569           output_asm_insn (\"rolb\", operands);
5570           output_asm_insn (\"andb\\t#3\", operands);
5571           break;
5573         default:
5574            while (val > 0)
5575              {
5576                 val --;
5577                 output_asm_insn (\"lsrb\", operands);
5578              }
5579            break;
5580         }
5581       return \"\";
5582     }
5584   if (!D_REG_P (operands[1]))
5585     m68hc11_gen_movhi (insn, operands);
5586   switch (val)
5587     {
5588     case 7:
5589       output_asm_insn (\"rolb\", operands);
5590       output_asm_insn (\"tab\", operands);
5591       output_asm_insn (\"rolb\", operands);
5592       output_asm_insn (\"rola\", operands);
5593       output_asm_insn (\"rola\", operands);
5594       output_asm_insn (\"anda\\t#1\", operands);
5595       CC_STATUS_INIT;
5596       break;
5598     default:
5599       while (val > 0) 
5600         {
5601           val --;
5602           output_asm_insn (\"lsrd\", operands);
5603         }
5604      }
5605   return \"\";
5608 (define_insn "*lshrhi3"
5609   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5610         (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5611                      (match_operand:HI 2 "register_operand" "+x,+d")))
5612    (clobber (match_dup 2))]
5613   ""
5614   "*
5616   if (A_REG_P (operands[0]))
5617     return \"#\";
5619   return \"bsr\\t___lshrhi3\";
5622 (define_expand "lshrqi3"
5623   [(set (match_operand:QI 0 "register_operand" "")
5624         (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5625                      (match_operand:QI 2 "general_operand" "")))]
5626    ""
5627    "")
5629 (define_insn "*lshrqi3_const1"
5630   [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5631         (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5632                      (const_int 1)))]
5633   ""
5634   "@
5635    lsr\\t%b0
5636    lsrb
5637    lsr\\t%b0
5638    lsr%0
5639    #")
5641 (define_insn "*lshrqi3_const"
5642   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5643         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5644                      (match_operand:QI 2 "const_int_operand" "")))]
5645   ""
5646   "*
5648   int i;
5649   const char* insn_code;
5651   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5652     insn_code = \"lsrb\";
5653   else if (DA_REG_P (operands[0]))
5654     insn_code = \"lsra\";
5655   else
5656     return \"#\";
5658   i = INTVAL (operands[2]);
5659   if (i >= 8)
5660     {
5661       if (DA_REG_P (operands[0]))
5662         return \"clra\";
5663       else
5664         return \"clrb\";
5665     }
5666   else if (i == 7)
5667     {
5668       if (DA_REG_P (operands[0]))
5669         {
5670           output_asm_insn (\"rola\", operands);
5671           output_asm_insn (\"ldaa\\t#0\", operands);
5672           return \"rola\";
5673         }
5674       else
5675         {
5676           output_asm_insn (\"rolb\", operands);
5677           output_asm_insn (\"ldab\\t#0\", operands);
5678           return \"rolb\";
5679         }
5680     }
5681   else if (i == 6)
5682     {
5683       if (DA_REG_P (operands[0]))
5684         {
5685           output_asm_insn (\"rola\", operands);
5686           output_asm_insn (\"rola\", operands);
5687           output_asm_insn (\"rola\", operands);
5688           return \"anda\\t#3\";
5689         }
5690       else
5691         {
5692           output_asm_insn (\"rolb\", operands);
5693           output_asm_insn (\"rolb\", operands);
5694           output_asm_insn (\"rolb\", operands);
5695           return \"andb\\t#3\";
5696         }
5697     }
5698   while (--i >= 0)
5699     {
5700       output_asm_insn (insn_code, operands);
5701     }
5702   return \"\";
5705 (define_insn "*lshrqi3"
5706   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5707         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5708                      (match_operand:QI 2 "nonimmediate_operand" 
5709                                          "m*u*d*A,m*u*d*A,m*u")))]
5710   ""
5711   "*
5713   rtx ops[2];
5715   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5716     return \"#\";
5718   CC_STATUS_INIT;
5719   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5720   ops[1] = operands[2];
5721   m68hc11_gen_movqi (insn, ops);
5723   if (!optimize || optimize_size)
5724     {
5725       return \"bsr\\t___lshrqi3\";
5726     }
5728   ops[0] = gen_label_rtx ();
5729   ops[1] = gen_label_rtx ();
5730   output_asm_insn (\"ble\\t%l1\", ops);
5732   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5733                              CODE_LABEL_NUMBER (ops[0]));
5735   output_asm_insn (\"lsrb\", operands);
5736   output_asm_insn (\"deca\", operands);
5737   output_asm_insn (\"bne\\t%l0\", ops);
5739   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5740                              CODE_LABEL_NUMBER (ops[1]));
5741   return \"\";
5744 (define_insn "*rotlqi3_with_carry"
5745   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5746         (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5747                    (reg:QI CC_REGNUM)))]
5748   ""
5749   "*
5751   if (DA_REG_P (operands[0]))
5752     return \"rola\";
5753   else
5754     return \"rolb\";
5757 (define_insn "*rotlhi3_with_carry"
5758   [(set (match_operand:HI 0 "register_operand" "=d")
5759         (rotate:HI (match_operand:HI 1 "register_operand" "0")
5760                    (const_int 1)))
5761    (clobber (reg:HI CC_REGNUM))]
5762   ""
5763   "*
5765   CC_STATUS_INIT;
5766   return \"rolb\\n\\trola\";
5769 (define_insn "*rotrhi3_with_carry"
5770   [(set (match_operand:HI 0 "register_operand" "=d")
5771         (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5772                      (const_int 1)))
5773    (clobber (reg:HI CC_REGNUM))]
5774   ""
5775   "*
5777   CC_STATUS_INIT;
5778   return \"rora\\n\\trorb\";
5781 (define_insn "rotlqi3"
5782   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5783         (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5784                    (match_operand:QI 2 "const_int_operand" "i,i")))]
5785   ""
5786   "*
5788   m68hc11_gen_rotate (ROTATE, insn, operands);
5789   return \"\";
5792 (define_insn "rotrqi3"
5793   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5794         (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5795                      (match_operand:QI 2 "const_int_operand" "i,i")))]
5796   ""
5797   "*
5799   m68hc11_gen_rotate (ROTATERT, insn, operands);
5800   return \"\";
5803 (define_expand "rotlhi3"
5804   [(set (match_operand:HI 0 "register_operand" "")
5805         (rotate:HI (match_operand:HI 1 "register_operand" "")
5806                    (match_operand:HI 2 "general_operand" "")))]
5807    ""
5808    "
5810   if (GET_CODE (operands[2]) != CONST_INT)
5811     {
5812       rtx scratch = gen_reg_rtx (HImode);
5813       operand1 = force_reg (HImode, operand1);
5815       emit_move_insn (scratch, operands[2]);
5816       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5817                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5818                                         operand0,
5819                                         gen_rtx_ROTATE (HImode,
5820                                                 operand1, scratch)),
5821                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5822       DONE;
5823     }
5826 (define_insn "rotlhi3_const"
5827   [(set (match_operand:HI 0 "register_operand" "=d")
5828         (rotate:HI (match_operand:HI 1 "register_operand" "0")
5829                    (match_operand:HI 2 "const_int_operand" "i")))]
5830   ""
5831   "*
5833   m68hc11_gen_rotate (ROTATE, insn, operands);
5834   return \"\";
5837 (define_insn "*rotlhi3"
5838   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5839         (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
5840                    (match_operand:HI 2 "general_operand" "+x,+d")))
5841    (clobber (match_dup 2))]
5842   ""
5843   "*
5845   if (A_REG_P (operands[0]))
5846     return \"#\";
5848   return \"bsr\\t___rotlhi3\";
5851 (define_expand "rotrhi3"
5852   [(set (match_operand:HI 0 "register_operand" "")
5853         (rotatert:HI (match_operand:HI 1 "general_operand" "")
5854                      (match_operand:HI 2 "general_operand" "")))]
5855    ""
5856    "
5858   if (GET_CODE (operands[2]) != CONST_INT)
5859     {
5860       rtx scratch = gen_reg_rtx (HImode);
5861       operand1 = force_reg (HImode, operand1);
5863       emit_move_insn (scratch, operands[2]);
5864       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5865                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5866                                         operand0,
5867                                         gen_rtx_ROTATERT (HImode,
5868                                                 operand1, scratch)),
5869                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5870       DONE;
5871     }
5874 (define_insn "rotrhi3_const"
5875   [(set (match_operand:HI 0 "register_operand" "=d")
5876         (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5877                      (match_operand:HI 2 "const_int_operand" "i")))]
5878   ""
5879   "*
5881   m68hc11_gen_rotate (ROTATERT, insn, operands);
5882   return \"\";
5885 (define_insn "*rotrhi3"
5886   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5887         (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
5888                      (match_operand:HI 2 "general_operand" "+x,+d")))
5889    (clobber (match_dup 2))]
5890   ""
5891   "*
5893   if (A_REG_P (operands[0]))
5894     return \"#\";
5896   return \"bsr\\t___rotrhi3\";
5899 ;; Split a shift operation on an address register in a shift
5900 ;; on D_REGNUM.
5901 (define_split /* "*rotrhi3_addr" */
5902   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
5903         (match_operator:HI 3 "m68hc11_shift_operator"
5904             [(match_operand:HI 1 "register_operand" "")
5905              (match_operand:HI 2 "register_operand" "")]))
5906    (clobber (match_dup 2))]
5907   "z_replacement_completed == 2"
5908   [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5909               (set (match_dup 0) (reg:HI D_REGNUM))])
5910    (parallel [(set (reg:HI D_REGNUM) 
5911                    (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
5912               (clobber (match_dup 0))])
5913    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5914               (set (match_dup 0) (reg:HI D_REGNUM))])]
5915   "")
5917 ;;--------------------------------------------------------------------
5918 ;;-  68HC12 Decrement/Increment and branch
5919 ;;--------------------------------------------------------------------
5920 ;; These patterns are used by loop optimization as well as peephole2
5921 ;; They must handle reloading themselves and the scratch register
5922 ;; is used for that.  Even if we accept memory operand, we must not
5923 ;; accept them on the predicate because it might create too many reloads.
5924 ;; (specially on HC12 due to its auto-incdec addressing modes).
5926 (define_expand "decrement_and_branch_until_zero"
5927   [(parallel [(set (pc)
5928                    (if_then_else
5929                     (ne (plus:HI (match_operand:HI 0 "register_operand" "")
5930                                  (const_int 0))
5931                         (const_int 1))
5932                     (label_ref (match_operand 1 "" ""))
5933                     (pc)))
5934               (set (match_dup 0)
5935                    (plus:HI (match_dup 0)
5936                             (const_int -1)))
5937               (clobber (match_scratch:HI 2 ""))])]
5938   "TARGET_M6812"
5939   "")
5941 (define_expand "doloop_end"
5942   [(use (match_operand 0 "" ""))        ; loop pseudo
5943    (use (match_operand 1 "" ""))        ; iterations; zero if unknown
5944    (use (match_operand 2 "" ""))        ; max iterations
5945    (use (match_operand 3 "" ""))        ; loop level
5946    (use (match_operand 4 "" ""))]       ; label
5947   "TARGET_M6812"
5948   "
5950   /* Reject non-constant loops as it generates bigger code due to
5951      the handling of the loop register.  We can do better by using
5952      the peephole2 dbcc/ibcc patterns.  */
5953   if (INTVAL (operands[1]) == 0)
5954     {
5955       FAIL;
5956     }
5958   /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
5959      the operator and its operands are not relevant.  */
5960   if (GET_MODE (operands[0]) == HImode)
5961     {
5962       emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
5963                                                gen_rtx_NE (HImode,
5964                                                            operands[0],
5965                                                            const1_rtx),
5966                                                operands[4]));
5967       DONE;
5968     }
5969   if (GET_MODE (operands[0]) == QImode)
5970     {
5971       emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
5972                                                gen_rtx_NE (QImode,
5973                                                            operands[0],
5974                                                            const1_rtx),
5975                                                operands[4]));
5976       DONE;
5977     }
5979   FAIL;
5982 ;; Decrement-and-branch insns.
5983 (define_insn "m68hc12_dbcc_dec_hi"
5984   [(set (pc)
5985         (if_then_else
5986           (match_operator 1 "m68hc11_eq_compare_operator"
5987              [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5988               (const_int 1)])
5989          (label_ref (match_operand 2 "" ""))
5990          (pc)))
5991    (set (match_dup 0)
5992         (plus:HI (match_dup 0) (const_int -1)))
5993    (clobber (match_scratch:HI 3 "=X,dxy"))]
5994   "TARGET_M6812"
5995   "*
5997   if (!H_REG_P (operands[0]))
5998     return \"#\";
6000   CC_STATUS_INIT;
6001   if (GET_CODE (operands[1]) == EQ)
6002     return \"dbeq\\t%0,%l2\";
6003   else
6004     return \"dbne\\t%0,%l2\";
6007 ;; Decrement-and-branch insns.
6008 (define_insn "m68hc12_dbcc_inc_hi"
6009   [(set (pc)
6010         (if_then_else
6011           (match_operator 1 "m68hc11_eq_compare_operator"
6012              [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
6013               (const_int -1)])
6014          (label_ref (match_operand 2 "" ""))
6015          (pc)))
6016    (set (match_dup 0)
6017         (plus:HI (match_dup 0) (const_int 1)))
6018    (clobber (match_scratch:HI 3 "=X,dxy"))]
6019   "TARGET_M6812"
6020   "*
6022   if (!H_REG_P (operands[0]))
6023     return \"#\";
6025   CC_STATUS_INIT;
6026   if (GET_CODE (operands[1]) == EQ)
6027     return \"ibeq\\t%0,%l2\";
6028   else
6029     return \"ibeq\\t%0,%l2\";
6032 ;; Decrement-and-branch (QImode).
6033 (define_insn "m68hc12_dbcc_dec_qi"
6034   [(set (pc)
6035         (if_then_else
6036           (match_operator 1 "m68hc11_eq_compare_operator"
6037              [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6038               (const_int 1)])
6039          (label_ref (match_operand 2 "" ""))
6040          (pc)))
6041    (set (match_dup 0)
6042         (plus:QI (match_dup 0) (const_int -1)))
6043    (clobber (match_scratch:QI 3 "=X,d"))]
6044   "TARGET_M6812"
6045   "*
6047   if (!D_REG_P (operands[0]))
6048     return \"#\";
6050   CC_STATUS_INIT;
6051   if (GET_CODE (operands[1]) == EQ)
6052     return \"dbeq\\tb,%l2\";
6053   else
6054     return \"dbne\\tb,%l2\";
6057 ;; Increment-and-branch (QImode).
6058 (define_insn "m68hc12_dbcc_inc_qi"
6059   [(set (pc)
6060         (if_then_else
6061           (match_operator 1 "m68hc11_eq_compare_operator"
6062              [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6063               (const_int -1)])
6064          (label_ref (match_operand 2 "" ""))
6065          (pc)))
6066    (set (match_dup 0)
6067         (plus:QI (match_dup 0) (const_int 1)))
6068    (clobber (match_scratch:QI 3 "=X,d"))]
6069   "TARGET_M6812"
6070   "*
6072   if (!D_REG_P (operands[0]))
6073     return \"#\";
6075   CC_STATUS_INIT;
6076   if (GET_CODE (operands[1]) == EQ)
6077     return \"ibeq\\tb,%l2\";
6078   else
6079     return \"ibeq\\tb,%l2\";
6082 ;; Split the above to handle the case where operand 0 is in memory
6083 ;; (a register that couldn't get a hard register)
6084 (define_split
6085   [(set (pc)
6086         (if_then_else
6087           (match_operator 3 "m68hc11_eq_compare_operator"
6088              [(match_operand:HI 0 "general_operand" "")
6089               (match_operand:HI 1 "const_int_operand" "")])
6090          (label_ref (match_operand 4 "" ""))
6091          (pc)))
6092    (set (match_dup 0)
6093         (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6094    (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
6095   "TARGET_M6812 && reload_completed"
6096   [(set (match_dup 5) (match_dup 0))
6097    (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
6098    (set (match_dup 0) (match_dup 5))
6099    (set (pc)
6100         (if_then_else (match_op_dup 3
6101                             [(match_dup 5) (const_int 0)])
6102                       (label_ref (match_dup 4)) (pc)))]
6103   "")
6105 ;; Split the above to handle the case where operand 0 is in memory
6106 ;; (a register that couldn't get a hard register)
6107 (define_split
6108   [(set (pc)
6109         (if_then_else
6110           (match_operator 3 "m68hc11_eq_compare_operator"
6111              [(match_operand:QI 0 "general_operand" "")
6112               (match_operand:QI 1 "const_int_operand" "")])
6113          (label_ref (match_operand 4 "" ""))
6114          (pc)))
6115    (set (match_dup 0)
6116         (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6117    (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
6118   "TARGET_M6812 && reload_completed"
6119   [(set (match_dup 5) (match_dup 0))
6120    (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
6121    (set (match_dup 0) (match_dup 5))
6122    (set (pc)
6123         (if_then_else (match_op_dup 3
6124                             [(match_dup 5) (const_int 0)])
6125                       (label_ref (match_dup 4)) (pc)))]
6126   "")
6128 ;;--------------------------------------------------------------------
6129 ;;-  Jumps and transfers
6130 ;;--------------------------------------------------------------------
6131 (define_insn "jump"
6132   [(set (pc)
6133         (label_ref (match_operand 0 "" "")))]
6134   ""
6135   "bra\\t%l0")
6137 (define_expand "beq"
6138   [(set (pc)
6139         (if_then_else (eq (cc0)
6140                           (const_int 0))
6141                       (label_ref (match_operand 0 "" ""))
6142                       (pc)))]
6143   ""
6144   "
6146   m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
6147                                      m68hc11_compare_op1, 
6148                                      operands[0]);
6149   DONE;
6152 (define_expand "bne"
6153   [(set (pc)
6154         (if_then_else (ne (cc0)
6155                           (const_int 0))
6156                       (label_ref (match_operand 0 "" ""))
6157                       (pc)))]
6158   ""
6159   "
6161   m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
6162                                      m68hc11_compare_op1, 
6163                                      operands[0]);
6164   DONE;
6167 (define_expand "bgt"
6168   [(set (pc)
6169         (if_then_else (gt (cc0)
6170                           (const_int 0))
6171                       (label_ref (match_operand 0 "" ""))
6172                       (pc)))]
6173   ""
6174   "
6176   m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
6177                                      m68hc11_compare_op1, 
6178                                      operands[0]);
6179   DONE;
6182 (define_expand "bgtu"
6183   [(set (pc)
6184         (if_then_else (gtu (cc0)
6185                            (const_int 0))
6186                       (label_ref (match_operand 0 "" ""))
6187                       (pc)))]
6188   ""
6189   "
6191   m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
6192                                      m68hc11_compare_op1, 
6193                                      operands[0]);
6194   DONE;
6197 (define_expand "blt"
6198   [(set (pc)
6199         (if_then_else (lt (cc0)
6200                           (const_int 0))
6201                       (label_ref (match_operand 0 "" ""))
6202                       (pc)))]
6203   ""
6204   "
6206   m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
6207                                      m68hc11_compare_op1, 
6208                                      operands[0]);
6209   DONE;
6212 (define_expand "bltu"
6213   [(set (pc)
6214         (if_then_else (ltu (cc0)
6215                            (const_int 0))
6216                       (label_ref (match_operand 0 "" ""))
6217                       (pc)))]
6218   ""
6219   "
6221   m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
6222                                      m68hc11_compare_op1, 
6223                                      operands[0]);
6224   DONE;
6227 (define_expand "bge"
6228   [(set (pc)
6229         (if_then_else (ge (cc0)
6230                            (const_int 0))
6231                       (label_ref (match_operand 0 "" ""))
6232                       (pc)))]
6233   ""
6234   "
6236   m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
6237                                      m68hc11_compare_op1, 
6238                                      operands[0]);
6239   DONE;
6242 (define_expand "bgeu"
6243   [(set (pc)
6244         (if_then_else (geu (cc0)
6245                            (const_int 0))
6246                       (label_ref (match_operand 0 "" ""))
6247                       (pc)))]
6248   ""
6249   "
6251   m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
6252                                      m68hc11_compare_op1, 
6253                                      operands[0]);
6254   DONE;
6257 (define_expand "ble"
6258   [(set (pc)
6259         (if_then_else (le (cc0)
6260                            (const_int 0))
6261                       (label_ref (match_operand 0 "" ""))
6262                       (pc)))]
6263   ""
6264   "
6266   m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
6267                                      m68hc11_compare_op1, 
6268                                      operands[0]);
6269   DONE;
6272 (define_expand "bleu"
6273   [(set (pc)
6274         (if_then_else (leu (cc0)
6275                            (const_int 0))
6276                       (label_ref (match_operand 0 "" ""))
6277                       (pc)))]
6278   ""
6279   "
6281   m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
6282                                      m68hc11_compare_op1, 
6283                                      operands[0]);
6284   DONE;
6288 ;; Test and branch instructions for 68HC12 for EQ and NE.
6289 ;; 'z' must not appear in the constraints because the z replacement 
6290 ;; pass does not know how to restore the replacement register.
6292 (define_insn "*tbeq"
6293   [(set (pc)
6294         (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
6295                           (const_int 0))
6296                       (label_ref (match_operand 1 "" ""))
6297                       (pc)))]
6298   "TARGET_M6812"
6299   "*
6301    /* If the flags are already set correctly, use 'bne/beq' which are
6302       smaller and a little bit faster.  This happens quite often due
6303       to reloading of operands[0].  In that case, flags are set correctly
6304       due to the load instruction.  */
6305   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6306       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6307     return \"beq\\t%l1\";
6308   else
6309     return \"tbeq\\t%0,%l1\";
6312 (define_insn "*tbne"
6313   [(set (pc)
6314         (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6315                           (const_int 0))
6316                       (label_ref (match_operand 1 "" ""))
6317                       (pc)))]
6318   "TARGET_M6812"
6319   "*
6321    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6322        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6323      return \"bne\\t%l1\";
6324    else
6325      return \"tbne\\t%0,%l1\";
6329 ;; Test and branch with 8-bit register.  Register must be B (or A).
6331 (define_insn "*tbeq8"
6332   [(set (pc)
6333         (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6334                           (const_int 0))
6335                       (label_ref (match_operand 1 "" ""))
6336                       (pc)))]
6337   "TARGET_M6812"
6338   "*
6340    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6341        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6342      return \"beq\\t%l1\";
6343    else
6344      return \"tbeq\\tb,%l1\";
6347 (define_insn "*tbne8"
6348   [(set (pc)
6349         (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6350                           (const_int 0))
6351                       (label_ref (match_operand 1 "" ""))
6352                       (pc)))]
6353   "TARGET_M6812"
6354   "*
6356    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6357        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6358      return \"bne\\t%l1\";
6359    else
6360      return \"tbne\\tb,%l1\";
6363 (define_insn "*beq"
6364   [(set (pc)
6365         (if_then_else (eq (cc0)
6366                           (const_int 0))
6367                       (label_ref (match_operand 0 "" ""))
6368                       (pc)))]
6369   ""
6370   "beq\\t%l0")
6372 (define_insn "*bne"
6373   [(set (pc)
6374         (if_then_else (ne (cc0)
6375                           (const_int 0))
6376                       (label_ref (match_operand 0 "" ""))
6377                       (pc)))]
6378   ""
6379   "bne\\t%l0")
6381 (define_insn "*bgt"
6382   [(set (pc)
6383         (if_then_else (gt (cc0)
6384                           (const_int 0))
6385                       (label_ref (match_operand 0 "" ""))
6386                       (pc)))]
6387   ""
6388   "bgt\\t%l0")
6390 (define_insn "*bgtu"
6391   [(set (pc)
6392         (if_then_else (gtu (cc0)
6393                            (const_int 0))
6394                       (label_ref (match_operand 0 "" ""))
6395                       (pc)))]
6396   ""
6397   "bhi\\t%l0")
6399 (define_insn "*blt"
6400   [(set (pc)
6401         (if_then_else (lt (cc0)
6402                           (const_int 0))
6403                       (label_ref (match_operand 0 "" ""))
6404                       (pc)))]
6405   ""
6406   "*
6408   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6409     return \"bmi\\t%l0\";
6410   else
6411     return \"blt\\t%l0\";
6414 (define_insn "*bltu"
6415   [(set (pc)
6416         (if_then_else (ltu (cc0)
6417                            (const_int 0))
6418                       (label_ref (match_operand 0 "" ""))
6419                       (pc)))]
6420   ""
6421   "blo\\t%l0")
6423 (define_insn "*bge"
6424   [(set (pc)
6425         (if_then_else (ge (cc0)
6426                           (const_int 0))
6427                       (label_ref (match_operand 0 "" ""))
6428                       (pc)))]
6429   ""
6430   "*
6432   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6433     return \"bpl\\t%l0\";
6434   else
6435     return \"bge\\t%l0\";
6438 (define_insn "*bgeu"
6439   [(set (pc)
6440         (if_then_else (geu (cc0)
6441                            (const_int 0))
6442                       (label_ref (match_operand 0 "" ""))
6443                       (pc)))]
6444   ""
6445   "bhs\\t%l0")
6447 (define_insn "*ble"
6448   [(set (pc)
6449         (if_then_else (le (cc0)
6450                           (const_int 0))
6451                       (label_ref (match_operand 0 "" ""))
6452                       (pc)))]
6453   ""
6454   "*
6456   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6457     return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6458   else
6459     return \"ble\\t%l0\";
6462 (define_insn "*bleu"
6463   [(set (pc)
6464         (if_then_else (leu (cc0)
6465                            (const_int 0))
6466                       (label_ref (match_operand 0 "" ""))
6467                       (pc)))]
6468   ""
6469   "bls\\t%l0")
6471 ;;--------------------------------------------------------------------
6472 ;;- Negative test and branch
6473 ;;--------------------------------------------------------------------
6474 (define_insn ""
6475   [(set (pc)
6476         (if_then_else (eq (cc0)
6477                           (const_int 0))
6478                       (pc)
6479                       (label_ref (match_operand 0 "" ""))))]
6480   ""
6481   "bne\\t%l0")
6483 (define_insn ""
6484   [(set (pc)
6485         (if_then_else (ne (cc0)
6486                           (const_int 0))
6487                       (pc)
6488                       (label_ref (match_operand 0 "" ""))))]
6489   ""
6490   "beq\\t%l0")
6492 (define_insn ""
6493   [(set (pc)
6494         (if_then_else (gt (cc0)
6495                           (const_int 0))
6496                       (pc)
6497                       (label_ref (match_operand 0 "" ""))))]
6498   ""
6499   "*
6501   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6502     return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6503   else
6504     return \"ble\\t%l0\";
6507 (define_insn ""
6508   [(set (pc)
6509         (if_then_else (gtu (cc0)
6510                            (const_int 0))
6511                       (pc)
6512                       (label_ref (match_operand 0 "" ""))))]
6513   ""
6514   "bls\\t%l0")
6516 (define_insn ""
6517   [(set (pc)
6518         (if_then_else (lt (cc0)
6519                           (const_int 0))
6520                       (pc)
6521                       (label_ref (match_operand 0 "" ""))))]
6522   ""
6523   "*
6525   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6526     return \"bpl\\t%l0\";
6527   else
6528     return \"bge\\t%l0\";
6531 (define_insn ""
6532   [(set (pc)
6533         (if_then_else (ltu (cc0)
6534                            (const_int 0))
6535                       (pc)
6536                       (label_ref (match_operand 0 "" ""))))]
6537   ""
6538   "bhs\\t%l0")
6540 (define_insn ""
6541   [(set (pc)
6542         (if_then_else (ge (cc0)
6543                           (const_int 0))
6544                       (pc)
6545                       (label_ref (match_operand 0 "" ""))))]
6546   ""
6547   "*
6549   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6550     return \"bmi\\t%l0\";
6551   else
6552     return \"blt\\t%l0\";
6555 (define_insn ""
6556   [(set (pc)
6557         (if_then_else (geu (cc0)
6558                            (const_int 0))
6559                       (pc)
6560                       (label_ref (match_operand 0 "" ""))))]
6561   ""
6562   "blo\\t%l0")
6564 (define_insn ""
6565   [(set (pc)
6566         (if_then_else (le (cc0)
6567                           (const_int 0))
6568                       (pc)
6569                       (label_ref (match_operand 0 "" ""))))]
6570   ""
6571   "bgt\\t%l0")
6573 (define_insn ""
6574   [(set (pc)
6575         (if_then_else (leu (cc0)
6576                            (const_int 0))
6577                       (pc)
6578                       (label_ref (match_operand 0 "" ""))))]
6579   ""
6580   "bhi\\t%l0")
6582 ;;--------------------------------------------------------------------
6583 ;;-  Calls
6584 ;;--------------------------------------------------------------------
6586 ;;- Call a function that returns no value.
6587 (define_insn "call"
6588   [(call (match_operand:QI 0 "memory_operand" "m")
6589          (match_operand:SI 1 "general_operand" "g"))]
6590   ;; Operand 1 not really used on the m68hc11.
6591   ""
6592  "*
6594   if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6595     {
6596       if (m68hc11_is_far_symbol (operands[0]))
6597         {
6598           if (TARGET_M6812)
6599             {
6600               output_asm_insn (\"call\\t%0\", operands);
6601               return \"\";
6602             }
6603           else
6604             {
6605               output_asm_insn (\"pshb\", operands);
6606               output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
6607               output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
6608               return \"jsr\\t__call_a32\";
6609             }
6610         }
6611       if (m68hc11_is_trap_symbol (operands[0]))
6612         return \"swi\";
6613       else
6614         return \"bsr\\t%0\";
6615     }
6616   else
6617     {
6618       return \"jsr\\t%0\";
6619     }
6622 (define_insn "call_value"
6623   [(set (match_operand 0 "" "=g")
6624         (call (match_operand:QI 1 "memory_operand" "m")
6625               (match_operand:SI 2 "general_operand" "g")))]
6626   ""
6627  "*
6629   if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6630     {
6631       if (m68hc11_is_far_symbol (operands[1]))
6632         {
6633           if (TARGET_M6812)
6634             {
6635               output_asm_insn (\"call\\t%1\", operands);
6636               return \"\";
6637             }
6638           else
6639             {
6640               output_asm_insn (\"pshb\", operands);
6641               output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
6642               output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
6643               return \"jsr\\t__call_a32\";
6644             }
6645         }
6646       if (m68hc11_is_trap_symbol (operands[1]))
6647         return \"swi\";
6648       else
6649         return \"bsr\\t%1\";
6650     }
6651   else
6652     {
6653       return \"jsr\\t%1\";
6654     }
6657 ;; Call subroutine returning any type.
6659 (define_expand "untyped_call"
6660   [(parallel [(call (match_operand 0 "" "")
6661                     (const_int 0))
6662               (match_operand 1 "" "")
6663               (match_operand 2 "" "")])]
6664   ""
6665   "
6667   int i;
6669   emit_call_insn (gen_call (operands[0], const0_rtx));
6671   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6672     {
6673       rtx set = XVECEXP (operands[2], 0, i);
6674       emit_move_insn (SET_DEST (set), SET_SRC (set));
6675     }
6677   /* The optimizer does not know that the call sets the function value
6678      registers we stored in the result block.  We avoid problems by
6679      claiming that all hard registers are used and clobbered at this
6680      point.  */
6681   emit_insn (gen_blockage ());
6683   DONE;
6686 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6687 ;; all of memory.  This blocks insns from being moved across this point.
6689 (define_insn "blockage"
6690   [(unspec_volatile [(const_int 0)] 0)]
6691   ""
6692   "")
6694 (define_insn "nop"
6695   [(const_int 0)]
6696   ""
6697   "nop")
6698     
6699 (define_expand "prologue"
6700   [(const_int 0)]
6701   ""
6702   "
6704   expand_prologue (); 
6705   DONE;
6708 (define_expand "epilogue"
6709   [(return)]
6710   ""
6711   "
6713   expand_epilogue ();
6714   DONE;
6717 ;; Used for frameless functions which save no regs and allocate no locals.
6718 (define_expand "return"
6719   [(return)]
6720   "reload_completed && m68hc11_total_frame_size () == 0"
6721   "
6723   int ret_size = 0;
6725   if (crtl->return_rtx)
6726     ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
6728   /* Emit use notes only when HAVE_return is true.  */
6729   if (m68hc11_total_frame_size () != 0)
6730     ret_size = 0;
6732   if (ret_size && ret_size <= 2)
6733     {
6734       emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6735                       gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6736                                  gen_rtx_USE (VOIDmode,
6737                                               gen_rtx_REG (HImode, 1)))));
6738       DONE;
6739     }
6740   if (ret_size)
6741     {
6742       emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6743                       gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6744                                  gen_rtx_USE (VOIDmode,
6745                                               gen_rtx_REG (SImode, 0)))));
6746       DONE;
6747     }
6750 (define_insn "*return_void"
6751   [(return)]
6752   "reload_completed"
6753   "*
6755   rtx next = next_active_insn (insn);
6757   if (next
6758       && GET_CODE (next) == JUMP_INSN
6759       && GET_CODE (PATTERN (next)) == RETURN)
6760     return \"\";
6761   if (current_function_interrupt || current_function_trap)
6762     return \"rti\";
6763   else if (!current_function_far)
6764     return \"rts\";
6765   else if (TARGET_M6812)
6766     return \"rtc\";
6767   else
6768     {
6769       int ret_size = 0;
6771       if (crtl->return_rtx)
6772         ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
6774       if (ret_size == 0)
6775         return \"jmp\\t__return_void\";
6776       if (ret_size <= 2)
6777         return \"jmp\\t__return_16\";
6778       if (ret_size <= 4)
6779         return \"jmp\\t__return_32\";
6780       return \"jmp\\t__return_16\";
6781     }
6784 (define_insn "*return_16bit"
6785   [(return)
6786    (use (reg:HI D_REGNUM))]
6787   "reload_completed && m68hc11_total_frame_size () == 0"
6788   "*
6790   rtx next = next_active_insn (insn);
6792   if (next
6793       && GET_CODE (next) == JUMP_INSN
6794       && GET_CODE (PATTERN (next)) == RETURN)
6795     return \"\";
6796   if (current_function_interrupt || current_function_trap)
6797     return \"rti\";
6798   else if (!current_function_far)
6799     return \"rts\";
6800   else if (TARGET_M6812)
6801     return \"rtc\";
6802   else
6803     return \"jmp\\t__return_16\";
6806 (define_insn "*return_32bit"
6807   [(return)
6808    (use (reg:SI 0))]
6809   "reload_completed && m68hc11_total_frame_size () == 0"
6810   "*
6812   rtx next = next_active_insn (insn);
6814   if (next
6815       && GET_CODE (next) == JUMP_INSN
6816       && GET_CODE (PATTERN (next)) == RETURN)
6817     return \"\";
6818   if (current_function_interrupt || current_function_trap)
6819     return \"rti\";
6820   else if (!current_function_far)
6821     return \"rts\";
6822   else if (TARGET_M6812)
6823     return \"rtc\";
6824   else
6825     return \"jmp\\t__return_32\";
6828 (define_insn "indirect_jump"
6829   [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6830   ""
6831   "jmp\\t0,%0")
6833 ;;--------------------------------------------------------------------
6834 ;;-  Table jump
6835 ;;--------------------------------------------------------------------
6837 ;; Operand 0 is the address of the table element to use
6838 ;; operand 1 is the CODE_LABEL for the table
6839 ;;--------------------------------------------------------------------
6840 (define_expand "tablejump"
6841   [(parallel [(set (pc) (match_operand 0 "" ""))
6842               (use (label_ref (match_operand 1 "" "")))])]
6843   ""
6844   "")
6846 (define_insn "*jump_indirect"
6847    [(parallel [
6848         (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6849         (use (label_ref (match_operand 1 "" "")))])]
6850    ""
6851   "jmp\\t0,%0")
6853 ;;--------------------------------------------------------------------
6854 ;;- Peepholes
6855 ;;--------------------------------------------------------------------
6857 ;;--------------------------------------------------------------------
6858 ;;- 68HC12 dbcc/ibcc peepholes
6859 ;;--------------------------------------------------------------------
6861 ;; Replace: "addd #-1; bne L1" into "dbne d,L1"
6862 ;;          "addd #-1; beq L1" into "dbeq d,L1"
6863 ;;          "addd #1; bne L1" into "ibne d,L1"
6864 ;;          "addd #1; beq L1" into "ibeq d,L1"
6866 (define_peephole2
6867   [(set (match_operand:HI 0 "hard_reg_operand" "")
6868         (plus:HI (match_dup 0)
6869                  (match_operand:HI 1 "const_int_operand" "")))
6870    (set (pc)
6871         (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6872                          [(match_dup 0)
6873                           (const_int 0)])
6874                       (label_ref (match_operand 3 "" "")) (pc)))]
6875   "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6876   [(parallel [
6877       (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6878                               (label_ref (match_dup 3)) (pc)))
6879       (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
6880       (clobber (match_dup 4))])]
6881   "operands[4] = gen_rtx_SCRATCH(HImode);
6882    operands[5] = GEN_INT (-INTVAL (operands[1]));")
6886 ;; Replace: "addb #-1; bne L1" into "dbne b,L1"
6887 ;;          "addb #-1; beq L1" into "dbeq b,L1"
6889 (define_peephole2
6890   [(set (match_operand:QI 0 "hard_reg_operand" "")
6891         (plus:QI (match_dup 0)
6892                  (match_operand:QI 1 "const_int_operand" "")))
6893    (set (pc)
6894         (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6895                          [(match_dup 0)
6896                           (const_int 0)])
6897                       (label_ref (match_operand 3 "" "")) (pc)))]
6898   "TARGET_M6812 && D_REG_P (operands[0])
6899    && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6900   [(parallel [
6901       (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6902                               (label_ref (match_dup 3)) (pc)))
6903       (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
6904       (clobber (match_dup 4))])]
6905   "operands[4] = gen_rtx_SCRATCH(QImode);
6906    operands[5] = GEN_INT (-INTVAL (operands[1]));")
6909 ;;--------------------------------------------------------------------
6910 ;;- Move peephole2
6911 ;;--------------------------------------------------------------------
6914 ;; Replace "leas 2,sp" with a "pulx" or a "puly".
6915 ;; On 68HC12, this is one cycle slower but one byte smaller.
6916 ;; pr target/6899: This peephole was not valid because a register CSE
6917 ;; pass removes the pulx/puly.  The 'use' clause ensure that the pulx is
6918 ;; not removed.
6920 (define_peephole2
6921   [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6922    (match_scratch:HI 0 "xy")]
6923   "TARGET_M6812 && optimize_size"
6924   [(set (match_dup 0) (match_dup 1))
6925    (use (match_dup 0))]
6926   "operands[1] = gen_rtx_MEM (HImode,
6927                           gen_rtx_POST_INC (HImode,
6928                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
6930 ;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
6932 ;; PR 14542: emit a use to pretend we need the value of initial register.
6933 ;; Otherwise verify_local_live_at_start will die due to a live change
6934 ;; of that register.
6936 (define_peephole2
6937   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6938         (match_operand:HI 0 "hard_reg_operand" ""))
6939    (set (match_dup 0)
6940         (match_operand:HI 1 "hard_reg_operand" ""))
6941    (set (mem:HI (reg:HI SP_REGNUM))
6942         (match_dup 0))]
6943   "TARGET_M6812"
6944   [(use (match_dup 0))
6945    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6946         (match_dup 1))
6947    (set (match_dup 0) (match_dup 1))]
6948   "")
6951 ;; Change: "ldd 0,sp; pulx" into  "puld"
6952 ;; This sequence usually appears at end a functions.
6953 (define_peephole2
6954   [(set (match_operand:HI 0 "hard_reg_operand" "")
6955         (mem:HI (reg:HI SP_REGNUM)))
6956    (use (match_dup 0))
6957    (set (match_operand:HI 1 "hard_reg_operand" "")
6958         (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
6959   "peep2_reg_dead_p (2, operands[1])"
6960   [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
6961    (use (match_dup 0))]
6962   "")
6964 ;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
6965 ;; Appears to allocate local variables.
6966 (define_peephole2
6967   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6968         (match_operand:HI 0 "hard_reg_operand" ""))
6969    (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
6970         (const_int 0))
6971    (set (mem:QI (reg:HI SP_REGNUM))
6972         (const_int 0))]
6973   "TARGET_M6812"
6974   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6975         (const_int 0))]
6976   "")
6978 ;; Likewise for HI mode
6979 (define_peephole2
6980   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6981         (match_operand:HI 0 "hard_reg_operand" ""))
6982    (set (mem:HI (reg:HI SP_REGNUM))
6983         (const_int 0))]
6984   "TARGET_M6812"
6985   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6986         (const_int 0))]
6987   "")
6988 ;;--------------------------------------------------------------------
6989 ;;- 
6990 ;;--------------------------------------------------------------------
6992 ;; Optimize memory<->memory moves when the value is also loaded in
6993 ;; a register.
6995 (define_peephole2
6996   [(set (match_operand:QI 0 "memory_operand" "")
6997         (match_operand:QI 1 "memory_operand" ""))
6998    (set (reg:QI D_REGNUM)
6999         (match_operand:QI 2 "memory_operand" ""))]
7000   "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
7001    || (GET_CODE (XEXP (operands[0], 0)) == REG
7002        && GET_CODE (XEXP (operands[2], 0)) == POST_INC
7003        && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
7004   [(set (reg:QI D_REGNUM) (match_dup 1))
7005    (set (match_dup 2) (reg:QI D_REGNUM))]
7006   "")
7009 ;; Remove a possible move before a compare instruction when that
7010 ;; move will go in a dead register.  Compare with the source then.
7012 (define_peephole2
7013   [(set (match_operand:HI 0 "hard_reg_operand" "")
7014         (match_operand:HI 1 "hard_reg_operand" ""))
7015    (set (cc0)
7016         (compare (match_dup 0)
7017                  (match_operand:HI 2 "cmp_operand" "")))]
7018   "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
7019    && peep2_reg_dead_p (2, operands[0])
7020    && !reg_mentioned_p (operands[0], operands[2])"
7021   [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
7022   "")
7025 ;; Optimize loading a constant to memory when that same constant
7026 ;; is loaded to a hard register.  Switch the two to use the register
7027 ;; for memory initialization.  In most cases, the constant is 0.
7029 (define_peephole2
7030   [(set (match_operand:HI 0 "memory_operand" "")
7031         (match_operand:HI 1 "immediate_operand" ""))
7032    (set (match_operand:HI 2 "hard_reg_operand" "")
7033         (match_dup 1))]
7034   "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
7035    && !reg_mentioned_p (operands[2], operands[0])"
7036   [(set (match_dup 2) (match_dup 1))
7037    (set (match_dup 0) (match_dup 2))]
7038   "")
7041 ;; Reorganize to optimize address computations.
7043 (define_peephole2
7044   [(set (match_operand:HI 0 "hard_reg_operand" "")
7045         (match_operand:HI 1 "const_int_operand" ""))
7046    (set (match_dup 0)
7047         (plus:HI (match_dup 0)
7048                  (match_operand:HI 2 "general_operand" "")))]
7049   "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7050   [(set (match_dup 0) (match_dup 2))
7051    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7052   "")
7055 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7057 (define_peephole2
7058   [(set (match_operand:HI 0 "hard_reg_operand" "")
7059         (match_operand:HI 1 "const_int_operand" ""))
7060    (set (match_dup 0)
7061         (plus:HI (match_dup 0)
7062                  (match_operand:HI 2 "general_operand" "")))
7063    (match_scratch:QI 3 "d")]
7064   "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
7065   [(set (match_dup 3) (match_dup 4))
7066    (set (match_dup 0) (match_dup 2))
7067    (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
7068   "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
7071 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7073 (define_peephole2
7074   [(set (match_operand:HI 0 "hard_reg_operand" "")
7075         (match_operand:HI 1 "const_int_operand" ""))
7076    (set (match_dup 0)
7077         (plus:HI (match_dup 0)
7078                  (match_operand:HI 2 "general_operand" "")))]
7079   "TARGET_M6812"
7080   [(set (match_dup 0) (match_dup 2))
7081    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7082   "")
7085 ;; Optimize an address register increment and a compare to use
7086 ;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
7087 ;; before reload, but can be enabled after).
7089 (define_peephole2
7090   [(set (match_operand:HI 0 "hard_reg_operand" "")
7091         (plus:HI (match_dup 0)
7092                  (match_operand:HI 1 "const_int_operand" "")))
7093    (set (cc0)
7094         (match_operand:QI 2 "memory_operand" ""))]
7095   "TARGET_AUTO_INC_DEC
7096    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7097    && reg_mentioned_p (operands[0], operands[2])"
7098   [(set (cc0) (match_dup 3))]
7099   "if (INTVAL (operands[1]) == 1)
7100      operands[3] = gen_rtx_MEM (QImode,
7101                             gen_rtx_PRE_INC (HImode, operands[0]));
7102    else
7103      operands[3] = gen_rtx_MEM (QImode,
7104                             gen_rtx_PRE_DEC (HImode, operands[0]));
7105   ")
7108 ;; Likewise for compare.
7110 (define_peephole2
7111   [(set (match_operand:HI 0 "hard_reg_operand" "")
7112         (plus:HI (match_dup 0)
7113                  (match_operand:HI 1 "const_int_operand" "")))
7114    (set (cc0)
7115         (compare (match_operand:QI 2 "hard_reg_operand" "")
7116                  (match_operand:QI 3 "memory_operand" "")))]
7117   "TARGET_AUTO_INC_DEC
7118    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7119    && reg_mentioned_p (operands[0], operands[3])"
7120   [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
7121   "if (INTVAL (operands[1]) == 1)
7122      operands[4] = gen_rtx_MEM (QImode,
7123                             gen_rtx_PRE_INC (HImode, operands[0]));
7124    else
7125      operands[4] = gen_rtx_MEM (QImode,
7126                             gen_rtx_PRE_DEC (HImode, operands[0]));
7127   ")
7129 (define_peephole2
7130   [(set (match_operand:HI 0 "hard_reg_operand" "")
7131         (plus:HI (match_dup 0)
7132                  (match_operand:HI 1 "const_int_operand" "")))
7133    (set (cc0)
7134         (compare (match_operand:QI 2 "memory_operand" "")
7135                  (match_operand:QI 3 "hard_reg_operand" "")))]
7136   "TARGET_AUTO_INC_DEC
7137    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7138    && reg_mentioned_p (operands[0], operands[2])"
7139   [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
7140   "if (INTVAL (operands[1]) == 1)
7141      operands[4] = gen_rtx_MEM (QImode,
7142                             gen_rtx_PRE_INC (HImode, operands[0]));
7143    else
7144      operands[4] = gen_rtx_MEM (QImode,
7145                             gen_rtx_PRE_DEC (HImode, operands[0]));
7146   ")
7149 ;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
7150 ;; (avoids many temporary moves because we can't add sp to another reg easily)
7152 (define_peephole2
7153   [(set (match_operand:HI 0 "hard_reg_operand" "")
7154         (match_operand:HI 1 "const_int_operand" ""))
7155    (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7156   ""
7157   [(set (match_dup 0) (reg:HI SP_REGNUM))
7158    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7159   "")
7162 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7164 (define_peephole2
7165   [(set (match_operand:HI 0 "hard_reg_operand" "")
7166         (match_operand:HI 1 "const_int_operand" ""))
7167    (set (match_dup 0)
7168         (plus:HI (match_dup 0)
7169                  (match_operand:HI 2 "general_operand" "")))]
7170   "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7171   [(set (match_dup 0) (match_dup 2))
7172    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7173   "")
7178 (define_peephole2
7179   [(parallel 
7180      [(set (match_operand:SI 0 "hard_reg_operand" "")
7181         (ashift:SI (match_operand:SI 1 "general_operand" "")
7182                    (const_int 1)))
7183       (clobber (match_scratch:HI 2 ""))])
7184    (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
7185    (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
7186   "!X_REG_P (operands[1])
7187    && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
7188    && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
7189   [(set (reg:HI D_REGNUM) (match_dup 5))
7190    (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
7191    (set (match_dup 3) (reg:HI D_REGNUM))
7192    (set (reg:HI D_REGNUM) (match_dup 6))
7193    (parallel [(set (reg:HI D_REGNUM)
7194                    (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
7195               (clobber (reg:HI CC_REGNUM))])
7196    (set (match_dup 4) (reg:HI D_REGNUM))]
7197   "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
7198    operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
7201 ;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
7203 (define_peephole2
7204   [(set (match_operand:HI 0 "hard_reg_operand" "")
7205         (match_operand:HI 1 "memory_operand" ""))
7206    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
7207         (match_dup 0))
7208    (match_scratch:HI 2 "x")]
7209   "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
7210   [(set (match_dup 2) (match_dup 1))
7211    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
7212   "")
7215 ;; Remove one load when copying a value to/from memory and also
7216 ;; to a register.  Take care not clobbering a possible register used
7217 ;; by operand 2.
7218 ;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
7220 (define_peephole2
7221   [(set (match_operand:HI 0 "hard_reg_operand" "")
7222         (match_operand:HI 1 "general_operand" ""))
7223    (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
7224    (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
7225   "peep2_reg_dead_p (2, operands[0])
7226    && !side_effects_p (operands[1])
7227    && !side_effects_p (operands[2])
7228    && !reg_mentioned_p (operands[3], operands[2])"
7229   [(set (match_dup 3) (match_dup 1))
7230    (set (match_dup 2) (match_dup 3))]
7231   "")
7234 ;; Replace a "ldd <mem>; addd #N; std <mem>" into a
7235 ;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
7236 ;; and the constant is small.
7238 (define_peephole2
7239   [(set (match_operand:HI 0 "hard_reg_operand" "")
7240         (match_operand:HI 1 "general_operand" ""))
7241    (set (match_dup 0) (plus:HI (match_dup 0)
7242                                (match_operand:HI 2 "const_int_operand" "")))
7243    (set (match_operand:HI 3 "nonimmediate_operand" "")
7244         (match_dup 0))
7245    (match_scratch:HI 4 "xy")]
7246   "D_REG_P (operands[0])
7247    && (TARGET_M6812 
7248        || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
7249    && peep2_reg_dead_p (3, operands[0])"
7250   [(set (match_dup 4) (match_dup 1))
7251    (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
7252    (set (match_dup 3) (match_dup 4))]
7253   "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
7254    if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
7256 ;;--------------------------------------------------------------------
7257 ;;- Bset peephole2
7258 ;;--------------------------------------------------------------------
7259 ;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
7261 ;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
7262 ;; Register D must be dead and there must be no register side effects for mem.
7263 ;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
7264 ;; The good side effect is that it makes the sequence atomic.
7266 (define_peephole2
7267   [(set (match_operand:QI 0 "hard_reg_operand" "")
7268         (match_operand:QI 1 "nonimmediate_operand" ""))
7269    (set (match_dup 0) (ior:QI (match_dup 0)
7270                               (match_operand:QI 2 "const_int_operand" "")))
7271    (set (match_dup 1) (match_dup 0))]
7272   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7273    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7274    && peep2_reg_dead_p (3, operands[0])"
7275   [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
7276   "")
7278 (define_peephole2
7279   [(set (match_operand:HI 0 "hard_reg_operand" "")
7280         (match_operand:HI 1 "nonimmediate_operand" ""))
7281    (set (match_dup 0) (ior:HI (match_dup 0)
7282                               (match_operand:HI 2 "const_int_operand" "")))
7283    (set (match_dup 1) (match_dup 0))]
7284   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7285    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7286    && peep2_reg_dead_p (3, operands[0])"
7287   [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
7288   "")
7290 ;;--------------------------------------------------------------------
7291 ;;- Bclr peephole2
7292 ;;--------------------------------------------------------------------
7293 ;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
7294 ;; See Bset peephole2.
7296 (define_peephole2
7297   [(set (match_operand:QI 0 "hard_reg_operand" "")
7298         (match_operand:QI 1 "nonimmediate_operand" ""))
7299    (set (match_dup 0) (and:QI (match_dup 0)
7300                               (match_operand:QI 2 "const_int_operand" "")))
7301    (set (match_dup 1) (match_dup 0))]
7302   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7303    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7304    && peep2_reg_dead_p (3, operands[0])"
7305   [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
7306   "")
7308 (define_peephole2
7309   [(set (match_operand:HI 0 "hard_reg_operand" "")
7310         (match_operand:HI 1 "nonimmediate_operand" ""))
7311    (set (match_dup 0) (and:HI (match_dup 0)
7312                               (match_operand:HI 2 "const_int_operand" "")))
7313    (set (match_dup 1) (match_dup 0))]
7314   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7315    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7316    && peep2_reg_dead_p (3, operands[0])"
7317   [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
7318   "")
7321 ;;--------------------------------------------------------------------
7322 ;;- Compare peephole2
7323 ;;--------------------------------------------------------------------
7324 (define_peephole2
7325   [(set (match_operand:HI 0 "hard_reg_operand" "")
7326         (match_operand:HI 1 "hard_reg_operand" ""))
7327    (set (match_dup 1) (plus:HI (match_dup 1) 
7328                                (match_operand:HI 2 "const_int_operand" "")))
7329    (set (cc0) (match_dup 0))]
7330   "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
7331   [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
7332    (set (cc0) (compare (match_dup 1) (match_dup 2)))]
7333   "")
7335 (define_peephole2
7336   [(set (match_operand:HI 0 "hard_reg_operand" "")
7337         (match_operand:HI 1 "hard_reg_operand" ""))
7338    (set (match_operand:HI 2 "hard_reg_operand" "")
7339         (plus:HI (match_dup 2) 
7340                  (match_operand:HI 3 "const_int_operand" "")))
7341    (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
7342    (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
7343   "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
7344    && !reg_mentioned_p (operands[2], operands[4])
7346    && ((rtx_equal_p (operands[5], operands[0])
7347         && rtx_equal_p (operands[2], operands[1]))
7349        || (rtx_equal_p (operands[5], operands[1])
7350            && rtx_equal_p (operands[2], operands[0])))"
7351   [(set (match_dup 2) (match_dup 1))
7352    (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
7353    (set (match_dup 4) (match_dup 2))
7354    (set (cc0) (compare (match_dup 2) (match_dup 3)))]
7355   "")
7358 ;;--------------------------------------------------------------------
7359 ;;- Load peephole2
7360 ;;--------------------------------------------------------------------
7362 ;; Optimize initialization of 2 hard regs from the same memory location
7363 ;; Since we can't copy easily X, Y and D to each other, load the 2 registers
7364 ;; from the same memory location.
7366 (define_peephole2
7367   [(set (match_operand:HI 0 "hard_reg_operand" "")
7368         (match_operand:HI 1 "memory_operand" ""))
7369    (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7370   "TARGET_M6811
7371    && !side_effects_p (operands[1])
7372    && !reg_mentioned_p (operands[0], operands[1])"
7373   [(set (match_dup 0) (match_dup 1))
7374    (set (match_dup 2) (match_dup 1))]
7375   "")
7377 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7379 (define_peephole2
7380   [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7381    (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7382    (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7383    (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
7384    (match_scratch:HI 4 "d")]
7385   ""
7386   [(set (match_dup 4) (const_int 0))
7387    (set (match_dup 0) (match_dup 4))
7388    (set (match_dup 1) (match_dup 4))
7389    (set (match_dup 2) (match_dup 4))
7390    (set (match_dup 3) (match_dup 4))]
7391   "")
7394 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7396 (define_peephole2
7397   [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7398    (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7399    (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7400    (match_scratch:HI 3 "d")]
7401   ""
7402   [(set (match_dup 3) (const_int 0))
7403    (set (match_dup 0) (match_dup 3))
7404    (set (match_dup 1) (match_dup 3))
7405    (set (match_dup 2) (match_dup 3))]
7406   "")
7409 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7411 (define_peephole2
7412   [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
7413    (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
7414    (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
7415    (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
7416    (match_scratch:HI 4 "x")]
7417   "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
7418   [(set (match_dup 4) (const_int 0))
7419    (set (match_dup 1) (match_dup 4))
7420    (set (match_dup 2) (match_dup 4))
7421    (set (match_dup 3) (match_dup 4))]
7422   "")
7425 ;; This peephole catches the address computations generated by the reload
7426 ;; pass. 
7427 (define_peephole
7428   [(set (match_operand:HI 0 "hard_reg_operand" "xy")
7429         (match_operand:HI 1 "const_int_operand" ""))
7430    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7431               (set (match_dup 0) (reg:HI D_REGNUM))])
7432    (set (reg:HI D_REGNUM)
7433         (plus (reg:HI D_REGNUM)
7434               (match_operand:HI 2 "general_operand" "")))
7435    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7436               (set (match_dup 0) (reg:HI D_REGNUM))])]
7437   "(INTVAL (operands[1]) & 0x0FF) == 0"
7438   "*
7440   int value_loaded = 1;
7442   if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
7443     {
7444       rtx ops[2];
7446       ops[0] = operands[0];
7447       ops[1] = operands[2];
7448       m68hc11_gen_movhi (insn, ops);
7449       output_asm_insn (\"xgd%0\", operands);
7450     }
7451   else if (Y_REG_P (operands[0]))
7452     {
7453       if (reg_mentioned_p (iy_reg, operands[2]))
7454         output_asm_insn (\"ldy\\t%2\", operands);
7455       else
7456         value_loaded = 0;
7457       output_asm_insn (\"xgdy\", operands);
7458     }
7459   else
7460     {
7461       output_asm_insn (\"ldd\\t%2\", operands);
7462     }
7464   if (value_loaded == 0)
7465     output_asm_insn (\"ldd\\t%2\", operands);
7466   if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
7467     output_asm_insn (\"inca\", operands);
7468   else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
7469     output_asm_insn (\"deca\", operands);
7470   else if (INTVAL (operands[1]) != 0)
7471     output_asm_insn (\"adda\\t%h1\", operands);
7473   if (X_REG_P (operands[0]))
7474     return \"xgdx\";
7475   else if (Y_REG_P (operands[0]))
7476     return \"xgdy\";
7477   else
7478     return \"\";
7482 (define_peephole
7483   [(set (match_operand:HI 0 "hard_reg_operand" "h")
7484         (match_operand:HI 1 "non_push_operand" "g"))
7485    (set (match_operand:HI 2 "hard_reg_operand" "h")
7486         (match_dup 0))]
7487   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7488    && !S_REG_P (operands[2])"
7489   "*
7491   rtx ops[2];
7493   ops[0] = operands[2];
7494   ops[1] = operands[1];
7495   m68hc11_gen_movhi (insn, ops);
7496   return \"\";
7500 (define_peephole
7501   [(set (match_operand:HI 0 "hard_reg_operand" "h")
7502         (match_operand:HI 1 "hard_reg_operand" "h"))
7503    (set (match_operand:HI 2 "non_push_operand" "g")
7504         (match_dup 0))]
7505   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7506    && !S_REG_P (operands[2])"
7507   "*
7509   rtx ops[2];
7511   ops[0] = operands[2];
7512   ops[1] = operands[1];
7513   m68hc11_gen_movhi (insn, ops);
7514   return \"\";
7519 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
7520 ;; the set, so we don't need to emit anything. 'ins1' refers to the
7521 ;; (set ...) insn.
7523 (define_peephole
7524   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7525    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7526               (set (match_dup 0) (reg:HI D_REGNUM))])]
7527   "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7528   "*
7530    cc_status = cc_prev_status;
7531    return \"\";
7535 ;; Same as above but due to some split, there may be a noop set
7536 ;; between the two.
7537 (define_peephole
7538   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7539    (set (match_dup 0) (match_dup 0))
7540    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7541               (set (match_dup 0) (reg:HI D_REGNUM))])]
7542   "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7543   "*
7545    cc_status = cc_prev_status;
7546    return \"\";
7551 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
7552 ;; and we must, at least, setup X/Y with value of D.
7554 (define_peephole
7555   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7556    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7557               (set (match_dup 0) (reg:HI D_REGNUM))])]
7558   ""
7559   "*
7561   rtx ops[2];
7563   ops[0] = operands[0];
7564   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7565   m68hc11_gen_movhi (insn, ops);
7566   return \"\";
7571 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7572 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7574 (define_peephole
7575   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7576               (set (match_dup 0) (reg:HI D_REGNUM))])
7577    (set (reg:HI D_REGNUM) (match_dup 0))]
7578   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7579   "*
7581   cc_status = cc_prev_status;
7582   return \"\";
7587 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7588 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7590 (define_peephole
7591   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7592               (set (match_dup 0) (reg:HI D_REGNUM))])
7593    (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7594   "REGNO (operands[0]) == REGNO (operands[1])
7595    && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7596   "*
7598   cc_status = cc_prev_status;
7599   return \"\";
7604 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7605 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7607 (define_peephole
7608   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7609               (set (match_dup 0) (reg:HI D_REGNUM))])
7610    (set (reg:HI D_REGNUM) (match_dup 0))]
7611   ""
7612   "*
7614   rtx ops[2];
7616   ops[0] = operands[0];
7617   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7618   m68hc11_gen_movhi (insn, ops);
7619   return \"\";
7624 ;;; Same peephole with a QI set.  The copy is made as 16-bit to comply
7625 ;;; with the xgdx.
7627 (define_peephole
7628   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7629               (set (match_dup 0) (reg:HI D_REGNUM))])
7630    (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7631   "REGNO (operands[0]) == REGNO (operands[1])"
7632   "*
7634   rtx ops[2];
7636   ops[0] = operands[0];
7637   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7638   m68hc11_gen_movhi (insn, ops);
7639   return \"\";
7644 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
7646 (define_peephole
7647   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7648               (set (match_dup 0) (reg:HI D_REGNUM))])
7649    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7650               (set (match_dup 0) (reg:HI D_REGNUM))])]
7651   ""
7652   "*
7654   cc_status = cc_prev_status;
7655   return \"\";
7659 (define_peephole
7660   [(set (match_operand:HI 0 "hard_reg_operand" "")
7661         (match_operand:HI 1 "stack_register_operand" ""))
7662    (set (match_operand:HI 2 "hard_reg_operand" "")
7663         (match_operand:HI 3 "memory_operand" "m"))
7664    (set (match_dup 0)
7665         (match_operand:HI 4 "memory_operand" "m"))]
7666   "IS_STACK_POP (operands[4])
7667    && (GET_CODE (operands[3]) == MEM &&
7668        rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
7669   "*
7671   rtx ops[2];
7673   ops[0] = operands[2];
7674   ops[1] = gen_rtx_MEM (HImode,
7675                     gen_rtx_POST_INC (HImode, stack_pointer_rtx));
7676   m68hc11_gen_movhi (insn, ops);
7677   return \"\";
7682 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
7684 (define_peephole
7685   [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
7686    (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7687   "TARGET_M6811"
7688   "*
7690   return \"sts\\t%t0\\n\\tld%0\\t%t0\";
7694 (define_peephole
7695   [(set (match_operand:HI 0 "hard_reg_operand" "")
7696         (match_operand:HI 1 "memory_operand" ""))
7697    (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7698   "TARGET_M6811
7699    && !side_effects_p (operands[1])
7700    && !reg_mentioned_p (operands[0], operands[1])"
7701   "*
7703   rtx ops[2];
7705   ops[0] = operands[0];
7706   ops[1] = operands[1];
7707   m68hc11_gen_movhi (insn, ops);
7708   ops[0] = operands[2];
7709   m68hc11_gen_movhi (insn, ops);
7710   return \"\";
7713 ;; Peephole for Z register replacement.
7714 ;; Avoid to use _.tmp register when comparing D and X if we can compare
7715 ;; with soft register
7716 (define_peephole
7717   [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
7718    (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
7719    (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
7720                        (reg:HI SOFT_TMP_REGNUM)))]
7721   "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
7722   "*
7724   rtx ops[2];
7726   ops[0] = operands[0];
7727   ops[1] = operands[1];
7728   m68hc11_gen_movhi (insn, ops);
7729   return \"cp%2\\t%1\";