OSDN Git Service

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