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