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