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