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