OSDN Git Service

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