Merge from mainline (165734:167278).
[official-gcc/graphite-test-results.git] / gcc / config / m68hc11 / m68hc11.md
blobf4ff3ebbb4c5783cfea8e5b708d0878a8d831e6c
1 ;;- Machine description file for Motorola 68HC11 and 68HC12.
2 ;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
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.
166 (define_insn "tsthi_1"
167   [(set (cc0)
168         (compare (match_operand:HI 0 "tst_operand" "dx,*y")
169                  (const_int 0)))]
170   ""
171   "*
173    if (D_REG_P (operands[0]) && !TARGET_M6812)
174      return \"std\\t%t0\";
175    else
176      return \"cp%0\\t#0\";
180 ;; Split pattern for (tst:QI) on an address register.
182 (define_split
183   [(set (cc0)
184         (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
185                  (const_int 0)))]
186   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
187   [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
188               (set (match_dup 1) (reg:HI D_REGNUM))])
189    (set (cc0) (compare (reg:QI D_REGNUM)
190                        (const_int 0)))
191    (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
192               (set (match_dup 1) (reg:HI D_REGNUM))])]
193   "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
195 (define_insn "tstqi_1"
196   [(set (cc0)
197         (compare (match_operand:QI 0 "tst_operand" "m,d,*A,!u")
198                  (const_int 0)))]
199   ""
200   "*
202   if (A_REG_P (operands[0]))
203     return \"#\";
205   else if (D_REG_P (operands[0]))
206     return \"tstb\";
208   else if (dead_register_here (insn, d_reg))
209     return \"ldab\\t%b0\";
211   else
212     return \"tst\\t%b0\";
216 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated 
217 ;; during the Z register replacement.  They are used when an operand
218 ;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
219 ;; In that case, we have to preserve the values of the replacement
220 ;; register (as well as the CC0 since the insns are compare insns).
221 ;; To do this, the replacement register is pushed on the stack and
222 ;; restored after the real compare.  A pattern+split is defined to
223 ;; avoid problems with the flow+cse register pass which are made
224 ;; after Z register replacement.
226 (define_insn_and_split "tstqi_z_used"
227   [(set (cc0) (compare (match_operand:QI 0 "tst_operand" "m")
228                        (const_int 0)))
229    (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
230    (use (reg:HI SOFT_Z_REGNUM))]
231   ""
232   "#"
233   "z_replacement_completed == 2"
234   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
235    (set (match_dup 1) (match_dup 2))
236    (set (cc0) (compare (match_dup 0)
237                        (const_int 0)))
238    (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
239   "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
242 ;;--------------------------------------------------------------------
243 ;;- Compare
244 ;;--------------------------------------------------------------------
247 ;; Comparison of a hard register with another one is provided because
248 ;; it helps GCC to avoid to spill a pseudo hard register.
249 ;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
250 ;; (except that we loose the information that the value is saved in it).
252 ;; The split pattern transforms the comparison into a save of one hard
253 ;; register and a comparison with the temporary.
255 (define_split
256   [(set (cc0)
257         (compare (match_operand:HI 0 "hard_reg_operand" "")
258                  (match_operand:HI 1 "hard_reg_operand" "")))]
259   "TARGET_M6811
260    && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
261   [(set (match_dup 2) (match_dup 1))
262    (set (cc0)
263         (compare (match_dup 0) (match_dup 2)))]
264   "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
266 (define_split
267   [(set (cc0)
268         (compare (match_operand:HI 0 "hard_reg_operand" "")
269                  (match_operand:HI 1 "hard_reg_operand" "")))]
270   "0 && TARGET_M6812
271    && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
272   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
273    (set (cc0)
274         (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
275   "")
277 (define_insn "cmphi_1_hc12"
278   [(set (cc0)
279         (compare (match_operand:HI 0 "tst_operand" 
280                                 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
281                  (match_operand:HI 1 "general_operand"
282                                 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
283   "TARGET_M6812"
284   "*
286   if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
287     {
288       cc_status.flags |= CC_REVERSED;
289       return \"cp%1\\t%0\";
290     }
291   else if (SP_REG_P (operands[1]))
292     return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
293   else if (H_REG_P (operands[1]))
294     return \"psh%1\n\\tcp%0\\t2,sp+\";
295   else
296     return \"cp%0\\t%1\";
299 (define_insn "cmphi_1_hc11"
300   [(set (cc0)
301         (compare (match_operand:HI 0 "tst_operand" 
302                                 "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
303                  (match_operand:HI 1 "cmp_operand"
304                                 "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
305   "TARGET_M6811"
306   "*
308   if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
309     {
310       cc_status.flags |= CC_REVERSED;
311       return \"cp%1\\t%0\";
312     }
313   else if (H_REG_P (operands[1]))
314     return \"#\";
315   else
316     return \"cp%0\\t%1\";
319 (define_insn_and_split "cmphi_z_used"
320   [(set (cc0)
321         (compare (match_operand:HI 0 "tst_operand" "dxy,m")
322                  (match_operand:HI 1 "cmp_operand" "mi,dxy")))
323    (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
324    (use (reg:HI SOFT_Z_REGNUM))]
325   ""
326   "#"
327   "z_replacement_completed == 2"
328   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
329    (set (match_dup 2) (match_dup 3))
330    (set (cc0) (compare (match_dup 0) (match_dup 1)))
331    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
332   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
335 ;; 8-bit comparison with address register.
336 ;; There is no such comparison instruction, we have to temporarily switch
337 ;; the address register and the D register and do the comparison with D.
338 ;; The xgdx and xgdy instructions preserve the flags.
340 (define_split
341   [(set (cc0)
342         (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
343                  (match_operand:QI 1 "cmp_operand" "")))]
344   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
345   [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
346               (set (match_dup 3) (reg:HI D_REGNUM))])
347    (set (cc0)
348         (compare (reg:QI D_REGNUM) (match_dup 1)))
349    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
350               (set (match_dup 3) (reg:HI D_REGNUM))])]
351   "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
353 (define_split
354   [(set (cc0)
355         (compare (match_operand:QI 0 "hard_reg_operand" "")
356                  (match_operand:QI 1 "hard_reg_operand" "")))]
357   "reload_completed"
358   [(set (match_dup 3) (match_dup 4))
359    (set (cc0)
360         (compare (match_dup 0) (match_dup 2)))]
361   "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
362    operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
363    operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
365 (define_insn "bitcmpqi"
366   [(set (cc0)
367         (compare (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
368                          (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d"))
369                  (const_int 0)))]
370   ""
371   "@
372    bitb\\t%b1
373    #
374    bitb\\t%b1
375    bitb\\t%b0
376    bitb\\t%b0")
378 (define_split /* "bitcmpqi" */
379   [(set (cc0)
380         (compare (and:QI (match_operand:QI 0 "tst_operand" "")
381                          (match_operand:QI 1 "hard_addr_reg_operand" ""))
382                  (const_int 0)))]
383   "z_replacement_completed == 2"
384   [(set (match_dup 3) (match_dup 2))
385    (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
386   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
387    operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
388    operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
390 (define_insn_and_split "bitcmpqi_z_used"
391   [(set (cc0)
392         (compare (and:QI (match_operand:QI 0 "tst_operand" "d,m")
393                          (match_operand:QI 1 "cmp_operand" "m,d"))
394                  (const_int 0)))
395    (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
396    (use (reg:HI SOFT_Z_REGNUM))]
397   ""
398   "#"
399   "z_replacement_completed == 2"
400   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
401    (set (match_dup 2) (match_dup 3))
402    (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
403    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
404   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
406 (define_insn "bitcmphi"
407   [(set (cc0)
408         (compare (and:HI (match_operand:HI 0 "tst_operand" "d")
409                          (match_operand:HI 1 "const_int_operand" "i"))
410                  (const_int 0)))]
411   "(INTVAL (operands[1]) & 0x0ff) == 0
412    || (INTVAL (operands[1]) & 0x0ff00) == 0"
413   "*
415    if ((INTVAL (operands[1]) & 0x0ff) == 0)
416      return \"bita\\t%h1\";
417    else
418      return \"bitb\\t%1\";
421 (define_insn "bitcmpqi_12"
422   [(set (cc0)
423         (compare (zero_extract:HI (match_operand:HI 0 "tst_operand" "d")
424                                   (match_operand:HI 1 "const_int_operand" "i")
425                                   (match_operand:HI 2 "const_int_operand" "i"))
426                  (const_int 0)))]
427   "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
428    || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
429        && (unsigned) INTVAL (operands[2]) >= 8)"
430   "*
432    rtx ops[1];
433    int mask;
434    int startpos = INTVAL (operands[2]);
435    int bitsize = INTVAL (operands[1]);
437    if (startpos >= 8)
438      {
439        startpos -= 8;
440        mask = (1 << (startpos + bitsize)) - 1;
441        mask &= ~((1 << startpos) - 1);
443        ops[0] = GEN_INT (mask);
444        output_asm_insn (\"bita\\t%0\", ops);
445      }
446    else
447      {
448        mask = (1 << (startpos + bitsize)) - 1;
449        mask &= ~((1 << startpos) - 1);
451        ops[0] = GEN_INT (mask);
452        output_asm_insn (\"bitb\\t%0\", ops);
453      }
454    return \"\";
457 (define_insn "cmpqi_1"
458   [(set (cc0)
459         (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
460                  (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
461   ""
462   "*
464    if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
465      {
466         return \"#\";
467      }
468    else if (D_REG_P (operands[0]))
469      {
470         return \"cmpb\\t%b1\";
471      }
472    cc_status.flags |= CC_REVERSED;
473    return \"cmpb\\t%b0\";
476 (define_insn_and_split "cmpqi_z_used"
477   [(set (cc0)
478         (compare (match_operand:QI 0 "tst_operand" "dxy,m")
479                  (match_operand:QI 1 "cmp_operand" "m,dxy")))
480    (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
481    (use (reg:HI SOFT_Z_REGNUM))]
482   ""
483   "#"
484   "z_replacement_completed == 2"
485   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
486    (set (match_dup 2) (match_dup 3))
487    (set (cc0) (compare (match_dup 0) (match_dup 1)))
488    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
489   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
491 ;;--------------------------------------------------------------------
492 ;;-  Move strict_low_part
493 ;;--------------------------------------------------------------------
495 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
496 ;; The replacement must be made at the very end because we loose the
497 ;; (strict_low_part ...) information.  This is correct for our machine
498 ;; description but not for GCC optimization passes.
500 (define_insn_and_split "movstrictsi"
501   [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
502         (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
503   ""
504   "#"
505   "z_replacement_completed == 2"
506   [(set (match_dup 0) (match_dup 1))]
507   "")
509 (define_insn_and_split "movstricthi"
510   [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
511         (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
512   ""
513   "#"
514   "z_replacement_completed == 2"
515   [(set (match_dup 0) (match_dup 1))]
516   "")
518 (define_insn_and_split "movstrictqi"
519   [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
520         (match_operand:QI 1 "general_operand" "d,imudA"))]
521   ""
522   "#"
523   "z_replacement_completed == 2"
524   [(set (match_dup 0) (match_dup 1))]
525   "")
527 ;;--------------------------------------------------------------------
528 ;;- 64-bit Move Operations.
529 ;; The movdi and movdf patterns are identical except for the mode.
530 ;; They are also very similar to those for movsi and movsf.
532 ;; For 68HC11, we need a scratch register (either D, X, Y) 
533 ;; because there is no memory->memory moves.  It must be defined with
534 ;; earlyclobber (&) so that it does not appear in the source or destination 
535 ;; address.  Providing patterns for movdi/movdf allows GCC to generate
536 ;; better code.  [Until now, the scratch register is limited to D because
537 ;; otherwise we can run out of registers in the A_REGS class for reload].
539 ;; For 68HC12, the scratch register is not necessary.  To use the same
540 ;; pattern and same split, we use the 'v' constraint.  This tells the
541 ;; reload to use the _.tmp register (which is not used at all).
542 ;; The insn will be split in one or several memory moves (movw).
543 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
544 ;;--------------------------------------------------------------------
545 (define_expand "movdi"
546   [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
547                    (match_operand:DI 1 "general_operand" ""))
548               (clobber (match_scratch:HI 2 ""))])]
549   ""
550   "
551   /* For push/pop, emit a REG_INC note to make sure the reload
552      inheritance and reload CSE pass notice the change of the stack
553      pointer.  */
554   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
555     {
556       rtx insn;
558       insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
559       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
560                                           stack_pointer_rtx,
561                                           REG_NOTES (insn));
562       DONE;
563     }
566 ;; Separate push from normal moves to avoid reloading problems
567 ;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
568 ;; We can also accept more scratch registers.
569 (define_insn_and_split "*pushdi_internal"
570   [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
571         (match_operand:DI 1 "general_operand" "i,U,m,!u"))
572    (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
573   ""
574   "#"
575   "reload_completed"
576   [(const_int 0)]
577   "m68hc11_split_move (operands[0], operands[1], operands[2]);
578    DONE;")
580 (define_insn_and_split "movdi_internal"
581   [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
582         (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
583    (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
584   ""
585   "#"
586   "reload_completed"
587   [(const_int 0)]
588   "m68hc11_split_move (operands[0], operands[1], operands[2]);
589    DONE;")
591 (define_expand "movdf"
592   [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
593                    (match_operand:DF 1 "general_operand" ""))
594               (clobber (match_scratch:HI 2 ""))])]
595   ""
596   "/* For push/pop, emit a REG_INC note to make sure the reload
597       inheritance and reload CSE pass notice the change of the stack
598       pointer.  */
599   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
600     {
601       rtx insn;
603       insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
604       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
605                                           stack_pointer_rtx,
606                                           REG_NOTES (insn));
607       DONE;
608     }
611 ;; See pushdi_internal
612 (define_insn_and_split "*pushdf_internal"
613   [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
614         (match_operand:DF 1 "general_operand" "i,U,m,!u"))
615    (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
616   ""
617   "#"
618   "reload_completed"
619   [(const_int 0)]
620   "m68hc11_split_move (operands[0], operands[1], operands[2]);
621    DONE;")
623 (define_insn_and_split "movdf_internal"
624   [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
625         (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
626    (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
627   ""
628   "#"
629   "reload_completed"
630   [(const_int 0)]
631   "m68hc11_split_move (operands[0], operands[1], operands[2]);
632    DONE;")
634 ;;--------------------------------------------------------------------
635 ;;- 32-bit Move Operations.
636 ;; The movsi and movsf patterns are identical except for the mode.
637 ;; When we move to/from a hard register (d+x), we don't need a scratch.
638 ;; Otherwise, a scratch register is used as intermediate register for
639 ;; the move.  The '&' constraint is necessary to make sure the reload
640 ;; pass does not give us a register that dies in the insn and is used
641 ;; for input/output operands.
642 ;;--------------------------------------------------------------------
643 (define_expand "movsi"
644   [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
645                    (match_operand:SI 1 "general_operand" ""))
646               (clobber (match_scratch:HI 2 ""))])]
647   ""
648   "/* For push/pop, emit a REG_INC note to make sure the reload
649       inheritance and reload CSE pass notice the change of the stack
650       pointer.  */
651   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
652     {
653       rtx insn;
655       insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
656       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
657                                           stack_pointer_rtx,
658                                           REG_NOTES (insn));
659       DONE;
660     }
663 (define_insn_and_split "*pushsi_internal"
664   [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
665         (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
666    (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
667   ""
668   "#"
669   "reload_completed"
670   [(const_int 0)]
671   "m68hc11_split_move (operands[0], operands[1], operands[2]);
672    DONE;")
674 (define_insn_and_split "movsi_internal"
675   [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
676         (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
677    (clobber (match_scratch:HI 2               "=X,&d,X,X,X,X,&d,&d,X"))]
678   ""
679   "#"
680   "reload_completed"
681   [(const_int 0)]
682   "m68hc11_split_move (operands[0], operands[1], operands[2]);
683    DONE;")
685 (define_expand "movsf"
686   [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
687                    (match_operand:SF 1 "general_operand" ""))
688               (clobber (match_scratch:HI 2 ""))])]
689   ""
690   "/* For push/pop, emit a REG_INC note to make sure the reload
691       inheritance and reload CSE pass notice the change of the stack
692       pointer.  */
693   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
694     {
695       rtx insn;
697       insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
698       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
699                                           stack_pointer_rtx,
700                                           REG_NOTES (insn));
701       DONE;
702     }
705 (define_insn_and_split "*pushsf_internal"
706   [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
707         (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
708    (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
709   ""
710   "#"
711   "reload_completed"
712   [(const_int 0)]
713   "m68hc11_split_move (operands[0], operands[1], operands[2]);
714    DONE;")
716 (define_insn_and_split "movsf_internal"
717   [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
718         (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
719    (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
720   ""
721   "#"
722   "reload_completed"
723   [(const_int 0)]
724   "m68hc11_split_move (operands[0], operands[1], operands[2]);
725    DONE;")
728 ;;--------------------------------------------------------------------
729 ;;- 16-bit Move Operations.
730 ;; We don't need a scratch register.
731 ;;--------------------------------------------------------------------
733 (define_insn "*movhi2_push"
734   [(set (match_operand:HI 0 "push_operand" "=<,<,<")
735         (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
736   "TARGET_M6811 && !TARGET_M6812"
737   "*
739   cc_status = cc_prev_status;
740   if (D_REG_P (operands[1]))
741     {
742       output_asm_insn (\"pshb\", operands);
743       return \"psha\";
744     }
745   else if (X_REG_P (operands[1]))
746     {
747       return \"pshx\";
748     }
749   else if (Y_REG_P (operands[1]))
750     {
751       return \"pshy\";
752     }
753   fatal_insn (\"Invalid register in the instruction\", insn);
756 (define_insn "*movhi2_pop"
757   [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
758         (match_operand:HI 1 "pop_operand" ">,>"))]
759   "TARGET_M6811"
760   "*
762   cc_status = cc_prev_status;
763   if (D_REG_P (operands[0]))
764     {
765       output_asm_insn (\"pula\", operands);
766       return \"pulb\";
767     }
768   else if (X_REG_P (operands[0]))
769     {
770       return \"pulx\";
771     }
772   else if (Y_REG_P (operands[0]))
773     {
774       return \"puly\";
775     }
776   fatal_insn (\"Invalid register in the instruction\", insn);
779 (define_expand "movhi"
780   [(set (match_operand:HI 0 "nonimmediate_operand" "")
781         (match_operand:HI 1 "general_operand" ""))]
782   ""
783   "
785   if (reload_in_progress)
786     {
787       if (m68hc11_reload_operands (operands))
788         {
789           DONE;
790         }
791     }
792   if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
793     {
794       if (GET_CODE (operands[0]) == MEM &&
795           (GET_CODE (operands[1]) == MEM
796            || GET_CODE (operands[1]) == CONST_INT))
797         {
798           operands[1] = force_reg (HImode, operands[1]);
799         }
800       else if (IS_STACK_PUSH (operands[0])
801                && GET_CODE (operands[1]) != REG)
802         {
803           operands[1] = force_reg (HImode, operands[1]);
804         }
805     }
806   /* For push/pop, emit a REG_INC note to make sure the reload
807      inheritance and reload CSE pass notice the change of the stack
808      pointer.  */
809   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
810     {
811       rtx insn;
813       insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
814       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
815                                           stack_pointer_rtx,
816                                           REG_NOTES (insn));
817       DONE;
818     }
821 (define_insn "*movhi_68hc12"
822   [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
823         (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
824   "TARGET_M6812"
825   "*
827   m68hc11_gen_movhi (insn, operands);
828   return \"\";
831 (define_insn "movhi_const0"
832   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
833         (const_int 0))]
834   "TARGET_M6811"
835   "@
836    clra\\n\\tclrb
837    ld%0\\t#0
838    clr\\t%b0\\n\\tclr\\t%h0")
840 (define_insn "*movhi_m68hc11"
841   [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
842         (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
843   "TARGET_M6811"
844   "*
846   m68hc11_gen_movhi (insn, operands);
847   return \"\";
850 ;;--------------------------------------------------------------------
851 ;;- 8-bit Move Operations.
852 ;; We don't need a scratch register.
853 ;;--------------------------------------------------------------------
855 ;; The *a alternative also clears the high part of the register.
856 ;; This should be ok since this is not the (strict_low_part) set.
858 (define_insn "movqi_const0"
859   [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
860         (const_int 0))]
861   ""
862   "@
863    clrb
864    clr\\t%b0
865    clr\\t%b0
866    ld%0\\t#0
867    clr%0")
870 ;; 8-bit operations on address registers.
872 ;; Switch temporary to the D register and load the value in B.
873 ;; This is possible as long as the address register does not
874 ;; appear in the source operand.
876 (define_split
877   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
878         (match_operand:QI 1 "general_operand" ""))]
879   "z_replacement_completed == 2
880    && !reg_mentioned_p (operands[0], operands[1])
881    && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
882   [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
883               (set (match_dup 2) (reg:HI D_REGNUM))])
884    (set (reg:QI D_REGNUM) (match_dup 1))
885    (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
886               (set (match_dup 2) (reg:HI D_REGNUM))])]
887   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
890 ;; 8-bit operations on address registers.
892 (define_split
893   [(set (match_operand:QI 0 "nonimmediate_operand" "")
894         (match_operand:QI 1 "hard_addr_reg_operand" ""))]
895   "z_replacement_completed == 2
896    && !reg_mentioned_p (operands[1], operands[0])
897    && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
898   [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
899               (set (match_dup 2) (reg:HI D_REGNUM))])
900    (set (match_dup 0) (reg:QI D_REGNUM))
901    (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
902               (set (match_dup 2) (reg:HI D_REGNUM))])]
903   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
905 (define_insn "*movqi2_push"
906   [(set (match_operand:QI 0 "push_operand" "=<,<")
907         (match_operand:QI 1 "general_operand" "d,!*A"))]
908   ""
909   "*
911   if (A_REG_P (operands[1]))
912     return \"#\";
914   cc_status = cc_prev_status;
915   return \"pshb\";
919 (define_expand "movqi"
920   [(set (match_operand:QI 0 "nonimmediate_operand" "")
921         (match_operand:QI 1 "general_operand" ""))]
922   ""
923   "
925   if (reload_in_progress)
926     {
927       if (m68hc11_reload_operands (operands))
928         {
929           DONE;
930         }
931     }
932   if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
933     {
934       if (GET_CODE (operands[0]) == MEM
935           && (GET_CODE (operands[1]) == MEM
936               || GET_CODE (operands[1]) == CONST_INT))
937         {
938           operands[1] = force_reg (QImode, operands[1]);
939         }
940       else if (IS_STACK_PUSH (operands[0])
941                && GET_CODE (operands[1]) != REG)
942         {
943           operands[1] = force_reg (QImode, operands[1]);
944         }
945     }
946   /* For push/pop, emit a REG_INC note to make sure the reload
947      inheritance and reload CSE pass notice the change of the stack
948      pointer.  */
949   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
950     {
951       rtx insn;
953       insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
954       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
955                                           stack_pointer_rtx,
956                                           REG_NOTES (insn));
957       DONE;
958     }
961 (define_insn "*movqi_68hc12"
962   [(set (match_operand:QI 0 "nonimmediate_operand" 
963                                 "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
964         (match_operand:QI 1 "general_operand" 
965                                 "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
966   "TARGET_M6812"
967   "*
969   m68hc11_gen_movqi (insn, operands);
970   return \"\";
973 (define_insn "*movqi_m68hc11"
974   [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
975         (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
976   "TARGET_M6811"
977   "*
979   m68hc11_gen_movqi (insn, operands);
980   return \"\";
983 ;;--------------------------------------------------------------------
984 ;;-  Swap registers
985 ;;--------------------------------------------------------------------
986 ;; Swapping registers is used for split patterns.
987 (define_insn "swap_areg"
988    [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
989          (match_operand:HI 1 "hard_reg_operand" "=A,d"))
990     (set (match_dup 1) (match_dup 0))]
991    ""
992    "*
994   m68hc11_output_swap (insn, operands);
995   return \"\";
998 ;;--------------------------------------------------------------------
999 ;;-  Truncation insns.
1000 ;;--------------------------------------------------------------------
1002 ;; Truncation are not necessary because GCC knows how to truncate,
1003 ;; specially when values lie in consecutive registers.
1006 (define_expand "floatunssisf2"
1007   [(set (match_operand:SF 0 "nonimmediate_operand" "")
1008         (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1009   ""
1010   "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT, 
1011                          SFmode, SImode, 2, operands);
1012    DONE;")
1014 (define_expand "floatunssidf2"
1015   [(set (match_operand:DF 0 "nonimmediate_operand" "")
1016         (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1017   ""
1018   "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT, 
1019                          DFmode, SImode, 2, operands);
1020    DONE;")
1022 ;;--------------------------------------------------------------------
1023 ;;-  Zero extension insns.
1024 ;;--------------------------------------------------------------------
1027 ;; 64-bit extend.  The insn will be split into 16-bit instructions just
1028 ;; before the final pass.  We need a scratch register for the split.
1029 ;; The final value can be generated on the stack directly.  This is more
1030 ;; efficient and useful for conversions made during parameter passing rules.
1032 (define_insn "zero_extendqidi2"
1033   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1034         (zero_extend:DI 
1035            (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1036    (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1037   ""
1038   "#")
1040 (define_split
1041   [(set (match_operand:DI 0 "push_operand" "")
1042         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1043    (clobber (match_scratch:HI 2 "=&dB"))]
1044   "z_replacement_completed == 2"
1045   [(const_int 0)]
1046   "
1048   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1049   rtx push = m68hc11_gen_lowpart (HImode, low);
1050   rtx src  = operands[1];
1052    /* Source operand must be in a hard register.  */
1053    if (!H_REG_P (src))
1054      {
1055        src = gen_rtx_REG (QImode, REGNO (operands[2]));
1056        emit_move_insn (src, operands[1]);
1057      }
1059    /* Source is in D, we can push B then one word of 0 and we do
1060       a correction on the stack pointer.  */
1061    if (D_REG_P (src))
1062      {
1063        emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1064        emit_move_insn (operands[2], const0_rtx);
1065        if (D_REG_P (operands[2]))
1066          {
1067            emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1068          }
1069        else
1070          {
1071            emit_move_insn (push, operands[2]);
1072            emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1073                                   gen_rtx_REG (HImode, HARD_SP_REGNUM),
1074                                   const1_rtx));
1075          }
1076      }
1077    else
1078      {
1079        /* Source is in X or Y.  It's better to push the 16-bit register
1080           and then to some stack adjustment.  */
1081        src = gen_rtx_REG (HImode, REGNO (src));
1082        emit_move_insn (push, src);
1083        emit_move_insn (operands[2], const0_rtx);
1084        emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1085                               gen_rtx_REG (HImode, HARD_SP_REGNUM),
1086                               const1_rtx));
1087        emit_move_insn (push, operands[2]);
1088        emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1089                               gen_rtx_REG (HImode, HARD_SP_REGNUM),
1090                               const1_rtx));
1091      }      
1092    emit_move_insn (push, operands[2]);
1093    emit_move_insn (push, operands[2]);
1094    emit_move_insn (push, operands[2]);
1095    DONE;
1098 (define_split
1099   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1100         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1101    (clobber (match_scratch:HI 2 "=&dB"))]
1102   "z_replacement_completed == 2"
1103   [(const_int 0)]
1104   "
1106   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1107   rtx low2 = m68hc11_gen_lowpart (HImode, low);
1108   rtx src  = operands[1];
1110    /* Source operand must be in a hard register.  */
1111    if (!H_REG_P (src))
1112      {
1113        src = gen_rtx_REG (QImode, REGNO (operands[2]));
1114        emit_move_insn (src, operands[1]);
1115      }
1117    emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1118    emit_move_insn (operands[2], const0_rtx);
1119    src = gen_rtx_REG (QImode, REGNO (operands[2]));
1120    emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1122    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1123    low = m68hc11_gen_highpart (SImode, operands[0]);
1124    emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1125    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1126    DONE;
1129 (define_insn "zero_extendhidi2"
1130   [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1131         (zero_extend:DI 
1132             (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1133    (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1134   ""
1135   "#")
1137 (define_split
1138   [(set (match_operand:DI 0 "non_push_operand" "")
1139         (zero_extend:DI 
1140             (match_operand:HI 1 "nonimmediate_operand" "")))
1141    (clobber (match_scratch:HI 2 ""))]
1142   "z_replacement_completed == 2"
1143   [(const_int 0)]
1144   "
1146    rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1147    rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1148    rtx src  = operands[1];
1150    /* Make sure the source is in a hard register.  */
1151    if (!H_REG_P (src))
1152      {
1153        src = operands[2];
1154        emit_move_insn (src, operands[1]);
1155      }
1157    /* Move the low part first for the push.  */
1158    emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1160    /* Now, use the scratch register to fill in the zeros.  */
1161    emit_move_insn (operands[2], const0_rtx);
1162    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1163    emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1164    emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1165    DONE;
1168 (define_insn "zero_extendsidi2"
1169   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1170         (zero_extend:DI 
1171             (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1172    (clobber (match_scratch:HI 2 "=d,d,d,d"))]
1173   ""
1174   "#")
1176 (define_split 
1177   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1178         (zero_extend:DI 
1179             (match_operand:SI 1 "nonimmediate_operand" "")))
1180    (clobber (match_scratch:HI 2 ""))]
1181   "z_replacement_completed == 2"
1182   [(const_int 0)]
1183   "
1185   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1186   rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1188   /* Move the low part first so that this is ok for a push.  */
1189   m68hc11_split_move (low, operands[1], operands[2]);
1191   /* Use the scratch register to clear the high part of the destination.  */
1192   emit_move_insn (operands[2], const0_rtx);
1193   emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1194   emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1195   DONE;
1199 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1200 ;; because it's less efficient.
1202 (define_insn "zero_extendhisi2"
1203   [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1204         (zero_extend:SI 
1205             (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1206    (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1207   ""
1208   "#")
1210 (define_split
1211   [(set (match_operand:SI 0 "non_push_operand" "")
1212         (zero_extend:SI 
1213             (match_operand:HI 1 "nonimmediate_operand" "")))
1214    (clobber (match_scratch:HI 2 ""))]
1215   "reload_completed"
1216   [(const_int 0)]
1217   "
1219   rtx src = operands[1];
1221   if (!H_REG_P (src) && !H_REG_P (operands[0]))
1222     {
1223       src = operands[2];
1224       emit_move_insn (src, operands[1]);
1225     }
1226   emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1227   emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1228   DONE;
1231 (define_insn "zero_extendqisi2"
1232   [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1233       (zero_extend:SI 
1234           (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1235   ""
1236   "#")
1238 (define_split 
1239   [(set (match_operand:SI 0 "non_push_operand" "")
1240         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1241   "reload_completed && !X_REG_P (operands[0])"
1242   [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1243    (set (match_dup 3) (const_int 0))]
1244   "
1245    operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1246    operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1248 (define_split 
1249   [(set (match_operand:SI 0 "hard_reg_operand" "")
1250         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1251   "z_replacement_completed == 2 && X_REG_P (operands[0])"
1252   [(set (match_dup 2) (match_dup 3))
1253    (set (match_dup 4) (const_int 0))
1254    (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1255   "
1256    if (X_REG_P (operands[1]))
1257      {
1258         emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
1259                                   gen_rtx_REG (HImode, HARD_X_REGNUM)));
1260         emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
1261                                          gen_rtx_REG (QImode, HARD_D_REGNUM)));
1262         emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
1263                         const0_rtx);
1264         DONE;
1265      }
1267    if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
1268      {
1269         emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1270                                                               operands[0]),
1271                                          operands[1]));
1272         emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
1273         DONE;
1274      }
1275    operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1276    operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1277    if (A_REG_P (operands[1]))
1278      {
1279        operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1280        operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
1281        operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
1282      }
1283    else
1284      {
1285        operands[5] = operands[2] =
1286        operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1287        operands[6] = operands[1];
1288      }
1291 (define_insn "zero_extendqihi2"
1292   [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
1293         (zero_extend:HI 
1294             (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1295   ""
1296  "*
1298   if (A_REG_P (operands[0]))
1299     return \"#\";
1301   if (H_REG_P (operands[0]))
1302     {
1303       output_asm_insn (\"clra\", operands);
1304       if (operands[0] != operands[1]
1305           && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1306         {
1307           if (X_REG_P (operands[1])
1308               || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1309             {
1310               output_asm_insn (\"stx\\t%t1\", operands);
1311               output_asm_insn (\"ldab\\t%T0\", operands);
1312             }
1313           else if (Y_REG_P (operands[1])
1314                    || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1315             {
1316               output_asm_insn (\"sty\\t%t1\", operands);
1317               output_asm_insn (\"ldab\\t%T0\", operands);
1318             }
1319           else
1320             {
1321               output_asm_insn (\"ldab\\t%b1\", operands);
1322             }
1323           cc_status.flags |= CC_NOT_NEGATIVE;
1324         }
1325       else
1326         {
1327           /* Status refers to the clra insn. Status is ok for others
1328            * since we have loaded the value in B.
1329            */
1330           CC_STATUS_INIT;
1331         }
1332       return \"\";
1333     }
1335   if (A_REG_P (operands[1]))
1336     {
1337       output_asm_insn (\"st%1\\t%0\", operands);
1338       output_asm_insn (\"clr\\t%h0\", operands);
1339       CC_STATUS_INIT;
1340     }
1341   else
1342     {
1343       output_asm_insn (\"clr\\t%h0\", operands);
1344       output_asm_insn (\"stab\\t%b0\", operands);
1345       cc_status.flags |= CC_NOT_NEGATIVE;
1346     }
1348   return \"\";
1352 ;;--------------------------------------------------------------------
1353 ;;-  Sign extension insns.
1354 ;;--------------------------------------------------------------------
1356 (define_insn "extendqisi2"
1357   [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1358         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1359   ""
1360   "*
1362   rtx ops[3];
1363   int need_tst = 0;
1365   /* The 68HC12 has a sign-extension instruction.  Use it when the
1366      destination is the register (X,D).  First sign-extend the low
1367      part and fill X with the sign-extension of the high part.  */
1368   if (TARGET_M6812 && X_REG_P (operands[0]))
1369     {
1370       if (!D_REG_P (operands[1]))
1371         {
1372           ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1373           ops[1] = operands[1];
1374           m68hc11_gen_movqi (insn, ops);
1375         }
1376       return \"sex\\tb,d\\n\\tsex\\ta,x\";
1377     }
1379   ops[2] = gen_label_rtx ();
1381   if (X_REG_P (operands[1]))
1382     {
1383       output_asm_insn (\"xgdx\", operands);
1384       need_tst = 1;
1385     }
1386   else if (X_REG_P (operands[0]))
1387     {
1388       /* X can be used as an indexed addressing in the source.
1389          Get the value before clearing it.  */
1390       if (reg_mentioned_p (ix_reg, operands[1]))
1391         {
1392           output_asm_insn (\"ldab\\t%b1\", operands);
1393           need_tst = 1;
1394         }
1395       output_asm_insn (\"ldx\\t#0\", operands);
1396     }
1398   output_asm_insn (\"clra\", operands);
1399   if (!X_REG_P (operands[0]))
1400     {
1401       ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1402       ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1404       if (IS_STACK_PUSH (operands[0]))
1405         {
1406           output_asm_insn (\"pshb\", ops);
1407           output_asm_insn (\"tstb\", ops);
1408         }
1409       else
1410         {
1411           output_asm_insn (\"stab\\t%b1\", ops);
1412         }
1413     }
1414   else if (D_REG_P (operands[1]) || need_tst)
1415     {
1416       output_asm_insn (\"tstb\", operands);
1417     }
1418   else
1419     {
1420       output_asm_insn (\"ldab\\t%b1\", operands);
1421     }
1422   output_asm_insn (\"bpl\\t%l2\", ops);
1423   output_asm_insn (\"deca\", operands);
1424   if (X_REG_P (operands[0]))
1425     output_asm_insn (\"dex\", operands);
1427   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1429   if (!X_REG_P (operands[0]))
1430     {
1431       if (IS_STACK_PUSH (operands[0]))
1432         {
1433           output_asm_insn (\"psha\", ops);
1434           output_asm_insn (\"psha\", ops);
1435           output_asm_insn (\"psha\", ops);
1436         }
1437       else
1438         {
1439           output_asm_insn (\"staa\\t%h0\", ops);
1441           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1442           if (dead_register_here (insn, d_reg))
1443             {
1444               output_asm_insn (\"tab\", ops);
1445               output_asm_insn (\"std\\t%0\", ops);
1446             }
1447           else
1448             {
1449               output_asm_insn (\"staa\\t%b0\", ops);
1450               output_asm_insn (\"staa\\t%h0\", ops);
1451             }
1452         }
1453     }
1455   CC_STATUS_INIT;
1456   return \"\";
1460 (define_insn "extendqihi2"
1461   [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1462         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1463   ""
1464   "*
1466   rtx ops[2];
1468   if (A_REG_P (operands[0]))
1469     return \"#\";
1471   ops[0] = gen_label_rtx ();
1472   if (D_REG_P (operands[0]))
1473     {
1474       if (TARGET_M6812)
1475         {
1476           if (!D_REG_P (operands[1]))
1477             {
1478               ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1479               ops[1] = operands[1];
1480               m68hc11_gen_movqi (insn, ops);
1481             }
1482           return \"sex\\tb,d\";
1483         }
1484       output_asm_insn (\"clra\", operands);
1485       if (H_REG_P (operands[1]))
1486         {
1487           output_asm_insn (\"tstb\", operands);
1488         }
1489       else
1490         {
1491           output_asm_insn (\"ldab\\t%b1\", operands);
1492         }
1493       output_asm_insn (\"bpl\\t%l0\", ops);
1494       output_asm_insn (\"deca\", operands);
1496       (*targetm.asm_out.internal_label) (asm_out_file, \"L\", 
1497                                  CODE_LABEL_NUMBER (ops[0]));
1498     }
1499    else
1500     {
1501       output_asm_insn (\"clr\\t%h0\", operands);
1502       if (m68hc11_register_indirect_p (operands[1], HImode))
1503         {
1504           ops[1] = operands[1];
1505           output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1506           CC_STATUS_INIT;
1507         }
1508       else
1509         {
1510           output_asm_insn (\"tst\\t%b1\", operands);
1511           output_asm_insn (\"bpl\\t%l0\", ops);
1512         }
1513       output_asm_insn (\"dec\\t%h0\", operands);
1514       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1515                                  CODE_LABEL_NUMBER (ops[0]));
1516     }
1518   return \"\";
1522 ;; Split the special case where the source of the sign extend is
1523 ;; either Y or Z. In that case, we can't move the source in the D
1524 ;; register directly. The movhi pattern handles this move by using
1525 ;; a temporary scratch memory location.
1527 (define_split
1528   [(set (match_operand:SI 0 "register_operand" "")
1529         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1530   "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1531   [(set (reg:HI D_REGNUM) (match_dup 1))
1532    (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1533   "")
1535 (define_insn "extendhisi2"
1536   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1537         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1538   ""
1539   "*
1541   rtx ops[2];
1542   int x_reg_used;
1544   if (Y_REG_P (operands[1]))
1545     return \"#\";
1547   if (X_REG_P (operands[1]))
1548     {
1549       output_asm_insn (\"xgdx\", operands);
1550       x_reg_used = 1;
1551     }
1552   else
1553     {
1554       /* X can be used as an indexed addressing in the source.
1555          Get the value before clearing it.  */
1556       x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1557       if (x_reg_used)
1558         {
1559           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1560           ops[1] = operands[1];
1561           m68hc11_gen_movhi (insn, ops);
1562         }
1563     }
1565   CC_STATUS_INIT;
1566   if (TARGET_M6812 && 0)
1567     {
1568       /* This sequence of code is larger than the one for 68HC11.
1569          Don't use it; keep it for documentation.  */
1570       if (!D_REG_P (operands[1]) && !x_reg_used)
1571         {
1572           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1573           ops[1] = operands[1];
1574           m68hc11_gen_movhi (insn, ops);
1575         }
1576       output_asm_insn (\"sex\\ta,x\", operands);
1577       output_asm_insn (\"xgdx\", operands);
1578       output_asm_insn (\"sex\\ta,d\", operands);
1579       return \"xgdx\";
1580     }
1582   output_asm_insn (\"ldx\\t#0\", operands);
1583   if (D_REG_P (operands[1]) || x_reg_used)
1584     {
1585       output_asm_insn (\"tsta\", operands);
1586     }
1587   else
1588     {
1589       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1590       ops[1] = operands[1];
1591       m68hc11_gen_movhi (insn, ops);
1592     }
1594   ops[0] = gen_label_rtx ();
1595   output_asm_insn (\"bpl\\t%l0\", ops);
1596   output_asm_insn (\"dex\", operands);
1597   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1599   return \"\";
1603 ;;--------------------------------------------------------------------
1604 ;;- Min and Max instructions (68HC12).
1605 ;;--------------------------------------------------------------------
1606 (define_insn "uminqi3"
1607   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1608         (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1609                  (match_operand:QI 2 "general_operand" "m,d")))]
1610   "TARGET_M6812 && TARGET_MIN_MAX"
1611   "*
1613   /* Flags are set according to (sub:QI (operand 1) (operand2)).
1614      The mina/minm use A as the source or destination.  This is the
1615      high part of D.  There is no way to express that in the pattern
1616      so we must use 'exg a,b' to put the operand in the good register.  */
1617   CC_STATUS_INIT;
1618   if (D_REG_P (operands[0]))
1619     {
1620       return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1621     }
1622   else
1623     {
1624       return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1625     }
1628 (define_insn "umaxqi3"
1629   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1630         (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1631                  (match_operand:QI 2 "general_operand" "m,d")))]
1632   "TARGET_M6812 && TARGET_MIN_MAX"
1633   "*
1635   /* Flags are set according to (sub:QI (operand 1) (operand2)).
1636      The maxa/maxm use A as the source or destination.  This is the
1637      high part of D.  There is no way to express that in the pattern
1638      so we must use 'exg a,b' to put the operand in the good register.  */
1639   CC_STATUS_INIT;
1640   if (D_REG_P (operands[0]))
1641     {
1642       return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1643     }
1644   else
1645     {
1646       return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1647     }
1650 (define_insn "uminhi3"
1651   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1652         (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1653                  (match_operand:HI 2 "general_operand" "m,d")))]
1654   "TARGET_M6812 && TARGET_MIN_MAX"
1655   "*
1657   /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
1658   CC_STATUS_INIT;
1659   if (D_REG_P (operands[0]))
1660     {
1661       return \"emind\\t%2\";
1662     }
1663   else
1664     {
1665       return \"eminm\\t%0\";
1666     }
1669 (define_insn "umaxhi3"
1670   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1671         (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1672                  (match_operand:HI 2 "general_operand" "m,d")))]
1673   "TARGET_M6812 && TARGET_MIN_MAX"
1674   "*
1676   /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
1677   CC_STATUS_INIT;
1678   if (D_REG_P (operands[0]))
1679     {
1680       return \"emaxd\\t%2\";
1681     }
1682   else
1683     {
1684       return \"emaxm\\t%0\";
1685     }
1689 ;;--------------------------------------------------------------------
1690 ;;- Add instructions.
1691 ;;--------------------------------------------------------------------
1692 ;; 64-bit: Use a library call because what GCC generates is huge.
1694 (define_expand "adddi3"
1695   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1696         (plus:DI (match_operand:DI 1 "general_operand" "")
1697                  (match_operand:DI 2 "general_operand" "")))]
1698   ""
1699   "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1700    DONE;")
1703 ;; - 32-bit Add.
1705 (define_expand "addsi3"
1706   [(parallel [(set (match_operand:SI 0 "register_operand" "")
1707                      (plus:SI (match_operand:SI 1 "general_operand" "")
1708                               (match_operand:SI 2 "general_operand" "")))
1709               (clobber (match_scratch:HI 3 ""))])]
1710   ""
1711   "")
1713 (define_insn "*addsi3_zero_extendhi"
1714   [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1715         (plus:SI (zero_extend:SI 
1716                  (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1717                  (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1718    (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1719   ""
1720   "*
1722   rtx ops[3];
1724   if (X_REG_P (operands[2]))
1725     {
1726       ops[0] = operands[1];
1727     }
1728   else
1729     {
1730       if (X_REG_P (operands[1]))
1731         {
1732           output_asm_insn (\"xgdx\", ops);
1733         }
1734       else if (!D_REG_P (operands[1]))
1735         {
1736           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1737           ops[1] = operands[1];
1738           m68hc11_gen_movhi (insn, ops);
1739         }
1740       ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1741       ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1742     }
1743   ops[2] = gen_label_rtx ();
1745   /* ldx preserves the carry, propagate it by incrementing X directly.  */
1746   output_asm_insn (\"addd\\t%0\", ops);
1747   if (!X_REG_P (operands[2]))
1748     output_asm_insn (\"ldx\\t%1\", ops);
1750   output_asm_insn (\"bcc\\t%l2\", ops);
1751   output_asm_insn (\"inx\", ops);
1753   CC_STATUS_INIT;
1754   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1755   return \"\";  
1759 (define_split /* "*addsi3_zero_extendqi" */
1760   [(set (match_operand:SI 0 "register_operand" "")
1761         (plus:SI (zero_extend:SI 
1762                    (match_operand:QI 1 "general_operand" ""))
1763                  (match_operand:SI 2 "memory_operand" "")))
1764    (clobber (match_scratch:HI 3 "=X,X"))]
1765   "reload_completed"
1766   [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1767    (parallel [(set (match_dup 0) 
1768                    (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1769               (clobber (match_dup 3))])]
1770   "")
1772 (define_insn "*addsi3_zero_extendqi"
1773   [(set (match_operand:SI 0 "register_operand" "=D,D")
1774         (plus:SI (zero_extend:SI 
1775                    (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1776                  (match_operand:SI 2 "general_operand" "miD,!muiD")))
1777    (clobber (match_scratch:HI 3 "=X,X"))]
1778   ""
1779   "*
1781   rtx ops[4];
1783   if (GET_CODE (operands[2]) == MEM)
1784     return \"#\";
1786   if (X_REG_P (operands[2]))
1787     {
1788       if (H_REG_P (operands[1]))
1789         {
1790           ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1791           ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1792           m68hc11_gen_movhi (insn, ops);
1793         }
1794       else
1795         {
1796           ops[0] = operands[1];
1797         }
1798       ops[1] = const0_rtx;
1799     }
1800   else
1801     {
1802       if (X_REG_P (operands[1]))
1803         {
1804           output_asm_insn (\"xgdx\", ops);
1805         }
1806       else if (!D_REG_P (operands[1]))
1807         {
1808           ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1809           ops[1] = operands[1];
1810           m68hc11_gen_movqi (insn, ops);
1811         }
1813       ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1814       ops[1] = ops[0];
1815       ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1816       output_asm_insn (\"clra\", ops);
1817     }
1819   /* ldx preserves the carry, propagate it by incrementing X directly.  */
1820   output_asm_insn (\"addb\\t%b0\", ops);
1821   output_asm_insn (\"adca\\t%h1\", ops);
1822   if (!X_REG_P (operands[2]))
1823     output_asm_insn (\"ldx\\t%2\", ops);
1825   /* If the above adca was adding some constant, we don't need to propagate
1826      the carry unless the constant was 0xff.  */
1827   if (X_REG_P (operands[2])
1828       || GET_CODE (ops[1]) != CONST_INT
1829       || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1830     {
1831       ops[3] = gen_label_rtx ();
1833       output_asm_insn (\"bcc\\t%l3\", ops);
1834       output_asm_insn (\"inx\", ops);
1836       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1837                                  CODE_LABEL_NUMBER (ops[3]));
1838     }
1839   CC_STATUS_INIT;
1840   return \"\";  
1843 (define_insn "*addsi3"
1844   [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
1845         (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1846                  (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
1847    (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1848   ""
1849   "*
1851   rtx   ops[3];
1852   const char* add_insn;
1853   const char* inc_insn;
1854   const char* incb_mem;
1855   const char* inch_mem;
1856   HOST_WIDE_INT val;
1858   if (which_alternative > 2)
1859     {
1860       return \"#\";
1861     }
1863   val = INTVAL (operands[2]);
1864   if ((val & 0x0ffffL) == 0)
1865     {
1866       if (!H_REG_P (operands[0]))
1867         {
1868           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1869           ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1870           output_asm_insn (\"ldd\\t%0\", ops);
1871           output_asm_insn (\"addd\\t%1\", ops);
1872           output_asm_insn (\"std\\t%0\", ops);
1873           return \"\";
1874         }
1875       else if (val == 1)
1876         {
1877           return \"inx\";
1878         }
1879       else
1880         {
1881           return \"#\";
1882         }
1883     }
1884   if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1885     {
1886       return \"#\";
1887     }
1889   if (val >= 0)
1890     {
1891       ops[1]   = operands[2];
1892       add_insn = \"addd\\t%1\";
1893       inc_insn = \"inx\\t\";
1894       incb_mem  = \"inc\\t%b1\";
1895       inch_mem  = \"inc\\t%h1\";
1896     }
1897   else
1898     {
1899       ops[1] = GEN_INT (- val);
1900       add_insn = \"subd\\t%1\";
1901       inc_insn = \"dex\";
1902       incb_mem  = \"dec\\t%b1\";
1903       inch_mem  = \"dec\\t%h1\";
1904     }
1905       
1906   ops[2] = gen_label_rtx ();
1907   if (!H_REG_P (operands[0]))
1908     {
1909       ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1910       output_asm_insn (\"ldd\\t%0\", ops);
1911     }
1912   output_asm_insn (add_insn, ops);
1913   if (!H_REG_P (operands[0]))
1914     {
1915       output_asm_insn (\"std\\t%0\", ops);
1916     }
1917   output_asm_insn (\"bcc\\t%l2\", ops);
1918   if (H_REG_P (operands[0]))
1919     {
1920       output_asm_insn (inc_insn, ops);
1921     }
1922   else
1923     {
1924       ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1925       ops[1] = ops[0];
1926       if (INTVAL (operands[2]) < 0)
1927         {
1928           output_asm_insn (\"ldd\\t%1\", ops);
1929           output_asm_insn (\"addd\\t#-1\", ops);
1930           output_asm_insn (\"std\\t%1\", ops);
1931         }
1932       else
1933         {
1934           output_asm_insn (incb_mem, ops);
1935           output_asm_insn (\"bne\\t%l2\", ops);
1936           output_asm_insn (inch_mem, ops);
1937         }
1938     }
1939   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1941   CC_STATUS_INIT;
1942   return \"\";
1945 (define_split
1946   [(set (match_operand:SI 0 "register_operand" "")
1947         (plus:SI (match_operand:SI 1 "register_operand" "")
1948                  (match_operand:SI 2 "const_int_operand" "")))
1949    (clobber (match_scratch:HI 3 ""))]
1950   "reload_completed && z_replacement_completed == 2
1951    && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
1952   [(set (match_dup 5) (match_dup 6))
1953    (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
1954    (set (match_dup 6) (match_dup 5))]
1955   "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
1956    if (X_REG_P (operands[0]))
1957      {
1958        operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1959      }
1960    else
1961      {
1962        operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
1963        operands[5] = operands[3];
1964      }
1965    ")
1967 (define_split
1968   [(set (match_operand:SI 0 "register_operand" "")
1969         (plus:SI (match_operand:SI 1 "register_operand" "")
1970                  (match_operand:SI 2 "general_operand" "")))
1971    (clobber (match_scratch:HI 3 "=X"))]
1972   "reload_completed && z_replacement_completed == 2
1973    && (GET_CODE (operands[2]) != CONST_INT || 
1974         (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
1975   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
1976    (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
1977               (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
1978    (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
1979    (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
1980    (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
1981               (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
1982   "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
1983    operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
1984    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
1985    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
1988 ;; Instruction generated to propagate the carry of a 16-bit add
1989 ;; to the upper 16-bit part (in register X).
1991 (define_insn "*addsi_carry"
1992   [(set (match_operand:HI 0 "register_operand" "=x")
1993            (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
1994                              (const_int 0)) 
1995                     (reg:HI CC_REGNUM)))]
1996   ""
1997   "*
1999   rtx ops[2];
2001   ops[0] = gen_label_rtx ();
2002   output_asm_insn (\"bcc\\t%l0\", ops);
2003   output_asm_insn (\"in%0\", operands);
2004   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2005   CC_STATUS_INIT;
2006   return \"\";
2010 ;; - 16-bit Add.
2012 (define_expand "addhi3"
2013   [(set (match_operand:HI 0 "register_operand" "")
2014            (plus:HI (match_operand:HI 1 "register_operand" "")
2015                     (match_operand:HI 2 "general_operand" "")))]
2016   ""
2017   "
2019   if (TARGET_M6811 && SP_REG_P (operands[0]))
2020     {
2021       emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
2022                          gen_rtx_SET (VOIDmode,
2023                                   operand0,
2024                                   gen_rtx_PLUS (HImode,
2025                                            operand1, operand2)),
2026                         gen_rtx_CLOBBER (VOIDmode,
2027                                 gen_rtx_SCRATCH (HImode)))));
2028       DONE;
2029     }
2032 (define_insn "*addhi3_68hc12"
2033   [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
2034         (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
2035                  (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
2036   "TARGET_M6812"
2037   "*
2039   int val;
2040   const char* insn_code;
2042   if (which_alternative >= 4)
2043     {
2044       if (A_REG_P (operands[2]))
2045         {
2046           CC_STATUS_INIT;
2047           output_asm_insn (\"xgd%2\", operands);
2048           output_asm_insn (\"lea%0 d,%0\", operands);
2049           return \"xgd%2\";
2050         }
2051       return \"#\";
2052     }
2054   if (D_REG_P (operands[0]))
2055     {
2056       if (X_REG_P (operands[2]))
2057         {
2058           m68hc11_notice_keep_cc (operands[0]);
2059           output_asm_insn (\"xgdx\", operands);
2060           output_asm_insn (\"leax\\td,%2\", operands);
2061           return \"xgdx\";
2062         }
2063       else if (Y_REG_P (operands[2]))
2064         {
2065           m68hc11_notice_keep_cc (operands[0]);
2066           output_asm_insn (\"xgdy\", operands);
2067           output_asm_insn (\"leay\\td,%2\", operands);
2068           return \"xgdy\";
2069         }
2070       else if (SP_REG_P (operands[2]))
2071         {
2072           output_asm_insn (\"sts\\t%t0\", operands);
2073           return \"addd\\t%t0\";
2074         }
2075       return \"addd\\t%2\";
2076     }
2078   if (GET_CODE (operands[2]) == CONST_INT)
2079     val = INTVAL (operands[2]);
2080   else
2081     val = 1000;
2083   if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
2084     {
2085       m68hc11_notice_keep_cc (operands[0]);
2086       switch (REGNO (operands[0]))
2087         {
2088         case HARD_X_REGNUM:
2089           return \"leax\\t%i2,%1\";
2091         case HARD_Y_REGNUM:
2092           return \"leay\\t%i2,%1\";
2094         case HARD_SP_REGNUM:
2095           return \"leas\\t%i2,%1\";
2097         default:
2098           fatal_insn (\"Invalid operands in the instruction\", insn);
2099         }
2100     }
2101   if (val > 0)
2102     {
2103       insn_code = X_REG_P (operands[0]) ? \"inx\"
2104                 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2105     }
2106   else
2107     {
2108       val  = -val;
2109       insn_code = X_REG_P (operands[0]) ? \"dex\"
2110                 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2111     }
2113   /* For X and Y increment, the flags are not complete. Only the Z flag
2114      is updated. For SP increment, flags are not changed.  */
2115   if (SP_REG_P (operands[0]))
2116     {
2117       cc_status = cc_prev_status; 
2118       if (INTVAL (operands[2]) < 0)
2119         {
2120           while (val > 2)
2121             {
2122               output_asm_insn (\"pshx\", operands);
2123               val -= 2;
2124             }
2125           if (val == 0)
2126             return \"\";
2127         }     
2128     }
2129   else
2130     {
2131       CC_STATUS_INIT;
2132     }
2134   while (val)
2135     {
2136       output_asm_insn (insn_code, operands);
2137       val--;
2138     }
2139   return \"\";
2143 ;; Specific pattern to add to the stack pointer.
2144 ;; We also take care of the clobbering of the IY register.
2146 (define_insn "addhi_sp"
2147   [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2148           (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2149                    (match_operand:HI 2 "general_operand" "P,im,u,im")))
2150    (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2151   "!TARGET_M6812"
2152   "*
2154   HOST_WIDE_INT val;
2156   if (optimize && Y_REG_P (operands[3])
2157       && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
2158     operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
2160   if (GET_CODE (operands[2]) == CONST_INT
2161       && (val = INTVAL (operands[2])) != 0
2162       && (CONST_OK_FOR_LETTER_P (val, 'P')
2163           || (val > 0 && val <= 8)))
2164     {
2165       while (val > 1 || val < -1)
2166         {
2167           if (val > 0)
2168             {
2169               if (!H_REG_P (operands[3]))
2170                 break;
2172               output_asm_insn (\"pul%3\", operands);
2173               val -= 2;
2174             }
2175           else
2176             {
2177               output_asm_insn (\"pshx\", operands);
2178               val += 2;
2179             }
2180         }
2181       while (val != 0)
2182         {
2183           if (val > 0)
2184             {
2185               output_asm_insn (\"ins\", operands);
2186               val--;
2187             }
2188           else
2189             {
2190               output_asm_insn (\"des\", operands);
2191               val++;
2192             }
2193         }
2194       cc_status = cc_prev_status;
2195       return \"\";
2196     }
2198   /* Need to transfer to SP to X/Y and then to D register.
2199      Register X/Y is lost, this is specified by the (clobber) statement.  */
2200   output_asm_insn (\"ts%3\", operands);
2201   if (GET_CODE (operands[2]) == CONST_INT
2202       && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
2203       && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
2204     {
2205       output_asm_insn (\"ldab\\t%2\", operands);
2206       output_asm_insn (\"ab%3\", operands);
2207       CC_STATUS_INIT;
2208     }
2209   else
2210     {
2211       output_asm_insn (\"xgd%3\", operands);
2212       output_asm_insn (\"addd\\t%2\", operands);
2213       output_asm_insn (\"xgd%3\", operands);
2214     }
2216    /* The status flags correspond to the addd.  xgdy and tys do not
2217       modify the flags.  */
2218   return \"t%3s\";
2221 (define_insn "*addhi3"
2222   [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
2223         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
2224                  (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
2225   "TARGET_M6811"
2226   "*
2228   const char* insn_code;
2229   int val;
2231   if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2232     {
2233       output_asm_insn (\"sts\\t%t0\", operands);
2234       output_asm_insn (\"addd\\t%t0\", operands);
2235       return \"addd\\t#1\";
2236     }
2237   if (GET_CODE (operands[2]) != CONST_INT)
2238     {
2239       /* Adding to an address register or with another/same register
2240          is not possible. This must be replaced.  */
2241       if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2242         return \"#\";
2244       return \"addd\\t%2\";
2245     }
2246   val = INTVAL (operands[2]);
2247   if (!SP_REG_P (operands[0]))
2248     {
2249       if (D_REG_P (operands[0]))
2250         {
2251           if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2252             {
2253               CC_STATUS_INIT;
2254               return \"adda\\t%h2\";
2255             }
2256           else
2257             {
2258               return \"addd\\t%2\";
2259             }
2260         }
2261       else if (GET_CODE (operands[2]) != CONST_INT
2262                || INTVAL (operands[2]) < -4
2263                || INTVAL (operands[2]) > 4)
2264         return \"#\";
2265     }
2266   if (val > 0)
2267     {
2268       insn_code = X_REG_P (operands[0]) ? \"inx\"
2269                     : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2270     }
2271   else
2272     {
2273       val  = -val;
2274       insn_code = X_REG_P (operands[0]) ? \"dex\"
2275                     : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2276     }
2278   /* For X and Y increment, the flags are not complete.  Only the Z flag
2279      is updated.  For SP increment, flags are not changed.  */
2280   if (SP_REG_P (operands[0]))
2281     {
2282       cc_status = cc_prev_status; 
2283       if (INTVAL (operands[2]) < 0)
2284         {
2285           while (val >= 2)
2286             {
2287               output_asm_insn (\"pshx\", operands);
2288               val -= 2;
2289             }
2290         }
2291       else if (optimize && dead_register_here (insn, ix_reg))
2292         {
2293           while (val >= 2)
2294             {
2295               output_asm_insn (\"pulx\", operands);
2296               val -= 2;
2297             }
2298         }
2299     }
2300   else
2301     {
2302       CC_STATUS_INIT;
2303     }
2305   while (val)
2306     {
2307       output_asm_insn (insn_code, operands);
2308       val--;
2309     }
2310   return \"\";
2313 (define_insn "*addhi3_zext"
2314   [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2315         (plus:HI (zero_extend:HI 
2316                      (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2317                  (match_operand:HI 2 "general_operand" "0,0")))]
2318   ""
2319   "*
2321   CC_STATUS_INIT;
2322   if (A_REG_P (operands[0]))
2323     return \"ab%0\";
2324   else if (A_REG_P (operands[1]))
2325     return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2326   else 
2327     return \"addb\\t%b1\\n\\tadca\\t#0\";
2331 ;; Translate d = d + d into d = << 1
2332 ;; We have to do this because adding a register to itself is not possible.
2333 ;; ??? It's not clear whether this is really necessary.
2335 (define_split
2336   [(set (match_operand:QI 0 "hard_reg_operand" "")
2337         (plus:QI (match_dup 0)
2338                  (match_dup 0)))]
2339   "0 && reload_completed"
2340   [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2341   "")
2343 (define_insn "addqi3"
2344   [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2345         (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2346                  (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2347   ""
2348   "*
2350   if (GET_CODE (operands[2]) == CONST_INT)
2351     {
2352       if (INTVAL (operands[2]) == 1)
2353         {
2354           if (DA_REG_P (operands[0]))
2355             {
2356               return \"inca\";
2357             }
2358           else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2359            {
2360              return \"incb\";
2362            }
2363           else if (A_REG_P (operands[0]))
2364            {
2365              /* This applies on the 16-bit register.  This should be ok since
2366                 this is not a strict_low_part increment.  */
2367              return \"in%0\";
2368            }
2369           else
2370            {
2371              return \"inc\\t%b0\";
2372            }
2373         }
2374       else if (INTVAL (operands[2]) == -1)
2375         {
2376           if (DA_REG_P (operands[0]))
2377             {
2378               return \"deca\";
2379             }
2380           else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2381             {
2382               return \"decb\";
2383             }
2384           else if (A_REG_P (operands[0]))
2385             {
2386              /* This applies on the 16-bit register.  This should be ok since
2387                 this is not a strict_low_part decrement.  */
2388               return \"de%0\";
2389             }
2390           else
2391             {
2392               return \"dec\\t%b0\";
2393             }
2394         }
2395     }
2396   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2397     return \"#\";
2398   else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2399     return \"addb\\t%b2\";
2400   else
2401     return \"adda\\t%b2\";
2405 ;; add with carry is used for 32-bit add.
2407 (define_insn "*adcq"
2408   [(set (match_operand:QI 0 "register_operand" "=q")
2409         (plus:QI (plus:QI (reg:QI CC_REGNUM)
2410                           (match_operand:QI 1 "register_operand" "%0"))
2411                  (match_operand:QI 2 "general_operand" "ium")))]
2412   ""
2413   "adc%0\\t%b2")
2415 ;;--------------------------------------------------------------------
2416 ;;- Subtract instructions.
2417 ;;--------------------------------------------------------------------
2419 (define_expand "subdi3"
2420   [(set (match_operand:DI 0 "nonimmediate_operand" "")
2421         (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2422                   (match_operand:DI 2 "general_operand" "")))]
2423   ""
2424   "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2425    DONE;")
2428 ;; 32-bit Subtract (see addsi3)
2429 ;; Subtract with a constant are handled by addsi3.
2432 ;; - 32-bit Add.
2434 (define_expand "subsi3"
2435   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2436                      (minus:SI (match_operand:SI 1 "register_operand" "")
2437                               (match_operand:SI 2 "general_operand" "")))
2438               (clobber (match_scratch:HI 3 ""))])]
2439   ""
2440   "")
2442 (define_insn "*subsi3"
2443   [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
2444         (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2445                   (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
2446    (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
2447   ""
2448   "#")
2450 (define_insn "*subsi3_zero_extendhi"
2451   [(set (match_operand:SI 0 "register_operand" "=D")
2452         (minus:SI (match_operand:SI 1 "register_operand" "0")
2453             (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
2454    (clobber (match_scratch:HI 3 "=X"))]
2455   ""
2456   "*
2458   rtx ops[2];
2460   if (A_REG_P (operands[2]))
2461     {
2462       if (TARGET_M6812)
2463         ops[0] = gen_rtx_MEM (HImode,
2464                           gen_rtx_PRE_DEC (HImode,
2465                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2466       else
2467         ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2469       ops[1] = operands[2];
2470       m68hc11_gen_movhi (insn, ops);
2471       if (TARGET_M6812)
2472         operands[2] = gen_rtx_MEM (HImode,
2473                                gen_rtx_POST_INC (HImode,
2474                                         gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2475       else
2476         operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2477     }
2478   ops[0] = gen_label_rtx (); 
2479   output_asm_insn (\"subd\\t%2\", operands);
2480   output_asm_insn (\"bcc\\t%l0\", ops);
2481   output_asm_insn (\"dex\", ops);
2482   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2483   CC_STATUS_INIT;
2484   return \"\";
2487 (define_insn "*subsi3_zero_extendqi"
2488   [(set (match_operand:SI 0 "register_operand" "=D")
2489         (minus:SI (match_operand:SI 1 "register_operand" "0")
2490             (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
2491    (clobber (match_scratch:HI 3 "=X"))]
2492   ""
2493   "*
2495   rtx ops[2];
2497   if (A_REG_P (operands[2]))
2498     {
2499       ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2500       ops[1] = operands[2];
2501       m68hc11_gen_movhi (insn, ops);
2502       operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2503     }
2504   ops[0] = gen_label_rtx (); 
2505   output_asm_insn (\"subb\\t%b2\", operands);
2506   output_asm_insn (\"sbca\\t#0\", operands);
2507   output_asm_insn (\"bcc\\t%l0\", ops);
2508   output_asm_insn (\"dex\", ops);
2509   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2510   CC_STATUS_INIT;
2511   return \"\";
2515 ;; reg:HI 1 -> d        reg:QI 6 -> B
2516 ;; reg:QI 7 -> ccr      reg:QI 5 -> A
2518 (define_split /* "*subsi3" */
2519   [(set (match_operand:SI 0 "register_operand" "")
2520         (minus:SI (match_operand:SI 1 "register_operand" "")
2521                   (match_operand:SI 2 "general_operand" "")))
2522    (clobber (match_scratch:HI 3 "=X"))]
2523   "reload_completed && z_replacement_completed == 2
2524    && X_REG_P (operands[1])"
2525   [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2526    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2527               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2528    (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2529    (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2530    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2531               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2532   "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2533    operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2534    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2535    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2537 (define_split /* "*subsi3" */
2538   [(set (match_operand:SI 0 "register_operand" "")
2539         (minus:SI (match_operand:SI 1 "general_operand" "")
2540                   (match_operand:SI 2 "register_operand" "")))
2541    (clobber (match_scratch:HI 3 "=X"))]
2542   "reload_completed && z_replacement_completed == 2
2543    && X_REG_P (operands[2])"
2544   [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2545    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2546               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2547    (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2548    (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2549    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2550               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2551    (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2552   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2553    operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2554    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2555    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2557 (define_split /* "*subsi3" */
2558   [(set (match_operand:SI 0 "nonimmediate_operand" "")
2559         (minus:SI (match_operand:SI 1 "general_operand" "")
2560                   (match_operand:SI 2 "general_operand" "")))
2561    (clobber (match_scratch:HI 3 "=d"))]
2562   "reload_completed && z_replacement_completed == 2
2563    && !X_REG_P (operands[0])"
2564   [(set (match_dup 3) (match_dup 4))
2565    (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2566    (set (match_dup 4) (match_dup 3))
2567    (set (match_dup 3) (match_dup 6))
2568    (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2569    (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2570    (set (match_dup 6) (match_dup 3))]
2571   "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2572    operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2573    operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2574    operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2575    operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2576    operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2579 ;; - 16-bit Subtract.
2581 (define_expand "subhi3"
2582   [(set (match_operand:HI 0 "register_operand" "=r")
2583         (minus:HI (match_operand:HI 1 "register_operand" "0")
2584                   (match_operand:HI 2 "general_operand" "g")))]
2585   ""
2586   "")
2589 ;; Subtract from stack. This is better if we provide a pattern.
2591 (define_insn "*subhi3_sp"
2592   [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2593         (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2594                   (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2595    (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2596   ""
2597   "*
2599   if (X_REG_P (operands[2]))
2600     {
2601       operands[2] = m68hc11_soft_tmp_reg;
2602       output_asm_insn (\"stx\\t%2\", operands);
2603     }
2604   else if (Y_REG_P (operands[2]))
2605     {
2606       operands[2] = m68hc11_soft_tmp_reg;
2607       output_asm_insn (\"sty\\t%2\", operands);
2608     }
2609   else if (D_REG_P (operands[2]))
2610     {
2611       operands[2] = m68hc11_soft_tmp_reg;
2612       output_asm_insn (\"std\\t%2\", operands);
2613     }
2615   if (D_REG_P (operands[3]))
2616     {
2617       int save_x;
2619       save_x = !dead_register_here (insn, ix_reg);
2620       if (save_x)
2621         output_asm_insn (\"xgdx\", operands);
2622       output_asm_insn (\"tsx\", operands);
2623       output_asm_insn (\"xgdx\", operands);
2624       output_asm_insn (\"subd\\t%2\", operands);
2625       output_asm_insn (\"xgdx\", operands);
2627       /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2628          modify the flags.  */
2629       output_asm_insn (\"txs\", operands);
2630       if (save_x)
2631         return \"xgdx\";
2632       else
2633         return \"\";
2634     }
2636   /* Need to transfer to SP to X,Y and then to D register.
2637      Register X,Y is lost, this is specified by the (clobber) statement.  */
2638   output_asm_insn (\"ts%3\", operands);
2639   output_asm_insn (\"xgd%3\", operands);
2640   output_asm_insn (\"subd\\t%2\", operands);
2641   output_asm_insn (\"xgd%3\", operands);
2643    /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2644       modify the flags.  */
2645   return \"t%3s\";
2649 (define_insn "*subhi3"
2650   [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
2651         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
2652                   (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
2653   ""
2654   "*
2656   /* Adding to an address register or with another/same register
2657      is not possible.  This must be replaced.  */
2658   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2659     return \"#\";
2661   return \"subd\\t%2\";
2664 (define_insn "*subhi3_zext"
2665   [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2666         (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2667            (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2668   ""
2669   "*
2671   CC_STATUS_INIT;
2672   if (A_REG_P (operands[2]))
2673     {
2674       rtx ops[2];
2676       ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2677       ops[1] = operands[2];
2678       m68hc11_gen_movqi (insn, ops);
2679       return \"subb\\t%T0\\n\\tsbca\\t#0\";
2680     }
2681   return \"subb\\t%b2\\n\\tsbca\\t#0\";
2684 (define_insn "subqi3"
2685   [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2686         (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2687                   (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2688   ""
2689   "*
2691   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2692     return \"#\";
2693   else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2694     return \"subb\\t%b2\";
2695   else
2696     return \"suba\\t%b2\";
2700 ;; subtract with carry is used for 32-bit subtract.
2702 (define_insn "*subcq"
2703   [(set (match_operand:QI 0 "register_operand" "=q")
2704         (minus:QI (minus:QI (reg:QI CC_REGNUM)
2705                             (match_operand:QI 1 "register_operand" "0"))
2706                   (match_operand:QI 2 "general_operand" "ium")))]
2707   ""
2708   "sbc%0\\t%b2")
2710 ;;--------------------------------------------------------------------
2711 ;;- Multiply instructions.
2712 ;;--------------------------------------------------------------------
2714 ;; 32 and 64-bit multiply are handled by the library
2717 (define_expand "mulsi3"
2718   [(set (match_operand:SI 0 "nonimmediate_operand" "")
2719         (mult:SI (match_operand:SI 1 "general_operand" "")
2720                  (match_operand:SI 2 "general_operand" "")))]
2721   ""
2722   "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2723    DONE;")
2725 (define_expand "mulhi3"
2726   [(parallel [(set (match_operand:HI 0 "register_operand" "")
2727                        (mult:HI (match_operand:HI 1 "register_operand" "")
2728                                 (match_operand:HI 2 "register_operand" "")))
2729               (clobber (match_scratch:HI 3 ""))])]
2730   ""
2731   "")
2733 (define_insn "mulhi3_m68hc11"
2734   [(set (match_operand:HI 0 "register_operand" "=d")
2735         (mult:HI (match_operand:HI 1 "register_operand" "%0")
2736                  (match_operand:HI 2 "register_operand" "x")))
2737    (clobber (match_scratch:HI 3 "=X"))]
2738   "TARGET_M6811"
2739   "*
2741   CC_STATUS_INIT;
2742   /* D * X -> D  (X and Y are preserved by this function call).  */
2743   return \"jsr\\t___mulhi3\";
2746 (define_insn "mulhi3_m68hc12"
2747   [(set (match_operand:HI 0 "register_operand" "=d,d")
2748         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2749                  (match_operand:HI 2 "register_operand" "y,x")))
2750    (clobber (match_scratch:HI 3 "=2,2"))]
2751   "TARGET_M6812"
2752   "*
2754   CC_STATUS_INIT;
2755   if (X_REG_P (operands[2]))
2756     return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2757   else
2758     return \"emul\";
2761 (define_insn "umulhisi3"
2762   [(set (match_operand:SI 0 "register_operand" "=D,D")
2763         (mult:SI (zero_extend:SI
2764                      (match_operand:HI 1 "register_operand" "%d,d"))
2765                  (zero_extend:SI
2766                      (match_operand:HI 2 "register_operand" "y,x"))))
2767    (clobber (match_scratch:HI 3 "=2,X"))]
2768   "TARGET_M6812"
2769   "*
2771   if (X_REG_P (operands [2]))
2772     output_asm_insn (\"exg\\tx,y\", operands);
2774   /* Can't use the carry after that; other flags are ok when testing
2775      the 32-bit result.  */
2776   cc_status.flags |= CC_NO_OVERFLOW;
2777   return \"emul\\n\\texg\\tx,y\";
2780 (define_insn "mulhisi3"
2781   [(set (match_operand:SI 0 "register_operand" "=D,D")
2782         (mult:SI (sign_extend:SI
2783                      (match_operand:HI 1 "register_operand" "%d,d"))
2784                  (sign_extend:SI
2785                      (match_operand:HI 2 "register_operand" "y,x"))))
2786    (clobber (match_scratch:HI 3 "=2,X"))]
2787   "TARGET_M6812"
2788   "*
2790   if (X_REG_P (operands [2]))
2791     output_asm_insn (\"exg\\tx,y\", operands);
2793   /* Can't use the carry after that; other flags are ok when testing
2794      the 32-bit result.  */
2795   cc_status.flags |= CC_NO_OVERFLOW;
2796   return \"emuls\\n\\texg\\tx,y\";
2799 (define_insn "umulqihi3"
2800   [(set (match_operand:HI 0 "register_operand" "=d")
2801         (mult:HI (zero_extend:HI
2802                      (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2803                  (zero_extend:HI
2804                      (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2805   ""
2806   "*
2808   if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2809     {
2810       output_asm_insn (\"tba\", operands);
2811     }
2812   else
2813     {
2814       rtx ops[2];
2816       if (D_REG_P (operands[2]))
2817         {
2818           rtx temp = operands[2];
2819           operands[2] = operands[1];
2820           operands[1] = temp;
2821         }
2823       ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2824       ops[1] = operands[2];
2825       m68hc11_gen_movqi (insn, ops);
2827       if (!D_REG_P (operands[1]))
2828         {
2829           output_asm_insn (\"ldab\\t%b1\", operands);
2830         }
2831     }
2833   CC_STATUS_INIT;
2834   return \"mul\";
2837 (define_insn "mulqi3"
2838   [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
2839         (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
2840                  (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
2841   ""
2842   "*
2844   if (A_REG_P (operands[0]))
2845     return \"#\";
2847   if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2848     {
2849       output_asm_insn (\"tba\", operands);
2850     }
2851   else
2852     {
2853       if (D_REG_P (operands[2]))
2854         {
2855           rtx temp = operands[2];
2856           operands[2] = operands[1];
2857           operands[1] = temp;
2858         }
2859         
2860       output_asm_insn (\"ldaa\\t%b2\", operands);
2862       if (!D_REG_P (operands[1]))
2863         {
2864           output_asm_insn (\"ldab\\t%b1\", operands);
2865         }
2866     }
2868   CC_STATUS_INIT;
2869   return \"mul\";
2872 (define_split
2873   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
2874         (mult:QI (match_operand:QI 1 "general_operand" "")
2875                  (match_operand:QI 2 "general_operand" "")))]
2876   "z_replacement_completed == 2"
2877   [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2878               (set (match_dup 3) (reg:HI D_REGNUM))])
2879    (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
2880    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2881               (set (match_dup 3) (reg:HI D_REGNUM))])]
2882   "
2883    operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
2884    if (A_REG_P (operands[1]))
2885      operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2886    else
2887      operands[5] = operands[1];
2888    if (A_REG_P (operands[2]))
2889      operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2890    else
2891      operands[6] = operands[2];
2892   ")
2894 (define_insn "mulqihi3"
2895   [(set (match_operand:HI 0 "register_operand" "=d,d,d")
2896         (mult:HI (sign_extend:HI
2897                         (match_operand:QI 1 "register_operand" "%0,0,0"))
2898                  (sign_extend:HI
2899                         (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
2900   ""
2901   "*
2903   CC_STATUS_INIT;
2905   /* Special case when multiplying the register with itself.  */
2906   if (D_REG_P (operands[2]))
2907     {
2908       output_asm_insn (\"tba\", operands);
2909       return \"mul\";
2910     }
2912   if (!H_REG_P (operands[2]))
2913     {
2914       output_asm_insn (\"ldaa\\t%b2\", operands);
2915     }
2916   else
2917     {
2918       rtx ops[2];
2920       ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2921       ops[1] = operands[2];
2922       m68hc11_gen_movqi (insn, ops);
2923     }
2924   return \"jsr\\t___mulqi3\";
2927 ;;--------------------------------------------------------------------
2928 ;;- Divide instructions.
2929 ;;--------------------------------------------------------------------
2931 (define_insn "divmodhi4"
2932   [(set (match_operand:HI 0 "register_operand" "=d,d")
2933           (div:HI (match_operand:HI 1 "register_operand" "0,0")
2934                   (match_operand:HI 2 "general_operand" "A,ium")))
2935    (set (match_operand:HI 3 "register_operand" "=&x,&x")
2936         (mod:HI (match_dup 1) (match_dup 2)))]
2937   ""
2938   "*
2940   if (!X_REG_P (operands[2])) 
2941     {
2942       if (Y_REG_P (operands[2]))
2943         {
2944           output_asm_insn (\"sty\\t%t1\", operands);
2945           output_asm_insn (\"ldx\\t%t1\", operands);
2946         }
2947       else
2948         {
2949           output_asm_insn (\"ldx\\t%2\", operands);
2950         }
2951     }
2952   if (TARGET_M6812)
2953     {
2954       /* Flags are ok after that.  */
2955       return \"idivs\\n\\txgdx\";      
2956     }
2957   else
2958     {
2959       CC_STATUS_INIT;
2960       return \"bsr\\t__divmodhi4\";
2961     }
2964 (define_insn "udivmodhi4"
2965   [(set (match_operand:HI 0 "register_operand" "=d,d")
2966           (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
2967                    (match_operand:HI 2 "general_operand" "A,ium")))
2968    (set (match_operand:HI 3 "register_operand" "=x,x")
2969         (umod:HI (match_dup 1) (match_dup 2)))]
2970   ""
2971   "*
2973   if (!X_REG_P (operands[2])) 
2974     {
2975       if (Y_REG_P (operands[2]))
2976         {
2977           output_asm_insn (\"sty\\t%t1\", operands);
2978           output_asm_insn (\"ldx\\t%t1\", operands);
2979         }
2980       else
2981         {
2982           output_asm_insn (\"ldx\\t%2\", operands);
2983         }
2984     }
2986   /* Z V and C flags are set but N is unchanged.
2987      Since this is an unsigned divide, we can probably keep the flags
2988      and indicate this.  */
2989   cc_status.flags |= CC_NOT_NEGATIVE;
2990   return \"idiv\\n\\txgdx\";
2993 ;;--------------------------------------------------------------------
2994 ;;- and instructions.
2995 ;;--------------------------------------------------------------------
2997 (define_insn_and_split "anddi3"
2998   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
2999         (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3000                 (match_operand:DI 2 "general_operand" "imu,imu")))
3001    (clobber (match_scratch:HI 3 "=d,d"))]
3002   ""
3003   "#"
3004   "reload_completed"
3005   [(const_int 0)]
3006   "m68hc11_split_logical (SImode, AND, operands);
3007    DONE;")
3009 (define_insn_and_split "andsi3"
3010   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3011         (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3012                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3013    (clobber (match_scratch:HI 3 "=X,d"))]
3014   ""
3015   "#"
3016   "reload_completed"
3017   [(const_int 0)]
3018   "m68hc11_split_logical (HImode, AND, operands);
3019    DONE;")
3021 (define_expand "andhi3"
3022   [(set (match_operand:HI 0 "register_operand" "")
3023         (and:HI (match_operand:HI 1 "register_operand" "")
3024                 (match_operand:HI 2 "general_operand" "")))]
3025   ""
3026   "")
3028 (define_insn "*andhi3_mem"
3029   [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3030         (and:HI (match_dup 0)
3031                 (match_operand:HI 1 "immediate_operand" "i,i")))
3032    (clobber (match_scratch:HI 2 "=X,xy"))]
3033   "TARGET_RELAX && !TARGET_M6812"
3034   "*
3036   int val = INTVAL (operands[1]) & 0x0FFFF;
3038   if (val == 0x0ffff)
3039     {
3040       cc_status = cc_prev_status;
3041       return \"\";
3042     }
3044   CC_STATUS_INIT;
3046   /* The bclr instruction uses an inverted mask.  */
3047   operands[1] = GEN_INT ((~val) & 0x0FFFF);
3049   /* When destination is a global variable, generate a .relax instruction
3050      and load the address in the clobber register.  That load can be
3051      eliminated by the linker if the address is in page0.  */
3052   if (which_alternative == 1)
3053     {
3054       rtx ops[3];
3056       ops[0] = operands[2];
3057       ops[1] = XEXP (operands[0], 0);
3058       ops[2] = gen_label_rtx ();
3059       output_asm_insn (\".relax\\t%l2\", ops);
3060       m68hc11_gen_movhi (insn, ops);
3061       if ((val & 0x0FF) != 0x0FF)
3062         output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
3064       if ((val & 0x0FF00) != 0x0FF00)
3065         output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
3067       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3068                                  CODE_LABEL_NUMBER (ops[2]));
3069       return \"\";
3070     }
3072   if ((val & 0x0FF) != 0x0FF)
3073     output_asm_insn (\"bclr\\t%b0, %b1\", operands);
3075   if ((val & 0x0FF00) != 0x0FF00)
3076     output_asm_insn (\"bclr\\t%h0, %h1\", operands);
3078   return \"\";
3081 (define_insn "*andhi3_const"
3082   [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3083         (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3084                 (match_operand:HI 2 "const_int_operand" "")))]
3085   ""
3086   "*
3088   int val = INTVAL (operands[2]) & 0x0FFFF;
3089   int lowpart_zero = 0;
3090   int highpart_zero = 0;
3091   int lowpart_unknown = 0;
3092   int highpart_unknown = 0;
3094   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3095     return \"#\";
3097   if (val == 0x0ffff)
3098     {
3099       cc_status = cc_prev_status;
3100       return \"\";
3101     }
3103   /* First, try to clear the low and high part.
3104      If that's possible, the second 'and' will give
3105      the good status flags and we can avoid a tsthi.  */
3106   if ((val & 0x0FF) == 0)
3107     {
3108       if (D_REG_P (operands[0]))
3109         output_asm_insn (\"clrb\", operands);
3110       else
3111         output_asm_insn (\"clr\\t%b0\", operands);
3112       lowpart_zero = 1;
3113     }
3114   if ((val & 0x0FF00) == 0)
3115     {
3116       if (D_REG_P (operands[0]))
3117         output_asm_insn (\"clra\", operands);
3118       else
3119         output_asm_insn (\"clr\\t%h0\", operands);
3120       highpart_zero = 1;
3121     }
3123   if ((val & 0x0FF) == 0x0FF)
3124     {
3125       lowpart_unknown = 1;
3126     }
3127   else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3128     {
3129       rtx ops[2];
3131       ops[0] = operands[0];
3132       ops[1] = GEN_INT ((~val) & 0x0FF);
3133       output_asm_insn (\"bclr\\t%b0, %1\", ops);
3134     }
3135   else if ((val & 0x0FF) != 0)
3136     {
3137       output_asm_insn (\"andb\\t%b2\", operands);
3138     }
3140   if ((val & 0x0FF00) == 0x0FF00)
3141     {
3142       highpart_unknown = 1;
3143     }
3144   else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3145     {
3146       rtx ops[2];
3148       ops[0] = operands[0];
3149       ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
3150       output_asm_insn (\"bclr\\t%h0, %1\", ops);
3151     }
3152   else if ((val & 0x0FF00) != 0)
3153     {
3154       output_asm_insn (\"anda\\t%h2\", operands);
3155     }
3157   if (highpart_unknown || lowpart_unknown)
3158      CC_STATUS_INIT;
3159   else if (highpart_zero == 0 && lowpart_zero == 0)
3160      CC_STATUS_INIT;
3162   return \"\";
3165 (define_insn "*andhi3_gen"
3166   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3167         (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3168                 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3169   ""
3170   "*
3172   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3173     return \"#\";
3175   CC_STATUS_INIT;
3176   return \"anda\\t%h2\\n\\tandb\\t%b2\";
3179 (define_expand "andqi3"
3180   [(set (match_operand:QI 0 "register_operand" "")
3181         (and:QI (match_operand:QI 1 "register_operand" "")
3182                 (match_operand:QI 2 "general_operand" "")))]
3183   ""
3184   "")
3186 (define_insn "*andqi3_mem"
3187   [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3188         (and:QI (match_dup 0)
3189                 (match_operand:QI 1 "const_int_operand" "i,i")))
3190    (clobber (match_scratch:HI 2 "=X,xy"))]
3191   "TARGET_RELAX && !TARGET_M6812"
3192   "*
3194   int val = INTVAL (operands[1]) & 0x0FF;
3196   if (val == 0x0ff)
3197     {
3198       cc_status = cc_prev_status;
3199       return \"\";
3200     }
3202   /* The bclr instruction uses an inverted mask.  */
3203   operands[1] = GEN_INT ((~val) & 0x0FF);
3205   /* When destination is a global variable, generate a .relax instruction
3206      and load the address in the clobber register.  That load can be
3207      eliminated by the linker if the address is in page0.  */
3208   if (which_alternative == 1)
3209     {
3210       rtx ops[3];
3212       ops[0] = operands[2];
3213       ops[1] = XEXP (operands[0], 0);
3214       ops[2] = gen_label_rtx ();
3215       output_asm_insn (\".relax\\t%l2\", ops);
3216       m68hc11_gen_movhi (insn, ops);
3217       output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3218       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3219                                  CODE_LABEL_NUMBER (ops[2]));
3220       return \"\";
3221     }
3222   return \"bclr\\t%b0, %1\";
3225 (define_insn "*andqi3_const"
3226   [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3227         (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3228                 (match_operand:QI 2 "const_int_operand" "")))]
3229   ""
3230   "*
3232   int val = INTVAL (operands[2]) & 0x0FF;
3234   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3235     return \"#\";
3237   if (val == 0x0ff)
3238     {
3239       cc_status = cc_prev_status;
3240       return \"\";
3241     }
3242   if (!H_REG_P (operands[0]))
3243     {
3244       rtx ops[2];
3246       ops[0] = operands[0];
3247       ops[1] = GEN_INT ((~val) & 0x0FF);
3248       output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3249       return \"\";
3250     }
3251   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3252     return \"andb\\t%b2\";
3253   else if (DA_REG_P (operands[0]))
3254     return \"anda\\t%b2\";
3255   else
3256     fatal_insn (\"Invalid operand in the instruction\", insn);
3259 (define_insn "*andqi3_gen"
3260   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3261         (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3262              (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
3263   ""
3264   "*
3266   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3267     return \"#\";
3269   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3270     return \"andb\\t%b2\";
3271   else if (DA_REG_P (operands[0]))
3272     return \"anda\\t%b2\";
3273   else
3274     fatal_insn (\"Invalid operand in the instruction\", insn);
3277 ;;--------------------------------------------------------------------
3278 ;;- Bit set or instructions.
3279 ;;--------------------------------------------------------------------
3281 (define_insn_and_split "iordi3"
3282   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3283         (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3284                 (match_operand:DI 2 "general_operand" "imu,imu")))
3285    (clobber (match_scratch:HI 3 "=d,d"))]
3286   ""
3287   "#"
3288   "reload_completed"
3289   [(const_int 0)]
3290   "m68hc11_split_logical (SImode, IOR, operands);
3291    DONE;")
3293 (define_insn_and_split "iorsi3"
3294   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3295         (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3296                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3297    (clobber (match_scratch:HI 3 "=X,d"))]
3298   ""
3299   "#"
3300   "reload_completed"
3301   [(const_int 0)]
3302   "m68hc11_split_logical (HImode, IOR, operands);
3303    DONE;")
3305 (define_expand "iorhi3"
3306   [(set (match_operand:HI 0 "register_operand" "")
3307         (ior:HI (match_operand:HI 1 "register_operand" "")
3308                 (match_operand:HI 2 "splitable_operand" "")))]
3309   ""
3310   "")
3312 (define_insn "*iorhi3_mem"
3313   [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3314         (ior:HI (match_dup 0)
3315                 (match_operand:HI 1 "const_int_operand" "")))
3316    (clobber (match_scratch:HI 2 "=X,xy"))]
3317   "TARGET_RELAX && !TARGET_M6812"
3318   "*
3320   int val = INTVAL (operands[1]) & 0x0FFFF;
3322   if (val == 0)
3323     {
3324       cc_status = cc_prev_status;
3325       return \"\";
3326     }
3327   CC_STATUS_INIT;
3328   if (which_alternative == 1)
3329     {
3330       rtx ops[3];
3332       ops[0] = operands[2];
3333       ops[1] = XEXP (operands[0], 0);
3334       ops[2] = gen_label_rtx ();
3335       output_asm_insn (\".relax\\t%l2\", ops);
3336       m68hc11_gen_movhi (insn, ops);
3337       if ((val & 0x0FF) != 0)
3338         output_asm_insn (\"bset\\t1,%2, %b1\", operands);
3340       if ((val & 0x0FF00) != 0)
3341         output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3342       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3343                                  CODE_LABEL_NUMBER (ops[2]));
3344       return \"\";
3345     }
3347   if ((val & 0x0FF) != 0)
3348     output_asm_insn (\"bset\\t%b0, %b1\", operands);
3350   if ((val & 0x0FF00) != 0)
3351     output_asm_insn (\"bset\\t%h0, %h1\", operands);
3353   return \"\";
3356 (define_insn "*iorhi3_const"
3357   [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3358         (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3359                 (match_operand:HI 2 "const_int_operand" "")))]
3360   ""
3361   "*
3363   int val = INTVAL (operands[2]) & 0x0FFFF;
3365   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3366     return \"#\";
3368   if (val == 0)
3369     {
3370       cc_status = cc_prev_status;
3371       return \"\";
3372     }
3374   if ((val & 0x0FF) != 0)
3375     {
3376       if (!H_REG_P (operands[0]))
3377         output_asm_insn (\"bset\\t%b0, %b2\", operands);
3378       else
3379         output_asm_insn (\"orab\\t%b2\", operands);
3380     }
3382   if ((val & 0x0FF00) != 0)
3383     {
3384       if (!H_REG_P (operands[0]))
3385          output_asm_insn (\"bset\\t%h0, %h2\", operands);
3386       else
3387          output_asm_insn (\"oraa\\t%h2\", operands);
3388     }
3390   CC_STATUS_INIT;
3391   return \"\";
3394 (define_insn "*iorhi3_gen"
3395   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3396         (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3397                 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3398   ""
3399   "*
3401   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3402     return \"#\";
3404   CC_STATUS_INIT;
3405   return \"oraa\\t%h2\\n\\torab\\t%b2\";
3408 (define_expand "iorqi3"
3409   [(set (match_operand:QI 0 "register_operand" "")
3410         (ior:QI (match_operand:QI 1 "register_operand" "")
3411                 (match_operand:QI 2 "general_operand" "")))]
3412   ""
3413   "")
3415 (define_insn "*iorqi3_mem"
3416   [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3417         (ior:QI (match_dup 0)
3418                 (match_operand:QI 1 "const_int_operand" "")))
3419    (clobber (match_scratch:HI 2 "=X,xy"))]
3420   "TARGET_RELAX && !TARGET_M6812"
3421   "*
3423   int val = INTVAL (operands[1]) & 0x0FF;
3425   if (val == 0)
3426     {
3427       cc_status = cc_prev_status;
3428       return \"\";
3429     }
3430   if (which_alternative == 1)
3431     {
3432       rtx ops[3];
3434       ops[0] = operands[2];
3435       ops[1] = XEXP (operands[0], 0);
3436       ops[2] = gen_label_rtx ();
3437       output_asm_insn (\".relax\\t%l2\", ops);
3438       m68hc11_gen_movhi (insn, ops);
3439       output_asm_insn (\"bset\\t0,%2, %1\", operands);
3440       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3441                                  CODE_LABEL_NUMBER (ops[2]));
3442       return \"\";
3443     }
3444   return \"bset\\t%b0, %1\";
3447 (define_insn "*iorqi3_const"
3448   [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3449         (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3450                 (match_operand:QI 2 "const_int_operand" "")))]
3451   ""
3452   "*
3454   int val = INTVAL (operands[2]) & 0x0FF;
3456   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3457     return \"#\";
3459   if (val == 0)
3460     {
3461       cc_status = cc_prev_status;
3462       return \"\";
3463     }
3464   if (!H_REG_P (operands[0]))
3465     {
3466       return \"bset\\t%b0, %2\";
3467     }
3469   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3470     return \"orab\\t%b2\";
3471   else if (DA_REG_P (operands[0]))
3472     return \"oraa\\t%b2\";
3473   else
3474     fatal_insn (\"Invalid operand in the instruction\", insn);
3477 (define_insn "*iorqi3_gen"
3478   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3479         (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3480              (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
3481   ""
3482   "*
3484   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3485     return \"#\";
3487   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3488     return \"orab\\t%b2\";
3489   else if (DA_REG_P (operands[0]))
3490     return \"oraa\\t%b2\";
3491   else
3492     fatal_insn (\"Invalid operand in the instruction\", insn);
3496 ;;--------------------------------------------------------------------
3497 ;;- xor instructions.
3498 ;;--------------------------------------------------------------------
3500 (define_insn_and_split "xordi3"
3501   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3502         (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3503                 (match_operand:DI 2 "general_operand" "imu,imu")))
3504    (clobber (match_scratch:HI 3 "=d,d"))]
3505   ""
3506   "#"
3507   "reload_completed"
3508   [(const_int 0)]
3509   "m68hc11_split_logical (SImode, XOR, operands);
3510    DONE;")
3512 (define_insn_and_split "xorsi3"
3513   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3514         (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3515                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3516    (clobber (match_scratch:HI 3 "=X,d"))]
3517   ""
3518   "#"
3519   "reload_completed"
3520   [(const_int 0)]
3521   "m68hc11_split_logical (HImode, XOR, operands);
3522    DONE;")
3524 (define_insn "xorhi3"
3525   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3526         (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3527                 (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
3528   ""
3529   "*
3531   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3532     return \"#\";
3534   if (GET_CODE (operands[2]) == CONST_INT)
3535     {
3536       int val = INTVAL (operands[2]) & 0x0FFFF;
3538       if (val == 0)
3539         {
3540           cc_status = cc_prev_status;
3541           return \"\";
3542         }
3543       if ((val & 0x0FF) != 0)
3544         {
3545           output_asm_insn (\"eorb\\t%b2\", operands);
3546         }
3547       else if ((val & 0x0FF) == 0x0FF)
3548         {
3549           output_asm_insn (\"comb\", operands);
3550         }
3552       if ((val & 0x0FF00) != 0)
3553         {
3554           output_asm_insn (\"eora\\t%h2\", operands);
3555         }
3556       else if ((val & 0x0FF00) == 0x0FF00)
3557         {
3558           output_asm_insn (\"coma\", operands);
3559         }
3561       CC_STATUS_INIT;
3562       return \"\";
3563     }
3565   CC_STATUS_INIT;
3566   return \"eora\\t%h2\\n\\teorb\\t%b2\";
3569 (define_insn "xorqi3"
3570   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3571         (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3572              (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
3573   ""
3574   "*
3576   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3577     return \"#\";
3579   if (GET_CODE (operands[2]) == CONST_INT)
3580     {
3581       int val = INTVAL (operands[2]) & 0x0FF;
3583       if (val == 0)
3584         {
3585           cc_status = cc_prev_status;
3586           return \"\";
3587         }
3588       if (val == 0x0FF)
3589         {
3590           if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3591             return \"comb\";
3592           else
3593             return \"coma\";
3594         }
3595     }
3596   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3597     return \"eorb\\t%b2\";
3598   else if (DA_REG_P (operands[0]))
3599     return \"eora\\t%b2\";
3600   else
3601     fatal_insn (\"Invalid operand in the instruction\", insn);
3604 ;;--------------------------------------------------------------------
3605 ;;- Bit set or instructions.
3606 ;;--------------------------------------------------------------------
3608 (define_insn_and_split "*logicalsi3_zexthi"
3609   [(set (match_operand:SI 0 "register_operand" "=D")
3610         (match_operator:SI 3 "m68hc11_logical_operator"
3611                 [(zero_extend:SI
3612                      (match_operand:HI 1 "general_operand" "imudA"))
3613                  (match_operand:SI 2 "general_operand" "Dimu")]))]
3614   ""
3615   "#"
3616   "reload_completed"
3617   [(set (reg:HI D_REGNUM) (match_dup 4))
3618    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3619    (set (reg:HI X_REGNUM) (match_dup 6))]
3620   "PUT_MODE (operands[3], HImode);
3621    if (X_REG_P (operands[2]))
3622      {
3623        operands[5] = operands[1];
3624        /* Make all the (set (REG:x) (REG:y)) a nop set.  */
3625        operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3626        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3627      }
3628    else
3629      {
3630        operands[4] = operands[1];
3631        operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3632        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3633      }
3634    /* For an AND, make sure the high 16-bit part is cleared.  */
3635    if (GET_CODE (operands[3]) == AND)
3636      {
3637        operands[6] = const0_rtx;
3638      }
3639    ")
3641 (define_insn_and_split "*logicalsi3_zextqi"
3642   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3643         (match_operator:SI 3 "m68hc11_logical_operator"
3644                 [(zero_extend:SI
3645                      (match_operand:QI 1 "general_operand" "d,*A,imu"))
3646                  (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3647   ""
3648   "#"
3649   "z_replacement_completed == 2"
3650   [(set (reg:QI A_REGNUM) (match_dup 4))
3651    (set (reg:QI D_REGNUM) (match_dup 7))
3652    (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3653    (set (reg:HI X_REGNUM) (match_dup 6))]
3654   "PUT_MODE (operands[3], QImode);
3655    if (X_REG_P (operands[2]))
3656      {
3657        operands[5] = operands[1];
3658        /* Make all the (set (REG:x) (REG:y)) a nop set.  */
3659        operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3660        operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
3661        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3662      }
3663    else
3664      {
3665        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3666        operands[7] = operands[1];
3667        operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3668        operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3669        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3670      }
3671    /* For an AND, make sure the high 24-bit part is cleared.  */
3672    if (GET_CODE (operands[3]) == AND)
3673      {
3674        operands[4] = const0_rtx;
3675        operands[6] = const0_rtx;
3676      }
3677    ")
3679 (define_insn_and_split "*logicalhi3_zexthi_ashift8"
3680   [(set (match_operand:HI 0 "register_operand" "=d")
3681         (match_operator:HI 3 "m68hc11_logical_operator"
3682                 [(zero_extend:HI
3683                      (match_operand:QI 1 "general_operand" "imud*A"))
3684                  (ashift:HI
3685                      (match_operand:HI 2 "general_operand" "imud*A")
3686                      (const_int 8))]))]
3687   ""
3688   "#"
3689   "z_replacement_completed == 2"
3690   [(set (reg:QI A_REGNUM) (match_dup 4))
3691    (set (reg:QI B_REGNUM) (match_dup 5))]
3692   "
3693    if (GET_CODE (operands[3]) == AND)
3694      {
3695        emit_insn (gen_movhi (operands[0], const0_rtx));
3696        DONE;
3697      }
3698    else
3699      {
3700        operands[5] = operands[1];
3701        if (D_REG_P (operands[2]))
3702          {
3703            operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3704          }
3705        else
3706          {
3707            operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3708          }
3709      }
3710   ")
3712 (define_insn_and_split "*logicalhi3_zexthi"
3713   [(set (match_operand:HI 0 "register_operand" "=d,d")
3714         (match_operator:HI 3 "m68hc11_logical_operator"
3715                 [(zero_extend:HI
3716                      (match_operand:QI 1 "general_operand" "imd*A,?u"))
3717                  (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3718   ""
3719   "#"
3720   "z_replacement_completed == 2"
3721   [(set (reg:QI B_REGNUM) (match_dup 6))
3722    (set (reg:QI A_REGNUM) (match_dup 4))
3723    (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3724   "
3725    PUT_MODE (operands[3], QImode);
3726    if (D_REG_P (operands[2]))
3727      {
3728        operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3729        operands[5] = operands[1];
3730        operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3731      }
3732    else
3733      {
3734        operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3735        operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3736        if (D_REG_P (operands[1]))
3737          operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3738        else
3739          operands[6] = operands[1];
3740      }
3741    /* For an AND, make sure the high 8-bit part is cleared.  */
3742    if (GET_CODE (operands[3]) == AND)
3743      {
3744        operands[4] = const0_rtx;
3745      }
3746   ")
3749 (define_insn_and_split "*logicalsi3_silshr16"
3750   [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
3751           (match_operator:SI 3 "m68hc11_logical_operator"
3752               [(lshiftrt:SI 
3753                    (match_operand:SI 1 "general_operand" "uim,uim,0,0")
3754                    (const_int 16))
3755                 (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
3756   ""
3757   "#"
3758   "reload_completed"
3759   [(set (reg:HI D_REGNUM) (match_dup 4))
3760    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3761    (set (reg:HI X_REGNUM) (match_dup 6))]
3762   "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3763    if (X_REG_P (operands[2]))
3764      {
3765        operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3766        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3767      }
3768    else
3769      {
3770        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3771        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3772      }
3773    PUT_MODE (operands[3], HImode);
3775    /* For an AND, make sure the high 16-bit part is cleared.  */
3776    if (GET_CODE (operands[3]) == AND)
3777      {
3778        operands[6] = const0_rtx;
3779      }
3782 (define_insn_and_split "*logicalsi3_silshl16"
3783   [(set (match_operand:SI 0 "register_operand" "=D,D")
3784           (match_operator:SI 3 "m68hc11_logical_operator"
3785               [(ashift:SI 
3786                    (match_operand:SI 1 "general_operand" "uim,?D")
3787                    (const_int 16))
3788                 (match_operand:SI 2 "general_operand" "0,0")]))]
3789   ""
3790   "#"
3791   "z_replacement_completed == 2"
3792   [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3793    (set (reg:HI D_REGNUM) (match_dup 5))]
3794   "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3795    PUT_MODE (operands[3], HImode);
3797    if (GET_CODE (operands[3]) == AND)
3798      operands[5] = const0_rtx;
3799    else
3800      operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3801    ")
3803 (define_insn_and_split "*logicalsi3_silshl16_zext"
3804   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3805           (match_operator:SI 3 "m68hc11_logical_operator"
3806               [(ashift:SI
3807                   (zero_extend:SI
3808                      (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
3809                   (const_int 16))
3810             (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
3811   ""
3812   "#"
3813   ;; Must split before z register replacement
3814   "reload_completed"
3815   [(set (match_dup 4) (match_dup 5))
3816    (set (match_dup 6) (match_dup 7))]
3817   "
3818     /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
3819    if (GET_CODE (operands[1]) == HARD_D_REGNUM
3820        && GET_CODE (operands[3]) != AND)
3821      {
3822        /* This particular case is too early to be split before
3823           Z register replacement because the cse-reg pass we do
3824           does not recognize the 'swap_areg'.  It is ok to handle
3825           this case after.  */
3826        if (z_replacement_completed != 2)
3827          {
3828            FAIL;
3829          }
3830        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
3831        emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
3832                                  gen_rtx_REG (HImode, HARD_X_REGNUM)));
3833      }
3834    operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3835    operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3836    operands[5] = operands[2];
3837    operands[7] = operands[1];
3839    if (GET_CODE (operands[3]) == AND)
3840      operands[5] = operands[7] = const0_rtx;
3841    ")
3843 ;;--------------------------------------------------------------------
3844 ;; 16-bit Arithmetic and logical operations on X and Y:
3846 ;;      PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3848 ;; Operations on X or Y registers are split here.  Instructions are
3849 ;; changed into:
3850 ;;   - xgdx/xgdy instruction pattern,
3851 ;;   - The same operation on register D,
3852 ;;   - xgdx/xgdy instruction pattern.
3853 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3854 ;; We also handle the case were the address register is used in both source
3855 ;; operands, such as:
3857 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3858 ;; or
3859 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3862 (define_split
3863   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3864         (match_operator:HI 3 "m68hc11_arith_operator"
3865             [(match_operand:HI 1 "hard_addr_reg_operand" "")
3866              (match_operand:HI 2 "general_operand" "")]))]
3867   "z_replacement_completed == 2
3868    /* If we are adding a small constant to X or Y, it's
3869      better to use one or several inx/iny instructions.  */
3870    && !(GET_CODE (operands[3]) == PLUS 
3871         && ((TARGET_M6812 
3872              && (immediate_operand (operands[2], HImode)
3873                  || hard_reg_operand (operands[2], HImode)))
3874             || (GET_CODE (operands[2]) == CONST_INT
3875                 && INTVAL (operands[2]) >= -4
3876                 && INTVAL (operands[2]) <= 4)))"
3877   [(set (match_dup 9) (match_dup 0))
3878    (set (match_dup 4) (match_dup 5))
3879    (set (match_dup 8) (match_dup 7))
3880    (set (match_dup 0) (match_dup 1))
3881    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3882               (set (match_dup 0) (reg:HI D_REGNUM))])
3883    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3884    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3885               (set (match_dup 0) (reg:HI D_REGNUM))])]
3886   "
3887    operands[9] = operands[0];
3888    /* For 68HC12, push the value on the stack and do the operation
3889       with a pop.  */
3890    if (TARGET_M6812
3891        && m68hc11_non_shift_operator (operands[3], HImode)
3892        && (H_REG_P (operands[2])
3893            || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3894                && reg_mentioned_p (operands[0], operands[2]))))
3895      {
3896        operands[4] = gen_rtx_MEM (HImode,
3897                               gen_rtx_PRE_DEC (HImode,
3898                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3899        operands[6] = gen_rtx_MEM (HImode,
3900                               gen_rtx_POST_INC (HImode,
3901                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3902        operands[5] = operands[2];
3903        operands[8] = operands[7] = operands[0];
3904      }
3905    /* Save the operand2 in a temporary location and use it.  */
3906    else if ((H_REG_P (operands[2])
3907              || reg_mentioned_p  (operands[0], operands[2]))
3908             && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3909      {
3910        if (GET_CODE (operands[3]) == MINUS
3911            && reg_mentioned_p (operands[0], operands[2]))
3912          {
3913            operands[9] = gen_rtx_MEM (HImode,
3914                               gen_rtx_PRE_DEC (HImode,
3915                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3916            operands[1] = gen_rtx_MEM (HImode,
3917                               gen_rtx_POST_INC (HImode,
3918                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3919            operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3920            operands[4] = operands[7] = operands[0];
3921            operands[6] = operands[8];
3922            operands[5] = operands[2];
3923          }
3924        else 
3925          {
3926        operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3927        operands[6] = operands[4];
3928        if (!H_REG_P (operands[2]))
3929          {
3930            operands[5] = operands[0];
3931            operands[7] = operands[2];
3932            operands[8] = operands[0];
3933          }
3934        else
3935          {
3936            operands[5] = operands[2];
3937            operands[8] = operands[7] = operands[0];
3938          }
3939          }
3940      }
3941    else
3942      {
3943        operands[4] = operands[5] = operands[0];
3944        operands[6] = operands[2];
3945        operands[8] = operands[7] = operands[0];
3946      }
3947    ")
3949 (define_split
3950   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3951         (match_operator:HI 3 "m68hc11_arith_operator"
3952             [(match_operand:HI 1 "general_operand" "")
3953              (match_operand:HI 2 "general_operand" "")]))]
3954   "z_replacement_completed == 2
3955    /* If we are adding a small constant to X or Y, it's
3956      better to use one or several inx/iny instructions.  */
3957    && !(GET_CODE (operands[3]) == PLUS 
3958         && ((TARGET_M6812 
3959             && (immediate_operand (operands[2], HImode)
3960                 || hard_reg_operand (operands[2], HImode)))
3961             || (GET_CODE (operands[2]) == CONST_INT
3962                 && INTVAL (operands[2]) >= -4
3963                 && INTVAL (operands[2]) <= 4)))"
3964   [(set (match_dup 0) (match_dup 1))
3965    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3966               (set (match_dup 0) (reg:HI D_REGNUM))])
3967    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
3968    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3969               (set (match_dup 0) (reg:HI D_REGNUM))])]
3970   "
3971    ")
3974 ;; Next split handles the logical operations on D register with
3975 ;; another hard register for the second operand.  For this, we
3976 ;; have to save the second operand in a scratch location and use
3977 ;; it instead.  This must be supported because in some (rare) cases
3978 ;; the second operand can come in a hard register and the reload
3979 ;; pass doesn't know how to reload it in a memory location.
3981 ;;      PLUS MINUS AND IOR XOR
3983 ;; The shift operators are special and must not appear here.
3985 (define_split
3986   [(set (match_operand:HI 0 "d_register_operand" "")
3987         (match_operator:HI 3 "m68hc11_non_shift_operator"
3988             [(match_operand:HI 1 "d_register_operand" "")
3989              (match_operand:HI 2 "hard_reg_operand" "")]))]
3990   "TARGET_M6811
3991    && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
3992   [(set (match_dup 4) (match_dup 2))
3993    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
3994   "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
3997 ;; For 68HC12, push the operand[2] value on the stack and do the
3998 ;; logical/arithmetic operation with a pop.
4000 (define_split
4001   [(set (match_operand:HI 0 "d_register_operand" "")
4002         (match_operator:HI 3 "m68hc11_non_shift_operator"
4003             [(match_operand:HI 1 "d_register_operand" "")
4004              (match_operand:HI 2 "hard_reg_operand" "")]))]
4005   "TARGET_M6812
4006    && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4007   [(set (match_dup 4) (match_dup 2))
4008    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4009   "operands[4] = gen_rtx_MEM (HImode,
4010                           gen_rtx_PRE_DEC (HImode,
4011                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4012    operands[5] = gen_rtx_MEM (HImode,
4013                           gen_rtx_POST_INC (HImode,
4014                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4015    ")
4017 ;;--------------------------------------------------------------------
4018 ;; 16-bit Unary operations on X and Y:
4020 ;;              NOT NEG
4022 ;; Operations on X or Y registers are split here.  Instructions are
4023 ;; changed into:
4024 ;;   - xgdx/xgdy instruction pattern,
4025 ;;   - The same operation on register D,
4026 ;;   - xgdx/xgdy instruction pattern.
4027 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4028 ;; We also handle the case were the address register is used in both source
4029 ;; operands, such as:
4031 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4032 ;; or
4033 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4035 (define_split
4036   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4037         (match_operator:HI 2 "m68hc11_unary_operator"
4038             [(match_operand 1 "general_operand" "")]))]
4039   "z_replacement_completed == 2"
4040   [(set (match_dup 4) (match_dup 5))
4041    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4042               (set (match_dup 0) (reg:HI D_REGNUM))])
4043    (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4044    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4045               (set (match_dup 0) (reg:HI D_REGNUM))])]
4046   "
4048   if ((H_REG_P (operands[1])
4049        && !rtx_equal_p (operands[0], operands[1]))
4050       || reg_mentioned_p (operands[0], operands[1]))
4051     {
4052       /* Move to the destination register, before the xgdx.  */
4053       operands[4] = gen_rtx_REG (GET_MODE (operands[1]), 
4054                              REGNO (operands[0]));
4055       operands[5] = operands[1];
4057       /* Apply the operation on D.  */
4058       operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
4059     }
4060   else
4061     {
4062       /* Generate a copy to same register (nop).  */
4063       operands[4] = operands[5] = operands[0];
4064       operands[3] = operands[1];
4065     }
4069 ;; 8-bit operations on address registers.
4071 ;; We have to take care that the address register is not used for the
4072 ;; source of operand2. If operand2 is the D register, we have to save
4073 ;; that register in a temporary location.
4075 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4077 (define_split
4078   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4079         (match_operator:QI 3 "m68hc11_arith_operator"
4080             [(match_operand:QI 1 "hard_addr_reg_operand" "")
4081              (match_operand:QI 2 "general_operand" "")]))]
4082   "z_replacement_completed == 2
4083    /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
4084       incqi pattern generates a better code.  */
4085    && !(GET_CODE (operands[3]) == PLUS
4086         && GET_CODE (operands[2]) == CONST_INT
4087         && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4088   [(set (match_dup 5) (match_dup 6))
4089    (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4090               (set (match_dup 4) (reg:HI D_REGNUM))])
4091    (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4092    (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4093               (set (match_dup 4) (reg:HI D_REGNUM))])]
4094   "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
4096    /* For the second operand is a hard register or if the address
4097       register appears in the source, we have to save the operand[2]
4098       value in a temporary location and then use that temp.
4099       Otherwise, it's ok and we generate a (set (D) (D)) that
4100       will result in a nop.  */
4101    if (H_REG_P (operands[2]))
4102      {
4103        operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4104        operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
4105        operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4106      }
4107    else if (reg_mentioned_p (operands[0], operands[2]))
4108      {
4109        operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4110        operands[6] = operands[2];
4111        operands[7] = operands[5];
4112      }
4113    else
4114      {
4115        operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4116        operands[7] = operands[2];
4117      }
4118   ")
4121 ;; Next split handles the logical operations on D register with
4122 ;; another hard register for the second operand.  For this, we
4123 ;; have to save the second operand in a scratch location and use
4124 ;; it instead.  This must be supported because in some (rare) cases
4125 ;; the second operand can come in a hard register and the reload
4126 ;; pass doesn't know how to reload it in a memory location.
4128 ;;      PLUS MINUS AND IOR XOR
4130 ;; The shift operators are special and must not appear here.
4132 (define_split
4133   [(set (match_operand:QI 0 "d_register_operand" "")
4134         (match_operator:QI 3 "m68hc11_non_shift_operator"
4135             [(match_operand:QI 1 "d_register_operand" "")
4136              (match_operand:QI 2 "hard_reg_operand" "")]))]
4137   "reload_completed"
4138   [(set (match_dup 5) (match_dup 6))
4139    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4140   "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4141    operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4142    operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
4144 ;;--------------------------------------------------------------------
4145 ;; 8-bit Unary operations on X and Y:
4147 ;;              NOT NEG
4149 ;; Operations on X or Y registers are split here.  Instructions are
4150 ;; changed into:
4151 ;;   - xgdx/xgdy instruction pattern,
4152 ;;   - The same operation on register D,
4153 ;;   - xgdx/xgdy instruction pattern.
4154 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4155 ;; We also handle the case were the address register is used in both source
4156 ;; operands, such as:
4158 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4159 ;; or
4160 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4162 (define_split
4163   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4164         (match_operator:QI 2 "m68hc11_unary_operator"
4165             [(match_operand:QI 1 "general_operand" "")]))]
4166   "z_replacement_completed == 2"
4167   [(set (match_dup 4) (match_dup 5))
4168    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4169               (set (match_dup 3) (reg:HI D_REGNUM))])
4170    (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4171    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4172               (set (match_dup 3) (reg:HI D_REGNUM))])]
4173   "
4175   operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4176   if ((H_REG_P (operands[1])
4177        && !rtx_equal_p (operands[0], operands[1]))
4178       || reg_mentioned_p (operands[0], operands[1]))
4179     {
4180       /* Move to the destination register, before the xgdx.  */
4181       operands[4] = operands[0];
4182       operands[5] = operands[1];
4184       /* Apply the operation on D.  */
4185       operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4186     }
4187   else
4188     {
4189       operands[4] = operands[5] = operands[0];
4190       operands[6] = operands[1];
4191     }
4195 ;;--------------------------------------------------------------------
4196 ;;-  Complements
4197 ;;--------------------------------------------------------------------
4199 (define_expand "negdi2"
4200   [(set (match_operand:DI 0 "nonimmediate_operand" "")
4201         (neg:DI (match_operand:DI 1 "general_operand" "")))]
4202   ""
4203   "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4204    DONE;")
4207 (define_insn "negsi2"
4208   [(set (match_operand:SI 0 "register_operand" "=D")
4209         (neg:SI (match_operand:SI 1 "general_operand" "0")))]
4210   ""
4211   "*
4213   rtx ops[1];
4215   CC_STATUS_INIT;
4217   /* With -Os or without -O, use a special library call.  */
4218   if (optimize_size || optimize == 0)
4219     return \"bsr\\t___negsi2\";
4221   ops[0] = gen_label_rtx ();
4223   /* 32-bit complement and add 1.  */
4224   output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4225   output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4226   output_asm_insn (\"bne\\t%l0\", ops);
4227   output_asm_insn (\"inx\", operands);
4228   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4229   return \"\";
4232 (define_insn "neghi2"
4233   [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
4234         (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4235   ""
4236   "@
4237    coma\\n\\tcomb\\n\\taddd\\t#1
4238    clra\\n\\tclrb\\n\\tsubd\\t%1
4239    xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4241 (define_insn "negqi2"
4242   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4243         (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
4244   ""
4245   "@
4246    negb
4247    neg\\t%b0
4248    neg\\t%b0
4249    #")
4252 ;; - 32-bit complement.  GCC knows how to translate them but providing a
4253 ;; pattern generates better/smaller code.
4255 (define_expand "one_cmpldi2"
4256   [(set (match_operand:DI 0 "nonimmediate_operand" "")
4257         (not:DI (match_operand:DI 1 "general_operand" "")))]
4258   ""
4259   "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4260    DONE;")
4262 (define_insn "one_cmplsi2"
4263   [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4264         (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4265    (clobber (match_scratch:HI 2 "=X,d,X"))]
4266   ""
4267   "@
4268    bsr\\t___one_cmplsi2
4269    #
4270    #")
4272 (define_insn "one_cmplhi2"
4273   [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
4274         (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
4275   ""
4276   "@
4277    comb\\n\\tcoma
4278    com\\t%b0\\n\\tcom\\t%h0
4279    #
4280    com\\t%b0\\n\\tcom\\t%h0")
4282 (define_insn "one_cmplqi2"
4283   [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
4284         (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
4285   ""
4286   "@
4287    comb
4288    com\\t%b0
4289    #
4290    com\\t%b0")
4292 (define_split /* "*one_cmplsi2" */
4293   [(set (match_operand:SI 0 "non_push_operand" "")
4294         (not:SI (match_dup 0)))
4295    (clobber (match_scratch:HI 1 ""))]
4296   "z_replacement_completed == 2
4297    && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4298   [(set (match_dup 2) (not:HI (match_dup 2)))
4299    (set (match_dup 3) (not:HI (match_dup 3)))]
4300   "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4301    operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
4303 (define_split /* "*one_cmplsi2" */
4304   [(set (match_operand:SI 0 "non_push_operand" "")
4305         (not:SI (match_operand:SI 1 "non_push_operand" "")))
4306    (clobber (match_operand:HI 2 "d_register_operand" ""))]
4307   "z_replacement_completed == 2
4308    && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4309   [(set (match_dup 2) (match_dup 3))
4310    (set (match_dup 2) (not:HI (match_dup 2)))
4311    (set (match_dup 4) (match_dup 2))
4312    (set (match_dup 2) (match_dup 5))
4313    (set (match_dup 2) (not:HI (match_dup 2)))
4314    (set (match_dup 6) (match_dup 2))]
4315   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4316    operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4317    operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4318    operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
4320 ;;--------------------------------------------------------------------
4321 ;;- arithmetic shifts
4322 ;;--------------------------------------------------------------------
4324 ;; Provide some 64-bit shift patterns. 
4325 (define_expand "ashldi3"
4326   [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4327                      (ashift:DI (match_operand:DI 1 "general_operand" "")
4328                                 (match_operand:HI 2 "general_operand" "")))
4329               (clobber (match_scratch:HI 3 ""))])]
4330    ""
4331    "
4333   if (GET_CODE (operands[2]) != CONST_INT 
4334       || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4335     {
4336       FAIL;
4337     }
4340 (define_insn_and_split "*ashldi3_const32"
4341   [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4342         (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4343                    (const_int 32)))
4344    (clobber (match_scratch:HI 2 "=&A,d,d"))]
4345    ""
4346    "#"
4347    "reload_completed"
4348    [(const_int 0)]
4349    "/* Move the lowpart in the highpart first in case the shift
4350        is applied on the source.  */
4351     if (IS_STACK_PUSH (operands[0]))
4352       {
4353          m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4354                              const0_rtx, operands[2]);
4356          /* Adjust first operand if it uses SP so that we take into
4357             account the above push.  Can occur only for 68HC12.  */
4358          if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
4359                               operands[1]))
4360            operands[1] = adjust_address (operands[1],
4361                                          GET_MODE (operands[0]), 4);
4362       }
4363     m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4364                         m68hc11_gen_lowpart (SImode, operands[1]),
4365                         operands[2]);
4366     if (!IS_STACK_PUSH (operands[0]))
4367       {
4368         m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4369                             const0_rtx, operands[2]);
4370       }
4371     DONE;")
4373 (define_insn_and_split "*ashldi3_const1"
4374   [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4375         (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4376                    (const_int 1)))
4377    (clobber (match_scratch:HI 2 "=d,d,d"))]
4378    ""
4379    "#"
4380    "z_replacement_completed == 2"
4381    [(set (match_dup 2) (match_dup 3))
4382     (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4383     (set (match_dup 4) (match_dup 2))
4385     (set (match_dup 2) (match_dup 5))
4386     (parallel [(set (match_dup 2)
4387                        (rotate:HI (match_dup 2) (const_int 1)))
4388                (clobber (reg:HI CC_REGNUM))])
4389     (set (match_dup 6) (match_dup 2))
4391     (set (match_dup 2) (match_dup 7))
4392     (parallel [(set (match_dup 2)
4393                        (rotate:HI (match_dup 2) (const_int 1)))
4394                (clobber (reg:HI CC_REGNUM))])
4395     (set (match_dup 8) (match_dup 2))
4397     (set (match_dup 2) (match_dup 9))
4398     (parallel [(set (match_dup 2)
4399                        (rotate:HI (match_dup 2) (const_int 1)))
4400                (clobber (reg:HI CC_REGNUM))])
4401     (set (match_dup 10) (match_dup 2))]
4402    "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4403     operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4404     operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4406     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4407     operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4408     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4410     operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4411     operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4412     operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4414     operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4415     operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4416     operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4418 (define_insn "addsi_silshr16"
4419   [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
4420           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
4421                                 (const_int 16))
4422                    (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
4423   ""
4424   "#")
4426 (define_split
4427   [(set (match_operand:SI 0 "register_operand" "")
4428           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4429                                 (const_int 16))
4430                    (match_operand:SI 2 "general_operand" "")))]
4431   "z_replacement_completed == 2 && !X_REG_P (operands[1])"
4432   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4433    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4434                                             (const_int 0))
4435                                    (reg:HI CC_REGNUM)))]
4436   "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4438 (define_split
4439   [(set (match_operand:SI 0 "register_operand" "")
4440           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4441                                 (const_int 16))
4442                    (match_operand:SI 2 "general_operand" "")))]
4443   "z_replacement_completed == 2 && X_REG_P (operands[1])"
4444   [(set (reg:HI D_REGNUM) (match_dup 5))
4445    (set (reg:HI X_REGNUM) (match_dup 3))
4446    (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4447    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4448                                             (const_int 0))
4449                                    (reg:HI CC_REGNUM)))]
4450   "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4451    if (X_REG_P (operands[2]))
4452      {
4453        operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4454        operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4455      }
4456    else
4457      {
4458        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4459        operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4460      }
4463 (define_insn "addsi_ashift16"
4464   [(set (match_operand:SI 0 "register_operand" "=D")
4465           (plus:SI 
4466                    (mult:SI (match_operand:SI 2 "general_operand" "uim")
4467                             (const_int 65536))
4468                 (match_operand:SI 1 "general_operand" "0")))
4469    (clobber (match_scratch:HI 3 "=X"))]
4470   "0"
4471   "#")
4473 (define_split
4474   [(set (match_operand:SI 0 "register_operand" "")
4475           (plus:SI 
4476                    (mult:SI (match_operand:SI 2 "general_operand" "")
4477                             (const_int 65536))
4478                    (match_operand:SI 1 "general_operand" "")))
4479    (clobber (match_scratch:HI 3 "=X"))]
4480   "0 && reload_completed && z_replacement_completed == 2"
4481   [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4482   "
4484   operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4487 (define_insn_and_split "addsi_andshr16"
4488   [(set (match_operand:SI 0 "register_operand" "=D")
4489           (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4490                            (const_int 65535))
4491                    (match_operand:SI 2 "general_operand" "0")))]
4492   ""
4493   "#"
4494   "z_replacement_completed == 2"
4495   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4496    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4497   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4500 ;; 32-bit shifts are made by a small library routine that uses
4501 ;; a specific passing convention for parameters (for efficiency reasons).
4503 ;; [D + X] -> Value to be shifted
4504 ;; Y       -> Shift count
4506 ;; The shift count is clobbered by the routine.
4508 (define_expand "ashlsi3"
4509   [(parallel
4510        [(set (match_operand:SI 0 "register_operand" "") 
4511              (match_operand:SI 1 "general_operand" ""))
4512         (clobber (scratch:HI))])
4513    (parallel
4514      [(set (match_dup 0) (ashift:SI (match_dup 0)
4515                          (match_operand:HI 2 "nonmemory_operand" "")))
4516       (clobber (scratch:HI))])]
4517    ""
4518    "")
4520 (define_split
4521   [(set (match_operand:SI 0 "nonimmediate_operand" "")
4522         (ashift:SI (match_operand:SI 1 "general_operand" "")
4523                    (const_int 16)))
4524    (clobber (match_scratch:HI 3 ""))]
4525    ""
4526   [(set (match_dup 2) (match_dup 3))
4527    (set (match_dup 4) (const_int 0))]
4528    "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4529     operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4530     operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4532 (define_insn "*ashlsi3_const16"
4533   [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4534         (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4535                    (const_int 16)))
4536    (clobber (match_scratch:HI 2 "=X,X,X"))]
4537    ""
4538    "#")
4540 (define_insn_and_split "*ashlsi3_const16_zexthi"
4541   [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4542         (ashift:SI (zero_extend:HI 
4543                         (match_operand:HI 1 "general_operand" "duim*A"))
4544                    (const_int 16)))
4545    (clobber (match_scratch:HI 2 "=X"))]
4546    ""
4547    "#"
4548    "reload_completed"
4549    [(set (reg:HI X_REGNUM) (match_dup 1))
4550     (set (reg:HI D_REGNUM) (const_int 0))]
4551    "")
4553 (define_insn "*ashlsi3_const1"
4554   [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
4555         (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
4556                    (const_int 1)))
4557    (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
4558    ""
4559    "*
4561   CC_STATUS_INIT;
4562   if (X_REG_P (operands[1]))
4563     {
4564       return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4565     }
4566   else
4567     {
4568       rtx ops[2];
4570       ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4571       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4572       m68hc11_gen_movhi (insn, ops);
4573       output_asm_insn (\"lsld\", ops);
4574       if (!X_REG_P (operands[0]))
4575         {
4576           ops[1] = ops[0];
4577           ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4578           m68hc11_gen_movhi (insn, ops);
4579           ops[0] = ops[1];
4580           ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4581           m68hc11_gen_movhi (insn, ops);
4582         }
4583       else
4584         {
4585           /* Load the high part in X in case the source operand
4586              uses X as a memory pointer.  */
4587           ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4588           ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4589           m68hc11_gen_movhi (insn, ops);
4590           output_asm_insn (\"xgdx\", ops);
4591         }
4592       output_asm_insn (\"rolb\", ops);
4593       output_asm_insn (\"rola\", ops);
4594       if (!X_REG_P (operands[0]))
4595         {
4596           ops[1] = ops[0];
4597           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4598           m68hc11_gen_movhi (insn, ops);
4599         }
4600       else
4601         {
4602           output_asm_insn (\"xgdx\", ops);
4603         }
4604       return \"\";
4605     }
4608 (define_insn "*ashlsi3_const"
4609   [(set (match_operand:SI 0 "register_operand" "+D")
4610         (ashift:SI (match_dup 0)
4611                    (match_operand:HI 1 "const_int_operand" "")))
4612    (clobber (match_scratch:HI 2 "=y"))]
4613    "TARGET_M6811 /* See *ashlsi3 note.  */"
4614    "*
4616   CC_STATUS_INIT;
4617   return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4620 (define_insn "*ashlsi3"
4621   [(set (match_operand:SI 0 "register_operand" "+D,D")
4622         (ashift:SI (match_dup 0)
4623                    (match_operand:HI 1 "general_operand" "y,mi")))
4624    (clobber (match_scratch:HI 2 "=1,X"))]
4625    ""
4626    "*
4628   CC_STATUS_INIT;
4630   /* There is a reload problem if we don't accept 'm' for the shift value.
4631      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4632      and this conflicts with all reloads.  Since X, Y, Z are used there
4633      is not enough register in class A_REGS.
4635      Assuming that 'operands[1]' does not refer to the stack (which 
4636      is true for 68hc11 only, we save temporary the value of Y.
4638      For 68HC12 we must also accept a constant because Z register is
4639      disabled when compiling with -fomit-frame-pointer.  We can come up
4640      with a reload problem and the *lshrsi3_const pattern was disabled
4641      for that reason.  */
4642   if (!Y_REG_P (operands[2]))
4643     {
4644       rtx ops[1];
4645       int y_dead = dead_register_here (insn, iy_reg);
4647       ops[0] = operands[1];
4648       if (y_dead == 0)
4649         {
4650           output_asm_insn (\"pshy\", operands);
4651           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4652             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4653         }
4654       output_asm_insn (\"ldy\\t%0\", ops);
4655       output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4656       return y_dead == 0 ? \"puly\" : \"\";
4657     }
4658   return \"bsr\\t___ashlsi3\";
4661 (define_expand "ashlhi3"
4662   [(set (match_operand:HI 0 "register_operand" "")
4663         (ashift:HI (match_operand:HI 1 "register_operand" "")
4664                    (match_operand:HI 2 "general_operand" "")))]
4665    ""
4666    "
4668   if (GET_CODE (operands[2]) != CONST_INT) 
4669     {
4670       rtx scratch = gen_reg_rtx (HImode);
4671       emit_move_insn (scratch, operands[2]);
4672       emit_insn (gen_rtx_PARALLEL (VOIDmode,
4673                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
4674                             operand0,
4675                             gen_rtx_ASHIFT (HImode,
4676                                         operand1, scratch)),
4677                               gen_rtx_CLOBBER (VOIDmode, scratch))));
4678       DONE;
4679     }
4682 (define_insn "*ashlhi3_const1"
4683   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4684         (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4685                    (const_int 1)))]
4686   ""
4687   "*
4689   if (A_REG_P (operands[0]))
4690     return \"#\";
4692   if (D_REG_P (operands[0]))
4693     {
4694       return \"asld\";
4695     }
4696   
4697   output_asm_insn (\"asl\\t%b0\", operands);
4698   output_asm_insn (\"rol\\t%h0\", operands);
4699   CC_STATUS_INIT;
4700   return \"\";
4704 (define_insn "*ashlhi3_2"
4705   [(set (match_operand:HI 0 "register_operand" "=d,*x")
4706         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4707                    (match_operand:HI 2 "register_operand" "+x,+d")))
4708    (clobber (match_dup 2))]
4709   ""
4710   "*
4712   if (A_REG_P (operands[0]))
4713     return \"#\";
4715   CC_STATUS_INIT;
4716   return \"bsr\\t___lshlhi3\";
4719 (define_insn "*ashlhi3"
4720   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4721         (ashift:HI (match_dup 0)
4722                    (match_operand:HI 1 "register_operand" "+x")))
4723    (clobber (match_dup 1))]
4724   ""
4725   "*
4727   CC_STATUS_INIT;
4728   return \"bsr\\t___lshlhi3\";
4731 (define_insn "*ashlhi3"
4732   [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4733         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4734                    (match_operand:HI 2 "const_int_operand" "")))]
4735   ""
4736   "*
4738   int   i;
4740   if (A_REG_P (operands[0]))
4741     return \"#\";
4743   i = INTVAL (operands[2]);
4744   if (i >= 8)
4745     {
4746       CC_STATUS_INIT;
4747       output_asm_insn (\"tba\", operands);
4748       if (i == 15)
4749         {
4750           output_asm_insn (\"rora\", operands);
4751           output_asm_insn (\"anda\\t#0\", operands);
4752           output_asm_insn (\"rora\", operands);
4753         }
4754       else
4755         while (i != 8 )
4756           {
4757             output_asm_insn (\"asla\", operands);
4758             i--;
4759           }
4760       return \"clrb\";
4761     }
4762   for (i = 0; i < INTVAL (operands[2]) - 1; i++) 
4763     {
4764       output_asm_insn (\"asld\", operands);
4765     }
4766   return \"asld\";
4769 (define_expand "ashlqi3"
4770   [(set (match_operand:QI 0 "register_operand" "")
4771         (ashift:QI (match_operand:QI 1 "register_operand" "")
4772                    (match_operand:QI 2 "general_operand" "")))]
4773    ""
4774    "")
4776 (define_insn "*ashlqi3_const1"
4777   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4778         (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4779                    (const_int 1)))]
4780   ""
4781   "@
4782    aslb
4783    asl\\t%b0
4784    asl\\t%b0
4785    asl%0
4786    #")
4788 (define_insn "*ashlqi3_const"
4789   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4790         (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4791                    (match_operand:QI 2 "const_int_operand" "")))]
4792   ""
4793   "*
4795   int i;
4796   const char* insn_code;
4798   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4799     insn_code = \"aslb\";
4800   else if (DA_REG_P (operands[0]))
4801     insn_code = \"asla\";
4802   else
4803     return \"#\";
4805   i = INTVAL (operands[2]);
4806   if (i >= 8)
4807     {
4808       if (DA_REG_P (operands[0]))
4809         return \"clra\";
4810       else
4811         return \"clrb\";
4812     }
4813   else if (i == 7)
4814     {
4815       if (DA_REG_P (operands[0]))
4816         {
4817           output_asm_insn (\"rora\", operands);
4818           output_asm_insn (\"ldaa\\t#0\", operands);
4819           return \"rora\";
4820         }
4821       else
4822         {
4823           output_asm_insn (\"rorb\", operands);
4824           output_asm_insn (\"ldab\\t#0\", operands);
4825           return \"rorb\";
4826         }
4827     }
4828   else if (i == 6)
4829     {
4830       if (DA_REG_P (operands[0]))
4831         {
4832           output_asm_insn (\"rora\", operands);
4833           output_asm_insn (\"rora\", operands);
4834           output_asm_insn (\"rora\", operands);
4835           return \"anda\\t#0xC0\";
4836         }
4837       else
4838         {
4839           output_asm_insn (\"rorb\", operands);
4840           output_asm_insn (\"rorb\", operands);
4841           output_asm_insn (\"rorb\", operands);
4842           return \"andb\\t#0xC0\";
4843         }
4844     }
4845   while (--i >= 0)
4846     {
4847       output_asm_insn (insn_code, operands);
4848     }
4849   return \"\";
4852 (define_insn "*ashlqi3"
4853   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4854         (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4855                      (match_operand:QI 2 "nonimmediate_operand" 
4856                                          "m*u*d*A,m*u*d*A,m*u")))]
4857   ""
4858   "*
4860   rtx ops[2];
4862   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4863     return \"#\";
4865   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
4866   ops[1] = operands[2];
4867   m68hc11_gen_movqi (insn, ops);
4869   CC_STATUS_INIT;
4870   return \"bsr\\t___lshlqi3\";
4873 (define_expand "ashrhi3"
4874   [(set (match_operand:HI 0 "register_operand" "")
4875         (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4876                      (match_operand:HI 2 "general_operand" "")))]
4877    ""
4878    "
4880   if (GET_CODE (operands[2]) != CONST_INT) 
4881     {
4882       rtx scratch = gen_reg_rtx (HImode);
4884       emit_move_insn (scratch, operands[2]);
4885       emit_insn (gen_rtx_PARALLEL (VOIDmode,
4886                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
4887                                 operand0,
4888                                 gen_rtx_ASHIFTRT (HImode,
4889                                         operand1, scratch)),
4890                               gen_rtx_CLOBBER (VOIDmode, scratch))));
4891        DONE;
4892     }
4895 (define_insn "*ashrhi3_const1"
4896   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4897         (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4898                      (const_int 1)))]
4899   ""
4900   "*
4902   if (A_REG_P (operands[0]))
4903     return \"#\";
4905   CC_STATUS_INIT;
4906   if (D_REG_P (operands[0]))
4907     {
4908       return \"asra\\n\\trorb\";
4909     }
4910   
4911   output_asm_insn (\"asr\\t%h0\", operands);
4912   output_asm_insn (\"ror\\t%b0\", operands);
4913   return \"\";
4917 (define_insn "*ashrhi3_const"
4918   [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4919         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4920                      (match_operand:HI 2 "const_int_operand" "")))]
4921   ""
4922   "*
4924   rtx ops[2];
4925   int val = INTVAL (operands[2]);
4927   if (A_REG_P (operands[0]))
4928     return \"#\";
4930   if (val >= 15)
4931     {
4932       ops[0] = gen_label_rtx ();
4934       output_asm_insn (\"clrb\", operands);
4935       output_asm_insn (\"rola\", operands);
4937         /* Clear A without clearing the carry flag.  */
4938       output_asm_insn (\"tba\", operands);
4939       output_asm_insn (\"bcc\\t%l0\", ops);
4940       output_asm_insn (\"coma\", operands);
4941       output_asm_insn (\"comb\", operands);
4943       CC_STATUS_INIT;
4944       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4945                                  CODE_LABEL_NUMBER (ops[0]));
4946       return \"\";
4947     }
4948   if (val >= 8)
4949     {
4950       ops[0] = gen_label_rtx ();
4952       output_asm_insn (\"tab\", operands);
4953       output_asm_insn (\"clra\", operands);
4954       output_asm_insn (\"tstb\", operands);
4955       output_asm_insn (\"bge\\t%l0\", ops);
4956       output_asm_insn (\"deca\", operands);
4958       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4959                                  CODE_LABEL_NUMBER (ops[0]));
4961       val -= 8;
4963       while (val > 0)
4964         {
4965           output_asm_insn (\"asrb\", operands);
4966           val--;
4967         }
4968         /* Status is ok.  */
4969       return \"\";
4970     }
4971   if (val == 7)
4972     {
4973       ops[0] = gen_label_rtx ();
4974       output_asm_insn (\"rolb\", operands);
4975       output_asm_insn (\"rola\", operands);
4976       output_asm_insn (\"tab\", operands);
4977       output_asm_insn (\"anda\\t#0\", operands);
4978       output_asm_insn (\"bcc\\t%l0\", ops);
4979       output_asm_insn (\"coma\", ops);
4981       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4982                                  CODE_LABEL_NUMBER (ops[0]));
4983       return \"\";
4984     }
4985   while (val > 0)
4986     {
4987       output_asm_insn (\"asra\", operands);
4988       output_asm_insn (\"rorb\", operands);
4989       val--;
4990     }
4991   CC_STATUS_INIT;
4993   return \"\";
4996 (define_insn "*ashrhi3"
4997   [(set (match_operand:HI 0 "register_operand" "=d,*x")
4998         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4999                      (match_operand:HI 2 "register_operand" "+x,+d")))
5000    (clobber (match_dup 2))]
5001   ""
5002   "*
5004   if (A_REG_P (operands[0]))
5005     return \"#\";
5007   output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5008   return \"\"; 
5011 (define_expand "ashrsi3"
5012   [(parallel
5013        [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5014         (clobber (scratch:HI))])
5015    (parallel
5016        [(set (match_operand:SI 0 "register_operand" "")
5017                 (ashiftrt:SI (match_dup 0)
5018                              (match_operand:HI 2 "general_operand" "")))
5019         (clobber (scratch:HI))])]
5020    ""
5021    "")
5023 (define_insn "*ashrsi3_const"
5024   [(set (match_operand:SI 0 "register_operand" "+D")
5025         (ashiftrt:SI (match_dup 0)
5026                      (match_operand:HI 1 "const_int_operand" "")))
5027    (clobber (match_scratch:HI 2 "=y"))]
5028    "TARGET_M6811 /* See *ashrsi3 note.  */"
5029    "*
5031   CC_STATUS_INIT;
5032   return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
5035 (define_insn "*ashrsi3"
5036   [(set (match_operand:SI 0 "register_operand" "+D,D")
5037         (ashiftrt:SI (match_dup 0)
5038                      (match_operand:HI 1 "general_operand" "y,mi")))
5039    (clobber (match_scratch:HI 2 "=1,X"))]
5040    ""
5041    "*
5043   CC_STATUS_INIT;
5044   /* There is a reload problem if we don't accept 'm' for the shift value.
5045      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5046      and this conflicts with all reloads.  Since X, Y, Z are used there
5047      is not enough register in class A_REGS.
5049      Assuming that 'operands[1]' does not refer to the stack (which 
5050      is true for 68hc11 only, we save temporary the value of Y.
5052      For 68HC12 we must also accept a constant because Z register is
5053      disabled when compiling with -fomit-frame-pointer.  We can come up
5054      with a reload problem and the *lshrsi3_const pattern was disabled
5055      for that reason.  */
5056   if (!Y_REG_P (operands[2]))
5057     {
5058       rtx ops[1];
5059       int y_dead = dead_register_here (insn, iy_reg);
5061       ops[0] = operands[1];
5062       if (y_dead == 0)
5063         {
5064           output_asm_insn (\"pshy\", operands);
5065           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5066             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5067         }
5068       output_asm_insn (\"ldy\\t%0\", ops);
5069       output_asm_insn (\"bsr\\t___ashrsi3\", operands);
5070       return y_dead == 0 ? \"puly\" : \"\";
5071     }
5072   return \"bsr\\t___ashrsi3\";
5075 (define_expand "ashrqi3"
5076   [(set (match_operand:QI 0 "register_operand" "")
5077         (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5078                      (match_operand:QI 2 "general_operand" "")))]
5079    ""
5080    "")
5082 (define_insn "*ashrqi3_const1"
5083   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5084         (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5085                      (const_int 1)))]
5086   ""
5087   "@
5088    asrb
5089    asr\\t%b0
5090    asr\\t%b0
5091    asr%0
5092    #")
5094 (define_insn "*ashrqi3_const"
5095   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5096         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5097                      (match_operand:QI 2 "const_int_operand" "")))]
5098   ""
5099   "*
5101   int i;
5102   const char* insn_code;
5104   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5105     insn_code = \"asrb\";
5106   else if (DA_REG_P (operands[0]))
5107     insn_code = \"asra\";
5108   else
5109     return \"#\";
5111   i = INTVAL (operands[2]);
5112   if (i > 8)
5113     i = 8;
5114   while (--i >= 0)
5115     {
5116       output_asm_insn (insn_code, operands);
5117     }
5118   return \"\";
5121 (define_insn "*ashrqi3"
5122   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5123         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5124                      (match_operand:QI 2 "nonimmediate_operand" 
5125                                          "m*u*d*A,m*u*d*A,m*u")))]
5126   ""
5127   "*
5129   rtx ops[2];
5131   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5132     return \"#\";
5134   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5135   ops[1] = operands[2];
5136   m68hc11_gen_movqi (insn, ops);
5138   CC_STATUS_INIT;
5139   return \"bsr\\t___ashrqi3\";
5142 ;;--------------------------------------------------------------------
5143 ;; logical shift instructions
5144 ;;--------------------------------------------------------------------
5145 (define_expand "lshrdi3"
5146   [(parallel [(set (match_operand:DI 0 "general_operand" "")
5147                      (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5148                                   (match_operand:HI 2 "general_operand" "")))
5149               (clobber (match_scratch:HI 3 ""))])]
5150    ""
5151    "
5153   if (GET_CODE (operands[2]) != CONST_INT 
5154      || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5155          && INTVAL (operands[2]) != 1))
5156     {
5157       FAIL;
5158     }
5161 (define_insn_and_split "*lshrdi3_const32"
5162   [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5163         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
5164                      (const_int 32)))
5165    (clobber (match_scratch:HI 2 "=&A,d,d"))]
5166    ""
5167    "#"
5168    "reload_completed"
5169    [(const_int 0)]
5170    "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5171                         m68hc11_gen_highpart (SImode, operands[1]),
5172                         operands[2]);
5173     m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5174                         const0_rtx, operands[2]);
5175     DONE;")
5177 (define_insn "*lshrdi3_const63"
5178   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5179         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5180                      (match_operand:DI 2 "const_int_operand" "")))
5181    (clobber (match_scratch:HI 3 "=d,d"))]
5182    "INTVAL (operands[2]) >= 48"
5183    "#")
5185 (define_split
5186   [(set (match_operand:DI 0 "nonimmediate_operand" "")
5187         (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5188                      (match_operand:DI 2 "const_int_operand" "")))
5189    (clobber (match_scratch:HI 3 "=d"))]
5190    "z_replacement_completed && INTVAL (operands[2]) >= 56"
5191    [(set (reg:QI D_REGNUM) (match_dup 9))
5192     (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5193     (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5194     (set (match_dup 4) (reg:HI D_REGNUM))
5195     (set (reg:QI D_REGNUM) (const_int 0))
5196     (set (match_dup 5) (reg:HI D_REGNUM))
5197     (set (match_dup 6) (reg:HI D_REGNUM))
5198     (set (match_dup 7) (reg:HI D_REGNUM))]
5199    "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
5200     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5201     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5202     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5204     operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5205     operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5206     operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5208     operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5209     operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5210     operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5212 (define_split
5213   [(set (match_operand:DI 0 "nonimmediate_operand" "")
5214         (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5215                      (match_operand:DI 2 "const_int_operand" "")))
5216    (clobber (match_scratch:HI 3 "=d"))]
5217    "z_replacement_completed && INTVAL (operands[2]) >= 48 
5218     && INTVAL (operands[2]) < 56"
5219    [(set (reg:HI D_REGNUM) (match_dup 9))
5220     (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5221     (set (match_dup 4) (reg:HI D_REGNUM))
5222     (set (reg:HI D_REGNUM) (const_int 0))
5223     (set (match_dup 5) (reg:HI D_REGNUM))
5224     (set (match_dup 6) (reg:HI D_REGNUM))
5225     (set (match_dup 7) (reg:HI D_REGNUM))]
5226    "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
5227     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5228     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5229     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5231     operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5232     operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5233     operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5234     operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5235     operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5237 (define_insn_and_split "*lshrdi_const1"
5238   [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5239         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5240                      (const_int 1)))
5241    (clobber (match_scratch:HI 2 "=d,d"))]
5242    ""
5243    "#"
5244    "z_replacement_completed == 2"
5245    [(set (match_dup 2) (match_dup 3))
5246     (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5247     (set (match_dup 4) (match_dup 2))
5249     (set (match_dup 2) (match_dup 5))
5250     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5251                (clobber (reg:HI CC_REGNUM))])
5252     (set (match_dup 6) (match_dup 2))
5254     (set (match_dup 2) (match_dup 7))
5255     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5256                (clobber (reg:HI CC_REGNUM))])
5257     (set (match_dup 8) (match_dup 2))
5259     (set (match_dup 2) (match_dup 9))
5260     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5261                (clobber (reg:HI CC_REGNUM))])
5262     (set (match_dup 10) (match_dup 2))]
5263    "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5264     operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5265     operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5267     operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5268     operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5269     operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5271     operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5272     operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5273     operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5275     operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5276     operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5277     operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5279 (define_expand "lshrsi3"
5280   [(parallel
5281        [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5282         (clobber (scratch:HI))])
5283    (parallel
5284        [(set (match_operand:SI 0 "register_operand" "")
5285              (lshiftrt:SI (match_dup 0)
5286                           (match_operand:HI 2 "general_operand" "")))
5287         (clobber (scratch:HI))])]
5288    ""
5289    "")
5291 (define_split
5292   [(set (match_operand:SI 0 "non_push_operand" "")
5293         (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
5294                      (const_int 16)))
5295    (clobber (match_scratch:HI 3 ""))]
5296    "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5297   [(set (match_dup 2) (match_dup 3))
5298    (set (match_dup 4) (const_int 0))]
5299    "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5300     operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5301     operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5303 (define_insn "*lshrsi3_const16"
5304   [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5305         (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
5306                      (const_int 16)))
5307    (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5308    ""
5309    "@
5310     #
5311     xgdx\\n\\tldx\\t#0
5312     #
5313     #")
5315 (define_insn "*lshrsi3_const1"
5316   [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
5317         (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
5318                      (const_int 1)))
5319    (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
5320    ""
5321    "*
5323   CC_STATUS_INIT;
5324   if (X_REG_P (operands[1]))
5325     {
5326       return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5327     }
5328   else
5329     {
5330       rtx ops[2];
5332       ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5333       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
5334       m68hc11_gen_movhi (insn, ops);
5335       output_asm_insn (\"lsrd\", ops);
5336       if (!X_REG_P (operands[0]))
5337         {
5338           ops[1] = ops[0];
5339           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5340           m68hc11_gen_movhi (insn, ops);
5341           ops[0] = ops[1];
5342           ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5343           m68hc11_gen_movhi (insn, ops);
5344         }
5345       else
5346         {
5347           /* Load the lowpart in X in case the operands is some N,x.  */
5348           ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
5349           ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5350           m68hc11_gen_movhi (insn, ops);
5351           output_asm_insn (\"xgdx\", ops);
5352         }
5353       output_asm_insn (\"rora\", ops);
5354       output_asm_insn (\"rorb\", ops);
5355       if (!X_REG_P (operands[0]))
5356         {
5357           ops[1] = ops[0];
5358           ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5359           m68hc11_gen_movhi (insn, ops);
5360         }
5361       return \"\";
5362     }
5365 (define_insn "*lshrsi3_const"
5366   [(set (match_operand:SI 0 "register_operand" "+D")
5367         (lshiftrt:SI (match_dup 0)
5368                      (match_operand:HI 1 "const_int_operand" "")))
5369    (clobber (match_scratch:HI 2 "=y"))]
5370    "TARGET_M6811 /* See *lshrsi3 note.  */"
5371    "*
5373   CC_STATUS_INIT;
5374   return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5377 (define_insn "*lshrsi3"
5378   [(set (match_operand:SI 0 "register_operand" "+D,D")
5379         (lshiftrt:SI (match_dup 0)
5380                      (match_operand:HI 1 "general_operand" "y,mi")))
5381    (clobber (match_scratch:HI 2 "=1,X"))]
5382    ""
5383    "*
5385   CC_STATUS_INIT;
5386   /* There is a reload problem if we don't accept 'm' for the shift value.
5387      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5388      and this conflicts with all reloads.  Since X, Y, Z are used there
5389      is not enough register in class A_REGS.
5391      Assuming that 'operands[1]' does not refer to the stack (which 
5392      is true for 68hc11 only, we save temporary the value of Y.
5394      For 68HC12 we must also accept a constant because Z register is
5395      disabled when compiling with -fomit-frame-pointer.  We can come up
5396      with a reload problem and the *lshrsi3_const pattern was disabled
5397      for that reason.  */
5398   if (!Y_REG_P (operands[2]))
5399     {
5400       rtx ops[1];
5401       int y_dead = dead_register_here (insn, iy_reg);
5403       ops[0] = operands[1];
5404       if (y_dead == 0)
5405         {
5406           output_asm_insn (\"pshy\", operands);
5407           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5408             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5409         }
5410       output_asm_insn (\"ldy\\t%0\", ops);
5411       output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5412       return y_dead == 0 ? \"puly\" : \"\";
5413     }
5414   return \"bsr\\t___lshrsi3\";
5417 (define_expand "lshrhi3"
5418   [(set (match_operand:HI 0 "register_operand" "")
5419         (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5420                      (match_operand:HI 2 "general_operand" "")))]
5421    ""
5422    "
5424   if (GET_CODE (operands[2]) != CONST_INT)
5425     {
5426       rtx scratch = gen_reg_rtx (HImode);
5427       operand1 = force_reg (HImode, operand1);
5429       emit_move_insn (scratch, operands[2]);
5430       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5431                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5432                                         operand0,
5433                                         gen_rtx_LSHIFTRT (HImode,
5434                                                 operand1, scratch)),
5435                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5436      DONE;
5437   }
5440 (define_insn "lshrhi3_const1"
5441   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5442         (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5443                      (const_int 1)))]
5444   ""
5445   "*
5447   if (A_REG_P (operands[0]))
5448     return \"#\";
5450   if (D_REG_P (operands[0]))
5451     return \"lsrd\";
5453   CC_STATUS_INIT;
5454   return \"lsr\\t%h0\\n\\tror\\t%b0\";
5457 (define_insn "lshrhi3_const"
5458   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5459         (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5460                      (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5461   ""
5462   "*
5464   int val = INTVAL (operands[2]);
5466   if (A_REG_P (operands[0]))
5467     return \"#\";
5469   if (val >= 8)
5470     {
5471       if (val == 8)
5472         CC_STATUS_INIT;
5474       if (!H_REG_P (operands[1]))
5475         {
5476           output_asm_insn (\"clra\", operands);
5477           output_asm_insn (\"ldab\\t%h1\", operands);
5478         }
5479       else if (A_REG_P (operands[1]))
5480         {
5481           output_asm_insn (\"st%1\\t%t0\", operands);
5482           output_asm_insn (\"ldab\\t%t0\", operands);
5483           output_asm_insn (\"clra\", operands);
5484         }
5485       else
5486         {
5487           output_asm_insn (\"tab\", operands);
5488           output_asm_insn (\"clra\", operands);
5489         }
5490       val -= 8;
5491       switch (val) 
5492         {
5493         case 7:
5494           output_asm_insn (\"rolb\", operands);
5495           output_asm_insn (\"tab\", operands);
5496           output_asm_insn (\"rolb\", operands);
5497           break;
5499         case 6:
5500           output_asm_insn (\"rolb\", operands);
5501           output_asm_insn (\"rolb\", operands);
5502           output_asm_insn (\"rolb\", operands);
5503           output_asm_insn (\"andb\\t#3\", operands);
5504           break;
5506         default:
5507            while (val > 0)
5508              {
5509                 val --;
5510                 output_asm_insn (\"lsrb\", operands);
5511              }
5512            break;
5513         }
5514       return \"\";
5515     }
5517   if (!D_REG_P (operands[1]))
5518     m68hc11_gen_movhi (insn, operands);
5519   switch (val)
5520     {
5521     case 7:
5522       output_asm_insn (\"rolb\", operands);
5523       output_asm_insn (\"tab\", operands);
5524       output_asm_insn (\"rolb\", operands);
5525       output_asm_insn (\"rola\", operands);
5526       output_asm_insn (\"rola\", operands);
5527       output_asm_insn (\"anda\\t#1\", operands);
5528       CC_STATUS_INIT;
5529       break;
5531     default:
5532       while (val > 0) 
5533         {
5534           val --;
5535           output_asm_insn (\"lsrd\", operands);
5536         }
5537      }
5538   return \"\";
5541 (define_insn "*lshrhi3"
5542   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5543         (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5544                      (match_operand:HI 2 "register_operand" "+x,+d")))
5545    (clobber (match_dup 2))]
5546   ""
5547   "*
5549   if (A_REG_P (operands[0]))
5550     return \"#\";
5552   return \"bsr\\t___lshrhi3\";
5555 (define_expand "lshrqi3"
5556   [(set (match_operand:QI 0 "register_operand" "")
5557         (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5558                      (match_operand:QI 2 "general_operand" "")))]
5559    ""
5560    "")
5562 (define_insn "*lshrqi3_const1"
5563   [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5564         (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5565                      (const_int 1)))]
5566   ""
5567   "@
5568    lsr\\t%b0
5569    lsrb
5570    lsr\\t%b0
5571    lsr%0
5572    #")
5574 (define_insn "*lshrqi3_const"
5575   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5576         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5577                      (match_operand:QI 2 "const_int_operand" "")))]
5578   ""
5579   "*
5581   int i;
5582   const char* insn_code;
5584   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5585     insn_code = \"lsrb\";
5586   else if (DA_REG_P (operands[0]))
5587     insn_code = \"lsra\";
5588   else
5589     return \"#\";
5591   i = INTVAL (operands[2]);
5592   if (i >= 8)
5593     {
5594       if (DA_REG_P (operands[0]))
5595         return \"clra\";
5596       else
5597         return \"clrb\";
5598     }
5599   else if (i == 7)
5600     {
5601       if (DA_REG_P (operands[0]))
5602         {
5603           output_asm_insn (\"rola\", operands);
5604           output_asm_insn (\"ldaa\\t#0\", operands);
5605           return \"rola\";
5606         }
5607       else
5608         {
5609           output_asm_insn (\"rolb\", operands);
5610           output_asm_insn (\"ldab\\t#0\", operands);
5611           return \"rolb\";
5612         }
5613     }
5614   else if (i == 6)
5615     {
5616       if (DA_REG_P (operands[0]))
5617         {
5618           output_asm_insn (\"rola\", operands);
5619           output_asm_insn (\"rola\", operands);
5620           output_asm_insn (\"rola\", operands);
5621           return \"anda\\t#3\";
5622         }
5623       else
5624         {
5625           output_asm_insn (\"rolb\", operands);
5626           output_asm_insn (\"rolb\", operands);
5627           output_asm_insn (\"rolb\", operands);
5628           return \"andb\\t#3\";
5629         }
5630     }
5631   while (--i >= 0)
5632     {
5633       output_asm_insn (insn_code, operands);
5634     }
5635   return \"\";
5638 (define_insn "*lshrqi3"
5639   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5640         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5641                      (match_operand:QI 2 "nonimmediate_operand" 
5642                                          "m*u*d*A,m*u*d*A,m*u")))]
5643   ""
5644   "*
5646   rtx ops[2];
5648   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5649     return \"#\";
5651   CC_STATUS_INIT;
5652   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5653   ops[1] = operands[2];
5654   m68hc11_gen_movqi (insn, ops);
5656   if (!optimize || optimize_size)
5657     {
5658       return \"bsr\\t___lshrqi3\";
5659     }
5661   ops[0] = gen_label_rtx ();
5662   ops[1] = gen_label_rtx ();
5663   output_asm_insn (\"ble\\t%l1\", ops);
5665   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5666                              CODE_LABEL_NUMBER (ops[0]));
5668   output_asm_insn (\"lsrb\", operands);
5669   output_asm_insn (\"deca\", operands);
5670   output_asm_insn (\"bne\\t%l0\", ops);
5672   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5673                              CODE_LABEL_NUMBER (ops[1]));
5674   return \"\";
5677 (define_insn "*rotlqi3_with_carry"
5678   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5679         (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5680                    (reg:QI CC_REGNUM)))]
5681   ""
5682   "*
5684   if (DA_REG_P (operands[0]))
5685     return \"rola\";
5686   else
5687     return \"rolb\";
5690 (define_insn "*rotlhi3_with_carry"
5691   [(set (match_operand:HI 0 "register_operand" "=d")
5692         (rotate:HI (match_operand:HI 1 "register_operand" "0")
5693                    (const_int 1)))
5694    (clobber (reg:HI CC_REGNUM))]
5695   ""
5696   "*
5698   CC_STATUS_INIT;
5699   return \"rolb\\n\\trola\";
5702 (define_insn "*rotrhi3_with_carry"
5703   [(set (match_operand:HI 0 "register_operand" "=d")
5704         (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5705                      (const_int 1)))
5706    (clobber (reg:HI CC_REGNUM))]
5707   ""
5708   "*
5710   CC_STATUS_INIT;
5711   return \"rora\\n\\trorb\";
5714 (define_insn "rotlqi3"
5715   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5716         (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5717                    (match_operand:QI 2 "const_int_operand" "i,i")))]
5718   ""
5719   "*
5721   m68hc11_gen_rotate (ROTATE, insn, operands);
5722   return \"\";
5725 (define_insn "rotrqi3"
5726   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5727         (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5728                      (match_operand:QI 2 "const_int_operand" "i,i")))]
5729   ""
5730   "*
5732   m68hc11_gen_rotate (ROTATERT, insn, operands);
5733   return \"\";
5736 (define_expand "rotlhi3"
5737   [(set (match_operand:HI 0 "register_operand" "")
5738         (rotate:HI (match_operand:HI 1 "register_operand" "")
5739                    (match_operand:HI 2 "general_operand" "")))]
5740    ""
5741    "
5743   if (GET_CODE (operands[2]) != CONST_INT)
5744     {
5745       rtx scratch = gen_reg_rtx (HImode);
5746       operand1 = force_reg (HImode, operand1);
5748       emit_move_insn (scratch, operands[2]);
5749       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5750                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5751                                         operand0,
5752                                         gen_rtx_ROTATE (HImode,
5753                                                 operand1, scratch)),
5754                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5755       DONE;
5756     }
5759 (define_insn "rotlhi3_const"
5760   [(set (match_operand:HI 0 "register_operand" "=d")
5761         (rotate:HI (match_operand:HI 1 "register_operand" "0")
5762                    (match_operand:HI 2 "const_int_operand" "i")))]
5763   ""
5764   "*
5766   m68hc11_gen_rotate (ROTATE, insn, operands);
5767   return \"\";
5770 (define_insn "*rotlhi3"
5771   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5772         (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
5773                    (match_operand:HI 2 "general_operand" "+x,+d")))
5774    (clobber (match_dup 2))]
5775   ""
5776   "*
5778   if (A_REG_P (operands[0]))
5779     return \"#\";
5781   return \"bsr\\t___rotlhi3\";
5784 (define_expand "rotrhi3"
5785   [(set (match_operand:HI 0 "register_operand" "")
5786         (rotatert:HI (match_operand:HI 1 "general_operand" "")
5787                      (match_operand:HI 2 "general_operand" "")))]
5788    ""
5789    "
5791   if (GET_CODE (operands[2]) != CONST_INT)
5792     {
5793       rtx scratch = gen_reg_rtx (HImode);
5794       operand1 = force_reg (HImode, operand1);
5796       emit_move_insn (scratch, operands[2]);
5797       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5798                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5799                                         operand0,
5800                                         gen_rtx_ROTATERT (HImode,
5801                                                 operand1, scratch)),
5802                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5803       DONE;
5804     }
5807 (define_insn "rotrhi3_const"
5808   [(set (match_operand:HI 0 "register_operand" "=d")
5809         (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5810                      (match_operand:HI 2 "const_int_operand" "i")))]
5811   ""
5812   "*
5814   m68hc11_gen_rotate (ROTATERT, insn, operands);
5815   return \"\";
5818 (define_insn "*rotrhi3"
5819   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5820         (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
5821                      (match_operand:HI 2 "general_operand" "+x,+d")))
5822    (clobber (match_dup 2))]
5823   ""
5824   "*
5826   if (A_REG_P (operands[0]))
5827     return \"#\";
5829   return \"bsr\\t___rotrhi3\";
5832 ;; Split a shift operation on an address register in a shift
5833 ;; on D_REGNUM.
5834 (define_split /* "*rotrhi3_addr" */
5835   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
5836         (match_operator:HI 3 "m68hc11_shift_operator"
5837             [(match_operand:HI 1 "register_operand" "")
5838              (match_operand:HI 2 "register_operand" "")]))
5839    (clobber (match_dup 2))]
5840   "z_replacement_completed == 2"
5841   [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5842               (set (match_dup 0) (reg:HI D_REGNUM))])
5843    (parallel [(set (reg:HI D_REGNUM) 
5844                    (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
5845               (clobber (match_dup 0))])
5846    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5847               (set (match_dup 0) (reg:HI D_REGNUM))])]
5848   "")
5850 ;;--------------------------------------------------------------------
5851 ;;-  68HC12 Decrement/Increment and branch
5852 ;;--------------------------------------------------------------------
5853 ;; These patterns are used by loop optimization as well as peephole2
5854 ;; They must handle reloading themselves and the scratch register
5855 ;; is used for that.  Even if we accept memory operand, we must not
5856 ;; accept them on the predicate because it might create too many reloads.
5857 ;; (specially on HC12 due to its auto-incdec addressing modes).
5859 (define_expand "decrement_and_branch_until_zero"
5860   [(parallel [(set (pc)
5861                    (if_then_else
5862                     (ne (plus:HI (match_operand:HI 0 "register_operand" "")
5863                                  (const_int 0))
5864                         (const_int 1))
5865                     (label_ref (match_operand 1 "" ""))
5866                     (pc)))
5867               (set (match_dup 0)
5868                    (plus:HI (match_dup 0)
5869                             (const_int -1)))
5870               (clobber (match_scratch:HI 2 ""))])]
5871   "TARGET_M6812"
5872   "")
5874 (define_expand "doloop_end"
5875   [(use (match_operand 0 "" ""))        ; loop pseudo
5876    (use (match_operand 1 "" ""))        ; iterations; zero if unknown
5877    (use (match_operand 2 "" ""))        ; max iterations
5878    (use (match_operand 3 "" ""))        ; loop level
5879    (use (match_operand 4 "" ""))]       ; label
5880   "TARGET_M6812"
5881   "
5883   /* Reject non-constant loops as it generates bigger code due to
5884      the handling of the loop register.  We can do better by using
5885      the peephole2 dbcc/ibcc patterns.  */
5886   if (INTVAL (operands[1]) == 0)
5887     {
5888       FAIL;
5889     }
5891   /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
5892      the operator and its operands are not relevant.  */
5893   if (GET_MODE (operands[0]) == HImode)
5894     {
5895       emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
5896                                                gen_rtx_NE (HImode,
5897                                                            operands[0],
5898                                                            const1_rtx),
5899                                                operands[4]));
5900       DONE;
5901     }
5902   if (GET_MODE (operands[0]) == QImode)
5903     {
5904       emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
5905                                                gen_rtx_NE (QImode,
5906                                                            operands[0],
5907                                                            const1_rtx),
5908                                                operands[4]));
5909       DONE;
5910     }
5912   FAIL;
5915 ;; Decrement-and-branch insns.
5916 (define_insn "m68hc12_dbcc_dec_hi"
5917   [(set (pc)
5918         (if_then_else
5919           (match_operator 1 "m68hc11_eq_compare_operator"
5920              [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5921               (const_int 1)])
5922          (label_ref (match_operand 2 "" ""))
5923          (pc)))
5924    (set (match_dup 0)
5925         (plus:HI (match_dup 0) (const_int -1)))
5926    (clobber (match_scratch:HI 3 "=X,dxy"))]
5927   "TARGET_M6812"
5928   "*
5930   if (!H_REG_P (operands[0]))
5931     return \"#\";
5933   CC_STATUS_INIT;
5934   if (GET_CODE (operands[1]) == EQ)
5935     return \"dbeq\\t%0,%l2\";
5936   else
5937     return \"dbne\\t%0,%l2\";
5940 ;; Decrement-and-branch insns.
5941 (define_insn "m68hc12_dbcc_inc_hi"
5942   [(set (pc)
5943         (if_then_else
5944           (match_operator 1 "m68hc11_eq_compare_operator"
5945              [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5946               (const_int -1)])
5947          (label_ref (match_operand 2 "" ""))
5948          (pc)))
5949    (set (match_dup 0)
5950         (plus:HI (match_dup 0) (const_int 1)))
5951    (clobber (match_scratch:HI 3 "=X,dxy"))]
5952   "TARGET_M6812"
5953   "*
5955   if (!H_REG_P (operands[0]))
5956     return \"#\";
5958   CC_STATUS_INIT;
5959   if (GET_CODE (operands[1]) == EQ)
5960     return \"ibeq\\t%0,%l2\";
5961   else
5962     return \"ibeq\\t%0,%l2\";
5965 ;; Decrement-and-branch (QImode).
5966 (define_insn "m68hc12_dbcc_dec_qi"
5967   [(set (pc)
5968         (if_then_else
5969           (match_operator 1 "m68hc11_eq_compare_operator"
5970              [(match_operand:QI 0 "register_operand" "+d,m*u*A")
5971               (const_int 1)])
5972          (label_ref (match_operand 2 "" ""))
5973          (pc)))
5974    (set (match_dup 0)
5975         (plus:QI (match_dup 0) (const_int -1)))
5976    (clobber (match_scratch:QI 3 "=X,d"))]
5977   "TARGET_M6812"
5978   "*
5980   if (!D_REG_P (operands[0]))
5981     return \"#\";
5983   CC_STATUS_INIT;
5984   if (GET_CODE (operands[1]) == EQ)
5985     return \"dbeq\\tb,%l2\";
5986   else
5987     return \"dbne\\tb,%l2\";
5990 ;; Increment-and-branch (QImode).
5991 (define_insn "m68hc12_dbcc_inc_qi"
5992   [(set (pc)
5993         (if_then_else
5994           (match_operator 1 "m68hc11_eq_compare_operator"
5995              [(match_operand:QI 0 "register_operand" "+d,m*u*A")
5996               (const_int -1)])
5997          (label_ref (match_operand 2 "" ""))
5998          (pc)))
5999    (set (match_dup 0)
6000         (plus:QI (match_dup 0) (const_int 1)))
6001    (clobber (match_scratch:QI 3 "=X,d"))]
6002   "TARGET_M6812"
6003   "*
6005   if (!D_REG_P (operands[0]))
6006     return \"#\";
6008   CC_STATUS_INIT;
6009   if (GET_CODE (operands[1]) == EQ)
6010     return \"ibeq\\tb,%l2\";
6011   else
6012     return \"ibeq\\tb,%l2\";
6015 ;; Split the above to handle the case where operand 0 is in memory
6016 ;; (a register that couldn't get a hard register)
6017 (define_split
6018   [(set (pc)
6019         (if_then_else
6020           (match_operator 3 "m68hc11_eq_compare_operator"
6021              [(match_operand:HI 0 "general_operand" "")
6022               (match_operand:HI 1 "const_int_operand" "")])
6023          (label_ref (match_operand 4 "" ""))
6024          (pc)))
6025    (set (match_dup 0)
6026         (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6027    (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
6028   "TARGET_M6812 && reload_completed"
6029   [(set (match_dup 5) (match_dup 0))
6030    (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
6031    (set (match_dup 0) (match_dup 5))
6032    (set (pc)
6033         (if_then_else (match_op_dup 3
6034                             [(match_dup 5) (const_int 0)])
6035                       (label_ref (match_dup 4)) (pc)))]
6036   "")
6038 ;; Split the above to handle the case where operand 0 is in memory
6039 ;; (a register that couldn't get a hard register)
6040 (define_split
6041   [(set (pc)
6042         (if_then_else
6043           (match_operator 3 "m68hc11_eq_compare_operator"
6044              [(match_operand:QI 0 "general_operand" "")
6045               (match_operand:QI 1 "const_int_operand" "")])
6046          (label_ref (match_operand 4 "" ""))
6047          (pc)))
6048    (set (match_dup 0)
6049         (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6050    (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
6051   "TARGET_M6812 && reload_completed"
6052   [(set (match_dup 5) (match_dup 0))
6053    (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
6054    (set (match_dup 0) (match_dup 5))
6055    (set (pc)
6056         (if_then_else (match_op_dup 3
6057                             [(match_dup 5) (const_int 0)])
6058                       (label_ref (match_dup 4)) (pc)))]
6059   "")
6061 ;;--------------------------------------------------------------------
6062 ;;-  Jumps and transfers
6063 ;;--------------------------------------------------------------------
6064 (define_insn "jump"
6065   [(set (pc)
6066         (label_ref (match_operand 0 "" "")))]
6067   ""
6068   "bra\\t%l0")
6070 (define_expand "cbranchsi4"
6071   [(set (cc0)
6072         (compare (match_operand:SI 1 "tst_operand" "")
6073                  (match_operand:SI 2 "cmp_operand" "")))
6074    (set (pc)
6075         (if_then_else (match_operator 0 "ordered_comparison_operator"
6076                        [(cc0) (const_int 0)])
6077                       (label_ref (match_operand 3 "" ""))
6078                       (pc)))]
6079   ""
6080   "
6082   if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
6083     operands[1] = force_reg (SImode, operands[1]);
6085   m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
6086                                      operands[2], operands[3]);
6087   DONE;
6090 (define_expand "cbranchhi4"
6091   [(set (cc0)
6092         (compare (match_operand:HI 1 "tst_operand" "")
6093                  (match_operand:HI 2 "cmp_operand" "")))
6094    (set (pc)
6095         (if_then_else (match_operator 0 "ordered_comparison_operator"
6096                        [(cc0) (const_int 0)])
6097                       (label_ref (match_operand 3 "" ""))
6098                       (pc)))]
6099   ""
6100   "
6102   if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
6103     operands[1] = force_reg (HImode, operands[1]);
6105   m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
6106                                      operands[2], operands[3]);
6107   DONE;
6110 (define_expand "cbranchqi4"
6111   [(set (cc0)
6112         (compare (match_operand:QI 1 "tst_operand" "")
6113                  (match_operand:QI 2 "cmp_operand" "")))
6114    (set (pc)
6115         (if_then_else (match_operator 0 "ordered_comparison_operator"
6116                        [(cc0) (const_int 0)])
6117                       (label_ref (match_operand 3 "" ""))
6118                       (pc)))]
6119   ""
6120   "
6122   if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
6123     operands[1] = force_reg (QImode, operands[1]);
6125   m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
6126                                      operands[2], operands[3]);
6127   DONE;
6132 ;; Test and branch instructions for 68HC12 for EQ and NE.
6133 ;; 'z' must not appear in the constraints because the z replacement 
6134 ;; pass does not know how to restore the replacement register.
6136 (define_insn "*tbeq"
6137   [(set (pc)
6138         (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
6139                           (const_int 0))
6140                       (label_ref (match_operand 1 "" ""))
6141                       (pc)))]
6142   "TARGET_M6812"
6143   "*
6145    /* If the flags are already set correctly, use 'bne/beq' which are
6146       smaller and a little bit faster.  This happens quite often due
6147       to reloading of operands[0].  In that case, flags are set correctly
6148       due to the load instruction.  */
6149   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6150       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6151     return \"beq\\t%l1\";
6152   else
6153     return \"tbeq\\t%0,%l1\";
6156 (define_insn "*tbne"
6157   [(set (pc)
6158         (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6159                           (const_int 0))
6160                       (label_ref (match_operand 1 "" ""))
6161                       (pc)))]
6162   "TARGET_M6812"
6163   "*
6165    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6166        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6167      return \"bne\\t%l1\";
6168    else
6169      return \"tbne\\t%0,%l1\";
6173 ;; Test and branch with 8-bit register.  Register must be B (or A).
6175 (define_insn "*tbeq8"
6176   [(set (pc)
6177         (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6178                           (const_int 0))
6179                       (label_ref (match_operand 1 "" ""))
6180                       (pc)))]
6181   "TARGET_M6812"
6182   "*
6184    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6185        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6186      return \"beq\\t%l1\";
6187    else
6188      return \"tbeq\\tb,%l1\";
6191 (define_insn "*tbne8"
6192   [(set (pc)
6193         (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6194                           (const_int 0))
6195                       (label_ref (match_operand 1 "" ""))
6196                       (pc)))]
6197   "TARGET_M6812"
6198   "*
6200    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6201        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6202      return \"bne\\t%l1\";
6203    else
6204      return \"tbne\\tb,%l1\";
6207 (define_insn "*beq"
6208   [(set (pc)
6209         (if_then_else (eq (cc0)
6210                           (const_int 0))
6211                       (label_ref (match_operand 0 "" ""))
6212                       (pc)))]
6213   ""
6214   "beq\\t%l0")
6216 (define_insn "*bne"
6217   [(set (pc)
6218         (if_then_else (ne (cc0)
6219                           (const_int 0))
6220                       (label_ref (match_operand 0 "" ""))
6221                       (pc)))]
6222   ""
6223   "bne\\t%l0")
6225 (define_insn "*bgt"
6226   [(set (pc)
6227         (if_then_else (gt (cc0)
6228                           (const_int 0))
6229                       (label_ref (match_operand 0 "" ""))
6230                       (pc)))]
6231   ""
6232   "bgt\\t%l0")
6234 (define_insn "*bgtu"
6235   [(set (pc)
6236         (if_then_else (gtu (cc0)
6237                            (const_int 0))
6238                       (label_ref (match_operand 0 "" ""))
6239                       (pc)))]
6240   ""
6241   "bhi\\t%l0")
6243 (define_insn "*blt"
6244   [(set (pc)
6245         (if_then_else (lt (cc0)
6246                           (const_int 0))
6247                       (label_ref (match_operand 0 "" ""))
6248                       (pc)))]
6249   ""
6250   "*
6252   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6253     return \"bmi\\t%l0\";
6254   else
6255     return \"blt\\t%l0\";
6258 (define_insn "*bltu"
6259   [(set (pc)
6260         (if_then_else (ltu (cc0)
6261                            (const_int 0))
6262                       (label_ref (match_operand 0 "" ""))
6263                       (pc)))]
6264   ""
6265   "blo\\t%l0")
6267 (define_insn "*bge"
6268   [(set (pc)
6269         (if_then_else (ge (cc0)
6270                           (const_int 0))
6271                       (label_ref (match_operand 0 "" ""))
6272                       (pc)))]
6273   ""
6274   "*
6276   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6277     return \"bpl\\t%l0\";
6278   else
6279     return \"bge\\t%l0\";
6282 (define_insn "*bgeu"
6283   [(set (pc)
6284         (if_then_else (geu (cc0)
6285                            (const_int 0))
6286                       (label_ref (match_operand 0 "" ""))
6287                       (pc)))]
6288   ""
6289   "bhs\\t%l0")
6291 (define_insn "*ble"
6292   [(set (pc)
6293         (if_then_else (le (cc0)
6294                           (const_int 0))
6295                       (label_ref (match_operand 0 "" ""))
6296                       (pc)))]
6297   ""
6298   "*
6300   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6301     return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6302   else
6303     return \"ble\\t%l0\";
6306 (define_insn "*bleu"
6307   [(set (pc)
6308         (if_then_else (leu (cc0)
6309                            (const_int 0))
6310                       (label_ref (match_operand 0 "" ""))
6311                       (pc)))]
6312   ""
6313   "bls\\t%l0")
6315 ;;--------------------------------------------------------------------
6316 ;;- Negative test and branch
6317 ;;--------------------------------------------------------------------
6318 (define_insn ""
6319   [(set (pc)
6320         (if_then_else (eq (cc0)
6321                           (const_int 0))
6322                       (pc)
6323                       (label_ref (match_operand 0 "" ""))))]
6324   ""
6325   "bne\\t%l0")
6327 (define_insn ""
6328   [(set (pc)
6329         (if_then_else (ne (cc0)
6330                           (const_int 0))
6331                       (pc)
6332                       (label_ref (match_operand 0 "" ""))))]
6333   ""
6334   "beq\\t%l0")
6336 (define_insn ""
6337   [(set (pc)
6338         (if_then_else (gt (cc0)
6339                           (const_int 0))
6340                       (pc)
6341                       (label_ref (match_operand 0 "" ""))))]
6342   ""
6343   "*
6345   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6346     return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6347   else
6348     return \"ble\\t%l0\";
6351 (define_insn ""
6352   [(set (pc)
6353         (if_then_else (gtu (cc0)
6354                            (const_int 0))
6355                       (pc)
6356                       (label_ref (match_operand 0 "" ""))))]
6357   ""
6358   "bls\\t%l0")
6360 (define_insn ""
6361   [(set (pc)
6362         (if_then_else (lt (cc0)
6363                           (const_int 0))
6364                       (pc)
6365                       (label_ref (match_operand 0 "" ""))))]
6366   ""
6367   "*
6369   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6370     return \"bpl\\t%l0\";
6371   else
6372     return \"bge\\t%l0\";
6375 (define_insn ""
6376   [(set (pc)
6377         (if_then_else (ltu (cc0)
6378                            (const_int 0))
6379                       (pc)
6380                       (label_ref (match_operand 0 "" ""))))]
6381   ""
6382   "bhs\\t%l0")
6384 (define_insn ""
6385   [(set (pc)
6386         (if_then_else (ge (cc0)
6387                           (const_int 0))
6388                       (pc)
6389                       (label_ref (match_operand 0 "" ""))))]
6390   ""
6391   "*
6393   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6394     return \"bmi\\t%l0\";
6395   else
6396     return \"blt\\t%l0\";
6399 (define_insn ""
6400   [(set (pc)
6401         (if_then_else (geu (cc0)
6402                            (const_int 0))
6403                       (pc)
6404                       (label_ref (match_operand 0 "" ""))))]
6405   ""
6406   "blo\\t%l0")
6408 (define_insn ""
6409   [(set (pc)
6410         (if_then_else (le (cc0)
6411                           (const_int 0))
6412                       (pc)
6413                       (label_ref (match_operand 0 "" ""))))]
6414   ""
6415   "bgt\\t%l0")
6417 (define_insn ""
6418   [(set (pc)
6419         (if_then_else (leu (cc0)
6420                            (const_int 0))
6421                       (pc)
6422                       (label_ref (match_operand 0 "" ""))))]
6423   ""
6424   "bhi\\t%l0")
6426 ;;--------------------------------------------------------------------
6427 ;;-  Calls
6428 ;;--------------------------------------------------------------------
6430 ;;- Call a function that returns no value.
6431 (define_insn "call"
6432   [(call (match_operand:QI 0 "memory_operand" "m")
6433          (match_operand:SI 1 "general_operand" "g"))]
6434   ;; Operand 1 not really used on the m68hc11.
6435   ""
6436  "*
6438   if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6439     {
6440       if (m68hc11_is_far_symbol (operands[0]))
6441         {
6442           if (TARGET_M6812)
6443             {
6444               output_asm_insn (\"call\\t%0\", operands);
6445               return \"\";
6446             }
6447           else
6448             {
6449               output_asm_insn (\"pshb\", operands);
6450               output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
6451               output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
6452               return \"jsr\\t__call_a32\";
6453             }
6454         }
6455       if (m68hc11_is_trap_symbol (operands[0]))
6456         return \"swi\";
6457       else
6458         return \"bsr\\t%0\";
6459     }
6460   else
6461     {
6462       return \"jsr\\t%0\";
6463     }
6466 (define_insn "call_value"
6467   [(set (match_operand 0 "" "=g")
6468         (call (match_operand:QI 1 "memory_operand" "m")
6469               (match_operand:SI 2 "general_operand" "g")))]
6470   ""
6471  "*
6473   if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6474     {
6475       if (m68hc11_is_far_symbol (operands[1]))
6476         {
6477           if (TARGET_M6812)
6478             {
6479               output_asm_insn (\"call\\t%1\", operands);
6480               return \"\";
6481             }
6482           else
6483             {
6484               output_asm_insn (\"pshb\", operands);
6485               output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
6486               output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
6487               return \"jsr\\t__call_a32\";
6488             }
6489         }
6490       if (m68hc11_is_trap_symbol (operands[1]))
6491         return \"swi\";
6492       else
6493         return \"bsr\\t%1\";
6494     }
6495   else
6496     {
6497       return \"jsr\\t%1\";
6498     }
6501 ;; Call subroutine returning any type.
6503 (define_expand "untyped_call"
6504   [(parallel [(call (match_operand 0 "" "")
6505                     (const_int 0))
6506               (match_operand 1 "" "")
6507               (match_operand 2 "" "")])]
6508   ""
6509   "
6511   int i;
6513   emit_call_insn (gen_call (operands[0], const0_rtx));
6515   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6516     {
6517       rtx set = XVECEXP (operands[2], 0, i);
6518       emit_move_insn (SET_DEST (set), SET_SRC (set));
6519     }
6521   /* The optimizer does not know that the call sets the function value
6522      registers we stored in the result block.  We avoid problems by
6523      claiming that all hard registers are used and clobbered at this
6524      point.  */
6525   emit_insn (gen_blockage ());
6527   DONE;
6530 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6531 ;; all of memory.  This blocks insns from being moved across this point.
6533 (define_insn "blockage"
6534   [(unspec_volatile [(const_int 0)] 0)]
6535   ""
6536   "")
6538 (define_insn "nop"
6539   [(const_int 0)]
6540   ""
6541   "nop")
6542     
6543 (define_expand "prologue"
6544   [(const_int 0)]
6545   ""
6546   "
6548   expand_prologue (); 
6549   DONE;
6552 (define_expand "epilogue"
6553   [(return)]
6554   ""
6555   "
6557   expand_epilogue ();
6558   DONE;
6561 ;; Used for frameless functions which save no regs and allocate no locals.
6562 (define_expand "return"
6563   [(return)]
6564   "reload_completed && m68hc11_total_frame_size () == 0"
6565   "
6567   int ret_size = 0;
6569   if (crtl->return_rtx)
6570     ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
6572   /* Emit use notes only when HAVE_return is true.  */
6573   if (m68hc11_total_frame_size () != 0)
6574     ret_size = 0;
6576   if (ret_size && ret_size <= 2)
6577     {
6578       emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6579                       gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6580                                  gen_rtx_USE (VOIDmode,
6581                                               gen_rtx_REG (HImode, 1)))));
6582       DONE;
6583     }
6584   if (ret_size)
6585     {
6586       emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6587                       gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6588                                  gen_rtx_USE (VOIDmode,
6589                                               gen_rtx_REG (SImode, 0)))));
6590       DONE;
6591     }
6594 (define_insn "*return_void"
6595   [(return)]
6596   "reload_completed"
6597   "*
6599   rtx next = next_active_insn (insn);
6601   if (next
6602       && GET_CODE (next) == JUMP_INSN
6603       && GET_CODE (PATTERN (next)) == RETURN)
6604     return \"\";
6605   if (current_function_interrupt || current_function_trap)
6606     return \"rti\";
6607   else if (!current_function_far)
6608     return \"rts\";
6609   else if (TARGET_M6812)
6610     return \"rtc\";
6611   else
6612     {
6613       int ret_size = 0;
6615       if (crtl->return_rtx)
6616         ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
6618       if (ret_size == 0)
6619         return \"jmp\\t__return_void\";
6620       if (ret_size <= 2)
6621         return \"jmp\\t__return_16\";
6622       if (ret_size <= 4)
6623         return \"jmp\\t__return_32\";
6624       return \"jmp\\t__return_16\";
6625     }
6628 (define_insn "*return_16bit"
6629   [(return)
6630    (use (reg:HI D_REGNUM))]
6631   "reload_completed && m68hc11_total_frame_size () == 0"
6632   "*
6634   rtx next = next_active_insn (insn);
6636   if (next
6637       && GET_CODE (next) == JUMP_INSN
6638       && GET_CODE (PATTERN (next)) == RETURN)
6639     return \"\";
6640   if (current_function_interrupt || current_function_trap)
6641     return \"rti\";
6642   else if (!current_function_far)
6643     return \"rts\";
6644   else if (TARGET_M6812)
6645     return \"rtc\";
6646   else
6647     return \"jmp\\t__return_16\";
6650 (define_insn "*return_32bit"
6651   [(return)
6652    (use (reg:SI 0))]
6653   "reload_completed && m68hc11_total_frame_size () == 0"
6654   "*
6656   rtx next = next_active_insn (insn);
6658   if (next
6659       && GET_CODE (next) == JUMP_INSN
6660       && GET_CODE (PATTERN (next)) == RETURN)
6661     return \"\";
6662   if (current_function_interrupt || current_function_trap)
6663     return \"rti\";
6664   else if (!current_function_far)
6665     return \"rts\";
6666   else if (TARGET_M6812)
6667     return \"rtc\";
6668   else
6669     return \"jmp\\t__return_32\";
6672 (define_insn "indirect_jump"
6673   [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6674   ""
6675   "jmp\\t0,%0")
6677 ;;--------------------------------------------------------------------
6678 ;;-  Table jump
6679 ;;--------------------------------------------------------------------
6681 ;; Operand 0 is the address of the table element to use
6682 ;; operand 1 is the CODE_LABEL for the table
6683 ;;--------------------------------------------------------------------
6684 (define_expand "tablejump"
6685   [(parallel [(set (pc) (match_operand 0 "" ""))
6686               (use (label_ref (match_operand 1 "" "")))])]
6687   ""
6688   "")
6690 (define_insn "*jump_indirect"
6691    [(parallel [
6692         (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6693         (use (label_ref (match_operand 1 "" "")))])]
6694    ""
6695   "jmp\\t0,%0")
6697 ;;--------------------------------------------------------------------
6698 ;;- Peepholes
6699 ;;--------------------------------------------------------------------
6701 ;;--------------------------------------------------------------------
6702 ;;- 68HC12 dbcc/ibcc peepholes
6703 ;;--------------------------------------------------------------------
6705 ;; Replace: "addd #-1; bne L1" into "dbne d,L1"
6706 ;;          "addd #-1; beq L1" into "dbeq d,L1"
6707 ;;          "addd #1; bne L1" into "ibne d,L1"
6708 ;;          "addd #1; beq L1" into "ibeq d,L1"
6710 (define_peephole2
6711   [(set (match_operand:HI 0 "hard_reg_operand" "")
6712         (plus:HI (match_dup 0)
6713                  (match_operand:HI 1 "const_int_operand" "")))
6714    (set (pc)
6715         (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6716                          [(match_dup 0)
6717                           (const_int 0)])
6718                       (label_ref (match_operand 3 "" "")) (pc)))]
6719   "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6720   [(parallel [
6721       (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6722                               (label_ref (match_dup 3)) (pc)))
6723       (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
6724       (clobber (match_dup 4))])]
6725   "operands[4] = gen_rtx_SCRATCH(HImode);
6726    operands[5] = GEN_INT (-INTVAL (operands[1]));")
6730 ;; Replace: "addb #-1; bne L1" into "dbne b,L1"
6731 ;;          "addb #-1; beq L1" into "dbeq b,L1"
6733 (define_peephole2
6734   [(set (match_operand:QI 0 "hard_reg_operand" "")
6735         (plus:QI (match_dup 0)
6736                  (match_operand:QI 1 "const_int_operand" "")))
6737    (set (pc)
6738         (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6739                          [(match_dup 0)
6740                           (const_int 0)])
6741                       (label_ref (match_operand 3 "" "")) (pc)))]
6742   "TARGET_M6812 && D_REG_P (operands[0])
6743    && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6744   [(parallel [
6745       (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6746                               (label_ref (match_dup 3)) (pc)))
6747       (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
6748       (clobber (match_dup 4))])]
6749   "operands[4] = gen_rtx_SCRATCH(QImode);
6750    operands[5] = GEN_INT (-INTVAL (operands[1]));")
6753 ;;--------------------------------------------------------------------
6754 ;;- Move peephole2
6755 ;;--------------------------------------------------------------------
6758 ;; Replace "leas 2,sp" with a "pulx" or a "puly".
6759 ;; On 68HC12, this is one cycle slower but one byte smaller.
6760 ;; pr target/6899: This peephole was not valid because a register CSE
6761 ;; pass removes the pulx/puly.  The 'use' clause ensure that the pulx is
6762 ;; not removed.
6764 (define_peephole2
6765   [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6766    (match_scratch:HI 0 "xy")]
6767   "TARGET_M6812 && optimize_size"
6768   [(set (match_dup 0) (match_dup 1))
6769    (use (match_dup 0))]
6770   "operands[1] = gen_rtx_MEM (HImode,
6771                           gen_rtx_POST_INC (HImode,
6772                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
6774 ;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
6776 ;; PR 14542: emit a use to pretend we need the value of initial register.
6777 ;; Otherwise verify_local_live_at_start will die due to a live change
6778 ;; of that register.
6780 (define_peephole2
6781   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6782         (match_operand:HI 0 "hard_reg_operand" ""))
6783    (set (match_dup 0)
6784         (match_operand:HI 1 "hard_reg_operand" ""))
6785    (set (mem:HI (reg:HI SP_REGNUM))
6786         (match_dup 0))]
6787   "TARGET_M6812"
6788   [(use (match_dup 0))
6789    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6790         (match_dup 1))
6791    (set (match_dup 0) (match_dup 1))]
6792   "")
6795 ;; Change: "ldd 0,sp; pulx" into  "puld"
6796 ;; This sequence usually appears at end a functions.
6797 (define_peephole2
6798   [(set (match_operand:HI 0 "hard_reg_operand" "")
6799         (mem:HI (reg:HI SP_REGNUM)))
6800    (use (match_dup 0))
6801    (set (match_operand:HI 1 "hard_reg_operand" "")
6802         (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
6803   "peep2_reg_dead_p (2, operands[1])"
6804   [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
6805    (use (match_dup 0))]
6806   "")
6808 ;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
6809 ;; Appears to allocate local variables.
6810 (define_peephole2
6811   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6812         (match_operand:HI 0 "hard_reg_operand" ""))
6813    (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
6814         (const_int 0))
6815    (set (mem:QI (reg:HI SP_REGNUM))
6816         (const_int 0))]
6817   "TARGET_M6812"
6818   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6819         (const_int 0))]
6820   "")
6822 ;; Likewise for HI mode
6823 (define_peephole2
6824   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6825         (match_operand:HI 0 "hard_reg_operand" ""))
6826    (set (mem:HI (reg:HI SP_REGNUM))
6827         (const_int 0))]
6828   "TARGET_M6812"
6829   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6830         (const_int 0))]
6831   "")
6832 ;;--------------------------------------------------------------------
6833 ;;- 
6834 ;;--------------------------------------------------------------------
6836 ;; Optimize memory<->memory moves when the value is also loaded in
6837 ;; a register.
6839 (define_peephole2
6840   [(set (match_operand:QI 0 "memory_operand" "")
6841         (match_operand:QI 1 "memory_operand" ""))
6842    (set (reg:QI D_REGNUM)
6843         (match_operand:QI 2 "memory_operand" ""))]
6844   "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
6845    || (GET_CODE (XEXP (operands[0], 0)) == REG
6846        && GET_CODE (XEXP (operands[2], 0)) == POST_INC
6847        && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
6848   [(set (reg:QI D_REGNUM) (match_dup 1))
6849    (set (match_dup 2) (reg:QI D_REGNUM))]
6850   "")
6853 ;; Remove a possible move before a compare instruction when that
6854 ;; move will go in a dead register.  Compare with the source then.
6856 (define_peephole2
6857   [(set (match_operand:HI 0 "hard_reg_operand" "")
6858         (match_operand:HI 1 "hard_reg_operand" ""))
6859    (set (cc0)
6860         (compare (match_dup 0)
6861                  (match_operand:HI 2 "cmp_operand" "")))]
6862   "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
6863    && peep2_reg_dead_p (2, operands[0])
6864    && !reg_mentioned_p (operands[0], operands[2])"
6865   [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
6866   "")
6869 ;; Optimize loading a constant to memory when that same constant
6870 ;; is loaded to a hard register.  Switch the two to use the register
6871 ;; for memory initialization.  In most cases, the constant is 0.
6873 (define_peephole2
6874   [(set (match_operand:HI 0 "memory_operand" "")
6875         (match_operand:HI 1 "immediate_operand" ""))
6876    (set (match_operand:HI 2 "hard_reg_operand" "")
6877         (match_dup 1))]
6878   "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
6879    && !reg_mentioned_p (operands[2], operands[0])"
6880   [(set (match_dup 2) (match_dup 1))
6881    (set (match_dup 0) (match_dup 2))]
6882   "")
6885 ;; Reorganize to optimize address computations.
6887 (define_peephole2
6888   [(set (match_operand:HI 0 "hard_reg_operand" "")
6889         (match_operand:HI 1 "const_int_operand" ""))
6890    (set (match_dup 0)
6891         (plus:HI (match_dup 0)
6892                  (match_operand:HI 2 "general_operand" "")))]
6893   "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
6894   [(set (match_dup 0) (match_dup 2))
6895    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
6896   "")
6899 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
6901 (define_peephole2
6902   [(set (match_operand:HI 0 "hard_reg_operand" "")
6903         (match_operand:HI 1 "const_int_operand" ""))
6904    (set (match_dup 0)
6905         (plus:HI (match_dup 0)
6906                  (match_operand:HI 2 "general_operand" "")))
6907    (match_scratch:QI 3 "d")]
6908   "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
6909   [(set (match_dup 3) (match_dup 4))
6910    (set (match_dup 0) (match_dup 2))
6911    (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
6912   "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
6915 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
6917 (define_peephole2
6918   [(set (match_operand:HI 0 "hard_reg_operand" "")
6919         (match_operand:HI 1 "const_int_operand" ""))
6920    (set (match_dup 0)
6921         (plus:HI (match_dup 0)
6922                  (match_operand:HI 2 "general_operand" "")))]
6923   "TARGET_M6812"
6924   [(set (match_dup 0) (match_dup 2))
6925    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
6926   "")
6929 ;; Optimize an address register increment and a compare to use
6930 ;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
6931 ;; before reload, but can be enabled after).
6933 (define_peephole2
6934   [(set (match_operand:HI 0 "hard_reg_operand" "")
6935         (plus:HI (match_dup 0)
6936                  (match_operand:HI 1 "const_int_operand" "")))
6937    (set (cc0)
6938         (compare (match_operand:QI 2 "memory_operand" "")
6939                  (const_int 0)))]
6940   "TARGET_AUTO_INC_DEC
6941    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6942    && reg_mentioned_p (operands[0], operands[2])"
6943   [(set (cc0)
6944         (compare (match_dup 3)
6945                  (const_int 0)))]
6946   "if (INTVAL (operands[1]) == 1)
6947      operands[3] = gen_rtx_MEM (QImode,
6948                             gen_rtx_PRE_INC (HImode, operands[0]));
6949    else
6950      operands[3] = gen_rtx_MEM (QImode,
6951                             gen_rtx_PRE_DEC (HImode, operands[0]));
6952   ")
6955 ;; Likewise for compare.
6957 (define_peephole2
6958   [(set (match_operand:HI 0 "hard_reg_operand" "")
6959         (plus:HI (match_dup 0)
6960                  (match_operand:HI 1 "const_int_operand" "")))
6961    (set (cc0)
6962         (compare (match_operand:QI 2 "hard_reg_operand" "")
6963                  (match_operand:QI 3 "memory_operand" "")))]
6964   "TARGET_AUTO_INC_DEC
6965    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6966    && reg_mentioned_p (operands[0], operands[3])"
6967   [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
6968   "if (INTVAL (operands[1]) == 1)
6969      operands[4] = gen_rtx_MEM (QImode,
6970                             gen_rtx_PRE_INC (HImode, operands[0]));
6971    else
6972      operands[4] = gen_rtx_MEM (QImode,
6973                             gen_rtx_PRE_DEC (HImode, operands[0]));
6974   ")
6976 (define_peephole2
6977   [(set (match_operand:HI 0 "hard_reg_operand" "")
6978         (plus:HI (match_dup 0)
6979                  (match_operand:HI 1 "const_int_operand" "")))
6980    (set (cc0)
6981         (compare (match_operand:QI 2 "memory_operand" "")
6982                  (match_operand:QI 3 "hard_reg_operand" "")))]
6983   "TARGET_AUTO_INC_DEC
6984    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6985    && reg_mentioned_p (operands[0], operands[2])"
6986   [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
6987   "if (INTVAL (operands[1]) == 1)
6988      operands[4] = gen_rtx_MEM (QImode,
6989                             gen_rtx_PRE_INC (HImode, operands[0]));
6990    else
6991      operands[4] = gen_rtx_MEM (QImode,
6992                             gen_rtx_PRE_DEC (HImode, operands[0]));
6993   ")
6996 ;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
6997 ;; (avoids many temporary moves because we can't add sp to another reg easily)
6999 (define_peephole2
7000   [(set (match_operand:HI 0 "hard_reg_operand" "")
7001         (match_operand:HI 1 "const_int_operand" ""))
7002    (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7003   ""
7004   [(set (match_dup 0) (reg:HI SP_REGNUM))
7005    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7006   "")
7009 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7011 (define_peephole2
7012   [(set (match_operand:HI 0 "hard_reg_operand" "")
7013         (match_operand:HI 1 "const_int_operand" ""))
7014    (set (match_dup 0)
7015         (plus:HI (match_dup 0)
7016                  (match_operand:HI 2 "general_operand" "")))]
7017   "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7018   [(set (match_dup 0) (match_dup 2))
7019    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7020   "")
7025 (define_peephole2
7026   [(parallel 
7027      [(set (match_operand:SI 0 "hard_reg_operand" "")
7028         (ashift:SI (match_operand:SI 1 "general_operand" "")
7029                    (const_int 1)))
7030       (clobber (match_scratch:HI 2 ""))])
7031    (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
7032    (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
7033   "!X_REG_P (operands[1])
7034    && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
7035    && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
7036   [(set (reg:HI D_REGNUM) (match_dup 5))
7037    (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
7038    (set (match_dup 3) (reg:HI D_REGNUM))
7039    (set (reg:HI D_REGNUM) (match_dup 6))
7040    (parallel [(set (reg:HI D_REGNUM)
7041                    (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
7042               (clobber (reg:HI CC_REGNUM))])
7043    (set (match_dup 4) (reg:HI D_REGNUM))]
7044   "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
7045    operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
7048 ;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
7050 (define_peephole2
7051   [(set (match_operand:HI 0 "hard_reg_operand" "")
7052         (match_operand:HI 1 "memory_operand" ""))
7053    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
7054         (match_dup 0))
7055    (match_scratch:HI 2 "x")]
7056   "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
7057   [(set (match_dup 2) (match_dup 1))
7058    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
7059   "")
7062 ;; Remove one load when copying a value to/from memory and also
7063 ;; to a register.  Take care not clobbering a possible register used
7064 ;; by operand 2.
7065 ;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
7067 (define_peephole2
7068   [(set (match_operand:HI 0 "hard_reg_operand" "")
7069         (match_operand:HI 1 "general_operand" ""))
7070    (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
7071    (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
7072   "peep2_reg_dead_p (2, operands[0])
7073    && !side_effects_p (operands[1])
7074    && !side_effects_p (operands[2])
7075    && !reg_mentioned_p (operands[3], operands[2])"
7076   [(set (match_dup 3) (match_dup 1))
7077    (set (match_dup 2) (match_dup 3))]
7078   "")
7081 ;; Replace a "ldd <mem>; addd #N; std <mem>" into a
7082 ;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
7083 ;; and the constant is small.
7085 (define_peephole2
7086   [(set (match_operand:HI 0 "hard_reg_operand" "")
7087         (match_operand:HI 1 "general_operand" ""))
7088    (set (match_dup 0) (plus:HI (match_dup 0)
7089                                (match_operand:HI 2 "const_int_operand" "")))
7090    (set (match_operand:HI 3 "nonimmediate_operand" "")
7091         (match_dup 0))
7092    (match_scratch:HI 4 "xy")]
7093   "D_REG_P (operands[0])
7094    && (TARGET_M6812 
7095        || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
7096    && peep2_reg_dead_p (3, operands[0])"
7097   [(set (match_dup 4) (match_dup 1))
7098    (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
7099    (set (match_dup 3) (match_dup 4))]
7100   "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
7101    if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
7103 ;;--------------------------------------------------------------------
7104 ;;- Bset peephole2
7105 ;;--------------------------------------------------------------------
7106 ;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
7108 ;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
7109 ;; Register D must be dead and there must be no register side effects for mem.
7110 ;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
7111 ;; The good side effect is that it makes the sequence atomic.
7113 (define_peephole2
7114   [(set (match_operand:QI 0 "hard_reg_operand" "")
7115         (match_operand:QI 1 "nonimmediate_operand" ""))
7116    (set (match_dup 0) (ior:QI (match_dup 0)
7117                               (match_operand:QI 2 "const_int_operand" "")))
7118    (set (match_dup 1) (match_dup 0))]
7119   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7120    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7121    && peep2_reg_dead_p (3, operands[0])"
7122   [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
7123   "")
7125 (define_peephole2
7126   [(set (match_operand:HI 0 "hard_reg_operand" "")
7127         (match_operand:HI 1 "nonimmediate_operand" ""))
7128    (set (match_dup 0) (ior:HI (match_dup 0)
7129                               (match_operand:HI 2 "const_int_operand" "")))
7130    (set (match_dup 1) (match_dup 0))]
7131   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7132    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7133    && peep2_reg_dead_p (3, operands[0])"
7134   [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
7135   "")
7137 ;;--------------------------------------------------------------------
7138 ;;- Bclr peephole2
7139 ;;--------------------------------------------------------------------
7140 ;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
7141 ;; See Bset peephole2.
7143 (define_peephole2
7144   [(set (match_operand:QI 0 "hard_reg_operand" "")
7145         (match_operand:QI 1 "nonimmediate_operand" ""))
7146    (set (match_dup 0) (and:QI (match_dup 0)
7147                               (match_operand:QI 2 "const_int_operand" "")))
7148    (set (match_dup 1) (match_dup 0))]
7149   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7150    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7151    && peep2_reg_dead_p (3, operands[0])"
7152   [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
7153   "")
7155 (define_peephole2
7156   [(set (match_operand:HI 0 "hard_reg_operand" "")
7157         (match_operand:HI 1 "nonimmediate_operand" ""))
7158    (set (match_dup 0) (and:HI (match_dup 0)
7159                               (match_operand:HI 2 "const_int_operand" "")))
7160    (set (match_dup 1) (match_dup 0))]
7161   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7162    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7163    && peep2_reg_dead_p (3, operands[0])"
7164   [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
7165   "")
7168 ;;--------------------------------------------------------------------
7169 ;;- Compare peephole2
7170 ;;--------------------------------------------------------------------
7171 (define_peephole2
7172   [(set (match_operand:HI 0 "hard_reg_operand" "")
7173         (match_operand:HI 1 "hard_reg_operand" ""))
7174    (set (match_dup 1) (plus:HI (match_dup 1) 
7175                                (match_operand:HI 2 "const_int_operand" "")))
7176    (set (cc0) (compare (match_dup 0)
7177                        (const_int 0)))]
7178   "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
7179   [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
7180    (set (cc0) (compare (match_dup 1) (match_dup 2)))]
7181   "")
7183 (define_peephole2
7184   [(set (match_operand:HI 0 "hard_reg_operand" "")
7185         (match_operand:HI 1 "hard_reg_operand" ""))
7186    (set (match_operand:HI 2 "hard_reg_operand" "")
7187         (plus:HI (match_dup 2) 
7188                  (match_operand:HI 3 "const_int_operand" "")))
7189    (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
7190    (set (cc0) (compare (match_operand:HI 5 "hard_reg_operand" "")
7191                        (const_int 0)))]
7192   "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
7193    && !reg_mentioned_p (operands[2], operands[4])
7195    && ((rtx_equal_p (operands[5], operands[0])
7196         && rtx_equal_p (operands[2], operands[1]))
7198        || (rtx_equal_p (operands[5], operands[1])
7199            && rtx_equal_p (operands[2], operands[0])))"
7200   [(set (match_dup 2) (match_dup 1))
7201    (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
7202    (set (match_dup 4) (match_dup 2))
7203    (set (cc0) (compare (match_dup 2) (match_dup 3)))]
7204   "")
7207 ;;--------------------------------------------------------------------
7208 ;;- Load peephole2
7209 ;;--------------------------------------------------------------------
7211 ;; Optimize initialization of 2 hard regs from the same memory location
7212 ;; Since we can't copy easily X, Y and D to each other, load the 2 registers
7213 ;; from the same memory location.
7215 (define_peephole2
7216   [(set (match_operand:HI 0 "hard_reg_operand" "")
7217         (match_operand:HI 1 "memory_operand" ""))
7218    (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7219   "TARGET_M6811
7220    && !side_effects_p (operands[1])
7221    && !reg_mentioned_p (operands[0], operands[1])"
7222   [(set (match_dup 0) (match_dup 1))
7223    (set (match_dup 2) (match_dup 1))]
7224   "")
7226 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7228 (define_peephole2
7229   [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7230    (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7231    (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7232    (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
7233    (match_scratch:HI 4 "d")]
7234   ""
7235   [(set (match_dup 4) (const_int 0))
7236    (set (match_dup 0) (match_dup 4))
7237    (set (match_dup 1) (match_dup 4))
7238    (set (match_dup 2) (match_dup 4))
7239    (set (match_dup 3) (match_dup 4))]
7240   "")
7243 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7245 (define_peephole2
7246   [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7247    (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7248    (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7249    (match_scratch:HI 3 "d")]
7250   ""
7251   [(set (match_dup 3) (const_int 0))
7252    (set (match_dup 0) (match_dup 3))
7253    (set (match_dup 1) (match_dup 3))
7254    (set (match_dup 2) (match_dup 3))]
7255   "")
7258 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7260 (define_peephole2
7261   [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
7262    (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
7263    (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
7264    (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
7265    (match_scratch:HI 4 "x")]
7266   "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
7267   [(set (match_dup 4) (const_int 0))
7268    (set (match_dup 1) (match_dup 4))
7269    (set (match_dup 2) (match_dup 4))
7270    (set (match_dup 3) (match_dup 4))]
7271   "")
7274 ;; This peephole catches the address computations generated by the reload
7275 ;; pass. 
7276 (define_peephole
7277   [(set (match_operand:HI 0 "hard_reg_operand" "xy")
7278         (match_operand:HI 1 "const_int_operand" ""))
7279    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7280               (set (match_dup 0) (reg:HI D_REGNUM))])
7281    (set (reg:HI D_REGNUM)
7282         (plus (reg:HI D_REGNUM)
7283               (match_operand:HI 2 "general_operand" "")))
7284    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7285               (set (match_dup 0) (reg:HI D_REGNUM))])]
7286   "(INTVAL (operands[1]) & 0x0FF) == 0"
7287   "*
7289   int value_loaded = 1;
7291   if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
7292     {
7293       rtx ops[2];
7295       ops[0] = operands[0];
7296       ops[1] = operands[2];
7297       m68hc11_gen_movhi (insn, ops);
7298       output_asm_insn (\"xgd%0\", operands);
7299     }
7300   else if (Y_REG_P (operands[0]))
7301     {
7302       if (reg_mentioned_p (iy_reg, operands[2]))
7303         output_asm_insn (\"ldy\\t%2\", operands);
7304       else
7305         value_loaded = 0;
7306       output_asm_insn (\"xgdy\", operands);
7307     }
7308   else
7309     {
7310       output_asm_insn (\"ldd\\t%2\", operands);
7311     }
7313   if (value_loaded == 0)
7314     output_asm_insn (\"ldd\\t%2\", operands);
7315   if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
7316     output_asm_insn (\"inca\", operands);
7317   else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
7318     output_asm_insn (\"deca\", operands);
7319   else if (INTVAL (operands[1]) != 0)
7320     output_asm_insn (\"adda\\t%h1\", operands);
7322   if (X_REG_P (operands[0]))
7323     return \"xgdx\";
7324   else if (Y_REG_P (operands[0]))
7325     return \"xgdy\";
7326   else
7327     return \"\";
7331 (define_peephole
7332   [(set (match_operand:HI 0 "hard_reg_operand" "h")
7333         (match_operand:HI 1 "non_push_operand" "g"))
7334    (set (match_operand:HI 2 "hard_reg_operand" "h")
7335         (match_dup 0))]
7336   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7337    && !S_REG_P (operands[2])"
7338   "*
7340   rtx ops[2];
7342   ops[0] = operands[2];
7343   ops[1] = operands[1];
7344   m68hc11_gen_movhi (insn, ops);
7345   return \"\";
7349 (define_peephole
7350   [(set (match_operand:HI 0 "hard_reg_operand" "h")
7351         (match_operand:HI 1 "hard_reg_operand" "h"))
7352    (set (match_operand:HI 2 "non_push_operand" "g")
7353         (match_dup 0))]
7354   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7355    && !S_REG_P (operands[2])"
7356   "*
7358   rtx ops[2];
7360   ops[0] = operands[2];
7361   ops[1] = operands[1];
7362   m68hc11_gen_movhi (insn, ops);
7363   return \"\";
7368 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
7369 ;; the set, so we don't need to emit anything. 'ins1' refers to the
7370 ;; (set ...) insn.
7372 (define_peephole
7373   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7374    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7375               (set (match_dup 0) (reg:HI D_REGNUM))])]
7376   "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7377   "*
7379    cc_status = cc_prev_status;
7380    return \"\";
7384 ;; Same as above but due to some split, there may be a noop set
7385 ;; between the two.
7386 (define_peephole
7387   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7388    (set (match_dup 0) (match_dup 0))
7389    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7390               (set (match_dup 0) (reg:HI D_REGNUM))])]
7391   "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7392   "*
7394    cc_status = cc_prev_status;
7395    return \"\";
7400 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
7401 ;; and we must, at least, setup X/Y with value of D.
7403 (define_peephole
7404   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7405    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7406               (set (match_dup 0) (reg:HI D_REGNUM))])]
7407   ""
7408   "*
7410   rtx ops[2];
7412   ops[0] = operands[0];
7413   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7414   m68hc11_gen_movhi (insn, ops);
7415   return \"\";
7420 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7421 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7423 (define_peephole
7424   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7425               (set (match_dup 0) (reg:HI D_REGNUM))])
7426    (set (reg:HI D_REGNUM) (match_dup 0))]
7427   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7428   "*
7430   cc_status = cc_prev_status;
7431   return \"\";
7436 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7437 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7439 (define_peephole
7440   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7441               (set (match_dup 0) (reg:HI D_REGNUM))])
7442    (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7443   "REGNO (operands[0]) == REGNO (operands[1])
7444    && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7445   "*
7447   cc_status = cc_prev_status;
7448   return \"\";
7453 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7454 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7456 (define_peephole
7457   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7458               (set (match_dup 0) (reg:HI D_REGNUM))])
7459    (set (reg:HI D_REGNUM) (match_dup 0))]
7460   ""
7461   "*
7463   rtx ops[2];
7465   ops[0] = operands[0];
7466   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7467   m68hc11_gen_movhi (insn, ops);
7468   return \"\";
7473 ;;; Same peephole with a QI set.  The copy is made as 16-bit to comply
7474 ;;; with the xgdx.
7476 (define_peephole
7477   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7478               (set (match_dup 0) (reg:HI D_REGNUM))])
7479    (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7480   "REGNO (operands[0]) == REGNO (operands[1])"
7481   "*
7483   rtx ops[2];
7485   ops[0] = operands[0];
7486   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7487   m68hc11_gen_movhi (insn, ops);
7488   return \"\";
7493 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
7495 (define_peephole
7496   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7497               (set (match_dup 0) (reg:HI D_REGNUM))])
7498    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7499               (set (match_dup 0) (reg:HI D_REGNUM))])]
7500   ""
7501   "*
7503   cc_status = cc_prev_status;
7504   return \"\";
7508 (define_peephole
7509   [(set (match_operand:HI 0 "hard_reg_operand" "")
7510         (match_operand:HI 1 "stack_register_operand" ""))
7511    (set (match_operand:HI 2 "hard_reg_operand" "")
7512         (match_operand:HI 3 "memory_operand" "m"))
7513    (set (match_dup 0)
7514         (match_operand:HI 4 "memory_operand" "m"))]
7515   "IS_STACK_POP (operands[4])
7516    && (GET_CODE (operands[3]) == MEM &&
7517        rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
7518   "*
7520   rtx ops[2];
7522   ops[0] = operands[2];
7523   ops[1] = gen_rtx_MEM (HImode,
7524                     gen_rtx_POST_INC (HImode, stack_pointer_rtx));
7525   m68hc11_gen_movhi (insn, ops);
7526   return \"\";
7531 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
7533 (define_peephole
7534   [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
7535    (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7536   "TARGET_M6811"
7537   "*
7539   return \"sts\\t%t0\\n\\tld%0\\t%t0\";
7543 (define_peephole
7544   [(set (match_operand:HI 0 "hard_reg_operand" "")
7545         (match_operand:HI 1 "memory_operand" ""))
7546    (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7547   "TARGET_M6811
7548    && !side_effects_p (operands[1])
7549    && !reg_mentioned_p (operands[0], operands[1])"
7550   "*
7552   rtx ops[2];
7554   ops[0] = operands[0];
7555   ops[1] = operands[1];
7556   m68hc11_gen_movhi (insn, ops);
7557   ops[0] = operands[2];
7558   m68hc11_gen_movhi (insn, ops);
7559   return \"\";
7562 ;; Peephole for Z register replacement.
7563 ;; Avoid to use _.tmp register when comparing D and X if we can compare
7564 ;; with soft register
7565 (define_peephole
7566   [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
7567    (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
7568    (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
7569                        (reg:HI SOFT_TMP_REGNUM)))]
7570   "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
7571   "*
7573   rtx ops[2];
7575   ops[0] = operands[0];
7576   ops[1] = operands[1];
7577   m68hc11_gen_movhi (insn, ops);
7578   return \"cp%2\\t%1\";