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