Update FSF address.
[official-gcc.git] / gcc / config / m68hc11 / m68hc11.md
blobd79770b1d6e371d47b44a2e76f8673aa12c2496f
1 ;;- Machine description file for Motorola 68HC11 and 68HC12.
2 ;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
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 2, 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 COPYING.  If not, write to
20 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 ;; Boston, MA 02110-1301, USA.
23 ;; Note:
24 ;;   A first 68HC11 port was made by Otto Lind (otto@coactive.com)
25 ;;   on gcc 2.6.3.  I have used it as a starting point for this port.
26 ;;   However, this new port is a complete re-write.  Its internal
27 ;;   design is completely different.  The generated code is not
28 ;;   compatible with the gcc 2.6.3 port.
30 ;;   The gcc 2.6.3 port is available at:
32 ;;   ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
35 ;;- Instruction patterns.  When multiple patterns apply,
36 ;;- the first one in the file is chosen.
37 ;;-
38 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
39 ;;-
40 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
41 ;;- updates for most instructions.
44 ;; The following constraints are used:
46 ;; Single pair registers:
47 ;; a    register 'a'                     8-bit
48 ;; b    register 'b'                     8-bit
49 ;; d    register 'd'                    16-bit
50 ;; t    pseudo soft register 'TMP'      16-bit
51 ;; v    register 'd' for 68hc11,        16-bit
52 ;;      NO_REG for 68hc12
53 ;;      (used for scratch register)
54 ;; w    register 'sp'                   16-bit 
55 ;; x    register 'x'                    16-bit
56 ;; y    register 'y'                    16-bit
57 ;; z    register 'z'                    16-bit  (fake r for 68HC11 and 68HC12)
58 ;; D    register 'd+x'                  32-bit 
60 ;; Group of registers:
61 ;; q    register 'a' or 'b' or 'd'       8-bit
62 ;; u    pseudo soft register            16-bit
63 ;; A    register 'x', 'y', 'z'          16-bit
64 ;; B    register 'x', 'y'               16-bit
65 ;; h    register 'd', 'x', 'y', 'z'     16-bit
67 ;; Other constraints:
69 ;; Q    an operand which is in memory but whose address is constant
70 ;;      (i.e., a (MEM (SYMBOL_REF x))).  This constraint is used by
71 ;;      bset/bclr instructions together with linker relaxation.  The
72 ;;      operand can be translated to a page0 addressing mode if the
73 ;;      symbol address is in page0 (0..255).
75 ;; R    an operand which is in memory and whose address is expressed
76 ;;      with 68HC11/68HC12 indexed addressing mode.  In general this
77 ;;      is any valid (MEM) except a (MEM (SYMBOL_REF x)).
79 ;; U    an operand which is in memory and if it uses the 68HC12 indexed
80 ;;      addressing mode, the offset is in the range -16..+15.  This is
81 ;;      used by 68HC12 movb/movw instructions since they do not accept
82 ;;      the full 16-bit offset range (as other insn do).
85 ;; Immediate integer operand constraints:
86 ;;   `L' is for range -65536 to 65536
87 ;;   `M' is for values whose 16-bit low part is 0
88 ;;   'N' is for +1 or -1.
89 ;;   'O' is for 16 (for rotate using swap).
90 ;;   'P' is for range -8 to 2 (used by addhi_sp)
92 ;; In many cases, it's not possible to use the 'g' or 'r' constraints.
94 ;; Operands modifiers:
96 ;;     %b       Get the low part of the operand (to obtain a QImode)
97 ;;              This modifier must always be used for QImode operations
98 ;;              because a correction must be applied when the operand
99 ;;              is a soft register (ex: *ZD1). Otherwise, we generate
100 ;;              *ZD1 and this is the high part of the register. For other
101 ;;              kinds of operands, if the operand is already QImode, no
102 ;;              additional correction is made.
103 ;;     %h       Get the high part of the operand (to obtain a QImode)
104 ;;     %t       Represents the temporary/scratch register *_.tmp
105 ;;              The scratch register is used in some cases when GCC puts
106 ;;              some values in bad registers. 
108 ;; 32/64-bit Patterns:
109 ;;     The 68HC11 does not support 32/64-bit operations.  Most of the
110 ;;     32/64-bit patterns are defined to split the instruction in
111 ;;     16-bits patterns.  Providing split patterns generates better code
112 ;;     than letting GCC implement the 32/64-bit operation itself.
115 ;; Notes:
117 ;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
118 ;;   otherwise some insn are not satisfied.
120 ;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
121 ;;   be valid only when z_replacement_completed == 2 because once these
122 ;;   swap instructions are generated, a flow/cse pass fails to handle
123 ;;   them correctly (it would treat the X, Y or D register as dead sometimes).
125 ;; o Some split pattern generate instructions that operate on 'a' or 'b'
126 ;;   register directly (high part and low part of D respectively).
127 ;;   Such split pattern must also be valid when z_replacement_completed == 2
128 ;;   because flow/cse is not aware that D is composed of {a, b}.
130 ;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
131 ;;   the high part of a soft register must be expanded after z_replacement
132 ;;   pass.
134 ;;---------------------------------------------------------------------------
135 ;; Constants
137 (define_constants [
138    ;; Register numbers
139    (X_REGNUM        0)          ; Index X register
140    (D_REGNUM        1)          ; Data register
141    (Y_REGNUM        2)          ; Index Y register
142    (SP_REGNUM       3)          ; Stack pointer
143    (PC_REGNUM       4)          ; Program counter
144    (A_REGNUM        5)          ; A (high part of D)
145    (B_REGNUM        6)          ; B (low part of D)
146    (CC_REGNUM       7)          ; Condition code register
147    (SOFT_TMP_REGNUM 10)         ; TMP soft register
148    (SOFT_Z_REGNUM   11)         ; Z soft register
149    (SOFT_XY_REGNUM  12)         ; XY soft register
152 (include "predicates.md")
154 ;;--------------------------------------------------------------------
155 ;;-  Test
156 ;;--------------------------------------------------------------------
158 ;; The test and compare insn must not accept a memory operand with
159 ;; an auto-inc mode.  If we do this, the reload can emit move insns
160 ;; after the test or compare.  Such move will set the flags and therefore
161 ;; break the comparison.  This can happen if the auto-inc register
162 ;; does not happen to be a hard register (i.e., reloading occurs).
163 ;; An offsetable memory operand should be ok.  The 'tst_operand' and
164 ;; 'cmp_operand' predicates take care of this rule.
166 (define_expand "tstsi"
167   [(set (cc0)
168         (match_operand:SI 0 "tst_operand" ""))]
169   ""
170   "
172   m68hc11_compare_op0 = operands[0];
173   m68hc11_compare_op1 = const0_rtx;
174   DONE;
177 (define_expand "tsthi"
178   [(set (cc0)
179         (match_operand:HI 0 "tst_operand" ""))]
180   ""
181   "
183   m68hc11_compare_op0 = operands[0];
184   m68hc11_compare_op1 = const0_rtx;
185   DONE;
188 (define_insn "tsthi_1"
189   [(set (cc0)
190         (match_operand:HI 0 "tst_operand" "dx,*y"))]
191   ""
192   "*
194    if (D_REG_P (operands[0]) && !TARGET_M6812)
195      return \"std\\t%t0\";
196    else
197      return \"cp%0\\t#0\";
200 (define_expand "tstqi"
201   [(set (cc0)
202         (match_operand:QI 0 "tst_operand" ""))]
203   ""
204   "
206   m68hc11_compare_op0 = operands[0];
207   m68hc11_compare_op1 = const0_rtx;
208   DONE;
212 ;; Split pattern for (tst:QI) on an address register.
214 (define_split
215   [(set (cc0)
216         (match_operand:QI 0 "hard_addr_reg_operand" ""))]
217   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
218   [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
219               (set (match_dup 1) (reg:HI D_REGNUM))])
220    (set (cc0) (reg:QI D_REGNUM))
221    (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
222               (set (match_dup 1) (reg:HI D_REGNUM))])]
223   "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
225 (define_insn "tstqi_1"
226   [(set (cc0)
227         (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
228   ""
229   "*
231   if (A_REG_P (operands[0]))
232     return \"#\";
234   else if (D_REG_P (operands[0]))
235     return \"tstb\";
237   else if (dead_register_here (insn, d_reg))
238     return \"ldab\\t%b0\";
240   else
241     return \"tst\\t%b0\";
245 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated 
246 ;; during the Z register replacement.  They are used when an operand
247 ;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
248 ;; In that case, we have to preserve the values of the replacement
249 ;; register (as well as the CC0 since the insns are compare insns).
250 ;; To do this, the replacement register is pushed on the stack and
251 ;; restored after the real compare.  A pattern+split is defined to
252 ;; avoid problems with the flow+cse register pass which are made
253 ;; after Z register replacement.
255 (define_insn_and_split "tstqi_z_used"
256   [(set (cc0)
257         (match_operand:QI 0 "tst_operand" "m"))
258    (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
259    (use (reg:HI SOFT_Z_REGNUM))]
260   ""
261   "#"
262   "z_replacement_completed == 2"
263   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
264    (set (match_dup 1) (match_dup 2))
265    (set (cc0) (match_dup 0))
266    (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
267   "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
270 ;;--------------------------------------------------------------------
271 ;;- Compare
272 ;;--------------------------------------------------------------------
274 (define_expand "cmpsi"
275   [(set (cc0)
276         (compare (match_operand:SI 0 "tst_operand" "")
277                  (match_operand:SI 1 "cmp_operand" "")))]
278   ""
279   "
281   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
282     operands[0] = force_reg (SImode, operands[0]);
284   m68hc11_compare_op0 = operands[0];
285   m68hc11_compare_op1 = operands[1];
286   DONE;
290 ;; Comparison of a hard register with another one is provided because
291 ;; it helps GCC to avoid to spill a pseudo hard register.
292 ;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
293 ;; (except that we loose the information that the value is saved in it).
295 ;; The split pattern transforms the comparison into a save of one hard
296 ;; register and a comparison with the temporary.
298 (define_split
299   [(set (cc0)
300         (compare (match_operand:HI 0 "hard_reg_operand" "")
301                  (match_operand:HI 1 "hard_reg_operand" "")))]
302   "TARGET_M6811
303    && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
304   [(set (match_dup 2) (match_dup 1))
305    (set (cc0)
306         (compare (match_dup 0) (match_dup 2)))]
307   "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
309 (define_split
310   [(set (cc0)
311         (compare (match_operand:HI 0 "hard_reg_operand" "")
312                  (match_operand:HI 1 "hard_reg_operand" "")))]
313   "0 && TARGET_M6812
314    && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
315   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
316    (set (cc0)
317         (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
318   "")
320 (define_expand "cmphi"
321   [(set (cc0)
322         (compare (match_operand:HI 0 "tst_operand" "")
323                  (match_operand:HI 1 "cmp_operand" "")))]
324   ""
325   "
327   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
328     operands[0] = force_reg (HImode, operands[0]);
330   m68hc11_compare_op0 = operands[0];
331   m68hc11_compare_op1 = operands[1];
332   DONE;
335 (define_insn "cmphi_1_hc12"
336   [(set (cc0)
337         (compare (match_operand:HI 0 "tst_operand" 
338                                 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
339                  (match_operand:HI 1 "general_operand"
340                                 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
341   "TARGET_M6812"
342   "*
344   if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
345     {
346       cc_status.flags |= CC_REVERSED;
347       return \"cp%1\\t%0\";
348     }
349   else if (SP_REG_P (operands[1]))
350     return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
351   else if (H_REG_P (operands[1]))
352     return \"psh%1\n\\tcp%0\\t2,sp+\";
353   else
354     return \"cp%0\\t%1\";
357 (define_insn "cmphi_1_hc11"
358   [(set (cc0)
359         (compare (match_operand:HI 0 "tst_operand" 
360                                 "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
361                  (match_operand:HI 1 "cmp_operand"
362                                 "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
363   "TARGET_M6811"
364   "*
366   if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
367     {
368       cc_status.flags |= CC_REVERSED;
369       return \"cp%1\\t%0\";
370     }
371   else if (H_REG_P (operands[1]))
372     return \"#\";
373   else
374     return \"cp%0\\t%1\";
377 (define_insn_and_split "cmphi_z_used"
378   [(set (cc0)
379         (compare (match_operand:HI 0 "tst_operand" "dxy,m")
380                  (match_operand:HI 1 "cmp_operand" "mi,dxy")))
381    (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
382    (use (reg:HI SOFT_Z_REGNUM))]
383   ""
384   "#"
385   "z_replacement_completed == 2"
386   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
387    (set (match_dup 2) (match_dup 3))
388    (set (cc0) (compare (match_dup 0) (match_dup 1)))
389    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
390   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
393 ;; 8-bit comparison with address register.
394 ;; There is no such comparison instruction, we have to temporarily switch
395 ;; the address register and the D register and do the comparison with D.
396 ;; The xgdx and xgdy instructions preserve the flags.
398 (define_split
399   [(set (cc0)
400         (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
401                  (match_operand:QI 1 "cmp_operand" "")))]
402   "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
403   [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
404               (set (match_dup 3) (reg:HI D_REGNUM))])
405    (set (cc0)
406         (compare (reg:QI D_REGNUM) (match_dup 1)))
407    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
408               (set (match_dup 3) (reg:HI D_REGNUM))])]
409   "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
411 (define_split
412   [(set (cc0)
413         (compare (match_operand:QI 0 "hard_reg_operand" "")
414                  (match_operand:QI 1 "hard_reg_operand" "")))]
415   "reload_completed"
416   [(set (match_dup 3) (match_dup 4))
417    (set (cc0)
418         (compare (match_dup 0) (match_dup 2)))]
419   "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
420    operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
421    operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
423 (define_expand "cmpqi"
424   [(set (cc0)
425         (compare (match_operand:QI 0 "tst_operand" "")
426                  (match_operand:QI 1 "cmp_operand" "")))]
427   ""
428   "
430   if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
431     operands[0] = force_reg (QImode, operands[0]);
433   m68hc11_compare_op0 = operands[0];
434   m68hc11_compare_op1 = operands[1];
435   DONE;
438 (define_insn "bitcmpqi"
439   [(set (cc0)
440         (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
441                 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
442   ""
443   "@
444    bitb\\t%b1
445    #
446    bitb\\t%b1
447    bitb\\t%b0
448    bitb\\t%b0")
450 (define_split /* "bitcmpqi" */
451   [(set (cc0)
452         (and:QI (match_operand:QI 0 "tst_operand" "")
453                 (match_operand:QI 1 "hard_addr_reg_operand" "")))]
454   "z_replacement_completed == 2"
455   [(set (match_dup 3) (match_dup 2))
456    (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
457   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
458    operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
459    operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
461 (define_insn_and_split "bitcmpqi_z_used"
462   [(set (cc0)
463         (and:QI (match_operand:QI 0 "tst_operand" "d,m")
464                 (match_operand:QI 1 "cmp_operand" "m,d")))
465    (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
466    (use (reg:HI SOFT_Z_REGNUM))]
467   ""
468   "#"
469   "z_replacement_completed == 2"
470   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
471    (set (match_dup 2) (match_dup 3))
472    (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
473    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
474   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
476 (define_insn "bitcmphi"
477   [(set (cc0)
478         (and:HI (match_operand:HI 0 "tst_operand" "d")
479                 (match_operand:HI 1 "const_int_operand" "i")))]
480   "(INTVAL (operands[1]) & 0x0ff) == 0
481    || (INTVAL (operands[1]) & 0x0ff00) == 0"
482   "*
484    if ((INTVAL (operands[1]) & 0x0ff) == 0)
485      return \"bita\\t%h1\";
486    else
487      return \"bitb\\t%1\";
490 (define_insn "bitcmpqi_12"
491   [(set (cc0)
492         (zero_extract (match_operand:HI 0 "tst_operand" "d")
493                       (match_operand:HI 1 "const_int_operand" "i")
494                       (match_operand:HI 2 "const_int_operand" "i")))]
495   "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
496    || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
497        && (unsigned) INTVAL (operands[2]) >= 8)"
498   "*
500    rtx ops[1];
501    int mask;
502    int startpos = INTVAL (operands[2]);
503    int bitsize = INTVAL (operands[1]);
505    if (startpos >= 8)
506      {
507        startpos -= 8;
508        mask = (1 << (startpos + bitsize)) - 1;
509        mask &= ~((1 << startpos) - 1);
511        ops[0] = GEN_INT (mask);
512        output_asm_insn (\"bita\\t%0\", ops);
513      }
514    else
515      {
516        mask = (1 << (startpos + bitsize)) - 1;
517        mask &= ~((1 << startpos) - 1);
519        ops[0] = GEN_INT (mask);
520        output_asm_insn (\"bitb\\t%0\", ops);
521      }
522    return \"\";
525 (define_insn "cmpqi_1"
526   [(set (cc0)
527         (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
528                  (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
529   ""
530   "*
532    if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
533      {
534         return \"#\";
535      }
536    else if (D_REG_P (operands[0]))
537      {
538         return \"cmpb\\t%b1\";
539      }
540    cc_status.flags |= CC_REVERSED;
541    return \"cmpb\\t%b0\";
544 (define_insn_and_split "cmpqi_z_used"
545   [(set (cc0)
546         (compare (match_operand:QI 0 "tst_operand" "dxy,m")
547                  (match_operand:QI 1 "cmp_operand" "m,dxy")))
548    (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
549    (use (reg:HI SOFT_Z_REGNUM))]
550   ""
551   "#"
552   "z_replacement_completed == 2"
553   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
554    (set (match_dup 2) (match_dup 3))
555    (set (cc0) (compare (match_dup 0) (match_dup 1)))
556    (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
557   "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
559 ;;--------------------------------------------------------------------
560 ;;-  Move strict_low_part
561 ;;--------------------------------------------------------------------
563 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
564 ;; The replacement must be made at the very end because we loose the
565 ;; (strict_low_part ...) information.  This is correct for our machine
566 ;; description but not for GCC optimization passes.
568 (define_insn_and_split "movstrictsi"
569   [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
570         (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
571   ""
572   "#"
573   "z_replacement_completed == 2"
574   [(set (match_dup 0) (match_dup 1))]
575   "")
577 (define_insn_and_split "movstricthi"
578   [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
579         (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
580   ""
581   "#"
582   "z_replacement_completed == 2"
583   [(set (match_dup 0) (match_dup 1))]
584   "")
586 (define_insn_and_split "movstrictqi"
587   [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
588         (match_operand:QI 1 "general_operand" "d,imudA"))]
589   ""
590   "#"
591   "z_replacement_completed == 2"
592   [(set (match_dup 0) (match_dup 1))]
593   "")
595 ;;--------------------------------------------------------------------
596 ;;- 64-bit Move Operations.
597 ;; The movdi and movdf patterns are identical except for the mode.
598 ;; They are also very similar to those for movsi and movsf.
600 ;; For 68HC11, we need a scratch register (either D, X, Y) 
601 ;; because there is no memory->memory moves.  It must be defined with
602 ;; earlyclobber (&) so that it does not appear in the source or destination 
603 ;; address.  Providing patterns for movdi/movdf allows GCC to generate
604 ;; better code.  [Until now, the scratch register is limited to D because
605 ;; otherwise we can run out of registers in the A_REGS class for reload].
607 ;; For 68HC12, the scratch register is not necessary.  To use the same
608 ;; pattern and same split, we use the 'v' constraint.  This tells the
609 ;; reload to use the _.tmp register (which is not used at all).
610 ;; The insn will be split in one or several memory moves (movw).
611 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
612 ;;--------------------------------------------------------------------
613 (define_expand "movdi"
614   [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
615                    (match_operand:DI 1 "general_operand" ""))
616               (clobber (match_scratch:HI 2 ""))])]
617   ""
618   "
619   /* For push/pop, emit a REG_INC note to make sure the reload
620      inheritance and reload CSE pass notice the change of the stack
621      pointer.  */
622   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
623     {
624       rtx insn;
626       insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
627       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
628                                           stack_pointer_rtx,
629                                           REG_NOTES (insn));
630       DONE;
631     }
634 ;; Separate push from normal moves to avoid reloading problems
635 ;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
636 ;; We can also accept more scratch registers.
637 (define_insn_and_split "*pushdi_internal"
638   [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
639         (match_operand:DI 1 "general_operand" "i,U,m,!u"))
640    (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
641   ""
642   "#"
643   "reload_completed"
644   [(const_int 0)]
645   "m68hc11_split_move (operands[0], operands[1], operands[2]);
646    DONE;")
648 (define_insn_and_split "movdi_internal"
649   [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
650         (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
651    (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
652   ""
653   "#"
654   "reload_completed"
655   [(const_int 0)]
656   "m68hc11_split_move (operands[0], operands[1], operands[2]);
657    DONE;")
659 (define_expand "movdf"
660   [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
661                    (match_operand:DF 1 "general_operand" ""))
662               (clobber (match_scratch:HI 2 ""))])]
663   ""
664   "/* For push/pop, emit a REG_INC note to make sure the reload
665       inheritance and reload CSE pass notice the change of the stack
666       pointer.  */
667   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
668     {
669       rtx insn;
671       insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
672       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
673                                           stack_pointer_rtx,
674                                           REG_NOTES (insn));
675       DONE;
676     }
679 ;; See pushdi_internal
680 (define_insn_and_split "*pushdf_internal"
681   [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
682         (match_operand:DF 1 "general_operand" "i,U,m,!u"))
683    (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
684   ""
685   "#"
686   "reload_completed"
687   [(const_int 0)]
688   "m68hc11_split_move (operands[0], operands[1], operands[2]);
689    DONE;")
691 (define_insn_and_split "movdf_internal"
692   [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
693         (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
694    (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
695   ""
696   "#"
697   "reload_completed"
698   [(const_int 0)]
699   "m68hc11_split_move (operands[0], operands[1], operands[2]);
700    DONE;")
702 ;;--------------------------------------------------------------------
703 ;;- 32-bit Move Operations.
704 ;; The movsi and movsf patterns are identical except for the mode.
705 ;; When we move to/from a hard register (d+x), we don't need a scratch.
706 ;; Otherwise, a scratch register is used as intermediate register for
707 ;; the move.  The '&' constraint is necessary to make sure the reload
708 ;; pass does not give us a register that dies in the insn and is used
709 ;; for input/output operands.
710 ;;--------------------------------------------------------------------
711 (define_expand "movsi"
712   [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
713                    (match_operand:SI 1 "general_operand" ""))
714               (clobber (match_scratch:HI 2 ""))])]
715   ""
716   "/* For push/pop, emit a REG_INC note to make sure the reload
717       inheritance and reload CSE pass notice the change of the stack
718       pointer.  */
719   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
720     {
721       rtx insn;
723       insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
724       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
725                                           stack_pointer_rtx,
726                                           REG_NOTES (insn));
727       DONE;
728     }
731 (define_insn_and_split "*pushsi_internal"
732   [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
733         (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
734    (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
735   ""
736   "#"
737   "reload_completed"
738   [(const_int 0)]
739   "m68hc11_split_move (operands[0], operands[1], operands[2]);
740    DONE;")
742 (define_insn_and_split "movsi_internal"
743   [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
744         (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
745    (clobber (match_scratch:HI 2               "=X,&d,X,X,X,X,&d,&d,X"))]
746   ""
747   "#"
748   "reload_completed"
749   [(const_int 0)]
750   "m68hc11_split_move (operands[0], operands[1], operands[2]);
751    DONE;")
753 (define_expand "movsf"
754   [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
755                    (match_operand:SF 1 "general_operand" ""))
756               (clobber (match_scratch:HI 2 ""))])]
757   ""
758   "/* For push/pop, emit a REG_INC note to make sure the reload
759       inheritance and reload CSE pass notice the change of the stack
760       pointer.  */
761   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
762     {
763       rtx insn;
765       insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
766       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
767                                           stack_pointer_rtx,
768                                           REG_NOTES (insn));
769       DONE;
770     }
773 (define_insn_and_split "*pushsf_internal"
774   [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
775         (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
776    (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
777   ""
778   "#"
779   "reload_completed"
780   [(const_int 0)]
781   "m68hc11_split_move (operands[0], operands[1], operands[2]);
782    DONE;")
784 (define_insn_and_split "movsf_internal"
785   [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
786         (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
787    (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
788   ""
789   "#"
790   "reload_completed"
791   [(const_int 0)]
792   "m68hc11_split_move (operands[0], operands[1], operands[2]);
793    DONE;")
796 ;;--------------------------------------------------------------------
797 ;;- 16-bit Move Operations.
798 ;; We don't need a scratch register.
799 ;;--------------------------------------------------------------------
801 (define_insn "*movhi2_push"
802   [(set (match_operand:HI 0 "push_operand" "=<,<,<")
803         (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
804   "TARGET_M6811 && !TARGET_M6812"
805   "*
807   cc_status = cc_prev_status;
808   if (D_REG_P (operands[1]))
809     {
810       output_asm_insn (\"pshb\", operands);
811       return \"psha\";
812     }
813   else if (X_REG_P (operands[1]))
814     {
815       return \"pshx\";
816     }
817   else if (Y_REG_P (operands[1]))
818     {
819       return \"pshy\";
820     }
821   fatal_insn (\"Invalid register in the instruction\", insn);
824 (define_insn "*movhi2_pop"
825   [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
826         (match_operand:HI 1 "pop_operand" ">,>"))]
827   "TARGET_M6811"
828   "*
830   cc_status = cc_prev_status;
831   if (D_REG_P (operands[0]))
832     {
833       output_asm_insn (\"pula\", operands);
834       return \"pulb\";
835     }
836   else if (X_REG_P (operands[0]))
837     {
838       return \"pulx\";
839     }
840   else if (Y_REG_P (operands[0]))
841     {
842       return \"puly\";
843     }
844   fatal_insn (\"Invalid register in the instruction\", insn);
847 (define_expand "movhi"
848   [(set (match_operand:HI 0 "nonimmediate_operand" "")
849         (match_operand:HI 1 "general_operand" ""))]
850   ""
851   "
853   if (reload_in_progress)
854     {
855       if (m68hc11_reload_operands (operands))
856         {
857           DONE;
858         }
859     }
860   if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
861     {
862       if (GET_CODE (operands[0]) == MEM &&
863           (GET_CODE (operands[1]) == MEM
864            || GET_CODE (operands[1]) == CONST_INT))
865         {
866           operands[1] = force_reg (HImode, operands[1]);
867         }
868       else if (IS_STACK_PUSH (operands[0])
869                && GET_CODE (operands[1]) != REG)
870         {
871           operands[1] = force_reg (HImode, operands[1]);
872         }
873     }
874   /* For push/pop, emit a REG_INC note to make sure the reload
875      inheritance and reload CSE pass notice the change of the stack
876      pointer.  */
877   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
878     {
879       rtx insn;
881       insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
882       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
883                                           stack_pointer_rtx,
884                                           REG_NOTES (insn));
885       DONE;
886     }
889 (define_insn "*movhi_68hc12"
890   [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
891         (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
892   "TARGET_M6812"
893   "*
895   m68hc11_gen_movhi (insn, operands);
896   return \"\";
899 (define_insn "movhi_const0"
900   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
901         (const_int 0))]
902   "TARGET_M6811"
903   "@
904    clra\\n\\tclrb
905    ld%0\\t#0
906    clr\\t%b0\\n\\tclr\\t%h0")
908 (define_insn "*movhi_m68hc11"
909   [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
910         (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
911   "TARGET_M6811"
912   "*
914   m68hc11_gen_movhi (insn, operands);
915   return \"\";
918 ;;--------------------------------------------------------------------
919 ;;- 8-bit Move Operations.
920 ;; We don't need a scratch register.
921 ;;--------------------------------------------------------------------
923 ;; The *a alternative also clears the high part of the register.
924 ;; This should be ok since this is not the (strict_low_part) set.
926 (define_insn "movqi_const0"
927   [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
928         (const_int 0))]
929   ""
930   "@
931    clrb
932    clr\\t%b0
933    clr\\t%b0
934    ld%0\\t#0
935    clr%0")
938 ;; 8-bit operations on address registers.
940 ;; Switch temporary to the D register and load the value in B.
941 ;; This is possible as long as the address register does not
942 ;; appear in the source operand.
944 (define_split
945   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
946         (match_operand:QI 1 "general_operand" ""))]
947   "z_replacement_completed == 2
948    && !reg_mentioned_p (operands[0], operands[1])
949    && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
950   [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
951               (set (match_dup 2) (reg:HI D_REGNUM))])
952    (set (reg:QI D_REGNUM) (match_dup 1))
953    (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
954               (set (match_dup 2) (reg:HI D_REGNUM))])]
955   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
958 ;; 8-bit operations on address registers.
960 (define_split
961   [(set (match_operand:QI 0 "nonimmediate_operand" "")
962         (match_operand:QI 1 "hard_addr_reg_operand" ""))]
963   "z_replacement_completed == 2
964    && !reg_mentioned_p (operands[1], operands[0])
965    && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
966   [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
967               (set (match_dup 2) (reg:HI D_REGNUM))])
968    (set (match_dup 0) (reg:QI D_REGNUM))
969    (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
970               (set (match_dup 2) (reg:HI D_REGNUM))])]
971   "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
973 (define_insn "*movqi2_push"
974   [(set (match_operand:QI 0 "push_operand" "=<,<")
975         (match_operand:QI 1 "general_operand" "d,!*A"))]
976   ""
977   "*
979   if (A_REG_P (operands[1]))
980     return \"#\";
982   cc_status = cc_prev_status;
983   return \"pshb\";
987 (define_expand "movqi"
988   [(set (match_operand:QI 0 "nonimmediate_operand" "")
989         (match_operand:QI 1 "general_operand" ""))]
990   ""
991   "
993   if (reload_in_progress)
994     {
995       if (m68hc11_reload_operands (operands))
996         {
997           DONE;
998         }
999     }
1000   if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
1001     {
1002       if (GET_CODE (operands[0]) == MEM
1003           && (GET_CODE (operands[1]) == MEM
1004               || GET_CODE (operands[1]) == CONST_INT))
1005         {
1006           operands[1] = force_reg (QImode, operands[1]);
1007         }
1008       else if (IS_STACK_PUSH (operands[0])
1009                && GET_CODE (operands[1]) != REG)
1010         {
1011           operands[1] = force_reg (QImode, operands[1]);
1012         }
1013     }
1014   /* For push/pop, emit a REG_INC note to make sure the reload
1015      inheritance and reload CSE pass notice the change of the stack
1016      pointer.  */
1017   if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
1018     {
1019       rtx insn;
1021       insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
1022       REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
1023                                           stack_pointer_rtx,
1024                                           REG_NOTES (insn));
1025       DONE;
1026     }
1029 (define_insn "*movqi_68hc12"
1030   [(set (match_operand:QI 0 "nonimmediate_operand" 
1031                                 "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
1032         (match_operand:QI 1 "general_operand" 
1033                                 "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
1034   "TARGET_M6812"
1035   "*
1037   m68hc11_gen_movqi (insn, operands);
1038   return \"\";
1041 (define_insn "*movqi_m68hc11"
1042   [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
1043         (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
1044   "TARGET_M6811"
1045   "*
1047   m68hc11_gen_movqi (insn, operands);
1048   return \"\";
1051 ;;--------------------------------------------------------------------
1052 ;;-  Swap registers
1053 ;;--------------------------------------------------------------------
1054 ;; Swapping registers is used for split patterns.
1055 (define_insn "swap_areg"
1056    [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1057          (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1058     (set (match_dup 1) (match_dup 0))]
1059    ""
1060    "*
1062   m68hc11_output_swap (insn, operands);
1063   return \"\";
1066 ;;--------------------------------------------------------------------
1067 ;;-  Truncation insns.
1068 ;;--------------------------------------------------------------------
1070 ;; Truncation are not necessary because GCC knows how to truncate,
1071 ;; specially when values lie in consecutive registers.
1074 (define_expand "floatunssisf2"
1075   [(set (match_operand:SF 0 "nonimmediate_operand" "")
1076         (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1077   ""
1078   "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT, 
1079                          SFmode, SImode, 2, operands);
1080    DONE;")
1082 (define_expand "floatunssidf2"
1083   [(set (match_operand:DF 0 "nonimmediate_operand" "")
1084         (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1085   ""
1086   "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT, 
1087                          DFmode, SImode, 2, operands);
1088    DONE;")
1090 ;;--------------------------------------------------------------------
1091 ;;-  Zero extension insns.
1092 ;;--------------------------------------------------------------------
1095 ;; 64-bit extend.  The insn will be split into 16-bit instructions just
1096 ;; before the final pass.  We need a scratch register for the split.
1097 ;; The final value can be generated on the stack directly.  This is more
1098 ;; efficient and useful for conversions made during parameter passing rules.
1100 (define_insn "zero_extendqidi2"
1101   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1102         (zero_extend:DI 
1103            (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1104    (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1105   ""
1106   "#")
1108 (define_split
1109   [(set (match_operand:DI 0 "push_operand" "")
1110         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1111    (clobber (match_scratch:HI 2 "=&dB"))]
1112   "z_replacement_completed == 2"
1113   [(const_int 0)]
1114   "
1116   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1117   rtx push = m68hc11_gen_lowpart (HImode, low);
1118   rtx src  = operands[1];
1120    /* Source operand must be in a hard register.  */
1121    if (!H_REG_P (src))
1122      {
1123        src = gen_rtx_REG (QImode, REGNO (operands[2]));
1124        emit_move_insn (src, operands[1]);
1125      }
1127    /* Source is in D, we can push B then one word of 0 and we do
1128       a correction on the stack pointer.  */
1129    if (D_REG_P (src))
1130      {
1131        emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1132        emit_move_insn (operands[2], const0_rtx);
1133        if (D_REG_P (operands[2]))
1134          {
1135            emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1136          }
1137        else
1138          {
1139            emit_move_insn (push, operands[2]);
1140            emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1141                                   gen_rtx_REG (HImode, HARD_SP_REGNUM),
1142                                   const1_rtx));
1143          }
1144      }
1145    else
1146      {
1147        /* Source is in X or Y.  It's better to push the 16-bit register
1148           and then to some stack adjustment.  */
1149        src = gen_rtx_REG (HImode, REGNO (src));
1150        emit_move_insn (push, src);
1151        emit_move_insn (operands[2], const0_rtx);
1152        emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1153                               gen_rtx_REG (HImode, HARD_SP_REGNUM),
1154                               const1_rtx));
1155        emit_move_insn (push, operands[2]);
1156        emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1157                               gen_rtx_REG (HImode, HARD_SP_REGNUM),
1158                               const1_rtx));
1159      }      
1160    emit_move_insn (push, operands[2]);
1161    emit_move_insn (push, operands[2]);
1162    emit_move_insn (push, operands[2]);
1163    DONE;
1166 (define_split
1167   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1168         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1169    (clobber (match_scratch:HI 2 "=&dB"))]
1170   "z_replacement_completed == 2"
1171   [(const_int 0)]
1172   "
1174   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1175   rtx low2 = m68hc11_gen_lowpart (HImode, low);
1176   rtx src  = operands[1];
1178    /* Source operand must be in a hard register.  */
1179    if (!H_REG_P (src))
1180      {
1181        src = gen_rtx_REG (QImode, REGNO (operands[2]));
1182        emit_move_insn (src, operands[1]);
1183      }
1185    emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1186    emit_move_insn (operands[2], const0_rtx);
1187    src = gen_rtx_REG (QImode, REGNO (operands[2]));
1188    emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1190    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1191    low = m68hc11_gen_highpart (SImode, operands[0]);
1192    emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1193    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1194    DONE;
1197 (define_insn "zero_extendhidi2"
1198   [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1199         (zero_extend:DI 
1200             (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1201    (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1202   ""
1203   "#")
1205 (define_split
1206   [(set (match_operand:DI 0 "non_push_operand" "")
1207         (zero_extend:DI 
1208             (match_operand:HI 1 "nonimmediate_operand" "")))
1209    (clobber (match_scratch:HI 2 ""))]
1210   "z_replacement_completed == 2"
1211   [(const_int 0)]
1212   "
1214    rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1215    rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1216    rtx src  = operands[1];
1218    /* Make sure the source is in a hard register.  */
1219    if (!H_REG_P (src))
1220      {
1221        src = operands[2];
1222        emit_move_insn (src, operands[1]);
1223      }
1225    /* Move the low part first for the push.  */
1226    emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1228    /* Now, use the scratch register to fill in the zeros.  */
1229    emit_move_insn (operands[2], const0_rtx);
1230    emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1231    emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1232    emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1233    DONE;
1236 (define_insn "zero_extendsidi2"
1237   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1238         (zero_extend:DI 
1239             (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1240    (clobber (match_scratch:HI 2 "=d,d,d,d"))]
1241   ""
1242   "#")
1244 (define_split 
1245   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1246         (zero_extend:DI 
1247             (match_operand:SI 1 "nonimmediate_operand" "")))
1248    (clobber (match_scratch:HI 2 ""))]
1249   "z_replacement_completed == 2"
1250   [(const_int 0)]
1251   "
1253   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
1254   rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1256   /* Move the low part first so that this is ok for a push.  */
1257   m68hc11_split_move (low, operands[1], operands[2]);
1259   /* Use the scratch register to clear the high part of the destination.  */
1260   emit_move_insn (operands[2], const0_rtx);
1261   emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1262   emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1263   DONE;
1267 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1268 ;; because it's less efficient.
1270 (define_insn "zero_extendhisi2"
1271   [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1272         (zero_extend:SI 
1273             (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1274    (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1275   ""
1276   "#")
1278 (define_split
1279   [(set (match_operand:SI 0 "non_push_operand" "")
1280         (zero_extend:SI 
1281             (match_operand:HI 1 "nonimmediate_operand" "")))
1282    (clobber (match_scratch:HI 2 ""))]
1283   "reload_completed"
1284   [(const_int 0)]
1285   "
1287   rtx src = operands[1];
1289   if (!H_REG_P (src) && !H_REG_P (operands[0]))
1290     {
1291       src = operands[2];
1292       emit_move_insn (src, operands[1]);
1293     }
1294   emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1295   emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1296   DONE;
1299 (define_insn "zero_extendqisi2"
1300   [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1301       (zero_extend:SI 
1302           (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1303   ""
1304   "#")
1306 (define_split 
1307   [(set (match_operand:SI 0 "non_push_operand" "")
1308         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1309   "reload_completed && !X_REG_P (operands[0])"
1310   [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1311    (set (match_dup 3) (const_int 0))]
1312   "
1313    operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1314    operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1316 (define_split 
1317   [(set (match_operand:SI 0 "hard_reg_operand" "")
1318         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1319   "z_replacement_completed == 2 && X_REG_P (operands[0])"
1320   [(set (match_dup 2) (match_dup 3))
1321    (set (match_dup 4) (const_int 0))
1322    (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1323   "
1324    if (X_REG_P (operands[1]))
1325      {
1326         emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
1327                                   gen_rtx_REG (HImode, HARD_X_REGNUM)));
1328         emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
1329                                          gen_rtx_REG (QImode, HARD_D_REGNUM)));
1330         emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
1331                         const0_rtx);
1332         DONE;
1333      }
1335    if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
1336      {
1337         emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1338                                                               operands[0]),
1339                                          operands[1]));
1340         emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
1341         DONE;
1342      }
1343    operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1344    operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1345    if (A_REG_P (operands[1]))
1346      {
1347        operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1348        operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
1349        operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
1350      }
1351    else
1352      {
1353        operands[5] = operands[2] =
1354        operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1355        operands[6] = operands[1];
1356      }
1359 (define_insn "zero_extendqihi2"
1360   [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
1361         (zero_extend:HI 
1362             (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1363   ""
1364  "*
1366   if (A_REG_P (operands[0]))
1367     return \"#\";
1369   if (H_REG_P (operands[0]))
1370     {
1371       output_asm_insn (\"clra\", operands);
1372       if (operands[0] != operands[1]
1373           && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1374         {
1375           if (X_REG_P (operands[1])
1376               || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1377             {
1378               output_asm_insn (\"stx\\t%t1\", operands);
1379               output_asm_insn (\"ldab\\t%T0\", operands);
1380             }
1381           else if (Y_REG_P (operands[1])
1382                    || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1383             {
1384               output_asm_insn (\"sty\\t%t1\", operands);
1385               output_asm_insn (\"ldab\\t%T0\", operands);
1386             }
1387           else
1388             {
1389               output_asm_insn (\"ldab\\t%b1\", operands);
1390             }
1391           cc_status.flags |= CC_NOT_NEGATIVE;
1392         }
1393       else
1394         {
1395           /* Status refers to the clra insn. Status is ok for others
1396            * since we have loaded the value in B.
1397            */
1398           CC_STATUS_INIT;
1399         }
1400       return \"\";
1401     }
1403   if (A_REG_P (operands[1]))
1404     {
1405       output_asm_insn (\"st%1\\t%0\", operands);
1406       output_asm_insn (\"clr\\t%h0\", operands);
1407       CC_STATUS_INIT;
1408     }
1409   else
1410     {
1411       output_asm_insn (\"clr\\t%h0\", operands);
1412       output_asm_insn (\"stab\\t%b0\", operands);
1413       cc_status.flags |= CC_NOT_NEGATIVE;
1414     }
1416   return \"\";
1420 ;;--------------------------------------------------------------------
1421 ;;-  Sign extension insns.
1422 ;;--------------------------------------------------------------------
1424 (define_insn "extendqisi2"
1425   [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1426         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1427   ""
1428   "*
1430   rtx ops[3];
1431   int need_tst = 0;
1433   /* The 68HC12 has a sign-extension instruction.  Use it when the
1434      destination is the register (X,D).  First sign-extend the low
1435      part and fill X with the sign-extension of the high part.  */
1436   if (TARGET_M6812 && X_REG_P (operands[0]))
1437     {
1438       if (!D_REG_P (operands[1]))
1439         {
1440           ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1441           ops[1] = operands[1];
1442           m68hc11_gen_movqi (insn, ops);
1443         }
1444       return \"sex\\tb,d\\n\\tsex\\ta,x\";
1445     }
1447   ops[2] = gen_label_rtx ();
1449   if (X_REG_P (operands[1]))
1450     {
1451       output_asm_insn (\"xgdx\", operands);
1452       need_tst = 1;
1453     }
1454   else if (X_REG_P (operands[0]))
1455     {
1456       /* X can be used as an indexed addressing in the source.
1457          Get the value before clearing it.  */
1458       if (reg_mentioned_p (ix_reg, operands[1]))
1459         {
1460           output_asm_insn (\"ldab\\t%b1\", operands);
1461           need_tst = 1;
1462         }
1463       output_asm_insn (\"ldx\\t#0\", operands);
1464     }
1466   output_asm_insn (\"clra\", operands);
1467   if (!X_REG_P (operands[0]))
1468     {
1469       ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1470       ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1472       if (IS_STACK_PUSH (operands[0]))
1473         {
1474           output_asm_insn (\"pshb\", ops);
1475           output_asm_insn (\"tstb\", ops);
1476         }
1477       else
1478         {
1479           output_asm_insn (\"stab\\t%b1\", ops);
1480         }
1481     }
1482   else if (D_REG_P (operands[1]) || need_tst)
1483     {
1484       output_asm_insn (\"tstb\", operands);
1485     }
1486   else
1487     {
1488       output_asm_insn (\"ldab\\t%b1\", operands);
1489     }
1490   output_asm_insn (\"bpl\\t%l2\", ops);
1491   output_asm_insn (\"deca\", operands);
1492   if (X_REG_P (operands[0]))
1493     output_asm_insn (\"dex\", operands);
1495   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1497   if (!X_REG_P (operands[0]))
1498     {
1499       if (IS_STACK_PUSH (operands[0]))
1500         {
1501           output_asm_insn (\"psha\", ops);
1502           output_asm_insn (\"psha\", ops);
1503           output_asm_insn (\"psha\", ops);
1504         }
1505       else
1506         {
1507           output_asm_insn (\"staa\\t%h0\", ops);
1509           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1510           if (dead_register_here (insn, d_reg))
1511             {
1512               output_asm_insn (\"tab\", ops);
1513               output_asm_insn (\"std\\t%0\", ops);
1514             }
1515           else
1516             {
1517               output_asm_insn (\"staa\\t%b0\", ops);
1518               output_asm_insn (\"staa\\t%h0\", ops);
1519             }
1520         }
1521     }
1523   CC_STATUS_INIT;
1524   return \"\";
1528 (define_insn "extendqihi2"
1529   [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1530         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1531   ""
1532   "*
1534   rtx ops[2];
1536   if (A_REG_P (operands[0]))
1537     return \"#\";
1539   ops[0] = gen_label_rtx ();
1540   if (D_REG_P (operands[0]))
1541     {
1542       if (TARGET_M6812)
1543         {
1544           if (!D_REG_P (operands[1]))
1545             {
1546               ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1547               ops[1] = operands[1];
1548               m68hc11_gen_movqi (insn, ops);
1549             }
1550           return \"sex\\tb,d\";
1551         }
1552       output_asm_insn (\"clra\", operands);
1553       if (H_REG_P (operands[1]))
1554         {
1555           output_asm_insn (\"tstb\", operands);
1556         }
1557       else
1558         {
1559           output_asm_insn (\"ldab\\t%b1\", operands);
1560         }
1561       output_asm_insn (\"bpl\\t%l0\", ops);
1562       output_asm_insn (\"deca\", operands);
1564       (*targetm.asm_out.internal_label) (asm_out_file, \"L\", 
1565                                  CODE_LABEL_NUMBER (ops[0]));
1566     }
1567    else
1568     {
1569       output_asm_insn (\"clr\\t%h0\", operands);
1570       if (m68hc11_register_indirect_p (operands[1], HImode))
1571         {
1572           ops[1] = operands[1];
1573           output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1574           CC_STATUS_INIT;
1575         }
1576       else
1577         {
1578           output_asm_insn (\"tst\\t%b1\", operands);
1579           output_asm_insn (\"bpl\\t%l0\", ops);
1580         }
1581       output_asm_insn (\"dec\\t%h0\", operands);
1582       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1583                                  CODE_LABEL_NUMBER (ops[0]));
1584     }
1586   return \"\";
1590 ;; Split the special case where the source of the sign extend is
1591 ;; either Y or Z. In that case, we can't move the source in the D
1592 ;; register directly. The movhi pattern handles this move by using
1593 ;; a temporary scratch memory location.
1595 (define_split
1596   [(set (match_operand:SI 0 "register_operand" "")
1597         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1598   "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1599   [(set (reg:HI D_REGNUM) (match_dup 1))
1600    (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1601   "")
1603 (define_insn "extendhisi2"
1604   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1605         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1606   ""
1607   "*
1609   rtx ops[2];
1610   int x_reg_used;
1612   if (Y_REG_P (operands[1]))
1613     return \"#\";
1615   if (X_REG_P (operands[1]))
1616     {
1617       output_asm_insn (\"xgdx\", operands);
1618       x_reg_used = 1;
1619     }
1620   else
1621     {
1622       /* X can be used as an indexed addressing in the source.
1623          Get the value before clearing it.  */
1624       x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1625       if (x_reg_used)
1626         {
1627           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1628           ops[1] = operands[1];
1629           m68hc11_gen_movhi (insn, ops);
1630         }
1631     }
1633   CC_STATUS_INIT;
1634   if (TARGET_M6812 && 0)
1635     {
1636       /* This sequence of code is larger than the one for 68HC11.
1637          Don't use it; keep it for documentation.  */
1638       if (!D_REG_P (operands[1]) && !x_reg_used)
1639         {
1640           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1641           ops[1] = operands[1];
1642           m68hc11_gen_movhi (insn, ops);
1643         }
1644       output_asm_insn (\"sex\\ta,x\", operands);
1645       output_asm_insn (\"xgdx\", operands);
1646       output_asm_insn (\"sex\\ta,d\", operands);
1647       return \"xgdx\";
1648     }
1650   output_asm_insn (\"ldx\\t#0\", operands);
1651   if (D_REG_P (operands[1]) || x_reg_used)
1652     {
1653       output_asm_insn (\"tsta\", operands);
1654     }
1655   else
1656     {
1657       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1658       ops[1] = operands[1];
1659       m68hc11_gen_movhi (insn, ops);
1660     }
1662   ops[0] = gen_label_rtx ();
1663   output_asm_insn (\"bpl\\t%l0\", ops);
1664   output_asm_insn (\"dex\", operands);
1665   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1667   return \"\";
1671 ;;--------------------------------------------------------------------
1672 ;;- Min and Max instructions (68HC12).
1673 ;;--------------------------------------------------------------------
1674 (define_insn "uminqi3"
1675   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1676         (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1677                  (match_operand:QI 2 "general_operand" "m,d")))]
1678   "TARGET_M6812 && TARGET_MIN_MAX"
1679   "*
1681   /* Flags are set according to (sub:QI (operand 1) (operand2)).
1682      The mina/minm use A as the source or destination.  This is the
1683      high part of D.  There is no way to express that in the pattern
1684      so we must use 'exg a,b' to put the operand in the good register.  */
1685   CC_STATUS_INIT;
1686   if (D_REG_P (operands[0]))
1687     {
1688       return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1689     }
1690   else
1691     {
1692       return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1693     }
1696 (define_insn "umaxqi3"
1697   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1698         (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1699                  (match_operand:QI 2 "general_operand" "m,d")))]
1700   "TARGET_M6812 && TARGET_MIN_MAX"
1701   "*
1703   /* Flags are set according to (sub:QI (operand 1) (operand2)).
1704      The maxa/maxm use A as the source or destination.  This is the
1705      high part of D.  There is no way to express that in the pattern
1706      so we must use 'exg a,b' to put the operand in the good register.  */
1707   CC_STATUS_INIT;
1708   if (D_REG_P (operands[0]))
1709     {
1710       return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1711     }
1712   else
1713     {
1714       return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1715     }
1718 (define_insn "uminhi3"
1719   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1720         (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1721                  (match_operand:HI 2 "general_operand" "m,d")))]
1722   "TARGET_M6812 && TARGET_MIN_MAX"
1723   "*
1725   /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
1726   CC_STATUS_INIT;
1727   if (D_REG_P (operands[0]))
1728     {
1729       return \"emind\\t%2\";
1730     }
1731   else
1732     {
1733       return \"eminm\\t%0\";
1734     }
1737 (define_insn "umaxhi3"
1738   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1739         (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1740                  (match_operand:HI 2 "general_operand" "m,d")))]
1741   "TARGET_M6812 && TARGET_MIN_MAX"
1742   "*
1744   /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
1745   CC_STATUS_INIT;
1746   if (D_REG_P (operands[0]))
1747     {
1748       return \"emaxd\\t%2\";
1749     }
1750   else
1751     {
1752       return \"emaxm\\t%0\";
1753     }
1757 ;;--------------------------------------------------------------------
1758 ;;- Add instructions.
1759 ;;--------------------------------------------------------------------
1760 ;; 64-bit: Use a library call because what GCC generates is huge.
1762 (define_expand "adddi3"
1763   [(set (match_operand:DI 0 "nonimmediate_operand" "")
1764         (plus:DI (match_operand:DI 1 "general_operand" "")
1765                  (match_operand:DI 2 "general_operand" "")))]
1766   ""
1767   "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1768    DONE;")
1771 ;; - 32-bit Add.
1773 (define_expand "addsi3"
1774   [(parallel [(set (match_operand:SI 0 "register_operand" "")
1775                      (plus:SI (match_operand:SI 1 "general_operand" "")
1776                               (match_operand:SI 2 "general_operand" "")))
1777               (clobber (match_scratch:HI 3 ""))])]
1778   ""
1779   "")
1781 (define_insn "*addsi3_zero_extendhi"
1782   [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1783         (plus:SI (zero_extend:SI 
1784                  (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1785                  (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1786    (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1787   ""
1788   "*
1790   rtx ops[3];
1792   if (X_REG_P (operands[2]))
1793     {
1794       ops[0] = operands[1];
1795     }
1796   else
1797     {
1798       if (X_REG_P (operands[1]))
1799         {
1800           output_asm_insn (\"xgdx\", ops);
1801         }
1802       else if (!D_REG_P (operands[1]))
1803         {
1804           ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1805           ops[1] = operands[1];
1806           m68hc11_gen_movhi (insn, ops);
1807         }
1808       ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1809       ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1810     }
1811   ops[2] = gen_label_rtx ();
1813   /* ldx preserves the carry, propagate it by incrementing X directly.  */
1814   output_asm_insn (\"addd\\t%0\", ops);
1815   if (!X_REG_P (operands[2]))
1816     output_asm_insn (\"ldx\\t%1\", ops);
1818   output_asm_insn (\"bcc\\t%l2\", ops);
1819   output_asm_insn (\"inx\", ops);
1821   CC_STATUS_INIT;
1822   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1823   return \"\";  
1827 (define_split /* "*addsi3_zero_extendqi" */
1828   [(set (match_operand:SI 0 "register_operand" "")
1829         (plus:SI (zero_extend:SI 
1830                    (match_operand:QI 1 "general_operand" ""))
1831                  (match_operand:SI 2 "memory_operand" "")))
1832    (clobber (match_scratch:HI 3 "=X,X"))]
1833   "reload_completed"
1834   [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1835    (parallel [(set (match_dup 0) 
1836                    (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1837               (clobber (match_dup 3))])]
1838   "")
1840 (define_insn "*addsi3_zero_extendqi"
1841   [(set (match_operand:SI 0 "register_operand" "=D,D")
1842         (plus:SI (zero_extend:SI 
1843                    (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1844                  (match_operand:SI 2 "general_operand" "miD,!muiD")))
1845    (clobber (match_scratch:HI 3 "=X,X"))]
1846   ""
1847   "*
1849   rtx ops[4];
1851   if (GET_CODE (operands[2]) == MEM)
1852     return \"#\";
1854   if (X_REG_P (operands[2]))
1855     {
1856       if (H_REG_P (operands[1]))
1857         {
1858           ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1859           ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1860           m68hc11_gen_movhi (insn, ops);
1861         }
1862       else
1863         {
1864           ops[0] = operands[1];
1865         }
1866       ops[1] = const0_rtx;
1867     }
1868   else
1869     {
1870       if (X_REG_P (operands[1]))
1871         {
1872           output_asm_insn (\"xgdx\", ops);
1873         }
1874       else if (!D_REG_P (operands[1]))
1875         {
1876           ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1877           ops[1] = operands[1];
1878           m68hc11_gen_movqi (insn, ops);
1879         }
1881       ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1882       ops[1] = ops[0];
1883       ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1884       output_asm_insn (\"clra\", ops);
1885     }
1887   /* ldx preserves the carry, propagate it by incrementing X directly.  */
1888   output_asm_insn (\"addb\\t%b0\", ops);
1889   output_asm_insn (\"adca\\t%h1\", ops);
1890   if (!X_REG_P (operands[2]))
1891     output_asm_insn (\"ldx\\t%2\", ops);
1893   /* If the above adca was adding some constant, we don't need to propagate
1894      the carry unless the constant was 0xff.  */
1895   if (X_REG_P (operands[2])
1896       || GET_CODE (ops[1]) != CONST_INT
1897       || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1898     {
1899       ops[3] = gen_label_rtx ();
1901       output_asm_insn (\"bcc\\t%l3\", ops);
1902       output_asm_insn (\"inx\", ops);
1904       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1905                                  CODE_LABEL_NUMBER (ops[3]));
1906     }
1907   CC_STATUS_INIT;
1908   return \"\";  
1911 (define_insn "*addsi3"
1912   [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
1913         (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1914                  (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
1915    (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1916   ""
1917   "*
1919   rtx   ops[3];
1920   const char* add_insn;
1921   const char* inc_insn;
1922   const char* incb_mem;
1923   const char* inch_mem;
1924   HOST_WIDE_INT val;
1926   if (which_alternative > 2)
1927     {
1928       return \"#\";
1929     }
1931   val = INTVAL (operands[2]);
1932   if ((val & 0x0ffffL) == 0)
1933     {
1934       if (!H_REG_P (operands[0]))
1935         {
1936           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1937           ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1938           output_asm_insn (\"ldd\\t%0\", ops);
1939           output_asm_insn (\"addd\\t%1\", ops);
1940           output_asm_insn (\"std\\t%0\", ops);
1941           return \"\";
1942         }
1943       else if (val == 1)
1944         {
1945           return \"inx\";
1946         }
1947       else
1948         {
1949           return \"#\";
1950         }
1951     }
1952   if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1953     {
1954       return \"#\";
1955     }
1957   if (val >= 0)
1958     {
1959       ops[1]   = operands[2];
1960       add_insn = \"addd\\t%1\";
1961       inc_insn = \"inx\\t\";
1962       incb_mem  = \"inc\\t%b1\";
1963       inch_mem  = \"inc\\t%h1\";
1964     }
1965   else
1966     {
1967       ops[1] = GEN_INT (- val);
1968       add_insn = \"subd\\t%1\";
1969       inc_insn = \"dex\";
1970       incb_mem  = \"dec\\t%b1\";
1971       inch_mem  = \"dec\\t%h1\";
1972     }
1973       
1974   ops[2] = gen_label_rtx ();
1975   if (!H_REG_P (operands[0]))
1976     {
1977       ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1978       output_asm_insn (\"ldd\\t%0\", ops);
1979     }
1980   output_asm_insn (add_insn, ops);
1981   if (!H_REG_P (operands[0]))
1982     {
1983       output_asm_insn (\"std\\t%0\", ops);
1984     }
1985   output_asm_insn (\"bcc\\t%l2\", ops);
1986   if (H_REG_P (operands[0]))
1987     {
1988       output_asm_insn (inc_insn, ops);
1989     }
1990   else
1991     {
1992       ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1993       ops[1] = ops[0];
1994       if (INTVAL (operands[2]) < 0)
1995         {
1996           output_asm_insn (\"ldd\\t%1\", ops);
1997           output_asm_insn (\"addd\\t#-1\", ops);
1998           output_asm_insn (\"std\\t%1\", ops);
1999         }
2000       else
2001         {
2002           output_asm_insn (incb_mem, ops);
2003           output_asm_insn (\"bne\\t%l2\", ops);
2004           output_asm_insn (inch_mem, ops);
2005         }
2006     }
2007   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
2009   CC_STATUS_INIT;
2010   return \"\";
2013 (define_split
2014   [(set (match_operand:SI 0 "register_operand" "")
2015         (plus:SI (match_operand:SI 1 "register_operand" "")
2016                  (match_operand:SI 2 "const_int_operand" "")))
2017    (clobber (match_scratch:HI 3 ""))]
2018   "reload_completed && z_replacement_completed == 2
2019    && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
2020   [(set (match_dup 5) (match_dup 6))
2021    (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
2022    (set (match_dup 6) (match_dup 5))]
2023   "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2024    if (X_REG_P (operands[0]))
2025      {
2026        operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
2027      }
2028    else
2029      {
2030        operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2031        operands[5] = operands[3];
2032      }
2033    ")
2035 (define_split
2036   [(set (match_operand:SI 0 "register_operand" "")
2037         (plus:SI (match_operand:SI 1 "register_operand" "")
2038                  (match_operand:SI 2 "general_operand" "")))
2039    (clobber (match_scratch:HI 3 "=X"))]
2040   "reload_completed && z_replacement_completed == 2
2041    && (GET_CODE (operands[2]) != CONST_INT || 
2042         (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
2043   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2044    (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2045               (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2046    (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2047    (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2048    (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2049               (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
2050   "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2051    operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2052    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2053    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2056 ;; Instruction generated to propagate the carry of a 16-bit add
2057 ;; to the upper 16-bit part (in register X).
2059 (define_insn "*addsi_carry"
2060   [(set (match_operand:HI 0 "register_operand" "=x")
2061            (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2062                              (const_int 0)) 
2063                     (reg:HI CC_REGNUM)))]
2064   ""
2065   "*
2067   rtx ops[2];
2069   ops[0] = gen_label_rtx ();
2070   output_asm_insn (\"bcc\\t%l0\", ops);
2071   output_asm_insn (\"in%0\", operands);
2072   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2073   CC_STATUS_INIT;
2074   return \"\";
2078 ;; - 16-bit Add.
2080 (define_expand "addhi3"
2081   [(set (match_operand:HI 0 "register_operand" "")
2082            (plus:HI (match_operand:HI 1 "register_operand" "")
2083                     (match_operand:HI 2 "general_operand" "")))]
2084   ""
2085   "
2087   if (TARGET_M6811 && SP_REG_P (operands[0]))
2088     {
2089       emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
2090                          gen_rtx_SET (VOIDmode,
2091                                   operand0,
2092                                   gen_rtx_PLUS (HImode,
2093                                            operand1, operand2)),
2094                         gen_rtx_CLOBBER (VOIDmode,
2095                                 gen_rtx_SCRATCH (HImode)))));
2096       DONE;
2097     }
2100 (define_insn "*addhi3_68hc12"
2101   [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
2102         (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
2103                  (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
2104   "TARGET_M6812"
2105   "*
2107   int val;
2108   const char* insn_code;
2110   if (which_alternative >= 4)
2111     {
2112       if (A_REG_P (operands[2]))
2113         {
2114           CC_STATUS_INIT;
2115           output_asm_insn (\"xgd%2\", operands);
2116           output_asm_insn (\"lea%0 d,%0\", operands);
2117           return \"xgd%2\";
2118         }
2119       return \"#\";
2120     }
2122   if (D_REG_P (operands[0]))
2123     {
2124       if (X_REG_P (operands[2]))
2125         {
2126           m68hc11_notice_keep_cc (operands[0]);
2127           output_asm_insn (\"xgdx\", operands);
2128           output_asm_insn (\"leax\\td,%2\", operands);
2129           return \"xgdx\";
2130         }
2131       else if (Y_REG_P (operands[2]))
2132         {
2133           m68hc11_notice_keep_cc (operands[0]);
2134           output_asm_insn (\"xgdy\", operands);
2135           output_asm_insn (\"leay\\td,%2\", operands);
2136           return \"xgdy\";
2137         }
2138       else if (SP_REG_P (operands[2]))
2139         {
2140           output_asm_insn (\"sts\\t%t0\", operands);
2141           return \"addd\\t%t0\";
2142         }
2143       return \"addd\\t%2\";
2144     }
2146   if (GET_CODE (operands[2]) == CONST_INT)
2147     val = INTVAL (operands[2]);
2148   else
2149     val = 1000;
2151   if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
2152     {
2153       m68hc11_notice_keep_cc (operands[0]);
2154       switch (REGNO (operands[0]))
2155         {
2156         case HARD_X_REGNUM:
2157           return \"leax\\t%i2,%1\";
2159         case HARD_Y_REGNUM:
2160           return \"leay\\t%i2,%1\";
2162         case HARD_SP_REGNUM:
2163           return \"leas\\t%i2,%1\";
2165         default:
2166           fatal_insn (\"Invalid operands in the instruction\", insn);
2167         }
2168     }
2169   if (val > 0)
2170     {
2171       insn_code = X_REG_P (operands[0]) ? \"inx\"
2172                 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2173     }
2174   else
2175     {
2176       val  = -val;
2177       insn_code = X_REG_P (operands[0]) ? \"dex\"
2178                 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2179     }
2181   /* For X and Y increment, the flags are not complete. Only the Z flag
2182      is updated. For SP increment, flags are not changed.  */
2183   if (SP_REG_P (operands[0]))
2184     {
2185       cc_status = cc_prev_status; 
2186       if (INTVAL (operands[2]) < 0)
2187         {
2188           while (val > 2)
2189             {
2190               output_asm_insn (\"pshx\", operands);
2191               val -= 2;
2192             }
2193           if (val == 0)
2194             return \"\";
2195         }     
2196     }
2197   else
2198     {
2199       CC_STATUS_INIT;
2200     }
2202   while (val)
2203     {
2204       output_asm_insn (insn_code, operands);
2205       val--;
2206     }
2207   return \"\";
2211 ;; Specific pattern to add to the stack pointer.
2212 ;; We also take care of the clobbering of the IY register.
2214 (define_insn "addhi_sp"
2215   [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2216           (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2217                    (match_operand:HI 2 "general_operand" "P,im,u,im")))
2218    (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2219   "!TARGET_M6812"
2220   "*
2222   HOST_WIDE_INT val;
2224   if (optimize && Y_REG_P (operands[3])
2225       && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
2226     operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
2228   if (GET_CODE (operands[2]) == CONST_INT
2229       && (val = INTVAL (operands[2])) != 0
2230       && (CONST_OK_FOR_LETTER_P (val, 'P')
2231           || (val > 0 && val <= 8)))
2232     {
2233       while (val > 1 || val < -1)
2234         {
2235           if (val > 0)
2236             {
2237               if (!H_REG_P (operands[3]))
2238                 break;
2240               output_asm_insn (\"pul%3\", operands);
2241               val -= 2;
2242             }
2243           else
2244             {
2245               output_asm_insn (\"pshx\", operands);
2246               val += 2;
2247             }
2248         }
2249       while (val != 0)
2250         {
2251           if (val > 0)
2252             {
2253               output_asm_insn (\"ins\", operands);
2254               val--;
2255             }
2256           else
2257             {
2258               output_asm_insn (\"des\", operands);
2259               val++;
2260             }
2261         }
2262       cc_status = cc_prev_status;
2263       return \"\";
2264     }
2266   /* Need to transfer to SP to X/Y and then to D register.
2267      Register X/Y is lost, this is specified by the (clobber) statement.  */
2268   output_asm_insn (\"ts%3\", operands);
2269   if (GET_CODE (operands[2]) == CONST_INT
2270       && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
2271       && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
2272     {
2273       output_asm_insn (\"ldab\\t%2\", operands);
2274       output_asm_insn (\"ab%3\", operands);
2275       CC_STATUS_INIT;
2276     }
2277   else
2278     {
2279       output_asm_insn (\"xgd%3\", operands);
2280       output_asm_insn (\"addd\\t%2\", operands);
2281       output_asm_insn (\"xgd%3\", operands);
2282     }
2284    /* The status flags correspond to the addd.  xgdy and tys do not
2285       modify the flags.  */
2286   return \"t%3s\";
2289 (define_insn "*addhi3"
2290   [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
2291         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
2292                  (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
2293   "TARGET_M6811"
2294   "*
2296   const char* insn_code;
2297   int val;
2299   if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2300     {
2301       output_asm_insn (\"sts\\t%t0\", operands);
2302       output_asm_insn (\"addd\\t%t0\", operands);
2303       return \"addd\\t#1\";
2304     }
2305   if (GET_CODE (operands[2]) != CONST_INT)
2306     {
2307       /* Adding to an address register or with another/same register
2308          is not possible. This must be replaced.  */
2309       if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2310         return \"#\";
2312       return \"addd\\t%2\";
2313     }
2314   val = INTVAL (operands[2]);
2315   if (!SP_REG_P (operands[0]))
2316     {
2317       if (D_REG_P (operands[0]))
2318         {
2319           if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2320             {
2321               CC_STATUS_INIT;
2322               return \"adda\\t%h2\";
2323             }
2324           else
2325             {
2326               return \"addd\\t%2\";
2327             }
2328         }
2329       else if (GET_CODE (operands[2]) != CONST_INT
2330                || INTVAL (operands[2]) < -4
2331                || INTVAL (operands[2]) > 4)
2332         return \"#\";
2333     }
2334   if (val > 0)
2335     {
2336       insn_code = X_REG_P (operands[0]) ? \"inx\"
2337                     : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2338     }
2339   else
2340     {
2341       val  = -val;
2342       insn_code = X_REG_P (operands[0]) ? \"dex\"
2343                     : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2344     }
2346   /* For X and Y increment, the flags are not complete.  Only the Z flag
2347      is updated.  For SP increment, flags are not changed.  */
2348   if (SP_REG_P (operands[0]))
2349     {
2350       cc_status = cc_prev_status; 
2351       if (INTVAL (operands[2]) < 0)
2352         {
2353           while (val >= 2)
2354             {
2355               output_asm_insn (\"pshx\", operands);
2356               val -= 2;
2357             }
2358         }
2359       else if (optimize && dead_register_here (insn, ix_reg))
2360         {
2361           while (val >= 2)
2362             {
2363               output_asm_insn (\"pulx\", operands);
2364               val -= 2;
2365             }
2366         }
2367     }
2368   else
2369     {
2370       CC_STATUS_INIT;
2371     }
2373   while (val)
2374     {
2375       output_asm_insn (insn_code, operands);
2376       val--;
2377     }
2378   return \"\";
2381 (define_insn "*addhi3_zext"
2382   [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2383         (plus:HI (zero_extend:HI 
2384                      (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2385                  (match_operand:HI 2 "general_operand" "0,0")))]
2386   ""
2387   "*
2389   CC_STATUS_INIT;
2390   if (A_REG_P (operands[0]))
2391     return \"ab%0\";
2392   else if (A_REG_P (operands[1]))
2393     return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2394   else 
2395     return \"addb\\t%b1\\n\\tadca\\t#0\";
2399 ;; Translate d = d + d into d = << 1
2400 ;; We have to do this because adding a register to itself is not possible.
2401 ;; ??? It's not clear whether this is really necessary.
2403 (define_split
2404   [(set (match_operand:QI 0 "hard_reg_operand" "")
2405         (plus:QI (match_dup 0)
2406                  (match_dup 0)))]
2407   "0 && reload_completed"
2408   [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2409   "")
2411 (define_insn "addqi3"
2412   [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2413         (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2414                  (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2415   ""
2416   "*
2418   if (GET_CODE (operands[2]) == CONST_INT)
2419     {
2420       if (INTVAL (operands[2]) == 1)
2421         {
2422           if (DA_REG_P (operands[0]))
2423             {
2424               return \"inca\";
2425             }
2426           else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2427            {
2428              return \"incb\";
2430            }
2431           else if (A_REG_P (operands[0]))
2432            {
2433              /* This applies on the 16-bit register.  This should be ok since
2434                 this is not a strict_low_part increment.  */
2435              return \"in%0\";
2436            }
2437           else
2438            {
2439              return \"inc\\t%b0\";
2440            }
2441         }
2442       else if (INTVAL (operands[2]) == -1)
2443         {
2444           if (DA_REG_P (operands[0]))
2445             {
2446               return \"deca\";
2447             }
2448           else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2449             {
2450               return \"decb\";
2451             }
2452           else if (A_REG_P (operands[0]))
2453             {
2454              /* This applies on the 16-bit register.  This should be ok since
2455                 this is not a strict_low_part decrement.  */
2456               return \"de%0\";
2457             }
2458           else
2459             {
2460               return \"dec\\t%b0\";
2461             }
2462         }
2463     }
2464   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2465     return \"#\";
2466   else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2467     return \"addb\\t%b2\";
2468   else
2469     return \"adda\\t%b2\";
2473 ;; add with carry is used for 32-bit add.
2475 (define_insn "*adcq"
2476   [(set (match_operand:QI 0 "register_operand" "=q")
2477         (plus:QI (plus:QI (reg:QI CC_REGNUM)
2478                           (match_operand:QI 1 "register_operand" "%0"))
2479                  (match_operand:QI 2 "general_operand" "ium")))]
2480   ""
2481   "adc%0\\t%b2")
2483 ;;--------------------------------------------------------------------
2484 ;;- Subtract instructions.
2485 ;;--------------------------------------------------------------------
2487 (define_expand "subdi3"
2488   [(set (match_operand:DI 0 "nonimmediate_operand" "")
2489         (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2490                   (match_operand:DI 2 "general_operand" "")))]
2491   ""
2492   "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2493    DONE;")
2496 ;; 32-bit Subtract (see addsi3)
2497 ;; Subtract with a constant are handled by addsi3.
2500 ;; - 32-bit Add.
2502 (define_expand "subsi3"
2503   [(parallel [(set (match_operand:SI 0 "register_operand" "")
2504                      (minus:SI (match_operand:SI 1 "register_operand" "")
2505                               (match_operand:SI 2 "general_operand" "")))
2506               (clobber (match_scratch:HI 3 ""))])]
2507   ""
2508   "")
2510 (define_insn "*subsi3"
2511   [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
2512         (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2513                   (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
2514    (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
2515   ""
2516   "#")
2518 (define_insn "*subsi3_zero_extendhi"
2519   [(set (match_operand:SI 0 "register_operand" "=D")
2520         (minus:SI (match_operand:SI 1 "register_operand" "0")
2521             (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
2522    (clobber (match_scratch:HI 3 "=X"))]
2523   ""
2524   "*
2526   rtx ops[2];
2528   if (A_REG_P (operands[2]))
2529     {
2530       if (TARGET_M6812)
2531         ops[0] = gen_rtx_MEM (HImode,
2532                           gen_rtx_PRE_DEC (HImode,
2533                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2534       else
2535         ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2537       ops[1] = operands[2];
2538       m68hc11_gen_movhi (insn, ops);
2539       if (TARGET_M6812)
2540         operands[2] = gen_rtx_MEM (HImode,
2541                                gen_rtx_POST_INC (HImode,
2542                                         gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2543       else
2544         operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2545     }
2546   ops[0] = gen_label_rtx (); 
2547   output_asm_insn (\"subd\\t%2\", operands);
2548   output_asm_insn (\"bcc\\t%l0\", ops);
2549   output_asm_insn (\"dex\", ops);
2550   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2551   CC_STATUS_INIT;
2552   return \"\";
2555 (define_insn "*subsi3_zero_extendqi"
2556   [(set (match_operand:SI 0 "register_operand" "=D")
2557         (minus:SI (match_operand:SI 1 "register_operand" "0")
2558             (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
2559    (clobber (match_scratch:HI 3 "=X"))]
2560   ""
2561   "*
2563   rtx ops[2];
2565   if (A_REG_P (operands[2]))
2566     {
2567       ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2568       ops[1] = operands[2];
2569       m68hc11_gen_movhi (insn, ops);
2570       operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2571     }
2572   ops[0] = gen_label_rtx (); 
2573   output_asm_insn (\"subb\\t%b2\", operands);
2574   output_asm_insn (\"sbca\\t#0\", operands);
2575   output_asm_insn (\"bcc\\t%l0\", ops);
2576   output_asm_insn (\"dex\", ops);
2577   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2578   CC_STATUS_INIT;
2579   return \"\";
2583 ;; reg:HI 1 -> d        reg:QI 6 -> B
2584 ;; reg:QI 7 -> ccr      reg:QI 5 -> A
2586 (define_split /* "*subsi3" */
2587   [(set (match_operand:SI 0 "register_operand" "")
2588         (minus:SI (match_operand:SI 1 "register_operand" "")
2589                   (match_operand:SI 2 "general_operand" "")))
2590    (clobber (match_scratch:HI 3 "=X"))]
2591   "reload_completed && z_replacement_completed == 2
2592    && X_REG_P (operands[1])"
2593   [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2594    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2595               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2596    (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2597    (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2598    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2599               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2600   "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2601    operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2602    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2603    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2605 (define_split /* "*subsi3" */
2606   [(set (match_operand:SI 0 "register_operand" "")
2607         (minus:SI (match_operand:SI 1 "general_operand" "")
2608                   (match_operand:SI 2 "register_operand" "")))
2609    (clobber (match_scratch:HI 3 "=X"))]
2610   "reload_completed && z_replacement_completed == 2
2611    && X_REG_P (operands[2])"
2612   [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2613    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2614               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2615    (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2616    (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2617    (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2618               (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2619    (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2620   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2621    operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2622    operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2623    operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2625 (define_split /* "*subsi3" */
2626   [(set (match_operand:SI 0 "nonimmediate_operand" "")
2627         (minus:SI (match_operand:SI 1 "general_operand" "")
2628                   (match_operand:SI 2 "general_operand" "")))
2629    (clobber (match_scratch:HI 3 "=d"))]
2630   "reload_completed && z_replacement_completed == 2
2631    && !X_REG_P (operands[0])"
2632   [(set (match_dup 3) (match_dup 4))
2633    (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2634    (set (match_dup 4) (match_dup 3))
2635    (set (match_dup 3) (match_dup 6))
2636    (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2637    (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2638    (set (match_dup 6) (match_dup 3))]
2639   "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2640    operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2641    operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2642    operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2643    operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2644    operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2647 ;; - 16-bit Subtract.
2649 (define_expand "subhi3"
2650   [(set (match_operand:HI 0 "register_operand" "=r")
2651         (minus:HI (match_operand:HI 1 "register_operand" "0")
2652                   (match_operand:HI 2 "general_operand" "g")))]
2653   ""
2654   "")
2657 ;; Subtract from stack. This is better if we provide a pattern.
2659 (define_insn "*subhi3_sp"
2660   [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2661         (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2662                   (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2663    (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2664   ""
2665   "*
2667   if (X_REG_P (operands[2]))
2668     {
2669       operands[2] = m68hc11_soft_tmp_reg;
2670       output_asm_insn (\"stx\\t%2\", operands);
2671     }
2672   else if (Y_REG_P (operands[2]))
2673     {
2674       operands[2] = m68hc11_soft_tmp_reg;
2675       output_asm_insn (\"sty\\t%2\", operands);
2676     }
2677   else if (D_REG_P (operands[2]))
2678     {
2679       operands[2] = m68hc11_soft_tmp_reg;
2680       output_asm_insn (\"std\\t%2\", operands);
2681     }
2683   if (D_REG_P (operands[3]))
2684     {
2685       int save_x;
2687       save_x = !dead_register_here (insn, ix_reg);
2688       if (save_x)
2689         output_asm_insn (\"xgdx\", operands);
2690       output_asm_insn (\"tsx\", operands);
2691       output_asm_insn (\"xgdx\", operands);
2692       output_asm_insn (\"subd\\t%2\", operands);
2693       output_asm_insn (\"xgdx\", operands);
2695       /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2696          modify the flags.  */
2697       output_asm_insn (\"txs\", operands);
2698       if (save_x)
2699         return \"xgdx\";
2700       else
2701         return \"\";
2702     }
2704   /* Need to transfer to SP to X,Y and then to D register.
2705      Register X,Y is lost, this is specified by the (clobber) statement.  */
2706   output_asm_insn (\"ts%3\", operands);
2707   output_asm_insn (\"xgd%3\", operands);
2708   output_asm_insn (\"subd\\t%2\", operands);
2709   output_asm_insn (\"xgd%3\", operands);
2711    /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2712       modify the flags.  */
2713   return \"t%3s\";
2717 (define_insn "*subhi3"
2718   [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
2719         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
2720                   (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
2721   ""
2722   "*
2724   /* Adding to an address register or with another/same register
2725      is not possible.  This must be replaced.  */
2726   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2727     return \"#\";
2729   return \"subd\\t%2\";
2732 (define_insn "*subhi3_zext"
2733   [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2734         (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2735            (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2736   ""
2737   "*
2739   CC_STATUS_INIT;
2740   if (A_REG_P (operands[2]))
2741     {
2742       rtx ops[2];
2744       ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2745       ops[1] = operands[2];
2746       m68hc11_gen_movqi (insn, ops);
2747       return \"subb\\t%T0\\n\\tsbca\\t#0\";
2748     }
2749   return \"subb\\t%b2\\n\\tsbca\\t#0\";
2752 (define_insn "subqi3"
2753   [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2754         (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2755                   (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2756   ""
2757   "*
2759   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2760     return \"#\";
2761   else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2762     return \"subb\\t%b2\";
2763   else
2764     return \"suba\\t%b2\";
2768 ;; subtract with carry is used for 32-bit subtract.
2770 (define_insn "*subcq"
2771   [(set (match_operand:QI 0 "register_operand" "=q")
2772         (minus:QI (minus:QI (reg:QI CC_REGNUM)
2773                             (match_operand:QI 1 "register_operand" "0"))
2774                   (match_operand:QI 2 "general_operand" "ium")))]
2775   ""
2776   "sbc%0\\t%b2")
2778 ;;--------------------------------------------------------------------
2779 ;;- Multiply instructions.
2780 ;;--------------------------------------------------------------------
2782 ;; 32 and 64-bit multiply are handled by the library
2785 (define_expand "mulsi3"
2786   [(set (match_operand:SI 0 "nonimmediate_operand" "")
2787         (mult:SI (match_operand:SI 1 "general_operand" "")
2788                  (match_operand:SI 2 "general_operand" "")))]
2789   ""
2790   "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2791    DONE;")
2793 (define_expand "mulhi3"
2794   [(parallel [(set (match_operand:HI 0 "register_operand" "")
2795                        (mult:HI (match_operand:HI 1 "register_operand" "")
2796                                 (match_operand:HI 2 "register_operand" "")))
2797               (clobber (match_scratch:HI 3 ""))])]
2798   ""
2799   "")
2801 (define_insn "mulhi3_m68hc11"
2802   [(set (match_operand:HI 0 "register_operand" "=d")
2803         (mult:HI (match_operand:HI 1 "register_operand" "%0")
2804                  (match_operand:HI 2 "register_operand" "x")))
2805    (clobber (match_scratch:HI 3 "=X"))]
2806   "TARGET_M6811"
2807   "*
2809   CC_STATUS_INIT;
2810   /* D * X -> D  (X and Y are preserved by this function call).  */
2811   return \"jsr\\t___mulhi3\";
2814 (define_insn "mulhi3_m68hc12"
2815   [(set (match_operand:HI 0 "register_operand" "=d,d")
2816         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2817                  (match_operand:HI 2 "register_operand" "y,x")))
2818    (clobber (match_scratch:HI 3 "=2,2"))]
2819   "TARGET_M6812"
2820   "*
2822   CC_STATUS_INIT;
2823   if (X_REG_P (operands[2]))
2824     return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2825   else
2826     return \"emul\";
2829 (define_insn "umulhisi3"
2830   [(set (match_operand:SI 0 "register_operand" "=D,D")
2831         (mult:SI (zero_extend:SI
2832                      (match_operand:HI 1 "register_operand" "%d,d"))
2833                  (zero_extend:SI
2834                      (match_operand:HI 2 "register_operand" "y,x"))))
2835    (clobber (match_scratch:HI 3 "=2,X"))]
2836   "TARGET_M6812"
2837   "*
2839   if (X_REG_P (operands [2]))
2840     output_asm_insn (\"exg\\tx,y\", operands);
2842   /* Can't use the carry after that; other flags are ok when testing
2843      the 32-bit result.  */
2844   cc_status.flags |= CC_NO_OVERFLOW;
2845   return \"emul\\n\\texg\\tx,y\";
2848 (define_insn "mulhisi3"
2849   [(set (match_operand:SI 0 "register_operand" "=D,D")
2850         (mult:SI (sign_extend:SI
2851                      (match_operand:HI 1 "register_operand" "%d,d"))
2852                  (sign_extend:SI
2853                      (match_operand:HI 2 "register_operand" "y,x"))))
2854    (clobber (match_scratch:HI 3 "=2,X"))]
2855   "TARGET_M6812"
2856   "*
2858   if (X_REG_P (operands [2]))
2859     output_asm_insn (\"exg\\tx,y\", operands);
2861   /* Can't use the carry after that; other flags are ok when testing
2862      the 32-bit result.  */
2863   cc_status.flags |= CC_NO_OVERFLOW;
2864   return \"emuls\\n\\texg\\tx,y\";
2867 (define_insn "umulqihi3"
2868   [(set (match_operand:HI 0 "register_operand" "=d")
2869         (mult:HI (zero_extend:HI
2870                      (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2871                  (zero_extend:HI
2872                      (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2873   ""
2874   "*
2876   if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2877     {
2878       output_asm_insn (\"tba\", operands);
2879     }
2880   else
2881     {
2882       rtx ops[2];
2884       if (D_REG_P (operands[2]))
2885         {
2886           rtx temp = operands[2];
2887           operands[2] = operands[1];
2888           operands[1] = temp;
2889         }
2891       ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2892       ops[1] = operands[2];
2893       m68hc11_gen_movqi (insn, ops);
2895       if (!D_REG_P (operands[1]))
2896         {
2897           output_asm_insn (\"ldab\\t%b1\", operands);
2898         }
2899     }
2901   CC_STATUS_INIT;
2902   return \"mul\";
2905 (define_insn "mulqi3"
2906   [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
2907         (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
2908                  (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
2909   ""
2910   "*
2912   if (A_REG_P (operands[0]))
2913     return \"#\";
2915   if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2916     {
2917       output_asm_insn (\"tba\", operands);
2918     }
2919   else
2920     {
2921       if (D_REG_P (operands[2]))
2922         {
2923           rtx temp = operands[2];
2924           operands[2] = operands[1];
2925           operands[1] = temp;
2926         }
2927         
2928       output_asm_insn (\"ldaa\\t%b2\", operands);
2930       if (!D_REG_P (operands[1]))
2931         {
2932           output_asm_insn (\"ldab\\t%b1\", operands);
2933         }
2934     }
2936   CC_STATUS_INIT;
2937   return \"mul\";
2940 (define_split
2941   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
2942         (mult:QI (match_operand:QI 1 "general_operand" "")
2943                  (match_operand:QI 2 "general_operand" "")))]
2944   "z_replacement_completed == 2"
2945   [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2946               (set (match_dup 3) (reg:HI D_REGNUM))])
2947    (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
2948    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2949               (set (match_dup 3) (reg:HI D_REGNUM))])]
2950   "
2951    operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
2952    if (A_REG_P (operands[1]))
2953      operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2954    else
2955      operands[5] = operands[1];
2956    if (A_REG_P (operands[2]))
2957      operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2958    else
2959      operands[6] = operands[2];
2960   ")
2962 (define_insn "mulqihi3"
2963   [(set (match_operand:HI 0 "register_operand" "=d,d,d")
2964         (mult:HI (sign_extend:HI
2965                         (match_operand:QI 1 "register_operand" "%0,0,0"))
2966                  (sign_extend:HI
2967                         (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
2968   ""
2969   "*
2971   CC_STATUS_INIT;
2973   /* Special case when multiplying the register with itself.  */
2974   if (D_REG_P (operands[2]))
2975     {
2976       output_asm_insn (\"tba\", operands);
2977       return \"mul\";
2978     }
2980   if (!H_REG_P (operands[2]))
2981     {
2982       output_asm_insn (\"ldaa\\t%b2\", operands);
2983     }
2984   else
2985     {
2986       rtx ops[2];
2988       ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2989       ops[1] = operands[2];
2990       m68hc11_gen_movqi (insn, ops);
2991     }
2992   return \"jsr\\t___mulqi3\";
2995 ;;--------------------------------------------------------------------
2996 ;;- Divide instructions.
2997 ;;--------------------------------------------------------------------
2999 (define_insn "divmodhi4"
3000   [(set (match_operand:HI 0 "register_operand" "=d,d")
3001           (div:HI (match_operand:HI 1 "register_operand" "0,0")
3002                   (match_operand:HI 2 "general_operand" "A,ium")))
3003    (set (match_operand:HI 3 "register_operand" "=&x,&x")
3004         (mod:HI (match_dup 1) (match_dup 2)))]
3005   ""
3006   "*
3008   if (!X_REG_P (operands[2])) 
3009     {
3010       if (Y_REG_P (operands[2]))
3011         {
3012           output_asm_insn (\"sty\\t%t1\", operands);
3013           output_asm_insn (\"ldx\\t%t1\", operands);
3014         }
3015       else
3016         {
3017           output_asm_insn (\"ldx\\t%2\", operands);
3018         }
3019     }
3020   if (TARGET_M6812)
3021     {
3022       /* Flags are ok after that.  */
3023       return \"idivs\\n\\txgdx\";      
3024     }
3025   else
3026     {
3027       CC_STATUS_INIT;
3028       return \"bsr\\t__divmodhi4\";
3029     }
3032 (define_insn "udivmodhi4"
3033   [(set (match_operand:HI 0 "register_operand" "=d,d")
3034           (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
3035                    (match_operand:HI 2 "general_operand" "A,ium")))
3036    (set (match_operand:HI 3 "register_operand" "=x,x")
3037         (umod:HI (match_dup 1) (match_dup 2)))]
3038   ""
3039   "*
3041   if (!X_REG_P (operands[2])) 
3042     {
3043       if (Y_REG_P (operands[2]))
3044         {
3045           output_asm_insn (\"sty\\t%t1\", operands);
3046           output_asm_insn (\"ldx\\t%t1\", operands);
3047         }
3048       else
3049         {
3050           output_asm_insn (\"ldx\\t%2\", operands);
3051         }
3052     }
3054   /* Z V and C flags are set but N is unchanged.
3055      Since this is an unsigned divide, we can probably keep the flags
3056      and indicate this.  */
3057   cc_status.flags |= CC_NOT_NEGATIVE;
3058   return \"idiv\\n\\txgdx\";
3061 ;;--------------------------------------------------------------------
3062 ;;- and instructions.
3063 ;;--------------------------------------------------------------------
3065 (define_insn_and_split "anddi3"
3066   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3067         (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3068                 (match_operand:DI 2 "general_operand" "imu,imu")))
3069    (clobber (match_scratch:HI 3 "=d,d"))]
3070   ""
3071   "#"
3072   "reload_completed"
3073   [(const_int 0)]
3074   "m68hc11_split_logical (SImode, AND, operands);
3075    DONE;")
3077 (define_insn_and_split "andsi3"
3078   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3079         (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3080                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3081    (clobber (match_scratch:HI 3 "=X,d"))]
3082   ""
3083   "#"
3084   "reload_completed"
3085   [(const_int 0)]
3086   "m68hc11_split_logical (HImode, AND, operands);
3087    DONE;")
3089 (define_expand "andhi3"
3090   [(set (match_operand:HI 0 "register_operand" "")
3091         (and:HI (match_operand:HI 1 "register_operand" "")
3092                 (match_operand:HI 2 "general_operand" "")))]
3093   ""
3094   "")
3096 (define_insn "*andhi3_mem"
3097   [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3098         (and:HI (match_dup 0)
3099                 (match_operand:HI 1 "immediate_operand" "i,i")))
3100    (clobber (match_scratch:HI 2 "=X,xy"))]
3101   "TARGET_RELAX && !TARGET_M6812"
3102   "*
3104   int val = INTVAL (operands[1]) & 0x0FFFF;
3106   if (val == 0x0ffff)
3107     {
3108       cc_status = cc_prev_status;
3109       return \"\";
3110     }
3112   CC_STATUS_INIT;
3114   /* The bclr instruction uses an inverted mask.  */
3115   operands[1] = GEN_INT ((~val) & 0x0FFFF);
3117   /* When destination is a global variable, generate a .relax instruction
3118      and load the address in the clobber register.  That load can be
3119      eliminated by the linker if the address is in page0.  */
3120   if (which_alternative == 1)
3121     {
3122       rtx ops[3];
3124       ops[0] = operands[2];
3125       ops[1] = XEXP (operands[0], 0);
3126       ops[2] = gen_label_rtx ();
3127       output_asm_insn (\".relax\\t%l2\", ops);
3128       m68hc11_gen_movhi (insn, ops);
3129       if ((val & 0x0FF) != 0x0FF)
3130         output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
3132       if ((val & 0x0FF00) != 0x0FF00)
3133         output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
3135       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3136                                  CODE_LABEL_NUMBER (ops[2]));
3137       return \"\";
3138     }
3140   if ((val & 0x0FF) != 0x0FF)
3141     output_asm_insn (\"bclr\\t%b0, %b1\", operands);
3143   if ((val & 0x0FF00) != 0x0FF00)
3144     output_asm_insn (\"bclr\\t%h0, %h1\", operands);
3146   return \"\";
3149 (define_insn "*andhi3_const"
3150   [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3151         (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3152                 (match_operand:HI 2 "const_int_operand" "")))]
3153   ""
3154   "*
3156   int val = INTVAL (operands[2]) & 0x0FFFF;
3157   int lowpart_zero = 0;
3158   int highpart_zero = 0;
3159   int lowpart_unknown = 0;
3160   int highpart_unknown = 0;
3162   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3163     return \"#\";
3165   if (val == 0x0ffff)
3166     {
3167       cc_status = cc_prev_status;
3168       return \"\";
3169     }
3171   /* First, try to clear the low and high part.
3172      If that's possible, the second 'and' will give
3173      the good status flags and we can avoid a tsthi.  */
3174   if ((val & 0x0FF) == 0)
3175     {
3176       if (D_REG_P (operands[0]))
3177         output_asm_insn (\"clrb\", operands);
3178       else
3179         output_asm_insn (\"clr\\t%b0\", operands);
3180       lowpart_zero = 1;
3181     }
3182   if ((val & 0x0FF00) == 0)
3183     {
3184       if (D_REG_P (operands[0]))
3185         output_asm_insn (\"clra\", operands);
3186       else
3187         output_asm_insn (\"clr\\t%h0\", operands);
3188       highpart_zero = 1;
3189     }
3191   if ((val & 0x0FF) == 0x0FF)
3192     {
3193       lowpart_unknown = 1;
3194     }
3195   else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3196     {
3197       rtx ops[2];
3199       ops[0] = operands[0];
3200       ops[1] = GEN_INT ((~val) & 0x0FF);
3201       output_asm_insn (\"bclr\\t%b0, %1\", ops);
3202     }
3203   else if ((val & 0x0FF) != 0)
3204     {
3205       output_asm_insn (\"andb\\t%b2\", operands);
3206     }
3208   if ((val & 0x0FF00) == 0x0FF00)
3209     {
3210       highpart_unknown = 1;
3211     }
3212   else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3213     {
3214       rtx ops[2];
3216       ops[0] = operands[0];
3217       ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
3218       output_asm_insn (\"bclr\\t%h0, %1\", ops);
3219     }
3220   else if ((val & 0x0FF00) != 0)
3221     {
3222       output_asm_insn (\"anda\\t%h2\", operands);
3223     }
3225   if (highpart_unknown || lowpart_unknown)
3226      CC_STATUS_INIT;
3227   else if (highpart_zero == 0 && lowpart_zero == 0)
3228      CC_STATUS_INIT;
3230   return \"\";
3233 (define_insn "*andhi3_gen"
3234   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3235         (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3236                 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3237   ""
3238   "*
3240   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3241     return \"#\";
3243   CC_STATUS_INIT;
3244   return \"anda\\t%h2\\n\\tandb\\t%b2\";
3247 (define_expand "andqi3"
3248   [(set (match_operand:QI 0 "register_operand" "")
3249         (and:QI (match_operand:QI 1 "register_operand" "")
3250                 (match_operand:QI 2 "general_operand" "")))]
3251   ""
3252   "")
3254 (define_insn "*andqi3_mem"
3255   [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3256         (and:QI (match_dup 0)
3257                 (match_operand:QI 1 "const_int_operand" "i,i")))
3258    (clobber (match_scratch:HI 2 "=X,xy"))]
3259   "TARGET_RELAX && !TARGET_M6812"
3260   "*
3262   int val = INTVAL (operands[1]) & 0x0FF;
3264   if (val == 0x0ff)
3265     {
3266       cc_status = cc_prev_status;
3267       return \"\";
3268     }
3270   /* The bclr instruction uses an inverted mask.  */
3271   operands[1] = GEN_INT ((~val) & 0x0FF);
3273   /* When destination is a global variable, generate a .relax instruction
3274      and load the address in the clobber register.  That load can be
3275      eliminated by the linker if the address is in page0.  */
3276   if (which_alternative == 1)
3277     {
3278       rtx ops[3];
3280       ops[0] = operands[2];
3281       ops[1] = XEXP (operands[0], 0);
3282       ops[2] = gen_label_rtx ();
3283       output_asm_insn (\".relax\\t%l2\", ops);
3284       m68hc11_gen_movhi (insn, ops);
3285       output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3286       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3287                                  CODE_LABEL_NUMBER (ops[2]));
3288       return \"\";
3289     }
3290   return \"bclr\\t%b0, %1\";
3293 (define_insn "*andqi3_const"
3294   [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3295         (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3296                 (match_operand:QI 2 "const_int_operand" "")))]
3297   ""
3298   "*
3300   int val = INTVAL (operands[2]) & 0x0FF;
3302   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3303     return \"#\";
3305   if (val == 0x0ff)
3306     {
3307       cc_status = cc_prev_status;
3308       return \"\";
3309     }
3310   if (!H_REG_P (operands[0]))
3311     {
3312       rtx ops[2];
3314       ops[0] = operands[0];
3315       ops[1] = GEN_INT ((~val) & 0x0FF);
3316       output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3317       return \"\";
3318     }
3319   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3320     return \"andb\\t%b2\";
3321   else if (DA_REG_P (operands[0]))
3322     return \"anda\\t%b2\";
3323   else
3324     fatal_insn (\"Invalid operand in the instruction\", insn);
3327 (define_insn "*andqi3_gen"
3328   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3329         (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3330              (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
3331   ""
3332   "*
3334   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3335     return \"#\";
3337   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3338     return \"andb\\t%b2\";
3339   else if (DA_REG_P (operands[0]))
3340     return \"anda\\t%b2\";
3341   else
3342     fatal_insn (\"Invalid operand in the instruction\", insn);
3345 ;;--------------------------------------------------------------------
3346 ;;- Bit set or instructions.
3347 ;;--------------------------------------------------------------------
3349 (define_insn_and_split "iordi3"
3350   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3351         (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3352                 (match_operand:DI 2 "general_operand" "imu,imu")))
3353    (clobber (match_scratch:HI 3 "=d,d"))]
3354   ""
3355   "#"
3356   "reload_completed"
3357   [(const_int 0)]
3358   "m68hc11_split_logical (SImode, IOR, operands);
3359    DONE;")
3361 (define_insn_and_split "iorsi3"
3362   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3363         (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3364                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3365    (clobber (match_scratch:HI 3 "=X,d"))]
3366   ""
3367   "#"
3368   "reload_completed"
3369   [(const_int 0)]
3370   "m68hc11_split_logical (HImode, IOR, operands);
3371    DONE;")
3373 (define_expand "iorhi3"
3374   [(set (match_operand:HI 0 "register_operand" "")
3375         (ior:HI (match_operand:HI 1 "register_operand" "")
3376                 (match_operand:HI 2 "splitable_operand" "")))]
3377   ""
3378   "")
3380 (define_insn "*iorhi3_mem"
3381   [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3382         (ior:HI (match_dup 0)
3383                 (match_operand:HI 1 "const_int_operand" "")))
3384    (clobber (match_scratch:HI 2 "=X,xy"))]
3385   "TARGET_RELAX && !TARGET_M6812"
3386   "*
3388   int val = INTVAL (operands[1]) & 0x0FFFF;
3390   if (val == 0)
3391     {
3392       cc_status = cc_prev_status;
3393       return \"\";
3394     }
3395   CC_STATUS_INIT;
3396   if (which_alternative == 1)
3397     {
3398       rtx ops[3];
3400       ops[0] = operands[2];
3401       ops[1] = XEXP (operands[0], 0);
3402       ops[2] = gen_label_rtx ();
3403       output_asm_insn (\".relax\\t%l2\", ops);
3404       m68hc11_gen_movhi (insn, ops);
3405       if ((val & 0x0FF) != 0)
3406         output_asm_insn (\"bset\\t1,%2, %b1\", operands);
3408       if ((val & 0x0FF00) != 0)
3409         output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3410       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3411                                  CODE_LABEL_NUMBER (ops[2]));
3412       return \"\";
3413     }
3415   if ((val & 0x0FF) != 0)
3416     output_asm_insn (\"bset\\t%b0, %b1\", operands);
3418   if ((val & 0x0FF00) != 0)
3419     output_asm_insn (\"bset\\t%h0, %h1\", operands);
3421   return \"\";
3424 (define_insn "*iorhi3_const"
3425   [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3426         (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3427                 (match_operand:HI 2 "const_int_operand" "")))]
3428   ""
3429   "*
3431   int val = INTVAL (operands[2]) & 0x0FFFF;
3433   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3434     return \"#\";
3436   if (val == 0)
3437     {
3438       cc_status = cc_prev_status;
3439       return \"\";
3440     }
3442   if ((val & 0x0FF) != 0)
3443     {
3444       if (!H_REG_P (operands[0]))
3445         output_asm_insn (\"bset\\t%b0, %b2\", operands);
3446       else
3447         output_asm_insn (\"orab\\t%b2\", operands);
3448     }
3450   if ((val & 0x0FF00) != 0)
3451     {
3452       if (!H_REG_P (operands[0]))
3453          output_asm_insn (\"bset\\t%h0, %h2\", operands);
3454       else
3455          output_asm_insn (\"oraa\\t%h2\", operands);
3456     }
3458   CC_STATUS_INIT;
3459   return \"\";
3462 (define_insn "*iorhi3_gen"
3463   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3464         (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3465                 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3466   ""
3467   "*
3469   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3470     return \"#\";
3472   CC_STATUS_INIT;
3473   return \"oraa\\t%h2\\n\\torab\\t%b2\";
3476 (define_expand "iorqi3"
3477   [(set (match_operand:QI 0 "register_operand" "")
3478         (ior:QI (match_operand:QI 1 "register_operand" "")
3479                 (match_operand:QI 2 "general_operand" "")))]
3480   ""
3481   "")
3483 (define_insn "*iorqi3_mem"
3484   [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3485         (ior:QI (match_dup 0)
3486                 (match_operand:QI 1 "const_int_operand" "")))
3487    (clobber (match_scratch:HI 2 "=X,xy"))]
3488   "TARGET_RELAX && !TARGET_M6812"
3489   "*
3491   int val = INTVAL (operands[1]) & 0x0FF;
3493   if (val == 0)
3494     {
3495       cc_status = cc_prev_status;
3496       return \"\";
3497     }
3498   if (which_alternative == 1)
3499     {
3500       rtx ops[3];
3502       ops[0] = operands[2];
3503       ops[1] = XEXP (operands[0], 0);
3504       ops[2] = gen_label_rtx ();
3505       output_asm_insn (\".relax\\t%l2\", ops);
3506       m68hc11_gen_movhi (insn, ops);
3507       output_asm_insn (\"bset\\t0,%2, %1\", operands);
3508       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3509                                  CODE_LABEL_NUMBER (ops[2]));
3510       return \"\";
3511     }
3512   return \"bset\\t%b0, %1\";
3515 (define_insn "*iorqi3_const"
3516   [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3517         (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3518                 (match_operand:QI 2 "const_int_operand" "")))]
3519   ""
3520   "*
3522   int val = INTVAL (operands[2]) & 0x0FF;
3524   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3525     return \"#\";
3527   if (val == 0)
3528     {
3529       cc_status = cc_prev_status;
3530       return \"\";
3531     }
3532   if (!H_REG_P (operands[0]))
3533     {
3534       return \"bset\\t%b0, %2\";
3535     }
3537   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3538     return \"orab\\t%b2\";
3539   else if (DA_REG_P (operands[0]))
3540     return \"oraa\\t%b2\";
3541   else
3542     fatal_insn (\"Invalid operand in the instruction\", insn);
3545 (define_insn "*iorqi3_gen"
3546   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3547         (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3548              (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
3549   ""
3550   "*
3552   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3553     return \"#\";
3555   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3556     return \"orab\\t%b2\";
3557   else if (DA_REG_P (operands[0]))
3558     return \"oraa\\t%b2\";
3559   else
3560     fatal_insn (\"Invalid operand in the instruction\", insn);
3564 ;;--------------------------------------------------------------------
3565 ;;- xor instructions.
3566 ;;--------------------------------------------------------------------
3568 (define_insn_and_split "xordi3"
3569   [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3570         (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3571                 (match_operand:DI 2 "general_operand" "imu,imu")))
3572    (clobber (match_scratch:HI 3 "=d,d"))]
3573   ""
3574   "#"
3575   "reload_completed"
3576   [(const_int 0)]
3577   "m68hc11_split_logical (SImode, XOR, operands);
3578    DONE;")
3580 (define_insn_and_split "xorsi3"
3581   [(set (match_operand:SI 0 "register_operand" "=D,!u")
3582         (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3583                 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3584    (clobber (match_scratch:HI 3 "=X,d"))]
3585   ""
3586   "#"
3587   "reload_completed"
3588   [(const_int 0)]
3589   "m68hc11_split_logical (HImode, XOR, operands);
3590    DONE;")
3592 (define_insn "xorhi3"
3593   [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3594         (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3595                 (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
3596   ""
3597   "*
3599   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3600     return \"#\";
3602   if (GET_CODE (operands[2]) == CONST_INT)
3603     {
3604       int val = INTVAL (operands[2]) & 0x0FFFF;
3606       if (val == 0)
3607         {
3608           cc_status = cc_prev_status;
3609           return \"\";
3610         }
3611       if ((val & 0x0FF) != 0)
3612         {
3613           output_asm_insn (\"eorb\\t%b2\", operands);
3614         }
3615       else if ((val & 0x0FF) == 0x0FF)
3616         {
3617           output_asm_insn (\"comb\", operands);
3618         }
3620       if ((val & 0x0FF00) != 0)
3621         {
3622           output_asm_insn (\"eora\\t%h2\", operands);
3623         }
3624       else if ((val & 0x0FF00) == 0x0FF00)
3625         {
3626           output_asm_insn (\"coma\", operands);
3627         }
3629       CC_STATUS_INIT;
3630       return \"\";
3631     }
3633   CC_STATUS_INIT;
3634   return \"eora\\t%h2\\n\\teorb\\t%b2\";
3637 (define_insn "xorqi3"
3638   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3639         (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3640              (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
3641   ""
3642   "*
3644   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3645     return \"#\";
3647   if (GET_CODE (operands[2]) == CONST_INT)
3648     {
3649       int val = INTVAL (operands[2]) & 0x0FF;
3651       if (val == 0)
3652         {
3653           cc_status = cc_prev_status;
3654           return \"\";
3655         }
3656       if (val == 0x0FF)
3657         {
3658           if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3659             return \"comb\";
3660           else
3661             return \"coma\";
3662         }
3663     }
3664   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3665     return \"eorb\\t%b2\";
3666   else if (DA_REG_P (operands[0]))
3667     return \"eora\\t%b2\";
3668   else
3669     fatal_insn (\"Invalid operand in the instruction\", insn);
3672 ;;--------------------------------------------------------------------
3673 ;;- Bit set or instructions.
3674 ;;--------------------------------------------------------------------
3676 (define_insn_and_split "*logicalsi3_zexthi"
3677   [(set (match_operand:SI 0 "register_operand" "=D")
3678         (match_operator:SI 3 "m68hc11_logical_operator"
3679                 [(zero_extend:SI
3680                      (match_operand:HI 1 "general_operand" "imudA"))
3681                  (match_operand:SI 2 "general_operand" "Dimu")]))]
3682   ""
3683   "#"
3684   "reload_completed"
3685   [(set (reg:HI D_REGNUM) (match_dup 4))
3686    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3687    (set (reg:HI X_REGNUM) (match_dup 6))]
3688   "PUT_MODE (operands[3], HImode);
3689    if (X_REG_P (operands[2]))
3690      {
3691        operands[5] = operands[1];
3692        /* Make all the (set (REG:x) (REG:y)) a nop set.  */
3693        operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3694        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3695      }
3696    else
3697      {
3698        operands[4] = operands[1];
3699        operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3700        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3701      }
3702    /* For an AND, make sure the high 16-bit part is cleared.  */
3703    if (GET_CODE (operands[3]) == AND)
3704      {
3705        operands[6] = const0_rtx;
3706      }
3707    ")
3709 (define_insn_and_split "*logicalsi3_zextqi"
3710   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3711         (match_operator:SI 3 "m68hc11_logical_operator"
3712                 [(zero_extend:SI
3713                      (match_operand:QI 1 "general_operand" "d,*A,imu"))
3714                  (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3715   ""
3716   "#"
3717   "z_replacement_completed == 2"
3718   [(set (reg:QI A_REGNUM) (match_dup 4))
3719    (set (reg:QI D_REGNUM) (match_dup 7))
3720    (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3721    (set (reg:HI X_REGNUM) (match_dup 6))]
3722   "PUT_MODE (operands[3], QImode);
3723    if (X_REG_P (operands[2]))
3724      {
3725        operands[5] = operands[1];
3726        /* Make all the (set (REG:x) (REG:y)) a nop set.  */
3727        operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3728        operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
3729        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3730      }
3731    else
3732      {
3733        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3734        operands[7] = operands[1];
3735        operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3736        operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3737        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3738      }
3739    /* For an AND, make sure the high 24-bit part is cleared.  */
3740    if (GET_CODE (operands[3]) == AND)
3741      {
3742        operands[4] = const0_rtx;
3743        operands[6] = const0_rtx;
3744      }
3745    ")
3747 (define_insn_and_split "*logicalhi3_zexthi_ashift8"
3748   [(set (match_operand:HI 0 "register_operand" "=d")
3749         (match_operator:HI 3 "m68hc11_logical_operator"
3750                 [(zero_extend:HI
3751                      (match_operand:QI 1 "general_operand" "imud*A"))
3752                  (ashift:HI
3753                      (match_operand:HI 2 "general_operand" "imud*A")
3754                      (const_int 8))]))]
3755   ""
3756   "#"
3757   "z_replacement_completed == 2"
3758   [(set (reg:QI A_REGNUM) (match_dup 4))
3759    (set (reg:QI B_REGNUM) (match_dup 5))]
3760   "
3761    if (GET_CODE (operands[3]) == AND)
3762      {
3763        emit_insn (gen_movhi (operands[0], const0_rtx));
3764        DONE;
3765      }
3766    else
3767      {
3768        operands[5] = operands[1];
3769        if (D_REG_P (operands[2]))
3770          {
3771            operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3772          }
3773        else
3774          {
3775            operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3776          }
3777      }
3778   ")
3780 (define_insn_and_split "*logicalhi3_zexthi"
3781   [(set (match_operand:HI 0 "register_operand" "=d,d")
3782         (match_operator:HI 3 "m68hc11_logical_operator"
3783                 [(zero_extend:HI
3784                      (match_operand:QI 1 "general_operand" "imd*A,?u"))
3785                  (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3786   ""
3787   "#"
3788   "z_replacement_completed == 2"
3789   [(set (reg:QI B_REGNUM) (match_dup 6))
3790    (set (reg:QI A_REGNUM) (match_dup 4))
3791    (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3792   "
3793    PUT_MODE (operands[3], QImode);
3794    if (D_REG_P (operands[2]))
3795      {
3796        operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3797        operands[5] = operands[1];
3798        operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3799      }
3800    else
3801      {
3802        operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3803        operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3804        if (D_REG_P (operands[1]))
3805          operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3806        else
3807          operands[6] = operands[1];
3808      }
3809    /* For an AND, make sure the high 8-bit part is cleared.  */
3810    if (GET_CODE (operands[3]) == AND)
3811      {
3812        operands[4] = const0_rtx;
3813      }
3814   ")
3817 (define_insn_and_split "*logicalsi3_silshr16"
3818   [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
3819           (match_operator:SI 3 "m68hc11_logical_operator"
3820               [(lshiftrt:SI 
3821                    (match_operand:SI 1 "general_operand" "uim,uim,0,0")
3822                    (const_int 16))
3823                 (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
3824   ""
3825   "#"
3826   "reload_completed"
3827   [(set (reg:HI D_REGNUM) (match_dup 4))
3828    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3829    (set (reg:HI X_REGNUM) (match_dup 6))]
3830   "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3831    if (X_REG_P (operands[2]))
3832      {
3833        operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3834        operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3835      }
3836    else
3837      {
3838        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3839        operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3840      }
3841    PUT_MODE (operands[3], HImode);
3843    /* For an AND, make sure the high 16-bit part is cleared.  */
3844    if (GET_CODE (operands[3]) == AND)
3845      {
3846        operands[6] = const0_rtx;
3847      }
3850 (define_insn_and_split "*logicalsi3_silshl16"
3851   [(set (match_operand:SI 0 "register_operand" "=D,D")
3852           (match_operator:SI 3 "m68hc11_logical_operator"
3853               [(ashift:SI 
3854                    (match_operand:SI 1 "general_operand" "uim,?D")
3855                    (const_int 16))
3856                 (match_operand:SI 2 "general_operand" "0,0")]))]
3857   ""
3858   "#"
3859   "z_replacement_completed == 2"
3860   [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3861    (set (reg:HI D_REGNUM) (match_dup 5))]
3862   "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3863    PUT_MODE (operands[3], HImode);
3865    if (GET_CODE (operands[3]) == AND)
3866      operands[5] = const0_rtx;
3867    else
3868      operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3869    ")
3871 (define_insn_and_split "*logicalsi3_silshl16_zext"
3872   [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3873           (match_operator:SI 3 "m68hc11_logical_operator"
3874               [(ashift:SI
3875                   (zero_extend:SI
3876                      (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
3877                   (const_int 16))
3878             (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
3879   ""
3880   "#"
3881   ;; Must split before z register replacement
3882   "reload_completed"
3883   [(set (match_dup 4) (match_dup 5))
3884    (set (match_dup 6) (match_dup 7))]
3885   "
3886     /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
3887    if (GET_CODE (operands[1]) == HARD_D_REGNUM
3888        && GET_CODE (operands[3]) != AND)
3889      {
3890        /* This particular case is too early to be split before
3891           Z register replacement because the cse-reg pass we do
3892           does not recognize the 'swap_areg'.  It is ok to handle
3893           this case after.  */
3894        if (z_replacement_completed != 2)
3895          {
3896            FAIL;
3897          }
3898        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
3899        emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
3900                                  gen_rtx_REG (HImode, HARD_X_REGNUM)));
3901      }
3902    operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3903    operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3904    operands[5] = operands[2];
3905    operands[7] = operands[1];
3907    if (GET_CODE (operands[3]) == AND)
3908      operands[5] = operands[7] = const0_rtx;
3909    ")
3911 ;;--------------------------------------------------------------------
3912 ;; 16-bit Arithmetic and logical operations on X and Y:
3914 ;;      PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3916 ;; Operations on X or Y registers are split here.  Instructions are
3917 ;; changed into:
3918 ;;   - xgdx/xgdy instruction pattern,
3919 ;;   - The same operation on register D,
3920 ;;   - xgdx/xgdy instruction pattern.
3921 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3922 ;; We also handle the case were the address register is used in both source
3923 ;; operands, such as:
3925 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3926 ;; or
3927 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3930 (define_split
3931   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3932         (match_operator:HI 3 "m68hc11_arith_operator"
3933             [(match_operand:HI 1 "hard_addr_reg_operand" "")
3934              (match_operand:HI 2 "general_operand" "")]))]
3935   "z_replacement_completed == 2
3936    /* If we are adding a small constant to X or Y, it's
3937      better to use one or several inx/iny instructions.  */
3938    && !(GET_CODE (operands[3]) == PLUS 
3939         && ((TARGET_M6812 
3940              && (immediate_operand (operands[2], HImode)
3941                  || hard_reg_operand (operands[2], HImode)))
3942             || (GET_CODE (operands[2]) == CONST_INT
3943                 && INTVAL (operands[2]) >= -4
3944                 && INTVAL (operands[2]) <= 4)))"
3945   [(set (match_dup 9) (match_dup 0))
3946    (set (match_dup 4) (match_dup 5))
3947    (set (match_dup 8) (match_dup 7))
3948    (set (match_dup 0) (match_dup 1))
3949    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3950               (set (match_dup 0) (reg:HI D_REGNUM))])
3951    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3952    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3953               (set (match_dup 0) (reg:HI D_REGNUM))])]
3954   "
3955    operands[9] = operands[0];
3956    /* For 68HC12, push the value on the stack and do the operation
3957       with a pop.  */
3958    if (TARGET_M6812
3959        && m68hc11_non_shift_operator (operands[3], HImode)
3960        && (H_REG_P (operands[2])
3961            || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3962                && reg_mentioned_p (operands[0], operands[2]))))
3963      {
3964        operands[4] = gen_rtx_MEM (HImode,
3965                               gen_rtx_PRE_DEC (HImode,
3966                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3967        operands[6] = gen_rtx_MEM (HImode,
3968                               gen_rtx_POST_INC (HImode,
3969                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3970        operands[5] = operands[2];
3971        operands[8] = operands[7] = operands[0];
3972      }
3973    /* Save the operand2 in a temporary location and use it.  */
3974    else if ((H_REG_P (operands[2])
3975              || reg_mentioned_p  (operands[0], operands[2]))
3976             && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3977      {
3978        if (GET_CODE (operands[3]) == MINUS
3979            && reg_mentioned_p (operands[0], operands[2]))
3980          {
3981            operands[9] = gen_rtx_MEM (HImode,
3982                               gen_rtx_PRE_DEC (HImode,
3983                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3984            operands[1] = gen_rtx_MEM (HImode,
3985                               gen_rtx_POST_INC (HImode,
3986                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3987            operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3988            operands[4] = operands[7] = operands[0];
3989            operands[6] = operands[8];
3990            operands[5] = operands[2];
3991          }
3992        else 
3993          {
3994        operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3995        operands[6] = operands[4];
3996        if (!H_REG_P (operands[2]))
3997          {
3998            operands[5] = operands[0];
3999            operands[7] = operands[2];
4000            operands[8] = operands[0];
4001          }
4002        else
4003          {
4004            operands[5] = operands[2];
4005            operands[8] = operands[7] = operands[0];
4006          }
4007          }
4008      }
4009    else
4010      {
4011        operands[4] = operands[5] = operands[0];
4012        operands[6] = operands[2];
4013        operands[8] = operands[7] = operands[0];
4014      }
4015    ")
4017 (define_split
4018   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4019         (match_operator:HI 3 "m68hc11_arith_operator"
4020             [(match_operand:HI 1 "general_operand" "")
4021              (match_operand:HI 2 "general_operand" "")]))]
4022   "z_replacement_completed == 2
4023    /* If we are adding a small constant to X or Y, it's
4024      better to use one or several inx/iny instructions.  */
4025    && !(GET_CODE (operands[3]) == PLUS 
4026         && ((TARGET_M6812 
4027             && (immediate_operand (operands[2], HImode)
4028                 || hard_reg_operand (operands[2], HImode)))
4029             || (GET_CODE (operands[2]) == CONST_INT
4030                 && INTVAL (operands[2]) >= -4
4031                 && INTVAL (operands[2]) <= 4)))"
4032   [(set (match_dup 0) (match_dup 1))
4033    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4034               (set (match_dup 0) (reg:HI D_REGNUM))])
4035    (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
4036    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4037               (set (match_dup 0) (reg:HI D_REGNUM))])]
4038   "
4039    ")
4042 ;; Next split handles the logical operations on D register with
4043 ;; another hard register for the second operand.  For this, we
4044 ;; have to save the second operand in a scratch location and use
4045 ;; it instead.  This must be supported because in some (rare) cases
4046 ;; the second operand can come in a hard register and the reload
4047 ;; pass doesn't know how to reload it in a memory location.
4049 ;;      PLUS MINUS AND IOR XOR
4051 ;; The shift operators are special and must not appear here.
4053 (define_split
4054   [(set (match_operand:HI 0 "d_register_operand" "")
4055         (match_operator:HI 3 "m68hc11_non_shift_operator"
4056             [(match_operand:HI 1 "d_register_operand" "")
4057              (match_operand:HI 2 "hard_reg_operand" "")]))]
4058   "TARGET_M6811
4059    && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4060   [(set (match_dup 4) (match_dup 2))
4061    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4062   "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
4065 ;; For 68HC12, push the operand[2] value on the stack and do the
4066 ;; logical/arithmetic operation with a pop.
4068 (define_split
4069   [(set (match_operand:HI 0 "d_register_operand" "")
4070         (match_operator:HI 3 "m68hc11_non_shift_operator"
4071             [(match_operand:HI 1 "d_register_operand" "")
4072              (match_operand:HI 2 "hard_reg_operand" "")]))]
4073   "TARGET_M6812
4074    && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4075   [(set (match_dup 4) (match_dup 2))
4076    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4077   "operands[4] = gen_rtx_MEM (HImode,
4078                           gen_rtx_PRE_DEC (HImode,
4079                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4080    operands[5] = gen_rtx_MEM (HImode,
4081                           gen_rtx_POST_INC (HImode,
4082                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4083    ")
4085 ;;--------------------------------------------------------------------
4086 ;; 16-bit Unary operations on X and Y:
4088 ;;              NOT NEG
4090 ;; Operations on X or Y registers are split here.  Instructions are
4091 ;; changed into:
4092 ;;   - xgdx/xgdy instruction pattern,
4093 ;;   - The same operation on register D,
4094 ;;   - xgdx/xgdy instruction pattern.
4095 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4096 ;; We also handle the case were the address register is used in both source
4097 ;; operands, such as:
4099 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4100 ;; or
4101 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4103 (define_split
4104   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4105         (match_operator:HI 2 "m68hc11_unary_operator"
4106             [(match_operand 1 "general_operand" "")]))]
4107   "z_replacement_completed == 2"
4108   [(set (match_dup 4) (match_dup 5))
4109    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4110               (set (match_dup 0) (reg:HI D_REGNUM))])
4111    (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4112    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4113               (set (match_dup 0) (reg:HI D_REGNUM))])]
4114   "
4116   if ((H_REG_P (operands[1])
4117        && !rtx_equal_p (operands[0], operands[1]))
4118       || reg_mentioned_p (operands[0], operands[1]))
4119     {
4120       /* Move to the destination register, before the xgdx.  */
4121       operands[4] = gen_rtx_REG (GET_MODE (operands[1]), 
4122                              REGNO (operands[0]));
4123       operands[5] = operands[1];
4125       /* Apply the operation on D.  */
4126       operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
4127     }
4128   else
4129     {
4130       /* Generate a copy to same register (nop).  */
4131       operands[4] = operands[5] = operands[0];
4132       operands[3] = operands[1];
4133     }
4137 ;; 8-bit operations on address registers.
4139 ;; We have to take care that the address register is not used for the
4140 ;; source of operand2. If operand2 is the D register, we have to save
4141 ;; that register in a temporary location.
4143 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4145 (define_split
4146   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4147         (match_operator:QI 3 "m68hc11_arith_operator"
4148             [(match_operand:QI 1 "hard_addr_reg_operand" "")
4149              (match_operand:QI 2 "general_operand" "")]))]
4150   "z_replacement_completed == 2
4151    /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
4152       incqi pattern generates a better code.  */
4153    && !(GET_CODE (operands[3]) == PLUS
4154         && GET_CODE (operands[2]) == CONST_INT
4155         && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4156   [(set (match_dup 5) (match_dup 6))
4157    (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4158               (set (match_dup 4) (reg:HI D_REGNUM))])
4159    (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4160    (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4161               (set (match_dup 4) (reg:HI D_REGNUM))])]
4162   "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
4164    /* For the second operand is a hard register or if the address
4165       register appears in the source, we have to save the operand[2]
4166       value in a temporary location and then use that temp.
4167       Otherwise, it's ok and we generate a (set (D) (D)) that
4168       will result in a nop.  */
4169    if (H_REG_P (operands[2]))
4170      {
4171        operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4172        operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
4173        operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4174      }
4175    else if (reg_mentioned_p (operands[0], operands[2]))
4176      {
4177        operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4178        operands[6] = operands[2];
4179        operands[7] = operands[5];
4180      }
4181    else
4182      {
4183        operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4184        operands[7] = operands[2];
4185      }
4186   ")
4189 ;; Next split handles the logical operations on D register with
4190 ;; another hard register for the second operand.  For this, we
4191 ;; have to save the second operand in a scratch location and use
4192 ;; it instead.  This must be supported because in some (rare) cases
4193 ;; the second operand can come in a hard register and the reload
4194 ;; pass doesn't know how to reload it in a memory location.
4196 ;;      PLUS MINUS AND IOR XOR
4198 ;; The shift operators are special and must not appear here.
4200 (define_split
4201   [(set (match_operand:QI 0 "d_register_operand" "")
4202         (match_operator:QI 3 "m68hc11_non_shift_operator"
4203             [(match_operand:QI 1 "d_register_operand" "")
4204              (match_operand:QI 2 "hard_reg_operand" "")]))]
4205   "reload_completed"
4206   [(set (match_dup 5) (match_dup 6))
4207    (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4208   "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4209    operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4210    operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
4212 ;;--------------------------------------------------------------------
4213 ;; 8-bit Unary operations on X and Y:
4215 ;;              NOT NEG
4217 ;; Operations on X or Y registers are split here.  Instructions are
4218 ;; changed into:
4219 ;;   - xgdx/xgdy instruction pattern,
4220 ;;   - The same operation on register D,
4221 ;;   - xgdx/xgdy instruction pattern.
4222 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4223 ;; We also handle the case were the address register is used in both source
4224 ;; operands, such as:
4226 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4227 ;; or
4228 ;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4230 (define_split
4231   [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4232         (match_operator:QI 2 "m68hc11_unary_operator"
4233             [(match_operand:QI 1 "general_operand" "")]))]
4234   "z_replacement_completed == 2"
4235   [(set (match_dup 4) (match_dup 5))
4236    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4237               (set (match_dup 3) (reg:HI D_REGNUM))])
4238    (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4239    (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4240               (set (match_dup 3) (reg:HI D_REGNUM))])]
4241   "
4243   operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4244   if ((H_REG_P (operands[1])
4245        && !rtx_equal_p (operands[0], operands[1]))
4246       || reg_mentioned_p (operands[0], operands[1]))
4247     {
4248       /* Move to the destination register, before the xgdx.  */
4249       operands[4] = operands[0];
4250       operands[5] = operands[1];
4252       /* Apply the operation on D.  */
4253       operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4254     }
4255   else
4256     {
4257       operands[4] = operands[5] = operands[0];
4258       operands[6] = operands[1];
4259     }
4263 ;;--------------------------------------------------------------------
4264 ;;-  Complements
4265 ;;--------------------------------------------------------------------
4267 (define_expand "negdi2"
4268   [(set (match_operand:DI 0 "nonimmediate_operand" "")
4269         (neg:DI (match_operand:DI 1 "general_operand" "")))]
4270   ""
4271   "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4272    DONE;")
4275 (define_insn "negsi2"
4276   [(set (match_operand:SI 0 "register_operand" "=D")
4277         (neg:SI (match_operand:SI 1 "general_operand" "0")))]
4278   ""
4279   "*
4281   rtx ops[1];
4283   CC_STATUS_INIT;
4285   /* With -Os or without -O, use a special library call.  */
4286   if (optimize_size || optimize == 0)
4287     return \"bsr\\t___negsi2\";
4289   ops[0] = gen_label_rtx ();
4291   /* 32-bit complement and add 1.  */
4292   output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4293   output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4294   output_asm_insn (\"bne\\t%l0\", ops);
4295   output_asm_insn (\"inx\", operands);
4296   (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4297   return \"\";
4300 (define_insn "neghi2"
4301   [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
4302         (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4303   ""
4304   "@
4305    coma\\n\\tcomb\\n\\taddd\\t#1
4306    clra\\n\\tclrb\\n\\tsubd\\t%1
4307    xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4309 (define_insn "negqi2"
4310   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4311         (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
4312   ""
4313   "@
4314    negb
4315    neg\\t%b0
4316    neg\\t%b0
4317    #")
4320 ;; - 32-bit complement.  GCC knows how to translate them but providing a
4321 ;; pattern generates better/smaller code.
4323 (define_expand "one_cmpldi2"
4324   [(set (match_operand:DI 0 "nonimmediate_operand" "")
4325         (not:DI (match_operand:DI 1 "general_operand" "")))]
4326   ""
4327   "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4328    DONE;")
4330 (define_insn "one_cmplsi2"
4331   [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4332         (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4333    (clobber (match_scratch:HI 2 "=X,d,X"))]
4334   ""
4335   "@
4336    bsr\\t___one_cmplsi2
4337    #
4338    #")
4340 (define_insn "one_cmplhi2"
4341   [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
4342         (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
4343   ""
4344   "@
4345    comb\\n\\tcoma
4346    com\\t%b0\\n\\tcom\\t%h0
4347    #
4348    com\\t%b0\\n\\tcom\\t%h0")
4350 (define_insn "one_cmplqi2"
4351   [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
4352         (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
4353   ""
4354   "@
4355    comb
4356    com\\t%b0
4357    #
4358    com\\t%b0")
4360 (define_split /* "*one_cmplsi2" */
4361   [(set (match_operand:SI 0 "non_push_operand" "")
4362         (not:SI (match_dup 0)))
4363    (clobber (match_scratch:HI 1 ""))]
4364   "z_replacement_completed == 2
4365    && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4366   [(set (match_dup 2) (not:HI (match_dup 2)))
4367    (set (match_dup 3) (not:HI (match_dup 3)))]
4368   "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4369    operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
4371 (define_split /* "*one_cmplsi2" */
4372   [(set (match_operand:SI 0 "non_push_operand" "")
4373         (not:SI (match_operand:SI 1 "non_push_operand" "")))
4374    (clobber (match_operand:HI 2 "d_register_operand" ""))]
4375   "z_replacement_completed == 2
4376    && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4377   [(set (match_dup 2) (match_dup 3))
4378    (set (match_dup 2) (not:HI (match_dup 2)))
4379    (set (match_dup 4) (match_dup 2))
4380    (set (match_dup 2) (match_dup 5))
4381    (set (match_dup 2) (not:HI (match_dup 2)))
4382    (set (match_dup 6) (match_dup 2))]
4383   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4384    operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4385    operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4386    operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
4388 ;;--------------------------------------------------------------------
4389 ;;- arithmetic shifts
4390 ;;--------------------------------------------------------------------
4392 ;; Provide some 64-bit shift patterns. 
4393 (define_expand "ashldi3"
4394   [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4395                      (ashift:DI (match_operand:DI 1 "general_operand" "")
4396                                 (match_operand:HI 2 "general_operand" "")))
4397               (clobber (match_scratch:HI 3 ""))])]
4398    ""
4399    "
4401   if (GET_CODE (operands[2]) != CONST_INT 
4402       || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4403     {
4404       FAIL;
4405     }
4408 (define_insn_and_split "*ashldi3_const32"
4409   [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4410         (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4411                    (const_int 32)))
4412    (clobber (match_scratch:HI 2 "=&A,d,d"))]
4413    ""
4414    "#"
4415    "reload_completed"
4416    [(const_int 0)]
4417    "/* Move the lowpart in the highpart first in case the shift
4418        is applied on the source.  */
4419     if (IS_STACK_PUSH (operands[0]))
4420       {
4421          m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4422                              const0_rtx, operands[2]);
4424          /* Adjust first operand if it uses SP so that we take into
4425             account the above push.  Can occur only for 68HC12.  */
4426          if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
4427                               operands[1]))
4428            operands[1] = adjust_address (operands[1],
4429                                          GET_MODE (operands[0]), 4);
4430       }
4431     m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4432                         m68hc11_gen_lowpart (SImode, operands[1]),
4433                         operands[2]);
4434     if (!IS_STACK_PUSH (operands[0]))
4435       {
4436         m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4437                             const0_rtx, operands[2]);
4438       }
4439     DONE;")
4441 (define_insn_and_split "*ashldi3_const1"
4442   [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4443         (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4444                    (const_int 1)))
4445    (clobber (match_scratch:HI 2 "=d,d,d"))]
4446    ""
4447    "#"
4448    "z_replacement_completed == 2"
4449    [(set (match_dup 2) (match_dup 3))
4450     (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4451     (set (match_dup 4) (match_dup 2))
4453     (set (match_dup 2) (match_dup 5))
4454     (parallel [(set (match_dup 2)
4455                        (rotate:HI (match_dup 2) (const_int 1)))
4456                (clobber (reg:HI CC_REGNUM))])
4457     (set (match_dup 6) (match_dup 2))
4459     (set (match_dup 2) (match_dup 7))
4460     (parallel [(set (match_dup 2)
4461                        (rotate:HI (match_dup 2) (const_int 1)))
4462                (clobber (reg:HI CC_REGNUM))])
4463     (set (match_dup 8) (match_dup 2))
4465     (set (match_dup 2) (match_dup 9))
4466     (parallel [(set (match_dup 2)
4467                        (rotate:HI (match_dup 2) (const_int 1)))
4468                (clobber (reg:HI CC_REGNUM))])
4469     (set (match_dup 10) (match_dup 2))]
4470    "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4471     operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4472     operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4474     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4475     operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4476     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4478     operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4479     operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4480     operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4482     operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4483     operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4484     operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4486 (define_insn "addsi_silshr16"
4487   [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
4488           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
4489                                 (const_int 16))
4490                    (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
4491   ""
4492   "#")
4494 (define_split
4495   [(set (match_operand:SI 0 "register_operand" "")
4496           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4497                                 (const_int 16))
4498                    (match_operand:SI 2 "general_operand" "")))]
4499   "z_replacement_completed == 2 && !X_REG_P (operands[1])"
4500   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4501    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4502                                             (const_int 0))
4503                                    (reg:HI CC_REGNUM)))]
4504   "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4506 (define_split
4507   [(set (match_operand:SI 0 "register_operand" "")
4508           (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4509                                 (const_int 16))
4510                    (match_operand:SI 2 "general_operand" "")))]
4511   "z_replacement_completed == 2 && X_REG_P (operands[1])"
4512   [(set (reg:HI D_REGNUM) (match_dup 5))
4513    (set (reg:HI X_REGNUM) (match_dup 3))
4514    (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4515    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4516                                             (const_int 0))
4517                                    (reg:HI CC_REGNUM)))]
4518   "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4519    if (X_REG_P (operands[2]))
4520      {
4521        operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4522        operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4523      }
4524    else
4525      {
4526        operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4527        operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4528      }
4531 (define_insn "addsi_ashift16"
4532   [(set (match_operand:SI 0 "register_operand" "=D")
4533           (plus:SI 
4534                    (mult:SI (match_operand:SI 2 "general_operand" "uim")
4535                             (const_int 65536))
4536                 (match_operand:SI 1 "general_operand" "0")))
4537    (clobber (match_scratch:HI 3 "=X"))]
4538   "0"
4539   "#")
4541 (define_split
4542   [(set (match_operand:SI 0 "register_operand" "")
4543           (plus:SI 
4544                    (mult:SI (match_operand:SI 2 "general_operand" "")
4545                             (const_int 65536))
4546                    (match_operand:SI 1 "general_operand" "")))
4547    (clobber (match_scratch:HI 3 "=X"))]
4548   "0 && reload_completed && z_replacement_completed == 2"
4549   [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4550   "
4552   operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4555 (define_insn_and_split "addsi_andshr16"
4556   [(set (match_operand:SI 0 "register_operand" "=D")
4557           (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4558                            (const_int 65535))
4559                    (match_operand:SI 2 "general_operand" "0")))]
4560   ""
4561   "#"
4562   "z_replacement_completed == 2"
4563   [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4564    (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4565   "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4568 ;; 32-bit shifts are made by a small library routine that uses
4569 ;; a specific passing convention for parameters (for efficiency reasons).
4571 ;; [D + X] -> Value to be shifted
4572 ;; Y       -> Shift count
4574 ;; The shift count is clobbered by the routine.
4576 (define_expand "ashlsi3"
4577   [(parallel
4578        [(set (match_operand:SI 0 "register_operand" "") 
4579              (match_operand:SI 1 "general_operand" ""))
4580         (clobber (scratch:HI))])
4581    (parallel
4582      [(set (match_dup 0) (ashift:SI (match_dup 0)
4583                          (match_operand:HI 2 "nonmemory_operand" "")))
4584       (clobber (scratch:HI))])]
4585    ""
4586    "")
4588 (define_split
4589   [(set (match_operand:SI 0 "nonimmediate_operand" "")
4590         (ashift:SI (match_operand:SI 1 "general_operand" "")
4591                    (const_int 16)))
4592    (clobber (match_scratch:HI 3 ""))]
4593    ""
4594   [(set (match_dup 2) (match_dup 3))
4595    (set (match_dup 4) (const_int 0))]
4596    "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4597     operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4598     operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4600 (define_insn "*ashlsi3_const16"
4601   [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4602         (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4603                    (const_int 16)))
4604    (clobber (match_scratch:HI 2 "=X,X,X"))]
4605    ""
4606    "#")
4608 (define_insn_and_split "*ashlsi3_const16_zexthi"
4609   [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4610         (ashift:SI (zero_extend:HI 
4611                         (match_operand:HI 1 "general_operand" "duim*A"))
4612                    (const_int 16)))
4613    (clobber (match_scratch:HI 2 "=X"))]
4614    ""
4615    "#"
4616    "reload_completed"
4617    [(set (reg:HI X_REGNUM) (match_dup 1))
4618     (set (reg:HI D_REGNUM) (const_int 0))]
4619    "")
4621 (define_insn "*ashlsi3_const1"
4622   [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
4623         (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
4624                    (const_int 1)))
4625    (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
4626    ""
4627    "*
4629   CC_STATUS_INIT;
4630   if (X_REG_P (operands[1]))
4631     {
4632       return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4633     }
4634   else
4635     {
4636       rtx ops[2];
4638       ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4639       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4640       m68hc11_gen_movhi (insn, ops);
4641       output_asm_insn (\"lsld\", ops);
4642       if (!X_REG_P (operands[0]))
4643         {
4644           ops[1] = ops[0];
4645           ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4646           m68hc11_gen_movhi (insn, ops);
4647           ops[0] = ops[1];
4648           ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4649           m68hc11_gen_movhi (insn, ops);
4650         }
4651       else
4652         {
4653           /* Load the high part in X in case the source operand
4654              uses X as a memory pointer.  */
4655           ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4656           ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4657           m68hc11_gen_movhi (insn, ops);
4658           output_asm_insn (\"xgdx\", ops);
4659         }
4660       output_asm_insn (\"rolb\", ops);
4661       output_asm_insn (\"rola\", ops);
4662       if (!X_REG_P (operands[0]))
4663         {
4664           ops[1] = ops[0];
4665           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4666           m68hc11_gen_movhi (insn, ops);
4667         }
4668       else
4669         {
4670           output_asm_insn (\"xgdx\", ops);
4671         }
4672       return \"\";
4673     }
4676 (define_insn "*ashlsi3_const"
4677   [(set (match_operand:SI 0 "register_operand" "+D")
4678         (ashift:SI (match_dup 0)
4679                    (match_operand:HI 1 "const_int_operand" "")))
4680    (clobber (match_scratch:HI 2 "=y"))]
4681    "TARGET_M6811 /* See *ashlsi3 note.  */"
4682    "*
4684   CC_STATUS_INIT;
4685   return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4688 (define_insn "*ashlsi3"
4689   [(set (match_operand:SI 0 "register_operand" "+D,D")
4690         (ashift:SI (match_dup 0)
4691                    (match_operand:HI 1 "general_operand" "y,mi")))
4692    (clobber (match_scratch:HI 2 "=1,X"))]
4693    ""
4694    "*
4696   CC_STATUS_INIT;
4698   /* There is a reload problem if we don't accept 'm' for the shift value.
4699      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4700      and this conflicts with all reloads.  Since X, Y, Z are used there
4701      is not enough register in class A_REGS.
4703      Assuming that 'operands[1]' does not refer to the stack (which 
4704      is true for 68hc11 only, we save temporary the value of Y.
4706      For 68HC12 we must also accept a constant because Z register is
4707      disabled when compiling with -fomit-frame-pointer.  We can come up
4708      with a reload problem and the *lshrsi3_const pattern was disabled
4709      for that reason.  */
4710   if (!Y_REG_P (operands[2]))
4711     {
4712       rtx ops[1];
4713       int y_dead = dead_register_here (insn, iy_reg);
4715       ops[0] = operands[1];
4716       if (y_dead == 0)
4717         {
4718           output_asm_insn (\"pshy\", operands);
4719           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4720             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4721         }
4722       output_asm_insn (\"ldy\\t%0\", ops);
4723       output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4724       return y_dead == 0 ? \"puly\" : \"\";
4725     }
4726   return \"bsr\\t___ashlsi3\";
4729 (define_expand "ashlhi3"
4730   [(set (match_operand:HI 0 "register_operand" "")
4731         (ashift:HI (match_operand:HI 1 "register_operand" "")
4732                    (match_operand:HI 2 "general_operand" "")))]
4733    ""
4734    "
4736   if (GET_CODE (operands[2]) != CONST_INT) 
4737     {
4738       rtx scratch = gen_reg_rtx (HImode);
4739       emit_move_insn (scratch, operands[2]);
4740       emit_insn (gen_rtx_PARALLEL (VOIDmode,
4741                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
4742                             operand0,
4743                             gen_rtx_ASHIFT (HImode,
4744                                         operand1, scratch)),
4745                               gen_rtx_CLOBBER (VOIDmode, scratch))));
4746       DONE;
4747     }
4750 (define_insn "*ashlhi3_const1"
4751   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4752         (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4753                    (const_int 1)))]
4754   ""
4755   "*
4757   if (A_REG_P (operands[0]))
4758     return \"#\";
4760   if (D_REG_P (operands[0]))
4761     {
4762       return \"asld\";
4763     }
4764   
4765   output_asm_insn (\"asl\\t%b0\", operands);
4766   output_asm_insn (\"rol\\t%h0\", operands);
4767   CC_STATUS_INIT;
4768   return \"\";
4772 (define_insn "*ashlhi3_2"
4773   [(set (match_operand:HI 0 "register_operand" "=d,*x")
4774         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4775                    (match_operand:HI 2 "register_operand" "+x,+d")))
4776    (clobber (match_dup 2))]
4777   ""
4778   "*
4780   if (A_REG_P (operands[0]))
4781     return \"#\";
4783   CC_STATUS_INIT;
4784   return \"bsr\\t___lshlhi3\";
4787 (define_insn "*ashlhi3"
4788   [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4789         (ashift:HI (match_dup 0)
4790                    (match_operand:HI 1 "register_operand" "+x")))
4791    (clobber (match_dup 1))]
4792   ""
4793   "*
4795   CC_STATUS_INIT;
4796   return \"bsr\\t___lshlhi3\";
4799 (define_insn "*ashlhi3"
4800   [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4801         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4802                    (match_operand:HI 2 "const_int_operand" "")))]
4803   ""
4804   "*
4806   int   i;
4808   if (A_REG_P (operands[0]))
4809     return \"#\";
4811   i = INTVAL (operands[2]);
4812   if (i >= 8)
4813     {
4814       CC_STATUS_INIT;
4815       output_asm_insn (\"tba\", operands);
4816       if (i == 15)
4817         {
4818           output_asm_insn (\"rora\", operands);
4819           output_asm_insn (\"anda\\t#0\", operands);
4820           output_asm_insn (\"rora\", operands);
4821         }
4822       else
4823         while (i != 8 )
4824           {
4825             output_asm_insn (\"asla\", operands);
4826             i--;
4827           }
4828       return \"clrb\";
4829     }
4830   for (i = 0; i < INTVAL (operands[2]) - 1; i++) 
4831     {
4832       output_asm_insn (\"asld\", operands);
4833     }
4834   return \"asld\";
4837 (define_expand "ashlqi3"
4838   [(set (match_operand:QI 0 "register_operand" "")
4839         (ashift:QI (match_operand:QI 1 "register_operand" "")
4840                    (match_operand:QI 2 "general_operand" "")))]
4841    ""
4842    "")
4844 (define_insn "*ashlqi3_const1"
4845   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4846         (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4847                    (const_int 1)))]
4848   ""
4849   "@
4850    aslb
4851    asl\\t%b0
4852    asl\\t%b0
4853    asl%0
4854    #")
4856 (define_insn "*ashlqi3_const"
4857   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4858         (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4859                    (match_operand:QI 2 "const_int_operand" "")))]
4860   ""
4861   "*
4863   int i;
4864   const char* insn_code;
4866   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4867     insn_code = \"aslb\";
4868   else if (DA_REG_P (operands[0]))
4869     insn_code = \"asla\";
4870   else
4871     return \"#\";
4873   i = INTVAL (operands[2]);
4874   if (i >= 8)
4875     {
4876       if (DA_REG_P (operands[0]))
4877         return \"clra\";
4878       else
4879         return \"clrb\";
4880     }
4881   else if (i == 7)
4882     {
4883       if (DA_REG_P (operands[0]))
4884         {
4885           output_asm_insn (\"rora\", operands);
4886           output_asm_insn (\"ldaa\\t#0\", operands);
4887           return \"rora\";
4888         }
4889       else
4890         {
4891           output_asm_insn (\"rorb\", operands);
4892           output_asm_insn (\"ldab\\t#0\", operands);
4893           return \"rorb\";
4894         }
4895     }
4896   else if (i == 6)
4897     {
4898       if (DA_REG_P (operands[0]))
4899         {
4900           output_asm_insn (\"rora\", operands);
4901           output_asm_insn (\"rora\", operands);
4902           output_asm_insn (\"rora\", operands);
4903           return \"anda\\t#0xC0\";
4904         }
4905       else
4906         {
4907           output_asm_insn (\"rorb\", operands);
4908           output_asm_insn (\"rorb\", operands);
4909           output_asm_insn (\"rorb\", operands);
4910           return \"andb\\t#0xC0\";
4911         }
4912     }
4913   while (--i >= 0)
4914     {
4915       output_asm_insn (insn_code, operands);
4916     }
4917   return \"\";
4920 (define_insn "*ashlqi3"
4921   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4922         (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4923                      (match_operand:QI 2 "nonimmediate_operand" 
4924                                          "m*u*d*A,m*u*d*A,m*u")))]
4925   ""
4926   "*
4928   rtx ops[2];
4930   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4931     return \"#\";
4933   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
4934   ops[1] = operands[2];
4935   m68hc11_gen_movqi (insn, ops);
4937   CC_STATUS_INIT;
4938   return \"bsr\\t___lshlqi3\";
4941 (define_expand "ashrhi3"
4942   [(set (match_operand:HI 0 "register_operand" "")
4943         (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4944                      (match_operand:HI 2 "general_operand" "")))]
4945    ""
4946    "
4948   if (GET_CODE (operands[2]) != CONST_INT) 
4949     {
4950       rtx scratch = gen_reg_rtx (HImode);
4952       emit_move_insn (scratch, operands[2]);
4953       emit_insn (gen_rtx_PARALLEL (VOIDmode,
4954                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
4955                                 operand0,
4956                                 gen_rtx_ASHIFTRT (HImode,
4957                                         operand1, scratch)),
4958                               gen_rtx_CLOBBER (VOIDmode, scratch))));
4959        DONE;
4960     }
4963 (define_insn "*ashrhi3_const1"
4964   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4965         (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4966                      (const_int 1)))]
4967   ""
4968   "*
4970   if (A_REG_P (operands[0]))
4971     return \"#\";
4973   CC_STATUS_INIT;
4974   if (D_REG_P (operands[0]))
4975     {
4976       return \"asra\\n\\trorb\";
4977     }
4978   
4979   output_asm_insn (\"asr\\t%h0\", operands);
4980   output_asm_insn (\"ror\\t%b0\", operands);
4981   return \"\";
4985 (define_insn "*ashrhi3_const"
4986   [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4987         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4988                      (match_operand:HI 2 "const_int_operand" "")))]
4989   ""
4990   "*
4992   rtx ops[2];
4993   int val = INTVAL (operands[2]);
4995   if (A_REG_P (operands[0]))
4996     return \"#\";
4998   if (val >= 15)
4999     {
5000       ops[0] = gen_label_rtx ();
5002       output_asm_insn (\"clrb\", operands);
5003       output_asm_insn (\"rola\", operands);
5005         /* Clear A without clearing the carry flag.  */
5006       output_asm_insn (\"tba\", operands);
5007       output_asm_insn (\"bcc\\t%l0\", ops);
5008       output_asm_insn (\"coma\", operands);
5009       output_asm_insn (\"comb\", operands);
5011       CC_STATUS_INIT;
5012       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5013                                  CODE_LABEL_NUMBER (ops[0]));
5014       return \"\";
5015     }
5016   if (val >= 8)
5017     {
5018       ops[0] = gen_label_rtx ();
5020       output_asm_insn (\"tab\", operands);
5021       output_asm_insn (\"clra\", operands);
5022       output_asm_insn (\"tstb\", operands);
5023       output_asm_insn (\"bge\\t%l0\", ops);
5024       output_asm_insn (\"deca\", operands);
5026       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5027                                  CODE_LABEL_NUMBER (ops[0]));
5029       val -= 8;
5031       while (val > 0)
5032         {
5033           output_asm_insn (\"asrb\", operands);
5034           val--;
5035         }
5036         /* Status is ok.  */
5037       return \"\";
5038     }
5039   if (val == 7)
5040     {
5041       ops[0] = gen_label_rtx ();
5042       output_asm_insn (\"rolb\", operands);
5043       output_asm_insn (\"rola\", operands);
5044       output_asm_insn (\"tab\", operands);
5045       output_asm_insn (\"anda\\t#0\", operands);
5046       output_asm_insn (\"bcc\\t%l0\", ops);
5047       output_asm_insn (\"coma\", ops);
5049       (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5050                                  CODE_LABEL_NUMBER (ops[0]));
5051       return \"\";
5052     }
5053   while (val > 0)
5054     {
5055       output_asm_insn (\"asra\", operands);
5056       output_asm_insn (\"rorb\", operands);
5057       val--;
5058     }
5059   CC_STATUS_INIT;
5061   return \"\";
5064 (define_insn "*ashrhi3"
5065   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5066         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5067                      (match_operand:HI 2 "register_operand" "+x,+d")))
5068    (clobber (match_dup 2))]
5069   ""
5070   "*
5072   if (A_REG_P (operands[0]))
5073     return \"#\";
5075   output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5076   return \"\"; 
5079 (define_expand "ashrsi3"
5080   [(parallel
5081        [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5082         (clobber (scratch:HI))])
5083    (parallel
5084        [(set (match_operand:SI 0 "register_operand" "")
5085                 (ashiftrt:SI (match_dup 0)
5086                              (match_operand:HI 2 "general_operand" "")))
5087         (clobber (scratch:HI))])]
5088    ""
5089    "")
5091 (define_insn "*ashrsi3_const"
5092   [(set (match_operand:SI 0 "register_operand" "+D")
5093         (ashiftrt:SI (match_dup 0)
5094                      (match_operand:HI 1 "const_int_operand" "")))
5095    (clobber (match_scratch:HI 2 "=y"))]
5096    "TARGET_M6811 /* See *ashrsi3 note.  */"
5097    "*
5099   CC_STATUS_INIT;
5100   return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
5103 (define_insn "*ashrsi3"
5104   [(set (match_operand:SI 0 "register_operand" "+D,D")
5105         (ashiftrt:SI (match_dup 0)
5106                      (match_operand:HI 1 "general_operand" "y,mi")))
5107    (clobber (match_scratch:HI 2 "=1,X"))]
5108    ""
5109    "*
5111   CC_STATUS_INIT;
5112   /* There is a reload problem if we don't accept 'm' for the shift value.
5113      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5114      and this conflicts with all reloads.  Since X, Y, Z are used there
5115      is not enough register in class A_REGS.
5117      Assuming that 'operands[1]' does not refer to the stack (which 
5118      is true for 68hc11 only, we save temporary the value of Y.
5120      For 68HC12 we must also accept a constant because Z register is
5121      disabled when compiling with -fomit-frame-pointer.  We can come up
5122      with a reload problem and the *lshrsi3_const pattern was disabled
5123      for that reason.  */
5124   if (!Y_REG_P (operands[2]))
5125     {
5126       rtx ops[1];
5127       int y_dead = dead_register_here (insn, iy_reg);
5129       ops[0] = operands[1];
5130       if (y_dead == 0)
5131         {
5132           output_asm_insn (\"pshy\", operands);
5133           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5134             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5135         }
5136       output_asm_insn (\"ldy\\t%0\", ops);
5137       output_asm_insn (\"bsr\\t___ashrsi3\", operands);
5138       return y_dead == 0 ? \"puly\" : \"\";
5139     }
5140   return \"bsr\\t___ashrsi3\";
5143 (define_expand "ashrqi3"
5144   [(set (match_operand:QI 0 "register_operand" "")
5145         (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5146                      (match_operand:QI 2 "general_operand" "")))]
5147    ""
5148    "")
5150 (define_insn "*ashrqi3_const1"
5151   [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5152         (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5153                      (const_int 1)))]
5154   ""
5155   "@
5156    asrb
5157    asr\\t%b0
5158    asr\\t%b0
5159    asr%0
5160    #")
5162 (define_insn "*ashrqi3_const"
5163   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5164         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5165                      (match_operand:QI 2 "const_int_operand" "")))]
5166   ""
5167   "*
5169   int i;
5170   const char* insn_code;
5172   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5173     insn_code = \"asrb\";
5174   else if (DA_REG_P (operands[0]))
5175     insn_code = \"asra\";
5176   else
5177     return \"#\";
5179   i = INTVAL (operands[2]);
5180   if (i > 8)
5181     i = 8;
5182   while (--i >= 0)
5183     {
5184       output_asm_insn (insn_code, operands);
5185     }
5186   return \"\";
5189 (define_insn "*ashrqi3"
5190   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5191         (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5192                      (match_operand:QI 2 "nonimmediate_operand" 
5193                                          "m*u*d*A,m*u*d*A,m*u")))]
5194   ""
5195   "*
5197   rtx ops[2];
5199   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5200     return \"#\";
5202   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5203   ops[1] = operands[2];
5204   m68hc11_gen_movqi (insn, ops);
5206   CC_STATUS_INIT;
5207   return \"bsr\\t___ashrqi3\";
5210 ;;--------------------------------------------------------------------
5211 ;; logical shift instructions
5212 ;;--------------------------------------------------------------------
5213 (define_expand "lshrdi3"
5214   [(parallel [(set (match_operand:DI 0 "general_operand" "")
5215                      (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5216                                   (match_operand:HI 2 "general_operand" "")))
5217               (clobber (match_scratch:HI 3 ""))])]
5218    ""
5219    "
5221   if (GET_CODE (operands[2]) != CONST_INT 
5222      || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5223          && INTVAL (operands[2]) != 1))
5224     {
5225       FAIL;
5226     }
5229 (define_insn_and_split "*lshrdi3_const32"
5230   [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5231         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
5232                      (const_int 32)))
5233    (clobber (match_scratch:HI 2 "=&A,d,d"))]
5234    ""
5235    "#"
5236    "reload_completed"
5237    [(const_int 0)]
5238    "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5239                         m68hc11_gen_highpart (SImode, operands[1]),
5240                         operands[2]);
5241     m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5242                         const0_rtx, operands[2]);
5243     DONE;")
5245 (define_insn "*lshrdi3_const63"
5246   [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5247         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5248                      (match_operand:DI 2 "const_int_operand" "")))
5249    (clobber (match_scratch:HI 3 "=d,d"))]
5250    "INTVAL (operands[2]) >= 48"
5251    "#")
5253 (define_split
5254   [(set (match_operand:DI 0 "nonimmediate_operand" "")
5255         (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5256                      (match_operand:DI 2 "const_int_operand" "")))
5257    (clobber (match_scratch:HI 3 "=d"))]
5258    "z_replacement_completed && INTVAL (operands[2]) >= 56"
5259    [(set (reg:QI D_REGNUM) (match_dup 9))
5260     (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5261     (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5262     (set (match_dup 4) (reg:HI D_REGNUM))
5263     (set (reg:QI D_REGNUM) (const_int 0))
5264     (set (match_dup 5) (reg:HI D_REGNUM))
5265     (set (match_dup 6) (reg:HI D_REGNUM))
5266     (set (match_dup 7) (reg:HI D_REGNUM))]
5267    "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
5268     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5269     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5270     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5272     operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5273     operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5274     operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5276     operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5277     operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5278     operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5280 (define_split
5281   [(set (match_operand:DI 0 "nonimmediate_operand" "")
5282         (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5283                      (match_operand:DI 2 "const_int_operand" "")))
5284    (clobber (match_scratch:HI 3 "=d"))]
5285    "z_replacement_completed && INTVAL (operands[2]) >= 48 
5286     && INTVAL (operands[2]) < 56"
5287    [(set (reg:HI D_REGNUM) (match_dup 9))
5288     (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5289     (set (match_dup 4) (reg:HI D_REGNUM))
5290     (set (reg:HI D_REGNUM) (const_int 0))
5291     (set (match_dup 5) (reg:HI D_REGNUM))
5292     (set (match_dup 6) (reg:HI D_REGNUM))
5293     (set (match_dup 7) (reg:HI D_REGNUM))]
5294    "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
5295     operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5296     operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5297     operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5299     operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5300     operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5301     operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5302     operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5303     operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5305 (define_insn_and_split "*lshrdi_const1"
5306   [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5307         (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5308                      (const_int 1)))
5309    (clobber (match_scratch:HI 2 "=d,d"))]
5310    ""
5311    "#"
5312    "z_replacement_completed == 2"
5313    [(set (match_dup 2) (match_dup 3))
5314     (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5315     (set (match_dup 4) (match_dup 2))
5317     (set (match_dup 2) (match_dup 5))
5318     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5319                (clobber (reg:HI CC_REGNUM))])
5320     (set (match_dup 6) (match_dup 2))
5322     (set (match_dup 2) (match_dup 7))
5323     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5324                (clobber (reg:HI CC_REGNUM))])
5325     (set (match_dup 8) (match_dup 2))
5327     (set (match_dup 2) (match_dup 9))
5328     (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5329                (clobber (reg:HI CC_REGNUM))])
5330     (set (match_dup 10) (match_dup 2))]
5331    "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5332     operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5333     operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5335     operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5336     operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5337     operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5339     operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5340     operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5341     operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5343     operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5344     operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5345     operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5347 (define_expand "lshrsi3"
5348   [(parallel
5349        [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5350         (clobber (scratch:HI))])
5351    (parallel
5352        [(set (match_operand:SI 0 "register_operand" "")
5353              (lshiftrt:SI (match_dup 0)
5354                           (match_operand:HI 2 "general_operand" "")))
5355         (clobber (scratch:HI))])]
5356    ""
5357    "")
5359 (define_split
5360   [(set (match_operand:SI 0 "non_push_operand" "")
5361         (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
5362                      (const_int 16)))
5363    (clobber (match_scratch:HI 3 ""))]
5364    "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5365   [(set (match_dup 2) (match_dup 3))
5366    (set (match_dup 4) (const_int 0))]
5367    "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5368     operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5369     operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5371 (define_insn "*lshrsi3_const16"
5372   [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5373         (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
5374                      (const_int 16)))
5375    (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5376    ""
5377    "@
5378     #
5379     xgdx\\n\\tldx\\t#0
5380     #
5381     #")
5383 (define_insn "*lshrsi3_const1"
5384   [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
5385         (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
5386                      (const_int 1)))
5387    (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
5388    ""
5389    "*
5391   CC_STATUS_INIT;
5392   if (X_REG_P (operands[1]))
5393     {
5394       return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5395     }
5396   else
5397     {
5398       rtx ops[2];
5400       ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5401       ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
5402       m68hc11_gen_movhi (insn, ops);
5403       output_asm_insn (\"lsrd\", ops);
5404       if (!X_REG_P (operands[0]))
5405         {
5406           ops[1] = ops[0];
5407           ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5408           m68hc11_gen_movhi (insn, ops);
5409           ops[0] = ops[1];
5410           ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5411           m68hc11_gen_movhi (insn, ops);
5412         }
5413       else
5414         {
5415           /* Load the lowpart in X in case the operands is some N,x.  */
5416           ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
5417           ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5418           m68hc11_gen_movhi (insn, ops);
5419           output_asm_insn (\"xgdx\", ops);
5420         }
5421       output_asm_insn (\"rora\", ops);
5422       output_asm_insn (\"rorb\", ops);
5423       if (!X_REG_P (operands[0]))
5424         {
5425           ops[1] = ops[0];
5426           ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5427           m68hc11_gen_movhi (insn, ops);
5428         }
5429       return \"\";
5430     }
5433 (define_insn "*lshrsi3_const"
5434   [(set (match_operand:SI 0 "register_operand" "+D")
5435         (lshiftrt:SI (match_dup 0)
5436                      (match_operand:HI 1 "const_int_operand" "")))
5437    (clobber (match_scratch:HI 2 "=y"))]
5438    "TARGET_M6811 /* See *lshrsi3 note.  */"
5439    "*
5441   CC_STATUS_INIT;
5442   return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5445 (define_insn "*lshrsi3"
5446   [(set (match_operand:SI 0 "register_operand" "+D,D")
5447         (lshiftrt:SI (match_dup 0)
5448                      (match_operand:HI 1 "general_operand" "y,mi")))
5449    (clobber (match_scratch:HI 2 "=1,X"))]
5450    ""
5451    "*
5453   CC_STATUS_INIT;
5454   /* There is a reload problem if we don't accept 'm' for the shift value.
5455      A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5456      and this conflicts with all reloads.  Since X, Y, Z are used there
5457      is not enough register in class A_REGS.
5459      Assuming that 'operands[1]' does not refer to the stack (which 
5460      is true for 68hc11 only, we save temporary the value of Y.
5462      For 68HC12 we must also accept a constant because Z register is
5463      disabled when compiling with -fomit-frame-pointer.  We can come up
5464      with a reload problem and the *lshrsi3_const pattern was disabled
5465      for that reason.  */
5466   if (!Y_REG_P (operands[2]))
5467     {
5468       rtx ops[1];
5469       int y_dead = dead_register_here (insn, iy_reg);
5471       ops[0] = operands[1];
5472       if (y_dead == 0)
5473         {
5474           output_asm_insn (\"pshy\", operands);
5475           if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5476             ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5477         }
5478       output_asm_insn (\"ldy\\t%0\", ops);
5479       output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5480       return y_dead == 0 ? \"puly\" : \"\";
5481     }
5482   return \"bsr\\t___lshrsi3\";
5485 (define_expand "lshrhi3"
5486   [(set (match_operand:HI 0 "register_operand" "")
5487         (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5488                      (match_operand:HI 2 "general_operand" "")))]
5489    ""
5490    "
5492   if (GET_CODE (operands[2]) != CONST_INT)
5493     {
5494       rtx scratch = gen_reg_rtx (HImode);
5495       operand1 = force_reg (HImode, operand1);
5497       emit_move_insn (scratch, operands[2]);
5498       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5499                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5500                                         operand0,
5501                                         gen_rtx_LSHIFTRT (HImode,
5502                                                 operand1, scratch)),
5503                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5504      DONE;
5505   }
5508 (define_insn "lshrhi3_const1"
5509   [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5510         (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5511                      (const_int 1)))]
5512   ""
5513   "*
5515   if (A_REG_P (operands[0]))
5516     return \"#\";
5518   if (D_REG_P (operands[0]))
5519     return \"lsrd\";
5521   CC_STATUS_INIT;
5522   return \"lsr\\t%h0\\n\\tror\\t%b0\";
5525 (define_insn "lshrhi3_const"
5526   [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5527         (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5528                      (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5529   ""
5530   "*
5532   int val = INTVAL (operands[2]);
5534   if (A_REG_P (operands[0]))
5535     return \"#\";
5537   if (val >= 8)
5538     {
5539       if (val == 8)
5540         CC_STATUS_INIT;
5542       if (!H_REG_P (operands[1]))
5543         {
5544           output_asm_insn (\"clra\", operands);
5545           output_asm_insn (\"ldab\\t%h1\", operands);
5546         }
5547       else if (A_REG_P (operands[1]))
5548         {
5549           output_asm_insn (\"st%1\\t%t0\", operands);
5550           output_asm_insn (\"ldab\\t%t0\", operands);
5551           output_asm_insn (\"clra\", operands);
5552         }
5553       else
5554         {
5555           output_asm_insn (\"tab\", operands);
5556           output_asm_insn (\"clra\", operands);
5557         }
5558       val -= 8;
5559       switch (val) 
5560         {
5561         case 7:
5562           output_asm_insn (\"rolb\", operands);
5563           output_asm_insn (\"tab\", operands);
5564           output_asm_insn (\"rolb\", operands);
5565           break;
5567         case 6:
5568           output_asm_insn (\"rolb\", operands);
5569           output_asm_insn (\"rolb\", operands);
5570           output_asm_insn (\"rolb\", operands);
5571           output_asm_insn (\"andb\\t#3\", operands);
5572           break;
5574         default:
5575            while (val > 0)
5576              {
5577                 val --;
5578                 output_asm_insn (\"lsrb\", operands);
5579              }
5580            break;
5581         }
5582       return \"\";
5583     }
5585   if (!D_REG_P (operands[1]))
5586     m68hc11_gen_movhi (insn, operands);
5587   switch (val)
5588     {
5589     case 7:
5590       output_asm_insn (\"rolb\", operands);
5591       output_asm_insn (\"tab\", operands);
5592       output_asm_insn (\"rolb\", operands);
5593       output_asm_insn (\"rola\", operands);
5594       output_asm_insn (\"rola\", operands);
5595       output_asm_insn (\"anda\\t#1\", operands);
5596       CC_STATUS_INIT;
5597       break;
5599     default:
5600       while (val > 0) 
5601         {
5602           val --;
5603           output_asm_insn (\"lsrd\", operands);
5604         }
5605      }
5606   return \"\";
5609 (define_insn "*lshrhi3"
5610   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5611         (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5612                      (match_operand:HI 2 "register_operand" "+x,+d")))
5613    (clobber (match_dup 2))]
5614   ""
5615   "*
5617   if (A_REG_P (operands[0]))
5618     return \"#\";
5620   return \"bsr\\t___lshrhi3\";
5623 (define_expand "lshrqi3"
5624   [(set (match_operand:QI 0 "register_operand" "")
5625         (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5626                      (match_operand:QI 2 "general_operand" "")))]
5627    ""
5628    "")
5630 (define_insn "*lshrqi3_const1"
5631   [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5632         (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5633                      (const_int 1)))]
5634   ""
5635   "@
5636    lsr\\t%b0
5637    lsrb
5638    lsr\\t%b0
5639    lsr%0
5640    #")
5642 (define_insn "*lshrqi3_const"
5643   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5644         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5645                      (match_operand:QI 2 "const_int_operand" "")))]
5646   ""
5647   "*
5649   int i;
5650   const char* insn_code;
5652   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5653     insn_code = \"lsrb\";
5654   else if (DA_REG_P (operands[0]))
5655     insn_code = \"lsra\";
5656   else
5657     return \"#\";
5659   i = INTVAL (operands[2]);
5660   if (i >= 8)
5661     {
5662       if (DA_REG_P (operands[0]))
5663         return \"clra\";
5664       else
5665         return \"clrb\";
5666     }
5667   else if (i == 7)
5668     {
5669       if (DA_REG_P (operands[0]))
5670         {
5671           output_asm_insn (\"rola\", operands);
5672           output_asm_insn (\"ldaa\\t#0\", operands);
5673           return \"rola\";
5674         }
5675       else
5676         {
5677           output_asm_insn (\"rolb\", operands);
5678           output_asm_insn (\"ldab\\t#0\", operands);
5679           return \"rolb\";
5680         }
5681     }
5682   else if (i == 6)
5683     {
5684       if (DA_REG_P (operands[0]))
5685         {
5686           output_asm_insn (\"rola\", operands);
5687           output_asm_insn (\"rola\", operands);
5688           output_asm_insn (\"rola\", operands);
5689           return \"anda\\t#3\";
5690         }
5691       else
5692         {
5693           output_asm_insn (\"rolb\", operands);
5694           output_asm_insn (\"rolb\", operands);
5695           output_asm_insn (\"rolb\", operands);
5696           return \"andb\\t#3\";
5697         }
5698     }
5699   while (--i >= 0)
5700     {
5701       output_asm_insn (insn_code, operands);
5702     }
5703   return \"\";
5706 (define_insn "*lshrqi3"
5707   [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5708         (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5709                      (match_operand:QI 2 "nonimmediate_operand" 
5710                                          "m*u*d*A,m*u*d*A,m*u")))]
5711   ""
5712   "*
5714   rtx ops[2];
5716   if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5717     return \"#\";
5719   CC_STATUS_INIT;
5720   ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5721   ops[1] = operands[2];
5722   m68hc11_gen_movqi (insn, ops);
5724   if (!optimize || optimize_size)
5725     {
5726       return \"bsr\\t___lshrqi3\";
5727     }
5729   ops[0] = gen_label_rtx ();
5730   ops[1] = gen_label_rtx ();
5731   output_asm_insn (\"ble\\t%l1\", ops);
5733   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5734                              CODE_LABEL_NUMBER (ops[0]));
5736   output_asm_insn (\"lsrb\", operands);
5737   output_asm_insn (\"deca\", operands);
5738   output_asm_insn (\"bne\\t%l0\", ops);
5740   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5741                              CODE_LABEL_NUMBER (ops[1]));
5742   return \"\";
5745 (define_insn "*rotlqi3_with_carry"
5746   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5747         (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5748                    (reg:QI CC_REGNUM)))]
5749   ""
5750   "*
5752   if (DA_REG_P (operands[0]))
5753     return \"rola\";
5754   else
5755     return \"rolb\";
5758 (define_insn "*rotlhi3_with_carry"
5759   [(set (match_operand:HI 0 "register_operand" "=d")
5760         (rotate:HI (match_operand:HI 1 "register_operand" "0")
5761                    (const_int 1)))
5762    (clobber (reg:HI CC_REGNUM))]
5763   ""
5764   "*
5766   CC_STATUS_INIT;
5767   return \"rolb\\n\\trola\";
5770 (define_insn "*rotrhi3_with_carry"
5771   [(set (match_operand:HI 0 "register_operand" "=d")
5772         (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5773                      (const_int 1)))
5774    (clobber (reg:HI CC_REGNUM))]
5775   ""
5776   "*
5778   CC_STATUS_INIT;
5779   return \"rora\\n\\trorb\";
5782 (define_insn "rotlqi3"
5783   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5784         (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5785                    (match_operand:QI 2 "const_int_operand" "i,i")))]
5786   ""
5787   "*
5789   m68hc11_gen_rotate (ROTATE, insn, operands);
5790   return \"\";
5793 (define_insn "rotrqi3"
5794   [(set (match_operand:QI 0 "register_operand" "=d,!q")
5795         (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5796                      (match_operand:QI 2 "const_int_operand" "i,i")))]
5797   ""
5798   "*
5800   m68hc11_gen_rotate (ROTATERT, insn, operands);
5801   return \"\";
5804 (define_expand "rotlhi3"
5805   [(set (match_operand:HI 0 "register_operand" "")
5806         (rotate:HI (match_operand:HI 1 "register_operand" "")
5807                    (match_operand:HI 2 "general_operand" "")))]
5808    ""
5809    "
5811   if (GET_CODE (operands[2]) != CONST_INT)
5812     {
5813       rtx scratch = gen_reg_rtx (HImode);
5814       operand1 = force_reg (HImode, operand1);
5816       emit_move_insn (scratch, operands[2]);
5817       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5818                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5819                                         operand0,
5820                                         gen_rtx_ROTATE (HImode,
5821                                                 operand1, scratch)),
5822                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5823       DONE;
5824     }
5827 (define_insn "rotlhi3_const"
5828   [(set (match_operand:HI 0 "register_operand" "=d")
5829         (rotate:HI (match_operand:HI 1 "register_operand" "0")
5830                    (match_operand:HI 2 "const_int_operand" "i")))]
5831   ""
5832   "*
5834   m68hc11_gen_rotate (ROTATE, insn, operands);
5835   return \"\";
5838 (define_insn "*rotlhi3"
5839   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5840         (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
5841                    (match_operand:HI 2 "general_operand" "+x,+d")))
5842    (clobber (match_dup 2))]
5843   ""
5844   "*
5846   if (A_REG_P (operands[0]))
5847     return \"#\";
5849   return \"bsr\\t___rotlhi3\";
5852 (define_expand "rotrhi3"
5853   [(set (match_operand:HI 0 "register_operand" "")
5854         (rotatert:HI (match_operand:HI 1 "general_operand" "")
5855                      (match_operand:HI 2 "general_operand" "")))]
5856    ""
5857    "
5859   if (GET_CODE (operands[2]) != CONST_INT)
5860     {
5861       rtx scratch = gen_reg_rtx (HImode);
5862       operand1 = force_reg (HImode, operand1);
5864       emit_move_insn (scratch, operands[2]);
5865       emit_insn (gen_rtx_PARALLEL (VOIDmode,
5866                  gen_rtvec (2, gen_rtx_SET (VOIDmode,
5867                                         operand0,
5868                                         gen_rtx_ROTATERT (HImode,
5869                                                 operand1, scratch)),
5870                               gen_rtx_CLOBBER (VOIDmode, scratch))));
5871       DONE;
5872     }
5875 (define_insn "rotrhi3_const"
5876   [(set (match_operand:HI 0 "register_operand" "=d")
5877         (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5878                      (match_operand:HI 2 "const_int_operand" "i")))]
5879   ""
5880   "*
5882   m68hc11_gen_rotate (ROTATERT, insn, operands);
5883   return \"\";
5886 (define_insn "*rotrhi3"
5887   [(set (match_operand:HI 0 "register_operand" "=d,*x")
5888         (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
5889                      (match_operand:HI 2 "general_operand" "+x,+d")))
5890    (clobber (match_dup 2))]
5891   ""
5892   "*
5894   if (A_REG_P (operands[0]))
5895     return \"#\";
5897   return \"bsr\\t___rotrhi3\";
5900 ;; Split a shift operation on an address register in a shift
5901 ;; on D_REGNUM.
5902 (define_split /* "*rotrhi3_addr" */
5903   [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
5904         (match_operator:HI 3 "m68hc11_shift_operator"
5905             [(match_operand:HI 1 "register_operand" "")
5906              (match_operand:HI 2 "register_operand" "")]))
5907    (clobber (match_dup 2))]
5908   "z_replacement_completed == 2"
5909   [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5910               (set (match_dup 0) (reg:HI D_REGNUM))])
5911    (parallel [(set (reg:HI D_REGNUM) 
5912                    (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
5913               (clobber (match_dup 0))])
5914    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5915               (set (match_dup 0) (reg:HI D_REGNUM))])]
5916   "")
5918 ;;--------------------------------------------------------------------
5919 ;;-  68HC12 Decrement/Increment and branch
5920 ;;--------------------------------------------------------------------
5921 ;; These patterns are used by loop optimization as well as peephole2
5922 ;; They must handle reloading themselves and the scratch register
5923 ;; is used for that.  Even if we accept memory operand, we must not
5924 ;; accept them on the predicate because it might create too many reloads.
5925 ;; (specially on HC12 due to its auto-incdec addressing modes).
5927 (define_expand "decrement_and_branch_until_zero"
5928   [(parallel [(set (pc)
5929                    (if_then_else
5930                     (ne (plus:HI (match_operand:HI 0 "register_operand" "")
5931                                  (const_int 0))
5932                         (const_int 1))
5933                     (label_ref (match_operand 1 "" ""))
5934                     (pc)))
5935               (set (match_dup 0)
5936                    (plus:HI (match_dup 0)
5937                             (const_int -1)))
5938               (clobber (match_scratch:HI 2 ""))])]
5939   "TARGET_M6812"
5940   "")
5942 (define_expand "doloop_end"
5943   [(use (match_operand 0 "" ""))        ; loop pseudo
5944    (use (match_operand 1 "" ""))        ; iterations; zero if unknown
5945    (use (match_operand 2 "" ""))        ; max iterations
5946    (use (match_operand 3 "" ""))        ; loop level
5947    (use (match_operand 4 "" ""))]       ; label
5948   "TARGET_M6812"
5949   "
5951   /* Reject non-constant loops as it generates bigger code due to
5952      the handling of the loop register.  We can do better by using
5953      the peephole2 dbcc/ibcc patterns.  */
5954   if (INTVAL (operands[1]) == 0)
5955     {
5956       FAIL;
5957     }
5959   /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
5960      the operator and its operands are not relevant.  */
5961   if (GET_MODE (operands[0]) == HImode)
5962     {
5963       emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
5964                                                gen_rtx_NE (HImode,
5965                                                            operands[0],
5966                                                            const1_rtx),
5967                                                operands[4]));
5968       DONE;
5969     }
5970   if (GET_MODE (operands[0]) == QImode)
5971     {
5972       emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
5973                                                gen_rtx_NE (QImode,
5974                                                            operands[0],
5975                                                            const1_rtx),
5976                                                operands[4]));
5977       DONE;
5978     }
5980   FAIL;
5983 ;; Decrement-and-branch insns.
5984 (define_insn "m68hc12_dbcc_dec_hi"
5985   [(set (pc)
5986         (if_then_else
5987           (match_operator 1 "m68hc11_eq_compare_operator"
5988              [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5989               (const_int 1)])
5990          (label_ref (match_operand 2 "" ""))
5991          (pc)))
5992    (set (match_dup 0)
5993         (plus:HI (match_dup 0) (const_int -1)))
5994    (clobber (match_scratch:HI 3 "=X,dxy"))]
5995   "TARGET_M6812"
5996   "*
5998   if (!H_REG_P (operands[0]))
5999     return \"#\";
6001   CC_STATUS_INIT;
6002   if (GET_CODE (operands[1]) == EQ)
6003     return \"dbeq\\t%0,%l2\";
6004   else
6005     return \"dbne\\t%0,%l2\";
6008 ;; Decrement-and-branch insns.
6009 (define_insn "m68hc12_dbcc_inc_hi"
6010   [(set (pc)
6011         (if_then_else
6012           (match_operator 1 "m68hc11_eq_compare_operator"
6013              [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
6014               (const_int -1)])
6015          (label_ref (match_operand 2 "" ""))
6016          (pc)))
6017    (set (match_dup 0)
6018         (plus:HI (match_dup 0) (const_int 1)))
6019    (clobber (match_scratch:HI 3 "=X,dxy"))]
6020   "TARGET_M6812"
6021   "*
6023   if (!H_REG_P (operands[0]))
6024     return \"#\";
6026   CC_STATUS_INIT;
6027   if (GET_CODE (operands[1]) == EQ)
6028     return \"ibeq\\t%0,%l2\";
6029   else
6030     return \"ibeq\\t%0,%l2\";
6033 ;; Decrement-and-branch (QImode).
6034 (define_insn "m68hc12_dbcc_dec_qi"
6035   [(set (pc)
6036         (if_then_else
6037           (match_operator 1 "m68hc11_eq_compare_operator"
6038              [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6039               (const_int 1)])
6040          (label_ref (match_operand 2 "" ""))
6041          (pc)))
6042    (set (match_dup 0)
6043         (plus:QI (match_dup 0) (const_int -1)))
6044    (clobber (match_scratch:QI 3 "=X,d"))]
6045   "TARGET_M6812"
6046   "*
6048   if (!D_REG_P (operands[0]))
6049     return \"#\";
6051   CC_STATUS_INIT;
6052   if (GET_CODE (operands[1]) == EQ)
6053     return \"dbeq\\tb,%l2\";
6054   else
6055     return \"dbne\\tb,%l2\";
6058 ;; Increment-and-branch (QImode).
6059 (define_insn "m68hc12_dbcc_inc_qi"
6060   [(set (pc)
6061         (if_then_else
6062           (match_operator 1 "m68hc11_eq_compare_operator"
6063              [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6064               (const_int -1)])
6065          (label_ref (match_operand 2 "" ""))
6066          (pc)))
6067    (set (match_dup 0)
6068         (plus:QI (match_dup 0) (const_int 1)))
6069    (clobber (match_scratch:QI 3 "=X,d"))]
6070   "TARGET_M6812"
6071   "*
6073   if (!D_REG_P (operands[0]))
6074     return \"#\";
6076   CC_STATUS_INIT;
6077   if (GET_CODE (operands[1]) == EQ)
6078     return \"ibeq\\tb,%l2\";
6079   else
6080     return \"ibeq\\tb,%l2\";
6083 ;; Split the above to handle the case where operand 0 is in memory
6084 ;; (a register that couldn't get a hard register)
6085 (define_split
6086   [(set (pc)
6087         (if_then_else
6088           (match_operator 3 "m68hc11_eq_compare_operator"
6089              [(match_operand:HI 0 "general_operand" "")
6090               (match_operand:HI 1 "const_int_operand" "")])
6091          (label_ref (match_operand 4 "" ""))
6092          (pc)))
6093    (set (match_dup 0)
6094         (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6095    (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
6096   "TARGET_M6812 && reload_completed"
6097   [(set (match_dup 5) (match_dup 0))
6098    (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
6099    (set (match_dup 0) (match_dup 5))
6100    (set (pc)
6101         (if_then_else (match_op_dup 3
6102                             [(match_dup 5) (const_int 0)])
6103                       (label_ref (match_dup 4)) (pc)))]
6104   "")
6106 ;; Split the above to handle the case where operand 0 is in memory
6107 ;; (a register that couldn't get a hard register)
6108 (define_split
6109   [(set (pc)
6110         (if_then_else
6111           (match_operator 3 "m68hc11_eq_compare_operator"
6112              [(match_operand:QI 0 "general_operand" "")
6113               (match_operand:QI 1 "const_int_operand" "")])
6114          (label_ref (match_operand 4 "" ""))
6115          (pc)))
6116    (set (match_dup 0)
6117         (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6118    (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
6119   "TARGET_M6812 && reload_completed"
6120   [(set (match_dup 5) (match_dup 0))
6121    (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
6122    (set (match_dup 0) (match_dup 5))
6123    (set (pc)
6124         (if_then_else (match_op_dup 3
6125                             [(match_dup 5) (const_int 0)])
6126                       (label_ref (match_dup 4)) (pc)))]
6127   "")
6129 ;;--------------------------------------------------------------------
6130 ;;-  Jumps and transfers
6131 ;;--------------------------------------------------------------------
6132 (define_insn "jump"
6133   [(set (pc)
6134         (label_ref (match_operand 0 "" "")))]
6135   ""
6136   "bra\\t%l0")
6138 (define_expand "beq"
6139   [(set (pc)
6140         (if_then_else (eq (cc0)
6141                           (const_int 0))
6142                       (label_ref (match_operand 0 "" ""))
6143                       (pc)))]
6144   ""
6145   "
6147   m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
6148                                      m68hc11_compare_op1, 
6149                                      operands[0]);
6150   DONE;
6153 (define_expand "bne"
6154   [(set (pc)
6155         (if_then_else (ne (cc0)
6156                           (const_int 0))
6157                       (label_ref (match_operand 0 "" ""))
6158                       (pc)))]
6159   ""
6160   "
6162   m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
6163                                      m68hc11_compare_op1, 
6164                                      operands[0]);
6165   DONE;
6168 (define_expand "bgt"
6169   [(set (pc)
6170         (if_then_else (gt (cc0)
6171                           (const_int 0))
6172                       (label_ref (match_operand 0 "" ""))
6173                       (pc)))]
6174   ""
6175   "
6177   m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
6178                                      m68hc11_compare_op1, 
6179                                      operands[0]);
6180   DONE;
6183 (define_expand "bgtu"
6184   [(set (pc)
6185         (if_then_else (gtu (cc0)
6186                            (const_int 0))
6187                       (label_ref (match_operand 0 "" ""))
6188                       (pc)))]
6189   ""
6190   "
6192   m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
6193                                      m68hc11_compare_op1, 
6194                                      operands[0]);
6195   DONE;
6198 (define_expand "blt"
6199   [(set (pc)
6200         (if_then_else (lt (cc0)
6201                           (const_int 0))
6202                       (label_ref (match_operand 0 "" ""))
6203                       (pc)))]
6204   ""
6205   "
6207   m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
6208                                      m68hc11_compare_op1, 
6209                                      operands[0]);
6210   DONE;
6213 (define_expand "bltu"
6214   [(set (pc)
6215         (if_then_else (ltu (cc0)
6216                            (const_int 0))
6217                       (label_ref (match_operand 0 "" ""))
6218                       (pc)))]
6219   ""
6220   "
6222   m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
6223                                      m68hc11_compare_op1, 
6224                                      operands[0]);
6225   DONE;
6228 (define_expand "bge"
6229   [(set (pc)
6230         (if_then_else (ge (cc0)
6231                            (const_int 0))
6232                       (label_ref (match_operand 0 "" ""))
6233                       (pc)))]
6234   ""
6235   "
6237   m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
6238                                      m68hc11_compare_op1, 
6239                                      operands[0]);
6240   DONE;
6243 (define_expand "bgeu"
6244   [(set (pc)
6245         (if_then_else (geu (cc0)
6246                            (const_int 0))
6247                       (label_ref (match_operand 0 "" ""))
6248                       (pc)))]
6249   ""
6250   "
6252   m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
6253                                      m68hc11_compare_op1, 
6254                                      operands[0]);
6255   DONE;
6258 (define_expand "ble"
6259   [(set (pc)
6260         (if_then_else (le (cc0)
6261                            (const_int 0))
6262                       (label_ref (match_operand 0 "" ""))
6263                       (pc)))]
6264   ""
6265   "
6267   m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
6268                                      m68hc11_compare_op1, 
6269                                      operands[0]);
6270   DONE;
6273 (define_expand "bleu"
6274   [(set (pc)
6275         (if_then_else (leu (cc0)
6276                            (const_int 0))
6277                       (label_ref (match_operand 0 "" ""))
6278                       (pc)))]
6279   ""
6280   "
6282   m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
6283                                      m68hc11_compare_op1, 
6284                                      operands[0]);
6285   DONE;
6289 ;; Test and branch instructions for 68HC12 for EQ and NE.
6290 ;; 'z' must not appear in the constraints because the z replacement 
6291 ;; pass does not know how to restore the replacement register.
6293 (define_insn "*tbeq"
6294   [(set (pc)
6295         (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
6296                           (const_int 0))
6297                       (label_ref (match_operand 1 "" ""))
6298                       (pc)))]
6299   "TARGET_M6812"
6300   "*
6302    /* If the flags are already set correctly, use 'bne/beq' which are
6303       smaller and a little bit faster.  This happens quite often due
6304       to reloading of operands[0].  In that case, flags are set correctly
6305       due to the load instruction.  */
6306   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6307       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6308     return \"beq\\t%l1\";
6309   else
6310     return \"tbeq\\t%0,%l1\";
6313 (define_insn "*tbne"
6314   [(set (pc)
6315         (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6316                           (const_int 0))
6317                       (label_ref (match_operand 1 "" ""))
6318                       (pc)))]
6319   "TARGET_M6812"
6320   "*
6322    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6323        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6324      return \"bne\\t%l1\";
6325    else
6326      return \"tbne\\t%0,%l1\";
6330 ;; Test and branch with 8-bit register.  Register must be B (or A).
6332 (define_insn "*tbeq8"
6333   [(set (pc)
6334         (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6335                           (const_int 0))
6336                       (label_ref (match_operand 1 "" ""))
6337                       (pc)))]
6338   "TARGET_M6812"
6339   "*
6341    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6342        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6343      return \"beq\\t%l1\";
6344    else
6345      return \"tbeq\\tb,%l1\";
6348 (define_insn "*tbne8"
6349   [(set (pc)
6350         (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6351                           (const_int 0))
6352                       (label_ref (match_operand 1 "" ""))
6353                       (pc)))]
6354   "TARGET_M6812"
6355   "*
6357    if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6358        || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6359      return \"bne\\t%l1\";
6360    else
6361      return \"tbne\\tb,%l1\";
6364 (define_insn "*beq"
6365   [(set (pc)
6366         (if_then_else (eq (cc0)
6367                           (const_int 0))
6368                       (label_ref (match_operand 0 "" ""))
6369                       (pc)))]
6370   ""
6371   "beq\\t%l0")
6373 (define_insn "*bne"
6374   [(set (pc)
6375         (if_then_else (ne (cc0)
6376                           (const_int 0))
6377                       (label_ref (match_operand 0 "" ""))
6378                       (pc)))]
6379   ""
6380   "bne\\t%l0")
6382 (define_insn "*bgt"
6383   [(set (pc)
6384         (if_then_else (gt (cc0)
6385                           (const_int 0))
6386                       (label_ref (match_operand 0 "" ""))
6387                       (pc)))]
6388   ""
6389   "bgt\\t%l0")
6391 (define_insn "*bgtu"
6392   [(set (pc)
6393         (if_then_else (gtu (cc0)
6394                            (const_int 0))
6395                       (label_ref (match_operand 0 "" ""))
6396                       (pc)))]
6397   ""
6398   "bhi\\t%l0")
6400 (define_insn "*blt"
6401   [(set (pc)
6402         (if_then_else (lt (cc0)
6403                           (const_int 0))
6404                       (label_ref (match_operand 0 "" ""))
6405                       (pc)))]
6406   ""
6407   "*
6409   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6410     return \"bmi\\t%l0\";
6411   else
6412     return \"blt\\t%l0\";
6415 (define_insn "*bltu"
6416   [(set (pc)
6417         (if_then_else (ltu (cc0)
6418                            (const_int 0))
6419                       (label_ref (match_operand 0 "" ""))
6420                       (pc)))]
6421   ""
6422   "blo\\t%l0")
6424 (define_insn "*bge"
6425   [(set (pc)
6426         (if_then_else (ge (cc0)
6427                           (const_int 0))
6428                       (label_ref (match_operand 0 "" ""))
6429                       (pc)))]
6430   ""
6431   "*
6433   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6434     return \"bpl\\t%l0\";
6435   else
6436     return \"bge\\t%l0\";
6439 (define_insn "*bgeu"
6440   [(set (pc)
6441         (if_then_else (geu (cc0)
6442                            (const_int 0))
6443                       (label_ref (match_operand 0 "" ""))
6444                       (pc)))]
6445   ""
6446   "bhs\\t%l0")
6448 (define_insn "*ble"
6449   [(set (pc)
6450         (if_then_else (le (cc0)
6451                           (const_int 0))
6452                       (label_ref (match_operand 0 "" ""))
6453                       (pc)))]
6454   ""
6455   "*
6457   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6458     return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6459   else
6460     return \"ble\\t%l0\";
6463 (define_insn "*bleu"
6464   [(set (pc)
6465         (if_then_else (leu (cc0)
6466                            (const_int 0))
6467                       (label_ref (match_operand 0 "" ""))
6468                       (pc)))]
6469   ""
6470   "bls\\t%l0")
6472 ;;--------------------------------------------------------------------
6473 ;;- Negative test and branch
6474 ;;--------------------------------------------------------------------
6475 (define_insn ""
6476   [(set (pc)
6477         (if_then_else (eq (cc0)
6478                           (const_int 0))
6479                       (pc)
6480                       (label_ref (match_operand 0 "" ""))))]
6481   ""
6482   "bne\\t%l0")
6484 (define_insn ""
6485   [(set (pc)
6486         (if_then_else (ne (cc0)
6487                           (const_int 0))
6488                       (pc)
6489                       (label_ref (match_operand 0 "" ""))))]
6490   ""
6491   "beq\\t%l0")
6493 (define_insn ""
6494   [(set (pc)
6495         (if_then_else (gt (cc0)
6496                           (const_int 0))
6497                       (pc)
6498                       (label_ref (match_operand 0 "" ""))))]
6499   ""
6500   "*
6502   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6503     return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6504   else
6505     return \"ble\\t%l0\";
6508 (define_insn ""
6509   [(set (pc)
6510         (if_then_else (gtu (cc0)
6511                            (const_int 0))
6512                       (pc)
6513                       (label_ref (match_operand 0 "" ""))))]
6514   ""
6515   "bls\\t%l0")
6517 (define_insn ""
6518   [(set (pc)
6519         (if_then_else (lt (cc0)
6520                           (const_int 0))
6521                       (pc)
6522                       (label_ref (match_operand 0 "" ""))))]
6523   ""
6524   "*
6526   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6527     return \"bpl\\t%l0\";
6528   else
6529     return \"bge\\t%l0\";
6532 (define_insn ""
6533   [(set (pc)
6534         (if_then_else (ltu (cc0)
6535                            (const_int 0))
6536                       (pc)
6537                       (label_ref (match_operand 0 "" ""))))]
6538   ""
6539   "bhs\\t%l0")
6541 (define_insn ""
6542   [(set (pc)
6543         (if_then_else (ge (cc0)
6544                           (const_int 0))
6545                       (pc)
6546                       (label_ref (match_operand 0 "" ""))))]
6547   ""
6548   "*
6550   if (cc_prev_status.flags & CC_NO_OVERFLOW)
6551     return \"bmi\\t%l0\";
6552   else
6553     return \"blt\\t%l0\";
6556 (define_insn ""
6557   [(set (pc)
6558         (if_then_else (geu (cc0)
6559                            (const_int 0))
6560                       (pc)
6561                       (label_ref (match_operand 0 "" ""))))]
6562   ""
6563   "blo\\t%l0")
6565 (define_insn ""
6566   [(set (pc)
6567         (if_then_else (le (cc0)
6568                           (const_int 0))
6569                       (pc)
6570                       (label_ref (match_operand 0 "" ""))))]
6571   ""
6572   "bgt\\t%l0")
6574 (define_insn ""
6575   [(set (pc)
6576         (if_then_else (leu (cc0)
6577                            (const_int 0))
6578                       (pc)
6579                       (label_ref (match_operand 0 "" ""))))]
6580   ""
6581   "bhi\\t%l0")
6583 ;;--------------------------------------------------------------------
6584 ;;-  Calls
6585 ;;--------------------------------------------------------------------
6587 ;;- Call a function that returns no value.
6588 (define_insn "call"
6589   [(call (match_operand:QI 0 "memory_operand" "m")
6590          (match_operand:SI 1 "general_operand" "g"))]
6591   ;; Operand 1 not really used on the m68hc11.
6592   ""
6593  "*
6595   if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6596     {
6597       if (m68hc11_is_far_symbol (operands[0]))
6598         {
6599           if (TARGET_M6812)
6600             {
6601               output_asm_insn (\"call\\t%0\", operands);
6602               return \"\";
6603             }
6604           else
6605             {
6606               output_asm_insn (\"pshb\", operands);
6607               output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
6608               output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
6609               return \"jsr\\t__call_a32\";
6610             }
6611         }
6612       if (m68hc11_is_trap_symbol (operands[0]))
6613         return \"swi\";
6614       else
6615         return \"bsr\\t%0\";
6616     }
6617   else
6618     {
6619       return \"jsr\\t%0\";
6620     }
6623 (define_insn "call_value"
6624   [(set (match_operand 0 "" "=g")
6625         (call (match_operand:QI 1 "memory_operand" "m")
6626               (match_operand:SI 2 "general_operand" "g")))]
6627   ""
6628  "*
6630   if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6631     {
6632       if (m68hc11_is_far_symbol (operands[1]))
6633         {
6634           if (TARGET_M6812)
6635             {
6636               output_asm_insn (\"call\\t%1\", operands);
6637               return \"\";
6638             }
6639           else
6640             {
6641               output_asm_insn (\"pshb\", operands);
6642               output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
6643               output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
6644               return \"jsr\\t__call_a32\";
6645             }
6646         }
6647       if (m68hc11_is_trap_symbol (operands[1]))
6648         return \"swi\";
6649       else
6650         return \"bsr\\t%1\";
6651     }
6652   else
6653     {
6654       return \"jsr\\t%1\";
6655     }
6658 ;; Call subroutine returning any type.
6660 (define_expand "untyped_call"
6661   [(parallel [(call (match_operand 0 "" "")
6662                     (const_int 0))
6663               (match_operand 1 "" "")
6664               (match_operand 2 "" "")])]
6665   ""
6666   "
6668   int i;
6670   emit_call_insn (gen_call (operands[0], const0_rtx));
6672   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6673     {
6674       rtx set = XVECEXP (operands[2], 0, i);
6675       emit_move_insn (SET_DEST (set), SET_SRC (set));
6676     }
6678   /* The optimizer does not know that the call sets the function value
6679      registers we stored in the result block.  We avoid problems by
6680      claiming that all hard registers are used and clobbered at this
6681      point.  */
6682   emit_insn (gen_blockage ());
6684   DONE;
6687 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6688 ;; all of memory.  This blocks insns from being moved across this point.
6690 (define_insn "blockage"
6691   [(unspec_volatile [(const_int 0)] 0)]
6692   ""
6693   "")
6695 (define_insn "nop"
6696   [(const_int 0)]
6697   ""
6698   "nop")
6699     
6700 (define_expand "prologue"
6701   [(const_int 0)]
6702   ""
6703   "
6705   expand_prologue (); 
6706   DONE;
6709 (define_expand "epilogue"
6710   [(return)]
6711   ""
6712   "
6714   expand_epilogue ();
6715   DONE;
6718 ;; Used for frameless functions which save no regs and allocate no locals.
6719 (define_expand "return"
6720   [(return)]
6721   "reload_completed && m68hc11_total_frame_size () == 0"
6722   "
6724   int ret_size = 0;
6726   if (current_function_return_rtx)
6727     ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6729   /* Emit use notes only when HAVE_return is true.  */
6730   if (m68hc11_total_frame_size () != 0)
6731     ret_size = 0;
6733   if (ret_size && ret_size <= 2)
6734     {
6735       emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6736                       gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6737                                  gen_rtx_USE (VOIDmode,
6738                                               gen_rtx_REG (HImode, 1)))));
6739       DONE;
6740     }
6741   if (ret_size)
6742     {
6743       emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6744                       gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6745                                  gen_rtx_USE (VOIDmode,
6746                                               gen_rtx_REG (SImode, 0)))));
6747       DONE;
6748     }
6751 (define_insn "*return_void"
6752   [(return)]
6753   "reload_completed"
6754   "*
6756   rtx next = next_active_insn (insn);
6758   if (next
6759       && GET_CODE (next) == JUMP_INSN
6760       && GET_CODE (PATTERN (next)) == RETURN)
6761     return \"\";
6762   if (current_function_interrupt || current_function_trap)
6763     return \"rti\";
6764   else if (!current_function_far)
6765     return \"rts\";
6766   else if (TARGET_M6812)
6767     return \"rtc\";
6768   else
6769     {
6770       int ret_size = 0;
6772       if (current_function_return_rtx)
6773         ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6775       if (ret_size == 0)
6776         return \"jmp\\t__return_void\";
6777       if (ret_size <= 2)
6778         return \"jmp\\t__return_16\";
6779       if (ret_size <= 4)
6780         return \"jmp\\t__return_32\";
6781       return \"jmp\\t__return_16\";
6782     }
6785 (define_insn "*return_16bit"
6786   [(return)
6787    (use (reg:HI D_REGNUM))]
6788   "reload_completed && m68hc11_total_frame_size () == 0"
6789   "*
6791   rtx next = next_active_insn (insn);
6793   if (next
6794       && GET_CODE (next) == JUMP_INSN
6795       && GET_CODE (PATTERN (next)) == RETURN)
6796     return \"\";
6797   if (current_function_interrupt || current_function_trap)
6798     return \"rti\";
6799   else if (!current_function_far)
6800     return \"rts\";
6801   else if (TARGET_M6812)
6802     return \"rtc\";
6803   else
6804     return \"jmp\\t__return_16\";
6807 (define_insn "*return_32bit"
6808   [(return)
6809    (use (reg:SI 0))]
6810   "reload_completed && m68hc11_total_frame_size () == 0"
6811   "*
6813   rtx next = next_active_insn (insn);
6815   if (next
6816       && GET_CODE (next) == JUMP_INSN
6817       && GET_CODE (PATTERN (next)) == RETURN)
6818     return \"\";
6819   if (current_function_interrupt || current_function_trap)
6820     return \"rti\";
6821   else if (!current_function_far)
6822     return \"rts\";
6823   else if (TARGET_M6812)
6824     return \"rtc\";
6825   else
6826     return \"jmp\\t__return_32\";
6829 (define_insn "indirect_jump"
6830   [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6831   ""
6832   "jmp\\t0,%0")
6834 ;;--------------------------------------------------------------------
6835 ;;-  Table jump
6836 ;;--------------------------------------------------------------------
6838 ;; Operand 0 is the address of the table element to use
6839 ;; operand 1 is the CODE_LABEL for the table
6840 ;;--------------------------------------------------------------------
6841 (define_expand "tablejump"
6842   [(parallel [(set (pc) (match_operand 0 "" ""))
6843               (use (label_ref (match_operand 1 "" "")))])]
6844   ""
6845   "")
6847 (define_insn "*jump_indirect"
6848    [(parallel [
6849         (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6850         (use (label_ref (match_operand 1 "" "")))])]
6851    ""
6852   "jmp\\t0,%0")
6854 ;;--------------------------------------------------------------------
6855 ;;- Peepholes
6856 ;;--------------------------------------------------------------------
6858 ;;--------------------------------------------------------------------
6859 ;;- 68HC12 dbcc/ibcc peepholes
6860 ;;--------------------------------------------------------------------
6862 ;; Replace: "addd #-1; bne L1" into "dbne d,L1"
6863 ;;          "addd #-1; beq L1" into "dbeq d,L1"
6864 ;;          "addd #1; bne L1" into "ibne d,L1"
6865 ;;          "addd #1; beq L1" into "ibeq d,L1"
6867 (define_peephole2
6868   [(set (match_operand:HI 0 "hard_reg_operand" "")
6869         (plus:HI (match_dup 0)
6870                  (match_operand:HI 1 "const_int_operand" "")))
6871    (set (pc)
6872         (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6873                          [(match_dup 0)
6874                           (const_int 0)])
6875                       (label_ref (match_operand 3 "" "")) (pc)))]
6876   "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6877   [(parallel [
6878       (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6879                               (label_ref (match_dup 3)) (pc)))
6880       (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
6881       (clobber (match_dup 4))])]
6882   "operands[4] = gen_rtx_SCRATCH(HImode);
6883    operands[5] = GEN_INT (-INTVAL (operands[1]));")
6887 ;; Replace: "addb #-1; bne L1" into "dbne b,L1"
6888 ;;          "addb #-1; beq L1" into "dbeq b,L1"
6890 (define_peephole2
6891   [(set (match_operand:QI 0 "hard_reg_operand" "")
6892         (plus:QI (match_dup 0)
6893                  (match_operand:QI 1 "const_int_operand" "")))
6894    (set (pc)
6895         (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6896                          [(match_dup 0)
6897                           (const_int 0)])
6898                       (label_ref (match_operand 3 "" "")) (pc)))]
6899   "TARGET_M6812 && D_REG_P (operands[0])
6900    && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6901   [(parallel [
6902       (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6903                               (label_ref (match_dup 3)) (pc)))
6904       (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
6905       (clobber (match_dup 4))])]
6906   "operands[4] = gen_rtx_SCRATCH(QImode);
6907    operands[5] = GEN_INT (-INTVAL (operands[1]));")
6910 ;;--------------------------------------------------------------------
6911 ;;- Move peephole2
6912 ;;--------------------------------------------------------------------
6915 ;; Replace "leas 2,sp" with a "pulx" or a "puly".
6916 ;; On 68HC12, this is one cycle slower but one byte smaller.
6917 ;; pr target/6899: This peephole was not valid because a register CSE
6918 ;; pass removes the pulx/puly.  The 'use' clause ensure that the pulx is
6919 ;; not removed.
6921 (define_peephole2
6922   [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6923    (match_scratch:HI 0 "xy")]
6924   "TARGET_M6812 && optimize_size"
6925   [(set (match_dup 0) (match_dup 1))
6926    (use (match_dup 0))]
6927   "operands[1] = gen_rtx_MEM (HImode,
6928                           gen_rtx_POST_INC (HImode,
6929                                    gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
6931 ;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
6933 ;; PR 14542: emit a use to pretend we need the value of initial register.
6934 ;; Otherwise verify_local_live_at_start will die due to a live change
6935 ;; of that register.
6937 (define_peephole2
6938   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6939         (match_operand:HI 0 "hard_reg_operand" ""))
6940    (set (match_dup 0)
6941         (match_operand:HI 1 "hard_reg_operand" ""))
6942    (set (mem:HI (reg:HI SP_REGNUM))
6943         (match_dup 0))]
6944   "TARGET_M6812"
6945   [(use (match_dup 0))
6946    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6947         (match_dup 1))
6948    (set (match_dup 0) (match_dup 1))]
6949   "")
6952 ;; Change: "ldd 0,sp; pulx" into  "puld"
6953 ;; This sequence usually appears at end a functions.
6954 (define_peephole2
6955   [(set (match_operand:HI 0 "hard_reg_operand" "")
6956         (mem:HI (reg:HI SP_REGNUM)))
6957    (use (match_dup 0))
6958    (set (match_operand:HI 1 "hard_reg_operand" "")
6959         (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
6960   "peep2_reg_dead_p (2, operands[1])"
6961   [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
6962    (use (match_dup 0))]
6963   "")
6965 ;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
6966 ;; Appears to allocate local variables.
6967 (define_peephole2
6968   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6969         (match_operand:HI 0 "hard_reg_operand" ""))
6970    (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
6971         (const_int 0))
6972    (set (mem:QI (reg:HI SP_REGNUM))
6973         (const_int 0))]
6974   "TARGET_M6812"
6975   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6976         (const_int 0))]
6977   "")
6979 ;; Likewise for HI mode
6980 (define_peephole2
6981   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6982         (match_operand:HI 0 "hard_reg_operand" ""))
6983    (set (mem:HI (reg:HI SP_REGNUM))
6984         (const_int 0))]
6985   "TARGET_M6812"
6986   [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6987         (const_int 0))]
6988   "")
6989 ;;--------------------------------------------------------------------
6990 ;;- 
6991 ;;--------------------------------------------------------------------
6993 ;; Optimize memory<->memory moves when the value is also loaded in
6994 ;; a register.
6996 (define_peephole2
6997   [(set (match_operand:QI 0 "memory_operand" "")
6998         (match_operand:QI 1 "memory_operand" ""))
6999    (set (reg:QI D_REGNUM)
7000         (match_operand:QI 2 "memory_operand" ""))]
7001   "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
7002    || (GET_CODE (XEXP (operands[0], 0)) == REG
7003        && GET_CODE (XEXP (operands[2], 0)) == POST_INC
7004        && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
7005   [(set (reg:QI D_REGNUM) (match_dup 1))
7006    (set (match_dup 2) (reg:QI D_REGNUM))]
7007   "")
7010 ;; Remove a possible move before a compare instruction when that
7011 ;; move will go in a dead register.  Compare with the source then.
7013 (define_peephole2
7014   [(set (match_operand:HI 0 "hard_reg_operand" "")
7015         (match_operand:HI 1 "hard_reg_operand" ""))
7016    (set (cc0)
7017         (compare (match_dup 0)
7018                  (match_operand:HI 2 "cmp_operand" "")))]
7019   "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
7020    && peep2_reg_dead_p (2, operands[0])
7021    && !reg_mentioned_p (operands[0], operands[2])"
7022   [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
7023   "")
7026 ;; Optimize loading a constant to memory when that same constant
7027 ;; is loaded to a hard register.  Switch the two to use the register
7028 ;; for memory initialization.  In most cases, the constant is 0.
7030 (define_peephole2
7031   [(set (match_operand:HI 0 "memory_operand" "")
7032         (match_operand:HI 1 "immediate_operand" ""))
7033    (set (match_operand:HI 2 "hard_reg_operand" "")
7034         (match_dup 1))]
7035   "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
7036    && !reg_mentioned_p (operands[2], operands[0])"
7037   [(set (match_dup 2) (match_dup 1))
7038    (set (match_dup 0) (match_dup 2))]
7039   "")
7042 ;; Reorganize to optimize address computations.
7044 (define_peephole2
7045   [(set (match_operand:HI 0 "hard_reg_operand" "")
7046         (match_operand:HI 1 "const_int_operand" ""))
7047    (set (match_dup 0)
7048         (plus:HI (match_dup 0)
7049                  (match_operand:HI 2 "general_operand" "")))]
7050   "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7051   [(set (match_dup 0) (match_dup 2))
7052    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7053   "")
7056 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7058 (define_peephole2
7059   [(set (match_operand:HI 0 "hard_reg_operand" "")
7060         (match_operand:HI 1 "const_int_operand" ""))
7061    (set (match_dup 0)
7062         (plus:HI (match_dup 0)
7063                  (match_operand:HI 2 "general_operand" "")))
7064    (match_scratch:QI 3 "d")]
7065   "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
7066   [(set (match_dup 3) (match_dup 4))
7067    (set (match_dup 0) (match_dup 2))
7068    (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
7069   "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
7072 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7074 (define_peephole2
7075   [(set (match_operand:HI 0 "hard_reg_operand" "")
7076         (match_operand:HI 1 "const_int_operand" ""))
7077    (set (match_dup 0)
7078         (plus:HI (match_dup 0)
7079                  (match_operand:HI 2 "general_operand" "")))]
7080   "TARGET_M6812"
7081   [(set (match_dup 0) (match_dup 2))
7082    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7083   "")
7086 ;; Optimize an address register increment and a compare to use
7087 ;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
7088 ;; before reload, but can be enabled after).
7090 (define_peephole2
7091   [(set (match_operand:HI 0 "hard_reg_operand" "")
7092         (plus:HI (match_dup 0)
7093                  (match_operand:HI 1 "const_int_operand" "")))
7094    (set (cc0)
7095         (match_operand:QI 2 "memory_operand" ""))]
7096   "TARGET_AUTO_INC_DEC
7097    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7098    && reg_mentioned_p (operands[0], operands[2])"
7099   [(set (cc0) (match_dup 3))]
7100   "if (INTVAL (operands[1]) == 1)
7101      operands[3] = gen_rtx_MEM (QImode,
7102                             gen_rtx_PRE_INC (HImode, operands[0]));
7103    else
7104      operands[3] = gen_rtx_MEM (QImode,
7105                             gen_rtx_PRE_DEC (HImode, operands[0]));
7106   ")
7109 ;; Likewise for compare.
7111 (define_peephole2
7112   [(set (match_operand:HI 0 "hard_reg_operand" "")
7113         (plus:HI (match_dup 0)
7114                  (match_operand:HI 1 "const_int_operand" "")))
7115    (set (cc0)
7116         (compare (match_operand:QI 2 "hard_reg_operand" "")
7117                  (match_operand:QI 3 "memory_operand" "")))]
7118   "TARGET_AUTO_INC_DEC
7119    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7120    && reg_mentioned_p (operands[0], operands[3])"
7121   [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
7122   "if (INTVAL (operands[1]) == 1)
7123      operands[4] = gen_rtx_MEM (QImode,
7124                             gen_rtx_PRE_INC (HImode, operands[0]));
7125    else
7126      operands[4] = gen_rtx_MEM (QImode,
7127                             gen_rtx_PRE_DEC (HImode, operands[0]));
7128   ")
7130 (define_peephole2
7131   [(set (match_operand:HI 0 "hard_reg_operand" "")
7132         (plus:HI (match_dup 0)
7133                  (match_operand:HI 1 "const_int_operand" "")))
7134    (set (cc0)
7135         (compare (match_operand:QI 2 "memory_operand" "")
7136                  (match_operand:QI 3 "hard_reg_operand" "")))]
7137   "TARGET_AUTO_INC_DEC
7138    && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7139    && reg_mentioned_p (operands[0], operands[2])"
7140   [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
7141   "if (INTVAL (operands[1]) == 1)
7142      operands[4] = gen_rtx_MEM (QImode,
7143                             gen_rtx_PRE_INC (HImode, operands[0]));
7144    else
7145      operands[4] = gen_rtx_MEM (QImode,
7146                             gen_rtx_PRE_DEC (HImode, operands[0]));
7147   ")
7150 ;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
7151 ;; (avoids many temporary moves because we can't add sp to another reg easily)
7153 (define_peephole2
7154   [(set (match_operand:HI 0 "hard_reg_operand" "")
7155         (match_operand:HI 1 "const_int_operand" ""))
7156    (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7157   ""
7158   [(set (match_dup 0) (reg:HI SP_REGNUM))
7159    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7160   "")
7163 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7165 (define_peephole2
7166   [(set (match_operand:HI 0 "hard_reg_operand" "")
7167         (match_operand:HI 1 "const_int_operand" ""))
7168    (set (match_dup 0)
7169         (plus:HI (match_dup 0)
7170                  (match_operand:HI 2 "general_operand" "")))]
7171   "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7172   [(set (match_dup 0) (match_dup 2))
7173    (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7174   "")
7179 (define_peephole2
7180   [(parallel 
7181      [(set (match_operand:SI 0 "hard_reg_operand" "")
7182         (ashift:SI (match_operand:SI 1 "general_operand" "")
7183                    (const_int 1)))
7184       (clobber (match_scratch:HI 2 ""))])
7185    (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
7186    (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
7187   "!X_REG_P (operands[1])
7188    && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
7189    && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
7190   [(set (reg:HI D_REGNUM) (match_dup 5))
7191    (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
7192    (set (match_dup 3) (reg:HI D_REGNUM))
7193    (set (reg:HI D_REGNUM) (match_dup 6))
7194    (parallel [(set (reg:HI D_REGNUM)
7195                    (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
7196               (clobber (reg:HI CC_REGNUM))])
7197    (set (match_dup 4) (reg:HI D_REGNUM))]
7198   "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
7199    operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
7202 ;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
7204 (define_peephole2
7205   [(set (match_operand:HI 0 "hard_reg_operand" "")
7206         (match_operand:HI 1 "memory_operand" ""))
7207    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
7208         (match_dup 0))
7209    (match_scratch:HI 2 "x")]
7210   "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
7211   [(set (match_dup 2) (match_dup 1))
7212    (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
7213   "")
7216 ;; Remove one load when copying a value to/from memory and also
7217 ;; to a register.  Take care not clobbering a possible register used
7218 ;; by operand 2.
7219 ;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
7221 (define_peephole2
7222   [(set (match_operand:HI 0 "hard_reg_operand" "")
7223         (match_operand:HI 1 "general_operand" ""))
7224    (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
7225    (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
7226   "peep2_reg_dead_p (2, operands[0])
7227    && !side_effects_p (operands[1])
7228    && !side_effects_p (operands[2])
7229    && !reg_mentioned_p (operands[3], operands[2])"
7230   [(set (match_dup 3) (match_dup 1))
7231    (set (match_dup 2) (match_dup 3))]
7232   "")
7235 ;; Replace a "ldd <mem>; addd #N; std <mem>" into a
7236 ;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
7237 ;; and the constant is small.
7239 (define_peephole2
7240   [(set (match_operand:HI 0 "hard_reg_operand" "")
7241         (match_operand:HI 1 "general_operand" ""))
7242    (set (match_dup 0) (plus:HI (match_dup 0)
7243                                (match_operand:HI 2 "const_int_operand" "")))
7244    (set (match_operand:HI 3 "nonimmediate_operand" "")
7245         (match_dup 0))
7246    (match_scratch:HI 4 "xy")]
7247   "D_REG_P (operands[0])
7248    && (TARGET_M6812 
7249        || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
7250    && peep2_reg_dead_p (3, operands[0])"
7251   [(set (match_dup 4) (match_dup 1))
7252    (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
7253    (set (match_dup 3) (match_dup 4))]
7254   "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
7255    if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
7257 ;;--------------------------------------------------------------------
7258 ;;- Bset peephole2
7259 ;;--------------------------------------------------------------------
7260 ;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
7262 ;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
7263 ;; Register D must be dead and there must be no register side effects for mem.
7264 ;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
7265 ;; The good side effect is that it makes the sequence atomic.
7267 (define_peephole2
7268   [(set (match_operand:QI 0 "hard_reg_operand" "")
7269         (match_operand:QI 1 "nonimmediate_operand" ""))
7270    (set (match_dup 0) (ior:QI (match_dup 0)
7271                               (match_operand:QI 2 "const_int_operand" "")))
7272    (set (match_dup 1) (match_dup 0))]
7273   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7274    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7275    && peep2_reg_dead_p (3, operands[0])"
7276   [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
7277   "")
7279 (define_peephole2
7280   [(set (match_operand:HI 0 "hard_reg_operand" "")
7281         (match_operand:HI 1 "nonimmediate_operand" ""))
7282    (set (match_dup 0) (ior:HI (match_dup 0)
7283                               (match_operand:HI 2 "const_int_operand" "")))
7284    (set (match_dup 1) (match_dup 0))]
7285   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7286    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7287    && peep2_reg_dead_p (3, operands[0])"
7288   [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
7289   "")
7291 ;;--------------------------------------------------------------------
7292 ;;- Bclr peephole2
7293 ;;--------------------------------------------------------------------
7294 ;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
7295 ;; See Bset peephole2.
7297 (define_peephole2
7298   [(set (match_operand:QI 0 "hard_reg_operand" "")
7299         (match_operand:QI 1 "nonimmediate_operand" ""))
7300    (set (match_dup 0) (and:QI (match_dup 0)
7301                               (match_operand:QI 2 "const_int_operand" "")))
7302    (set (match_dup 1) (match_dup 0))]
7303   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7304    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7305    && peep2_reg_dead_p (3, operands[0])"
7306   [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
7307   "")
7309 (define_peephole2
7310   [(set (match_operand:HI 0 "hard_reg_operand" "")
7311         (match_operand:HI 1 "nonimmediate_operand" ""))
7312    (set (match_dup 0) (and:HI (match_dup 0)
7313                               (match_operand:HI 2 "const_int_operand" "")))
7314    (set (match_dup 1) (match_dup 0))]
7315   "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7316    && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7317    && peep2_reg_dead_p (3, operands[0])"
7318   [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
7319   "")
7322 ;;--------------------------------------------------------------------
7323 ;;- Compare peephole2
7324 ;;--------------------------------------------------------------------
7325 (define_peephole2
7326   [(set (match_operand:HI 0 "hard_reg_operand" "")
7327         (match_operand:HI 1 "hard_reg_operand" ""))
7328    (set (match_dup 1) (plus:HI (match_dup 1) 
7329                                (match_operand:HI 2 "const_int_operand" "")))
7330    (set (cc0) (match_dup 0))]
7331   "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
7332   [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
7333    (set (cc0) (compare (match_dup 1) (match_dup 2)))]
7334   "")
7336 (define_peephole2
7337   [(set (match_operand:HI 0 "hard_reg_operand" "")
7338         (match_operand:HI 1 "hard_reg_operand" ""))
7339    (set (match_operand:HI 2 "hard_reg_operand" "")
7340         (plus:HI (match_dup 2) 
7341                  (match_operand:HI 3 "const_int_operand" "")))
7342    (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
7343    (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
7344   "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
7345    && !reg_mentioned_p (operands[2], operands[4])
7347    && ((rtx_equal_p (operands[5], operands[0])
7348         && rtx_equal_p (operands[2], operands[1]))
7350        || (rtx_equal_p (operands[5], operands[1])
7351            && rtx_equal_p (operands[2], operands[0])))"
7352   [(set (match_dup 2) (match_dup 1))
7353    (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
7354    (set (match_dup 4) (match_dup 2))
7355    (set (cc0) (compare (match_dup 2) (match_dup 3)))]
7356   "")
7359 ;;--------------------------------------------------------------------
7360 ;;- Load peephole2
7361 ;;--------------------------------------------------------------------
7363 ;; Optimize initialization of 2 hard regs from the same memory location
7364 ;; Since we can't copy easily X, Y and D to each other, load the 2 registers
7365 ;; from the same memory location.
7367 (define_peephole2
7368   [(set (match_operand:HI 0 "hard_reg_operand" "")
7369         (match_operand:HI 1 "memory_operand" ""))
7370    (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7371   "TARGET_M6811
7372    && !side_effects_p (operands[1])
7373    && !reg_mentioned_p (operands[0], operands[1])"
7374   [(set (match_dup 0) (match_dup 1))
7375    (set (match_dup 2) (match_dup 1))]
7376   "")
7378 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7380 (define_peephole2
7381   [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7382    (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7383    (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7384    (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
7385    (match_scratch:HI 4 "d")]
7386   ""
7387   [(set (match_dup 4) (const_int 0))
7388    (set (match_dup 0) (match_dup 4))
7389    (set (match_dup 1) (match_dup 4))
7390    (set (match_dup 2) (match_dup 4))
7391    (set (match_dup 3) (match_dup 4))]
7392   "")
7395 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7397 (define_peephole2
7398   [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7399    (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7400    (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7401    (match_scratch:HI 3 "d")]
7402   ""
7403   [(set (match_dup 3) (const_int 0))
7404    (set (match_dup 0) (match_dup 3))
7405    (set (match_dup 1) (match_dup 3))
7406    (set (match_dup 2) (match_dup 3))]
7407   "")
7410 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7412 (define_peephole2
7413   [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
7414    (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
7415    (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
7416    (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
7417    (match_scratch:HI 4 "x")]
7418   "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
7419   [(set (match_dup 4) (const_int 0))
7420    (set (match_dup 1) (match_dup 4))
7421    (set (match_dup 2) (match_dup 4))
7422    (set (match_dup 3) (match_dup 4))]
7423   "")
7426 ;; This peephole catches the address computations generated by the reload
7427 ;; pass. 
7428 (define_peephole
7429   [(set (match_operand:HI 0 "hard_reg_operand" "xy")
7430         (match_operand:HI 1 "const_int_operand" ""))
7431    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7432               (set (match_dup 0) (reg:HI D_REGNUM))])
7433    (set (reg:HI D_REGNUM)
7434         (plus (reg:HI D_REGNUM)
7435               (match_operand:HI 2 "general_operand" "")))
7436    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7437               (set (match_dup 0) (reg:HI D_REGNUM))])]
7438   "(INTVAL (operands[1]) & 0x0FF) == 0"
7439   "*
7441   int value_loaded = 1;
7443   if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
7444     {
7445       rtx ops[2];
7447       ops[0] = operands[0];
7448       ops[1] = operands[2];
7449       m68hc11_gen_movhi (insn, ops);
7450       output_asm_insn (\"xgd%0\", operands);
7451     }
7452   else if (Y_REG_P (operands[0]))
7453     {
7454       if (reg_mentioned_p (iy_reg, operands[2]))
7455         output_asm_insn (\"ldy\\t%2\", operands);
7456       else
7457         value_loaded = 0;
7458       output_asm_insn (\"xgdy\", operands);
7459     }
7460   else
7461     {
7462       output_asm_insn (\"ldd\\t%2\", operands);
7463     }
7465   if (value_loaded == 0)
7466     output_asm_insn (\"ldd\\t%2\", operands);
7467   if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
7468     output_asm_insn (\"inca\", operands);
7469   else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
7470     output_asm_insn (\"deca\", operands);
7471   else if (INTVAL (operands[1]) != 0)
7472     output_asm_insn (\"adda\\t%h1\", operands);
7474   if (X_REG_P (operands[0]))
7475     return \"xgdx\";
7476   else if (Y_REG_P (operands[0]))
7477     return \"xgdy\";
7478   else
7479     return \"\";
7483 (define_peephole
7484   [(set (match_operand:HI 0 "hard_reg_operand" "h")
7485         (match_operand:HI 1 "non_push_operand" "g"))
7486    (set (match_operand:HI 2 "hard_reg_operand" "h")
7487         (match_dup 0))]
7488   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7489    && !S_REG_P (operands[2])"
7490   "*
7492   rtx ops[2];
7494   ops[0] = operands[2];
7495   ops[1] = operands[1];
7496   m68hc11_gen_movhi (insn, ops);
7497   return \"\";
7501 (define_peephole
7502   [(set (match_operand:HI 0 "hard_reg_operand" "h")
7503         (match_operand:HI 1 "hard_reg_operand" "h"))
7504    (set (match_operand:HI 2 "non_push_operand" "g")
7505         (match_dup 0))]
7506   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7507    && !S_REG_P (operands[2])"
7508   "*
7510   rtx ops[2];
7512   ops[0] = operands[2];
7513   ops[1] = operands[1];
7514   m68hc11_gen_movhi (insn, ops);
7515   return \"\";
7520 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
7521 ;; the set, so we don't need to emit anything. 'ins1' refers to the
7522 ;; (set ...) insn.
7524 (define_peephole
7525   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7526    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7527               (set (match_dup 0) (reg:HI D_REGNUM))])]
7528   "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7529   "*
7531    cc_status = cc_prev_status;
7532    return \"\";
7536 ;; Same as above but due to some split, there may be a noop set
7537 ;; between the two.
7538 (define_peephole
7539   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7540    (set (match_dup 0) (match_dup 0))
7541    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7542               (set (match_dup 0) (reg:HI D_REGNUM))])]
7543   "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7544   "*
7546    cc_status = cc_prev_status;
7547    return \"\";
7552 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
7553 ;; and we must, at least, setup X/Y with value of D.
7555 (define_peephole
7556   [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7557    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7558               (set (match_dup 0) (reg:HI D_REGNUM))])]
7559   ""
7560   "*
7562   rtx ops[2];
7564   ops[0] = operands[0];
7565   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7566   m68hc11_gen_movhi (insn, ops);
7567   return \"\";
7572 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7573 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7575 (define_peephole
7576   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7577               (set (match_dup 0) (reg:HI D_REGNUM))])
7578    (set (reg:HI D_REGNUM) (match_dup 0))]
7579   "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7580   "*
7582   cc_status = cc_prev_status;
7583   return \"\";
7588 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7589 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7591 (define_peephole
7592   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7593               (set (match_dup 0) (reg:HI D_REGNUM))])
7594    (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7595   "REGNO (operands[0]) == REGNO (operands[1])
7596    && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7597   "*
7599   cc_status = cc_prev_status;
7600   return \"\";
7605 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7606 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7608 (define_peephole
7609   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7610               (set (match_dup 0) (reg:HI D_REGNUM))])
7611    (set (reg:HI D_REGNUM) (match_dup 0))]
7612   ""
7613   "*
7615   rtx ops[2];
7617   ops[0] = operands[0];
7618   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7619   m68hc11_gen_movhi (insn, ops);
7620   return \"\";
7625 ;;; Same peephole with a QI set.  The copy is made as 16-bit to comply
7626 ;;; with the xgdx.
7628 (define_peephole
7629   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7630               (set (match_dup 0) (reg:HI D_REGNUM))])
7631    (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7632   "REGNO (operands[0]) == REGNO (operands[1])"
7633   "*
7635   rtx ops[2];
7637   ops[0] = operands[0];
7638   ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7639   m68hc11_gen_movhi (insn, ops);
7640   return \"\";
7645 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
7647 (define_peephole
7648   [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7649               (set (match_dup 0) (reg:HI D_REGNUM))])
7650    (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7651               (set (match_dup 0) (reg:HI D_REGNUM))])]
7652   ""
7653   "*
7655   cc_status = cc_prev_status;
7656   return \"\";
7660 (define_peephole
7661   [(set (match_operand:HI 0 "hard_reg_operand" "")
7662         (match_operand:HI 1 "stack_register_operand" ""))
7663    (set (match_operand:HI 2 "hard_reg_operand" "")
7664         (match_operand:HI 3 "memory_operand" "m"))
7665    (set (match_dup 0)
7666         (match_operand:HI 4 "memory_operand" "m"))]
7667   "IS_STACK_POP (operands[4])
7668    && (GET_CODE (operands[3]) == MEM &&
7669        rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
7670   "*
7672   rtx ops[2];
7674   ops[0] = operands[2];
7675   ops[1] = gen_rtx_MEM (HImode,
7676                     gen_rtx_POST_INC (HImode, stack_pointer_rtx));
7677   m68hc11_gen_movhi (insn, ops);
7678   return \"\";
7683 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
7685 (define_peephole
7686   [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
7687    (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7688   "TARGET_M6811"
7689   "*
7691   return \"sts\\t%t0\\n\\tld%0\\t%t0\";
7695 (define_peephole
7696   [(set (match_operand:HI 0 "hard_reg_operand" "")
7697         (match_operand:HI 1 "memory_operand" ""))
7698    (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7699   "TARGET_M6811
7700    && !side_effects_p (operands[1])
7701    && !reg_mentioned_p (operands[0], operands[1])"
7702   "*
7704   rtx ops[2];
7706   ops[0] = operands[0];
7707   ops[1] = operands[1];
7708   m68hc11_gen_movhi (insn, ops);
7709   ops[0] = operands[2];
7710   m68hc11_gen_movhi (insn, ops);
7711   return \"\";
7714 ;; Peephole for Z register replacement.
7715 ;; Avoid to use _.tmp register when comparing D and X if we can compare
7716 ;; with soft register
7717 (define_peephole
7718   [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
7719    (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
7720    (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
7721                        (reg:HI SOFT_TMP_REGNUM)))]
7722   "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
7723   "*
7725   rtx ops[2];
7727   ops[0] = operands[0];
7728   ops[1] = operands[1];
7729   m68hc11_gen_movhi (insn, ops);
7730   return \"cp%2\\t%1\";