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