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