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