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