OSDN Git Service

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