1 ;;- Machine description file for Motorola 68HC11 and 68HC12.
2 ;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
3 ;;- Free Software Foundation, Inc.
4 ;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING. If not, write to
20 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
21 ;; Boston, MA 02111-1307, USA.
24 ;; A first 68HC11 port was made by Otto Lind (otto@coactive.com)
25 ;; on gcc 2.6.3. I have used it as a starting point for this port.
26 ;; However, this new port is a complete re-write. Its internal
27 ;; design is completely different. The generated code is not
28 ;; compatible with the gcc 2.6.3 port.
30 ;; The gcc 2.6.3 port is available at:
32 ;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
35 ;;- Instruction patterns. When multiple patterns apply,
36 ;;- the first one in the file is chosen.
38 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
40 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
41 ;;- updates for most instructions.
44 ;; The following constraints are used:
46 ;; Single pair registers:
47 ;; a register 'a' 8-bit
48 ;; b register 'b' 8-bit
49 ;; d register 'd' 16-bit
50 ;; t pseudo soft register 'TMP' 16-bit
51 ;; v register 'd' for 68hc11, 16-bit
53 ;; (used for scratch register)
54 ;; w register 'sp' 16-bit
55 ;; x register 'x' 16-bit
56 ;; y register 'y' 16-bit
57 ;; z register 'z' 16-bit (fake r for 68HC11 and 68HC12)
58 ;; D register 'd+x' 32-bit
60 ;; Group of registers:
61 ;; q register 'a' or 'b' or 'd' 8-bit
62 ;; u pseudo soft register 16-bit
63 ;; A register 'x', 'y', 'z' 16-bit
64 ;; B register 'x', 'y' 16-bit
65 ;; h register 'd', 'x', 'y', 'z' 16-bit
69 ;; Q an operand which is in memory but whose address is constant
70 ;; (ie, a (MEM (SYMBOL_REF x))). This constraint is used by
71 ;; bset/bclr instructions together with linker relaxation. The
72 ;; operand can be translated to a page0 addressing mode if the
73 ;; symbol address is in page0 (0..255).
75 ;; R an operand which is in memory and whose address is expressed
76 ;; with 68HC11/68HC12 indexed addressing mode. In general this
77 ;; is any valid (MEM) except a (MEM (SYMBOL_REF x)).
79 ;; U an operand which is in memory and if it uses the 68HC12 indexed
80 ;; addressing mode, the offset is in the range -16..+15. This is
81 ;; used by 68HC12 movb/movw instructions since they do not accept
82 ;; the full 16-bit offset range (as other insn do).
85 ;; Immediate integer operand constraints:
86 ;; `L' is for range -65536 to 65536
87 ;; `M' is for values whose 16-bit low part is 0
88 ;; 'N' is for +1 or -1.
89 ;; 'O' is for 16 (for rotate using swap).
90 ;; 'P' is for range -8 to 2 (used by addhi_sp)
92 ;; In many cases, it's not possible to use the 'g' or 'r' constraints.
94 ;; Operands modifiers:
96 ;; %b Get the low part of the operand (to obtain a QImode)
97 ;; This modifier must always be used for QImode operations
98 ;; because a correction must be applied when the operand
99 ;; is a soft register (ex: *ZD1). Otherwise, we generate
100 ;; *ZD1 and this is the high part of the register. For other
101 ;; kinds of operands, if the operand is already QImode, no
102 ;; additional correction is made.
103 ;; %h Get the high part of the operand (to obtain a QImode)
104 ;; %t Represents the temporary/scratch register *_.tmp
105 ;; The scratch register is used in some cases when GCC puts
106 ;; some values in bad registers.
108 ;; 32/64-bit Patterns:
109 ;; The 68HC11 does not support 32/64-bit operations. Most of the
110 ;; 32/64-bit patterns are defined to split the instruction in
111 ;; 16-bits patterns. Providing split patterns generates better code
112 ;; than letting GCC implement the 32/64-bit operation itself.
117 ;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
118 ;; otherwise some insn are not satisfied.
120 ;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
121 ;; be valid only when z_replacement_completed == 2 because once these
122 ;; swap instructions are generated, a flow/cse pass fails to handle
123 ;; them correctly (it would treat the X, Y or D register as dead sometimes).
125 ;; o Some split pattern generate instructions that operate on 'a' or 'b'
126 ;; register directly (high part and low part of D respectively).
127 ;; Such split pattern must also be valid when z_replacement_completed == 2
128 ;; because flow/cse is not aware that D is composed of {a, b}.
130 ;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
131 ;; the high part of a soft register must be expanded after z_replacement
134 ;;---------------------------------------------------------------------------
139 (X_REGNUM 0) ; Index X register
140 (D_REGNUM 1) ; Data register
141 (Y_REGNUM 2) ; Index Y register
142 (SP_REGNUM 3) ; Stack pointer
143 (PC_REGNUM 4) ; Program counter
144 (A_REGNUM 5) ; A (high part of D)
145 (B_REGNUM 6) ; B (low part of D)
146 (CC_REGNUM 7) ; Condition code register
147 (SOFT_TMP_REGNUM 10) ; TMP soft register
148 (SOFT_Z_REGNUM 11) ; Z soft register
149 (SOFT_XY_REGNUM 12) ; XY soft register
152 ;;--------------------------------------------------------------------
154 ;;--------------------------------------------------------------------
156 ;; The test and compare insn must not accept a memory operand with
157 ;; an auto-inc mode. If we do this, the reload can emit move insns
158 ;; after the test or compare. Such move will set the flags and therefore
159 ;; break the comparison. This can happen if the auto-inc register
160 ;; does not happen to be a hard register (ie, reloading occurs).
161 ;; An offsetable memory operand should be ok. The 'tst_operand' and
162 ;; 'cmp_operand' predicates take care of this rule.
164 (define_expand "tstsi"
166 (match_operand:SI 0 "tst_operand" ""))]
170 m68hc11_compare_op0 = operands[0];
171 m68hc11_compare_op1 = const0_rtx;
175 (define_expand "tsthi"
177 (match_operand:HI 0 "tst_operand" ""))]
181 m68hc11_compare_op0 = operands[0];
182 m68hc11_compare_op1 = const0_rtx;
186 (define_insn "tsthi_1"
188 (match_operand:HI 0 "tst_operand" "dx,*y"))]
192 if (D_REG_P (operands[0]) && !TARGET_M6812)
193 return \"std\\t%t0\";
195 return \"cp%0\\t#0\";
198 (define_expand "tstqi"
200 (match_operand:QI 0 "tst_operand" ""))]
204 m68hc11_compare_op0 = operands[0];
205 m68hc11_compare_op1 = const0_rtx;
210 ;; Split pattern for (tst:QI) on an address register.
214 (match_operand:QI 0 "hard_addr_reg_operand" ""))]
215 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
216 [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
217 (set (match_dup 1) (reg:HI D_REGNUM))])
218 (set (cc0) (reg:QI D_REGNUM))
219 (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
220 (set (match_dup 1) (reg:HI D_REGNUM))])]
221 "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
223 (define_insn "tstqi_1"
225 (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
229 if (A_REG_P (operands[0]))
232 else if (D_REG_P (operands[0]))
235 else if (dead_register_here (insn, d_reg))
236 return \"ldab\\t%b0\";
239 return \"tst\\t%b0\";
243 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
244 ;; during the Z register replacement. They are used when an operand
245 ;; uses the Z register as an index register (ie, (MEM:QI (REG:HI Z))).
246 ;; In that case, we have to preserve the values of the replacement
247 ;; register (as well as the CC0 since the insns are compare insns).
248 ;; To do this, the replacement register is pushed on the stack and
249 ;; restored after the real compare. A pattern+split is defined to
250 ;; avoid problems with the flow+cse register pass which are made
251 ;; after Z register replacement.
253 (define_insn_and_split "tstqi_z_used"
255 (match_operand:QI 0 "tst_operand" "m"))
256 (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
257 (use (reg:HI SOFT_Z_REGNUM))]
260 "z_replacement_completed == 2"
261 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
262 (set (match_dup 1) (match_dup 2))
263 (set (cc0) (match_dup 0))
264 (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
265 "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
268 ;;--------------------------------------------------------------------
270 ;;--------------------------------------------------------------------
272 (define_expand "cmpsi"
274 (compare (match_operand:SI 0 "tst_operand" "")
275 (match_operand:SI 1 "cmp_operand" "")))]
279 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
280 operands[0] = force_reg (SImode, operands[0]);
282 m68hc11_compare_op0 = operands[0];
283 m68hc11_compare_op1 = operands[1];
288 ;; Comparison of a hard register with another one is provided because
289 ;; it helps GCC to avoid to spill a pseudo hard register.
290 ;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
291 ;; (except that we loose the information that the value is saved in it).
293 ;; The split pattern transforms the comparison into a save of one hard
294 ;; register and a comparison with the temporary.
298 (compare (match_operand:HI 0 "hard_reg_operand" "")
299 (match_operand:HI 1 "hard_reg_operand" "")))]
301 && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
302 [(set (match_dup 2) (match_dup 1))
304 (compare (match_dup 0) (match_dup 2)))]
305 "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
309 (compare (match_operand:HI 0 "hard_reg_operand" "")
310 (match_operand:HI 1 "hard_reg_operand" "")))]
312 && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
313 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
315 (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
318 (define_expand "cmphi"
320 (compare (match_operand:HI 0 "tst_operand" "")
321 (match_operand:HI 1 "cmp_operand" "")))]
325 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
326 operands[0] = force_reg (HImode, operands[0]);
328 m68hc11_compare_op0 = operands[0];
329 m68hc11_compare_op1 = operands[1];
333 (define_insn "cmphi_1_hc12"
335 (compare (match_operand:HI 0 "tst_operand"
336 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
337 (match_operand:HI 1 "general_operand"
338 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
342 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
344 cc_status.flags |= CC_REVERSED;
345 return \"cp%1\\t%0\";
347 else if (SP_REG_P (operands[1]))
348 return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
349 else if (H_REG_P (operands[1]))
350 return \"psh%1\n\\tcp%0\\t2,sp+\";
352 return \"cp%0\\t%1\";
355 (define_insn "cmphi_1_hc11"
357 (compare (match_operand:HI 0 "tst_operand"
358 "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
359 (match_operand:HI 1 "cmp_operand"
360 "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
364 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
366 cc_status.flags |= CC_REVERSED;
367 return \"cp%1\\t%0\";
369 else if (H_REG_P (operands[1]))
372 return \"cp%0\\t%1\";
375 (define_insn_and_split "cmphi_z_used"
377 (compare (match_operand:HI 0 "tst_operand" "dxy,m")
378 (match_operand:HI 1 "cmp_operand" "mi,dxy")))
379 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
380 (use (reg:HI SOFT_Z_REGNUM))]
383 "z_replacement_completed == 2"
384 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
385 (set (match_dup 2) (match_dup 3))
386 (set (cc0) (compare (match_dup 0) (match_dup 1)))
387 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
388 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
391 ;; 8-bit comparison with address register.
392 ;; There is no such comparison instruction, we have to temporarily switch
393 ;; the address register and the D register and do the comparison with D.
394 ;; The xgdx and xgdy instructions preserve the flags.
398 (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
399 (match_operand:QI 1 "cmp_operand" "")))]
400 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
401 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
402 (set (match_dup 3) (reg:HI D_REGNUM))])
404 (compare (reg:QI D_REGNUM) (match_dup 1)))
405 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
406 (set (match_dup 3) (reg:HI D_REGNUM))])]
407 "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
411 (compare (match_operand:QI 0 "hard_reg_operand" "")
412 (match_operand:QI 1 "hard_reg_operand" "")))]
414 [(set (match_dup 3) (match_dup 4))
416 (compare (match_dup 0) (match_dup 2)))]
417 "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
418 operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
419 operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
421 (define_expand "cmpqi"
423 (compare (match_operand:QI 0 "tst_operand" "")
424 (match_operand:QI 1 "cmp_operand" "")))]
428 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
429 operands[0] = force_reg (QImode, operands[0]);
431 m68hc11_compare_op0 = operands[0];
432 m68hc11_compare_op1 = operands[1];
436 (define_insn "bitcmpqi"
438 (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
439 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
448 (define_split /* "bitcmpqi" */
450 (and:QI (match_operand:QI 0 "tst_operand" "")
451 (match_operand:QI 1 "hard_addr_reg_operand" "")))]
452 "z_replacement_completed == 2"
453 [(set (match_dup 3) (match_dup 2))
454 (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
455 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
456 operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
457 operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
459 (define_insn_and_split "bitcmpqi_z_used"
461 (and:QI (match_operand:QI 0 "tst_operand" "d,m")
462 (match_operand:QI 1 "cmp_operand" "m,d")))
463 (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
464 (use (reg:HI SOFT_Z_REGNUM))]
467 "z_replacement_completed == 2"
468 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
469 (set (match_dup 2) (match_dup 3))
470 (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
471 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
472 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
474 (define_insn "bitcmphi"
476 (and:HI (match_operand:HI 0 "tst_operand" "d")
477 (match_operand:HI 1 "const_int_operand" "i")))]
478 "(INTVAL (operands[1]) & 0x0ff) == 0
479 || (INTVAL (operands[1]) & 0x0ff00) == 0"
482 if ((INTVAL (operands[1]) & 0x0ff) == 0)
483 return \"bita\\t%h1\";
485 return \"bitb\\t%1\";
488 (define_insn "bitcmpqi_12"
490 (zero_extract (match_operand:HI 0 "tst_operand" "d")
491 (match_operand:HI 1 "const_int_operand" "i")
492 (match_operand:HI 2 "const_int_operand" "i")))]
493 "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
494 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
495 && (unsigned) INTVAL (operands[2]) >= 8)"
500 int startpos = INTVAL (operands[2]);
501 int bitsize = INTVAL (operands[1]);
506 mask = (1 << (startpos + bitsize)) - 1;
507 mask &= ~((1 << startpos) - 1);
509 ops[0] = GEN_INT (mask);
510 output_asm_insn (\"bita\\t%0\", ops);
514 mask = (1 << (startpos + bitsize)) - 1;
515 mask &= ~((1 << startpos) - 1);
517 ops[0] = GEN_INT (mask);
518 output_asm_insn (\"bitb\\t%0\", ops);
523 (define_insn "cmpqi_1"
525 (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
526 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
530 if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
534 else if (D_REG_P (operands[0]))
536 return \"cmpb\\t%b1\";
538 cc_status.flags |= CC_REVERSED;
539 return \"cmpb\\t%b0\";
542 (define_insn_and_split "cmpqi_z_used"
544 (compare (match_operand:QI 0 "tst_operand" "dxy,m")
545 (match_operand:QI 1 "cmp_operand" "m,dxy")))
546 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
547 (use (reg:HI SOFT_Z_REGNUM))]
550 "z_replacement_completed == 2"
551 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
552 (set (match_dup 2) (match_dup 3))
553 (set (cc0) (compare (match_dup 0) (match_dup 1)))
554 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
555 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
557 ;;--------------------------------------------------------------------
558 ;;- Move strict_low_part
559 ;;--------------------------------------------------------------------
561 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
562 ;; The replacement must be made at the very end because we loose the
563 ;; (strict_low_part ...) information. This is correct for our machine
564 ;; description but not for GCC optimization passes.
566 (define_insn_and_split "movstrictsi"
567 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
568 (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
571 "z_replacement_completed == 2"
572 [(set (match_dup 0) (match_dup 1))]
575 (define_insn_and_split "movstricthi"
576 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
577 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
580 "z_replacement_completed == 2"
581 [(set (match_dup 0) (match_dup 1))]
584 (define_insn_and_split "movstrictqi"
585 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
586 (match_operand:QI 1 "general_operand" "d,imudA"))]
589 "z_replacement_completed == 2"
590 [(set (match_dup 0) (match_dup 1))]
593 ;;--------------------------------------------------------------------
594 ;;- 64-bit Move Operations.
595 ;; The movdi and movdf patterns are identical except for the mode.
596 ;; They are also very similar to those for movsi and movsf.
598 ;; For 68HC11, we need a scratch register (either D, X, Y)
599 ;; because there is no memory->memory moves. It must be defined with
600 ;; earlyclobber (&) so that it does not appear in the source or destination
601 ;; address. Providing patterns for movdi/movdf allows GCC to generate
602 ;; better code. [Until now, the scratch register is limited to D because
603 ;; otherwise we can run out of registers in the A_REGS class for reload].
605 ;; For 68HC12, the scratch register is not necessary. To use the same
606 ;; pattern and same split, we use the 'v' constraint. This tells the
607 ;; reload to use the _.tmp register (which is not used at all).
608 ;; The insn will be split in one or several memory moves (movw).
609 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
610 ;;--------------------------------------------------------------------
611 (define_expand "movdi"
612 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
613 (match_operand:DI 1 "general_operand" ""))
614 (clobber (match_scratch:HI 2 ""))])]
617 /* For push/pop, emit a REG_INC note to make sure the reload
618 inheritance and reload CSE pass notice the change of the stack
620 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
624 insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
625 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
632 ;; Separate push from normal moves to avoid reloading problems
633 ;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
634 ;; We can also accept more scratch registers.
635 (define_insn_and_split "*pushdi_internal"
636 [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
637 (match_operand:DI 1 "general_operand" "i,U,m,!u"))
638 (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
643 "m68hc11_split_move (operands[0], operands[1], operands[2]);
646 (define_insn_and_split "movdi_internal"
647 [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
648 (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
649 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
654 "m68hc11_split_move (operands[0], operands[1], operands[2]);
657 (define_expand "movdf"
658 [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
659 (match_operand:DF 1 "general_operand" ""))
660 (clobber (match_scratch:HI 2 ""))])]
662 "/* For push/pop, emit a REG_INC note to make sure the reload
663 inheritance and reload CSE pass notice the change of the stack
665 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
669 insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
670 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
677 ;; See pushdi_internal
678 (define_insn_and_split "*pushdf_internal"
679 [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
680 (match_operand:DF 1 "general_operand" "i,U,m,!u"))
681 (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
686 "m68hc11_split_move (operands[0], operands[1], operands[2]);
689 (define_insn_and_split "movdf_internal"
690 [(set (match_operand:DF 0 "non_push_operand" "=mu,U,!u,U,m,m,!u")
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"))]
697 "m68hc11_split_move (operands[0], operands[1], operands[2]);
700 ;;--------------------------------------------------------------------
701 ;;- 32-bit Move Operations.
702 ;; The movsi and movsf patterns are identical except for the mode.
703 ;; When we move to/from a hard register (d+x), we don't need a scratch.
704 ;; Otherwise, a scratch register is used as intermediate register for
705 ;; the move. The '&' constraint is necessary to make sure the reload
706 ;; pass does not give us a register that dies in the insn and is used
707 ;; for input/output operands.
708 ;;--------------------------------------------------------------------
709 (define_expand "movsi"
710 [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
711 (match_operand:SI 1 "general_operand" ""))
712 (clobber (match_scratch:HI 2 ""))])]
714 "/* For push/pop, emit a REG_INC note to make sure the reload
715 inheritance and reload CSE pass notice the change of the stack
717 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
721 insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
722 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
729 (define_insn_and_split "*pushsi_internal"
730 [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
731 (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
732 (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
737 "m68hc11_split_move (operands[0], operands[1], operands[2]);
740 (define_insn_and_split "movsi_internal"
741 [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
742 (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
743 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
748 "m68hc11_split_move (operands[0], operands[1], operands[2]);
751 (define_expand "movsf"
752 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
753 (match_operand:SF 1 "general_operand" ""))
754 (clobber (match_scratch:HI 2 ""))])]
756 "/* For push/pop, emit a REG_INC note to make sure the reload
757 inheritance and reload CSE pass notice the change of the stack
759 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
763 insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
764 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
771 (define_insn_and_split "*pushsf_internal"
772 [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
773 (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
774 (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
779 "m68hc11_split_move (operands[0], operands[1], operands[2]);
782 (define_insn_and_split "movsf_internal"
783 [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
784 (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
785 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
790 "m68hc11_split_move (operands[0], operands[1], operands[2]);
794 ;;--------------------------------------------------------------------
795 ;;- 16-bit Move Operations.
796 ;; We don't need a scratch register.
797 ;;--------------------------------------------------------------------
799 (define_insn "*movhi2_push"
800 [(set (match_operand:HI 0 "push_operand" "=<,<,<")
801 (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
802 "TARGET_M6811 && !TARGET_M6812"
805 cc_status = cc_prev_status;
806 if (D_REG_P (operands[1]))
808 output_asm_insn (\"pshb\", operands);
811 else if (X_REG_P (operands[1]))
815 else if (Y_REG_P (operands[1]))
819 fatal_insn (\"Invalid register in the instruction\", insn);
822 (define_insn "*movhi2_pop"
823 [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
824 (match_operand:HI 1 "pop_operand" ">,>"))]
828 cc_status = cc_prev_status;
829 if (D_REG_P (operands[0]))
831 output_asm_insn (\"pula\", operands);
834 else if (X_REG_P (operands[0]))
838 else if (Y_REG_P (operands[0]))
842 fatal_insn (\"Invalid register in the instruction\", insn);
845 (define_expand "movhi"
846 [(set (match_operand:HI 0 "nonimmediate_operand" "")
847 (match_operand:HI 1 "general_operand" ""))]
851 if (reload_in_progress)
853 if (m68hc11_reload_operands (operands))
858 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
860 if (GET_CODE (operands[0]) == MEM &&
861 (GET_CODE (operands[1]) == MEM
862 || GET_CODE (operands[1]) == CONST_INT))
864 operands[1] = force_reg (HImode, operands[1]);
866 else if (IS_STACK_PUSH (operands[0])
867 && GET_CODE (operands[1]) != REG)
869 operands[1] = force_reg (HImode, operands[1]);
872 /* For push/pop, emit a REG_INC note to make sure the reload
873 inheritance and reload CSE pass notice the change of the stack
875 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
879 insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
880 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
887 (define_insn "movhi_const0"
888 [(set (match_operand:HI 0 "non_push_operand" "=d,A,um")
894 clr\\t%b0\\n\\tclr\\t%h0")
896 (define_insn "*movhi_68hc12"
897 [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,U,U,m,!u")
898 (match_operand:HI 1 "general_operand" "U,dAwim,!u,dAwi,!u,dAw,riU"))]
902 m68hc11_gen_movhi (insn, operands);
906 (define_insn "*movhi_m68hc11"
907 [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
908 (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
912 m68hc11_gen_movhi (insn, operands);
916 ;;--------------------------------------------------------------------
917 ;;- 8-bit Move Operations.
918 ;; We don't need a scratch register.
919 ;;--------------------------------------------------------------------
921 ;; The *a alternative also clears the high part of the register.
922 ;; This should be ok since this is not the (strict_low_part) set.
924 (define_insn "movqi_const0"
925 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
936 ;; 8-bit operations on address registers.
938 ;; Switch temporary to the D register and load the value in B.
939 ;; This is possible as long as the address register does not
940 ;; appear in the source operand.
943 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
944 (match_operand:QI 1 "general_operand" ""))]
945 "z_replacement_completed == 2
946 && !reg_mentioned_p (operands[0], operands[1])
947 && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
948 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
949 (set (match_dup 2) (reg:HI D_REGNUM))])
950 (set (reg:QI D_REGNUM) (match_dup 1))
951 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
952 (set (match_dup 2) (reg:HI D_REGNUM))])]
953 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
956 ;; 8-bit operations on address registers.
959 [(set (match_operand:QI 0 "nonimmediate_operand" "")
960 (match_operand:QI 1 "hard_addr_reg_operand" ""))]
961 "z_replacement_completed == 2
962 && !reg_mentioned_p (operands[1], operands[0])
963 && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
964 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
965 (set (match_dup 2) (reg:HI D_REGNUM))])
966 (set (match_dup 0) (reg:QI D_REGNUM))
967 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
968 (set (match_dup 2) (reg:HI D_REGNUM))])]
969 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
971 (define_insn "*movqi2_push"
972 [(set (match_operand:QI 0 "push_operand" "=<,<")
973 (match_operand:QI 1 "general_operand" "d,!*A"))]
977 if (A_REG_P (operands[1]))
980 cc_status = cc_prev_status;
985 (define_expand "movqi"
986 [(set (match_operand:QI 0 "nonimmediate_operand" "")
987 (match_operand:QI 1 "general_operand" ""))]
991 if (reload_in_progress)
993 if (m68hc11_reload_operands (operands))
998 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
1000 if (GET_CODE (operands[0]) == MEM
1001 && (GET_CODE (operands[1]) == MEM
1002 || GET_CODE (operands[1]) == CONST_INT))
1004 operands[1] = force_reg (QImode, operands[1]);
1006 else if (IS_STACK_PUSH (operands[0])
1007 && GET_CODE (operands[1]) != REG)
1009 operands[1] = force_reg (QImode, operands[1]);
1012 /* For push/pop, emit a REG_INC note to make sure the reload
1013 inheritance and reload CSE pass notice the change of the stack
1015 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
1019 insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
1020 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
1027 (define_insn "*movqi_68hc12"
1028 [(set (match_operand:QI 0 "nonimmediate_operand"
1029 "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
1030 (match_operand:QI 1 "general_operand"
1031 "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
1035 m68hc11_gen_movqi (insn, operands);
1039 (define_insn "*movqi_m68hc11"
1040 [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
1041 (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
1045 m68hc11_gen_movqi (insn, operands);
1049 ;;--------------------------------------------------------------------
1051 ;;--------------------------------------------------------------------
1052 ;; Swapping registers is used for split patterns.
1053 (define_insn "swap_areg"
1054 [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1055 (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1056 (set (match_dup 1) (match_dup 0))]
1060 m68hc11_output_swap (insn, operands);
1064 ;;--------------------------------------------------------------------
1065 ;;- Truncation insns.
1066 ;;--------------------------------------------------------------------
1068 ;; Truncation are not necessary because GCC knows how to truncate,
1069 ;; specially when values lie in consecutive registers.
1072 (define_expand "floatunssisf2"
1073 [(set (match_operand:SF 0 "nonimmediate_operand" "")
1074 (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1076 "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
1077 SFmode, SImode, 2, operands);
1080 (define_expand "floatunssidf2"
1081 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1082 (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1084 "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
1085 DFmode, SImode, 2, operands);
1088 ;;--------------------------------------------------------------------
1089 ;;- Zero extension insns.
1090 ;;--------------------------------------------------------------------
1093 ;; 64-bit extend. The insn will be split into 16-bit instructions just
1094 ;; before the final pass. We need a scratch register for the split.
1095 ;; The final value can be generated on the stack directly. This is more
1096 ;; efficient and useful for conversions made during parameter passing rules.
1098 (define_insn "zero_extendqidi2"
1099 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1101 (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1102 (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1107 [(set (match_operand:DI 0 "push_operand" "")
1108 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1109 (clobber (match_scratch:HI 2 "=&dB"))]
1110 "z_replacement_completed == 2"
1114 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1115 rtx push = m68hc11_gen_lowpart (HImode, low);
1116 rtx src = operands[1];
1118 /* Source operand must be in a hard register. */
1121 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1122 emit_move_insn (src, operands[1]);
1125 /* Source is in D, we can push B then one word of 0 and we do
1126 a correction on the stack pointer. */
1129 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1130 emit_move_insn (operands[2], const0_rtx);
1131 if (D_REG_P (operands[2]))
1133 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1137 emit_move_insn (push, operands[2]);
1138 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1139 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1145 /* Source is in X or Y. It's better to push the 16-bit register
1146 and then to some stack adjustment. */
1147 src = gen_rtx_REG (HImode, REGNO (src));
1148 emit_move_insn (push, src);
1149 emit_move_insn (operands[2], const0_rtx);
1150 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1151 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1153 emit_move_insn (push, operands[2]);
1154 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1155 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1158 emit_move_insn (push, operands[2]);
1159 emit_move_insn (push, operands[2]);
1160 emit_move_insn (push, operands[2]);
1165 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1166 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1167 (clobber (match_scratch:HI 2 "=&dB"))]
1168 "z_replacement_completed == 2"
1172 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1173 rtx low2 = m68hc11_gen_lowpart (HImode, low);
1174 rtx src = operands[1];
1176 /* Source operand must be in a hard register. */
1179 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1180 emit_move_insn (src, operands[1]);
1183 emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1184 emit_move_insn (operands[2], const0_rtx);
1185 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1186 emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1188 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1189 low = m68hc11_gen_highpart (SImode, operands[0]);
1190 emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1191 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1195 (define_insn "zero_extendhidi2"
1196 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1198 (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1199 (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1204 [(set (match_operand:DI 0 "non_push_operand" "")
1206 (match_operand:HI 1 "nonimmediate_operand" "")))
1207 (clobber (match_scratch:HI 2 ""))]
1208 "z_replacement_completed == 2"
1212 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1213 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1214 rtx src = operands[1];
1216 /* Make sure the source is in a hard register. */
1220 emit_move_insn (src, operands[1]);
1223 /* Move the low part first for the push. */
1224 emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1226 /* Now, use the scratch register to fill in the zeros. */
1227 emit_move_insn (operands[2], const0_rtx);
1228 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1229 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1230 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1234 (define_insn "zero_extendsidi2"
1235 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1237 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1238 (clobber (match_scratch:HI 2 "=d,d,&d,d"))]
1243 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1245 (match_operand:SI 1 "nonimmediate_operand" "")))
1246 (clobber (match_scratch:HI 2 ""))]
1247 "z_replacement_completed == 2"
1251 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1252 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1254 /* Move the low part first so that this is ok for a push. */
1255 m68hc11_split_move (low, operands[1], operands[2]);
1257 /* Use the scratch register to clear the high part of the destination. */
1258 emit_move_insn (operands[2], const0_rtx);
1259 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1260 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1265 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1266 ;; because it's less efficient.
1268 (define_insn "zero_extendhisi2"
1269 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1271 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1272 (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1277 [(set (match_operand:SI 0 "non_push_operand" "")
1279 (match_operand:HI 1 "nonimmediate_operand" "")))
1280 (clobber (match_scratch:HI 2 ""))]
1285 rtx src = operands[1];
1287 if (!H_REG_P (src) && !H_REG_P (operands[0]))
1290 emit_move_insn (src, operands[1]);
1292 emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1293 emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1297 (define_insn "zero_extendqisi2"
1298 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1300 (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1305 [(set (match_operand:SI 0 "non_push_operand" "")
1306 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1307 "reload_completed && !X_REG_P (operands[0])"
1308 [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1309 (set (match_dup 3) (const_int 0))]
1311 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1312 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1315 [(set (match_operand:SI 0 "hard_reg_operand" "")
1316 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1317 "z_replacement_completed == 2 && X_REG_P (operands[0])"
1318 [(set (match_dup 2) (match_dup 3))
1319 (set (match_dup 4) (const_int 0))
1320 (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1322 if (X_REG_P (operands[1]))
1324 emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
1325 gen_rtx_REG (HImode, HARD_X_REGNUM)));
1326 emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
1327 gen_rtx_REG (QImode, HARD_D_REGNUM)));
1328 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
1333 if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
1335 emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1338 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
1341 operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1342 operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1343 if (A_REG_P (operands[1]))
1345 operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1346 operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
1347 operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
1351 operands[5] = operands[2] =
1352 operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1353 operands[6] = operands[1];
1357 (define_insn "zero_extendqihi2"
1358 [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
1360 (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1364 if (A_REG_P (operands[0]))
1367 if (H_REG_P (operands[0]))
1369 output_asm_insn (\"clra\", operands);
1370 if (operands[0] != operands[1]
1371 && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1373 if (X_REG_P (operands[1])
1374 || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1376 output_asm_insn (\"stx\\t%t1\", operands);
1377 output_asm_insn (\"ldab\\t%T0\", operands);
1379 else if (Y_REG_P (operands[1])
1380 || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1382 output_asm_insn (\"sty\\t%t1\", operands);
1383 output_asm_insn (\"ldab\\t%T0\", operands);
1387 output_asm_insn (\"ldab\\t%b1\", operands);
1389 cc_status.flags |= CC_NOT_NEGATIVE;
1393 /* Status refers to the clra insn. Status is ok for others
1394 * since we have loaded the value in B.
1401 if (A_REG_P (operands[1]))
1403 output_asm_insn (\"st%1\\t%0\", operands);
1404 output_asm_insn (\"clr\\t%h0\", operands);
1409 output_asm_insn (\"clr\\t%h0\", operands);
1410 output_asm_insn (\"stab\\t%b0\", operands);
1411 cc_status.flags |= CC_NOT_NEGATIVE;
1418 ;;--------------------------------------------------------------------
1419 ;;- Sign extension insns.
1420 ;;--------------------------------------------------------------------
1422 (define_insn "extendqisi2"
1423 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1424 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1431 /* The 68HC12 has a sign-extension instruction. Use it when the
1432 destination is the register (X,D). First sign-extend the low
1433 part and fill X with the sign-extension of the high part. */
1434 if (TARGET_M6812 && X_REG_P (operands[0]))
1436 if (!D_REG_P (operands[1]))
1438 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1439 ops[1] = operands[1];
1440 m68hc11_gen_movqi (insn, ops);
1442 return \"sex\\tb,d\\n\\tsex\\ta,x\";
1445 ops[2] = gen_label_rtx ();
1447 if (X_REG_P (operands[1]))
1449 output_asm_insn (\"xgdx\", operands);
1452 else if (X_REG_P (operands[0]))
1454 /* X can be used as an indexed addressing in the source.
1455 Get the value before clearing it. */
1456 if (reg_mentioned_p (ix_reg, operands[1]))
1458 output_asm_insn (\"ldab\\t%b1\", operands);
1461 output_asm_insn (\"ldx\\t#0\", operands);
1464 output_asm_insn (\"clra\", operands);
1465 if (!X_REG_P (operands[0]))
1467 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1468 ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1470 if (IS_STACK_PUSH (operands[0]))
1472 output_asm_insn (\"pshb\", ops);
1473 output_asm_insn (\"tstb\", ops);
1477 output_asm_insn (\"stab\\t%b1\", ops);
1480 else if (D_REG_P (operands[1]) || need_tst)
1482 output_asm_insn (\"tstb\", operands);
1486 output_asm_insn (\"ldab\\t%b1\", operands);
1488 output_asm_insn (\"bpl\\t%l2\", ops);
1489 output_asm_insn (\"deca\", operands);
1490 if (X_REG_P (operands[0]))
1491 output_asm_insn (\"dex\", operands);
1493 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1495 if (!X_REG_P (operands[0]))
1497 if (IS_STACK_PUSH (operands[0]))
1499 output_asm_insn (\"psha\", ops);
1500 output_asm_insn (\"psha\", ops);
1501 output_asm_insn (\"psha\", ops);
1505 output_asm_insn (\"staa\\t%h0\", ops);
1507 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1508 if (dead_register_here (insn, d_reg))
1510 output_asm_insn (\"tab\", ops);
1511 output_asm_insn (\"std\\t%0\", ops);
1515 output_asm_insn (\"staa\\t%b0\", ops);
1516 output_asm_insn (\"staa\\t%h0\", ops);
1526 (define_insn "extendqihi2"
1527 [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1528 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1534 if (A_REG_P (operands[0]))
1537 ops[0] = gen_label_rtx ();
1538 if (D_REG_P (operands[0]))
1542 if (!D_REG_P (operands[1]))
1544 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1545 ops[1] = operands[1];
1546 m68hc11_gen_movqi (insn, ops);
1548 return \"sex\\tb,d\";
1550 output_asm_insn (\"clra\", operands);
1551 if (H_REG_P (operands[1]))
1553 output_asm_insn (\"tstb\", operands);
1557 output_asm_insn (\"ldab\\t%b1\", operands);
1559 output_asm_insn (\"bpl\\t%l0\", ops);
1560 output_asm_insn (\"deca\", operands);
1562 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1563 CODE_LABEL_NUMBER (ops[0]));
1567 output_asm_insn (\"clr\\t%h0\", operands);
1568 if (m68hc11_register_indirect_p (operands[1], HImode))
1570 ops[1] = operands[1];
1571 output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1576 output_asm_insn (\"tst\\t%b1\", operands);
1577 output_asm_insn (\"bpl\\t%l0\", ops);
1579 output_asm_insn (\"dec\\t%h0\", operands);
1580 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1581 CODE_LABEL_NUMBER (ops[0]));
1588 ;; Split the special case where the source of the sign extend is
1589 ;; either Y or Z. In that case, we can't move the source in the D
1590 ;; register directly. The movhi pattern handles this move by using
1591 ;; a temporary scratch memory location.
1594 [(set (match_operand:SI 0 "register_operand" "")
1595 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1596 "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1597 [(set (reg:HI D_REGNUM) (match_dup 1))
1598 (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1601 (define_insn "extendhisi2"
1602 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1603 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1610 if (Y_REG_P (operands[1]))
1613 if (X_REG_P (operands[1]))
1615 output_asm_insn (\"xgdx\", operands);
1620 /* X can be used as an indexed addressing in the source.
1621 Get the value before clearing it. */
1622 x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1625 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1626 ops[1] = operands[1];
1627 m68hc11_gen_movhi (insn, ops);
1632 if (TARGET_M6812 && 0)
1634 /* This sequence of code is larger than the one for 68HC11.
1635 Don't use it; keep it for documentation. */
1636 if (!D_REG_P (operands[1]) && !x_reg_used)
1638 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1639 ops[1] = operands[1];
1640 m68hc11_gen_movhi (insn, ops);
1642 output_asm_insn (\"sex\\ta,x\", operands);
1643 output_asm_insn (\"xgdx\", operands);
1644 output_asm_insn (\"sex\\ta,d\", operands);
1648 output_asm_insn (\"ldx\\t#0\", operands);
1649 if (D_REG_P (operands[1]) || x_reg_used)
1651 output_asm_insn (\"tsta\", operands);
1655 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1656 ops[1] = operands[1];
1657 m68hc11_gen_movhi (insn, ops);
1660 ops[0] = gen_label_rtx ();
1661 output_asm_insn (\"bpl\\t%l0\", ops);
1662 output_asm_insn (\"dex\", operands);
1663 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1669 ;;--------------------------------------------------------------------
1670 ;;- Min and Max instructions (68HC12).
1671 ;;--------------------------------------------------------------------
1672 (define_insn "uminqi3"
1673 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1674 (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1675 (match_operand:QI 2 "general_operand" "m,d")))]
1676 "TARGET_M6812 && TARGET_MIN_MAX"
1679 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1680 The mina/minm use A as the source or destination. This is the
1681 high part of D. There is no way to express that in the pattern
1682 so we must use 'exg a,b' to put the operand in the good register. */
1684 if (D_REG_P (operands[0]))
1686 return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1690 return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1694 (define_insn "umaxqi3"
1695 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1696 (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1697 (match_operand:QI 2 "general_operand" "m,d")))]
1698 "TARGET_M6812 && TARGET_MIN_MAX"
1701 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1702 The maxa/maxm use A as the source or destination. This is the
1703 high part of D. There is no way to express that in the pattern
1704 so we must use 'exg a,b' to put the operand in the good register. */
1706 if (D_REG_P (operands[0]))
1708 return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1712 return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1716 (define_insn "uminhi3"
1717 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1718 (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1719 (match_operand:HI 2 "general_operand" "m,d")))]
1720 "TARGET_M6812 && TARGET_MIN_MAX"
1723 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1725 if (D_REG_P (operands[0]))
1727 return \"emind\\t%2\";
1731 return \"eminm\\t%0\";
1735 (define_insn "umaxhi3"
1736 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1737 (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1738 (match_operand:HI 2 "general_operand" "m,d")))]
1739 "TARGET_M6812 && TARGET_MIN_MAX"
1742 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1744 if (D_REG_P (operands[0]))
1746 return \"emaxd\\t%2\";
1750 return \"emaxm\\t%0\";
1755 ;;--------------------------------------------------------------------
1756 ;;- Add instructions.
1757 ;;--------------------------------------------------------------------
1758 ;; 64-bit: Use a library call because what GCC generates is huge.
1760 (define_expand "adddi3"
1761 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1762 (plus:DI (match_operand:DI 1 "general_operand" "")
1763 (match_operand:DI 2 "general_operand" "")))]
1765 "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1771 (define_expand "addsi3"
1772 [(parallel [(set (match_operand:SI 0 "register_operand" "")
1773 (plus:SI (match_operand:SI 1 "general_operand" "")
1774 (match_operand:SI 2 "general_operand" "")))
1775 (clobber (match_scratch:HI 3 ""))])]
1779 (define_insn "*addsi3_zero_extendhi"
1780 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1781 (plus:SI (zero_extend:SI
1782 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1783 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1784 (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1790 if (X_REG_P (operands[2]))
1792 ops[0] = operands[1];
1796 if (X_REG_P (operands[1]))
1798 output_asm_insn (\"xgdx\", ops);
1800 else if (!D_REG_P (operands[1]))
1802 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1803 ops[1] = operands[1];
1804 m68hc11_gen_movhi (insn, ops);
1806 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1807 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1809 ops[2] = gen_label_rtx ();
1811 /* ldx preserves the carry, propagate it by incrementing X directly. */
1812 output_asm_insn (\"addd\\t%0\", ops);
1813 if (!X_REG_P (operands[2]))
1814 output_asm_insn (\"ldx\\t%1\", ops);
1816 output_asm_insn (\"bcc\\t%l2\", ops);
1817 output_asm_insn (\"inx\", ops);
1820 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1825 (define_split /* "*addsi3_zero_extendqi" */
1826 [(set (match_operand:SI 0 "register_operand" "")
1827 (plus:SI (zero_extend:SI
1828 (match_operand:QI 1 "general_operand" ""))
1829 (match_operand:SI 2 "memory_operand" "")))
1830 (clobber (match_scratch:HI 3 "=X,X"))]
1832 [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1833 (parallel [(set (match_dup 0)
1834 (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1835 (clobber (match_dup 3))])]
1838 (define_insn "*addsi3_zero_extendqi"
1839 [(set (match_operand:SI 0 "register_operand" "=D,D")
1840 (plus:SI (zero_extend:SI
1841 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1842 (match_operand:SI 2 "general_operand" "miD,!muiD")))
1843 (clobber (match_scratch:HI 3 "=X,X"))]
1849 if (GET_CODE (operands[2]) == MEM)
1852 if (X_REG_P (operands[2]))
1854 if (H_REG_P (operands[1]))
1856 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1857 ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1858 m68hc11_gen_movhi (insn, ops);
1862 ops[0] = operands[1];
1864 ops[1] = const0_rtx;
1868 if (X_REG_P (operands[1]))
1870 output_asm_insn (\"xgdx\", ops);
1872 else if (!D_REG_P (operands[1]))
1874 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1875 ops[1] = operands[1];
1876 m68hc11_gen_movqi (insn, ops);
1879 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1881 ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1882 output_asm_insn (\"clra\", ops);
1885 /* ldx preserves the carry, propagate it by incrementing X directly. */
1886 output_asm_insn (\"addb\\t%b0\", ops);
1887 output_asm_insn (\"adca\\t%h1\", ops);
1888 if (!X_REG_P (operands[2]))
1889 output_asm_insn (\"ldx\\t%2\", ops);
1891 /* If the above adca was adding some constant, we don't need to propagate
1892 the carry unless the constant was 0xff. */
1893 if (X_REG_P (operands[2])
1894 || GET_CODE (ops[1]) != CONST_INT
1895 || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1897 ops[3] = gen_label_rtx ();
1899 output_asm_insn (\"bcc\\t%l3\", ops);
1900 output_asm_insn (\"inx\", ops);
1902 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1903 CODE_LABEL_NUMBER (ops[3]));
1909 (define_insn "*addsi3"
1910 [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
1911 (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1912 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
1913 (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1918 const char* add_insn;
1919 const char* inc_insn;
1920 const char* incb_mem;
1921 const char* inch_mem;
1924 if (which_alternative > 2)
1929 val = INTVAL (operands[2]);
1930 if ((val & 0x0ffffL) == 0)
1932 if (!H_REG_P (operands[0]))
1934 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1935 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1936 output_asm_insn (\"ldd\\t%0\", ops);
1937 output_asm_insn (\"addd\\t%1\", ops);
1938 output_asm_insn (\"std\\t%0\", ops);
1950 if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1957 ops[1] = operands[2];
1958 add_insn = \"addd\\t%1\";
1959 inc_insn = \"inx\\t\";
1960 incb_mem = \"inc\\t%b1\";
1961 inch_mem = \"inc\\t%h1\";
1965 ops[1] = GEN_INT (- val);
1966 add_insn = \"subd\\t%1\";
1968 incb_mem = \"dec\\t%b1\";
1969 inch_mem = \"dec\\t%h1\";
1972 ops[2] = gen_label_rtx ();
1973 if (!H_REG_P (operands[0]))
1975 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1976 output_asm_insn (\"ldd\\t%0\", ops);
1978 output_asm_insn (add_insn, ops);
1979 if (!H_REG_P (operands[0]))
1981 output_asm_insn (\"std\\t%0\", ops);
1983 output_asm_insn (\"bcc\\t%l2\", ops);
1984 if (H_REG_P (operands[0]))
1986 output_asm_insn (inc_insn, ops);
1990 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1992 if (INTVAL (operands[2]) < 0)
1994 output_asm_insn (\"ldd\\t%1\", ops);
1995 output_asm_insn (\"addd\\t#-1\", ops);
1996 output_asm_insn (\"std\\t%1\", ops);
2000 output_asm_insn (incb_mem, ops);
2001 output_asm_insn (\"bne\\t%l2\", ops);
2002 output_asm_insn (inch_mem, ops);
2005 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
2012 [(set (match_operand:SI 0 "register_operand" "")
2013 (plus:SI (match_operand:SI 1 "register_operand" "")
2014 (match_operand:SI 2 "const_int_operand" "")))
2015 (clobber (match_scratch:HI 3 ""))]
2016 "reload_completed && z_replacement_completed == 2
2017 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
2018 [(set (match_dup 5) (match_dup 6))
2019 (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
2020 (set (match_dup 6) (match_dup 5))]
2021 "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2022 if (X_REG_P (operands[0]))
2024 operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
2028 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2029 operands[5] = operands[3];
2034 [(set (match_operand:SI 0 "register_operand" "")
2035 (plus:SI (match_operand:SI 1 "register_operand" "")
2036 (match_operand:SI 2 "general_operand" "")))
2037 (clobber (match_scratch:HI 3 "=X"))]
2038 "reload_completed && z_replacement_completed == 2
2039 && (GET_CODE (operands[2]) != CONST_INT ||
2040 (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
2041 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2042 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2043 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2044 (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2045 (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2046 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2047 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
2048 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2049 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2050 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2051 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2054 ;; Instruction generated to propagate the carry of a 16-bit add
2055 ;; to the upper 16-bit part (in register X).
2057 (define_insn "*addsi_carry"
2058 [(set (match_operand:HI 0 "register_operand" "=x")
2059 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2061 (reg:HI CC_REGNUM)))]
2067 ops[0] = gen_label_rtx ();
2068 output_asm_insn (\"bcc\\t%l0\", ops);
2069 output_asm_insn (\"in%0\", operands);
2070 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2078 (define_expand "addhi3"
2079 [(set (match_operand:HI 0 "register_operand" "")
2080 (plus:HI (match_operand:HI 1 "register_operand" "")
2081 (match_operand:HI 2 "general_operand" "")))]
2085 if (TARGET_M6811 && SP_REG_P (operands[0]))
2087 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
2088 gen_rtx_SET (VOIDmode,
2090 gen_rtx_PLUS (HImode,
2091 operand1, operand2)),
2092 gen_rtx_CLOBBER (VOIDmode,
2093 gen_rtx_SCRATCH (HImode)))));
2098 (define_insn "*addhi3_68hc12"
2099 [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
2100 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
2101 (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
2106 const char* insn_code;
2108 if (which_alternative >= 4)
2110 if (A_REG_P (operands[2]))
2113 output_asm_insn (\"xgd%2\", operands);
2114 output_asm_insn (\"lea%0 d,%0\", operands);
2120 if (D_REG_P (operands[0]))
2122 if (X_REG_P (operands[2]))
2124 m68hc11_notice_keep_cc (operands[0]);
2125 output_asm_insn (\"xgdx\", operands);
2126 output_asm_insn (\"leax\\td,%2\", operands);
2129 else if (Y_REG_P (operands[2]))
2131 m68hc11_notice_keep_cc (operands[0]);
2132 output_asm_insn (\"xgdy\", operands);
2133 output_asm_insn (\"leay\\td,%2\", operands);
2136 else if (SP_REG_P (operands[2]))
2138 output_asm_insn (\"sts\\t%t0\", operands);
2139 return \"addd\\t%t0\";
2141 return \"addd\\t%2\";
2144 if (GET_CODE (operands[2]) == CONST_INT)
2145 val = INTVAL (operands[2]);
2149 if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
2151 m68hc11_notice_keep_cc (operands[0]);
2152 switch (REGNO (operands[0]))
2155 return \"leax\\t%i2,%1\";
2158 return \"leay\\t%i2,%1\";
2160 case HARD_SP_REGNUM:
2161 return \"leas\\t%i2,%1\";
2164 fatal_insn (\"Invalid operands in the instruction\", insn);
2169 insn_code = X_REG_P (operands[0]) ? \"inx\"
2170 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2175 insn_code = X_REG_P (operands[0]) ? \"dex\"
2176 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2179 /* For X and Y increment, the flags are not complete. Only the Z flag
2180 is updated. For SP increment, flags are not changed. */
2181 if (SP_REG_P (operands[0]))
2183 cc_status = cc_prev_status;
2184 if (INTVAL (operands[2]) < 0)
2188 output_asm_insn (\"pshx\", operands);
2202 output_asm_insn (insn_code, operands);
2209 ;; Specific pattern to add to the stack pointer.
2210 ;; We also take care of the clobbering of the IY register.
2212 (define_insn "addhi_sp"
2213 [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2214 (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2215 (match_operand:HI 2 "general_operand" "P,im,u,im")))
2216 (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2222 if (optimize && Y_REG_P (operands[3])
2223 && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
2224 operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
2226 if (GET_CODE (operands[2]) == CONST_INT
2227 && (val = INTVAL (operands[2])) != 0
2228 && (CONST_OK_FOR_LETTER_P (val, 'P')
2229 || (val > 0 && val <= 8)))
2231 while (val > 1 || val < -1)
2235 if (!H_REG_P (operands[3]))
2238 output_asm_insn (\"pul%3\", operands);
2243 output_asm_insn (\"pshx\", operands);
2251 output_asm_insn (\"ins\", operands);
2256 output_asm_insn (\"des\", operands);
2260 cc_status = cc_prev_status;
2264 /* Need to transfer to SP to X/Y and then to D register.
2265 Register X/Y is lost, this is specified by the (clobber) statement. */
2266 output_asm_insn (\"ts%3\", operands);
2267 if (GET_CODE (operands[2]) == CONST_INT
2268 && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
2269 && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
2271 output_asm_insn (\"ldab\\t%2\", operands);
2272 output_asm_insn (\"ab%3\", operands);
2277 output_asm_insn (\"xgd%3\", operands);
2278 output_asm_insn (\"addd\\t%2\", operands);
2279 output_asm_insn (\"xgd%3\", operands);
2282 /* The status flags correspond to the addd. xgdy and tys do not
2283 modify the flags. */
2287 (define_insn "*addhi3"
2288 [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
2289 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
2290 (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
2294 const char* insn_code;
2297 if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2299 output_asm_insn (\"sts\\t%t0\", operands);
2300 output_asm_insn (\"addd\\t%t0\", operands);
2301 return \"addd\\t#1\";
2303 if (GET_CODE (operands[2]) != CONST_INT)
2305 /* Adding to an address register or with another/same register
2306 is not possible. This must be replaced. */
2307 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2310 return \"addd\\t%2\";
2312 val = INTVAL (operands[2]);
2313 if (!SP_REG_P (operands[0]))
2315 if (D_REG_P (operands[0]))
2317 if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2320 return \"adda\\t%h2\";
2324 return \"addd\\t%2\";
2327 else if (GET_CODE (operands[2]) != CONST_INT
2328 || INTVAL (operands[2]) < -4
2329 || INTVAL (operands[2]) > 4)
2334 insn_code = X_REG_P (operands[0]) ? \"inx\"
2335 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2340 insn_code = X_REG_P (operands[0]) ? \"dex\"
2341 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2344 /* For X and Y increment, the flags are not complete. Only the Z flag
2345 is updated. For SP increment, flags are not changed. */
2346 if (SP_REG_P (operands[0]))
2348 cc_status = cc_prev_status;
2349 if (INTVAL (operands[2]) < 0)
2353 output_asm_insn (\"pshx\", operands);
2357 else if (optimize && dead_register_here (insn, ix_reg))
2361 output_asm_insn (\"pulx\", operands);
2373 output_asm_insn (insn_code, operands);
2379 (define_insn "*addhi3_zext"
2380 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2381 (plus:HI (zero_extend:HI
2382 (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2383 (match_operand:HI 2 "hard_reg_operand" "0,0")))]
2388 if (A_REG_P (operands[0]))
2390 else if (A_REG_P (operands[1]))
2391 return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2393 return \"addb\\t%b1\\n\\tadca\\t#0\";
2397 ;; Translate d = d + d into d = << 1
2398 ;; We have to do this because adding a register to itself is not possible.
2399 ;; ??? It's not clear whether this is really necessary.
2402 [(set (match_operand:QI 0 "hard_reg_operand" "")
2403 (plus:QI (match_dup 0)
2405 "0 && reload_completed"
2406 [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2409 (define_insn "addqi3"
2410 [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2411 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2412 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2416 if (GET_CODE (operands[2]) == CONST_INT)
2418 if (INTVAL (operands[2]) == 1)
2420 if (DA_REG_P (operands[0]))
2424 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2429 else if (A_REG_P (operands[0]))
2431 /* This applies on the 16-bit register. This should be ok since
2432 this is not a strict_low_part increment. */
2437 return \"inc\\t%b0\";
2440 else if (INTVAL (operands[2]) == -1)
2442 if (DA_REG_P (operands[0]))
2446 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2450 else if (A_REG_P (operands[0]))
2452 /* This applies on the 16-bit register. This should be ok since
2453 this is not a strict_low_part decrement. */
2458 return \"dec\\t%b0\";
2462 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2464 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2465 return \"addb\\t%b2\";
2467 return \"adda\\t%b2\";
2471 ;; add with carry is used for 32-bit add.
2473 (define_insn "*adcq"
2474 [(set (match_operand:QI 0 "register_operand" "=q")
2475 (plus:QI (plus:QI (reg:QI CC_REGNUM)
2476 (match_operand:QI 1 "register_operand" "%0"))
2477 (match_operand:QI 2 "general_operand" "ium")))]
2481 ;;--------------------------------------------------------------------
2482 ;;- Subtract instructions.
2483 ;;--------------------------------------------------------------------
2485 (define_expand "subdi3"
2486 [(set (match_operand:DI 0 "nonimmediate_operand" "")
2487 (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2488 (match_operand:DI 2 "general_operand" "")))]
2490 "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2494 ;; 32-bit Subtract (see addsi3)
2495 ;; Subtract with a constant are handled by addsi3.
2500 (define_expand "subsi3"
2501 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2502 (minus:SI (match_operand:SI 1 "register_operand" "")
2503 (match_operand:SI 2 "general_operand" "")))
2504 (clobber (match_scratch:HI 3 ""))])]
2508 (define_insn "*subsi3"
2509 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
2510 (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2511 (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
2512 (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
2516 (define_insn "*subsi3_zero_extendhi"
2517 [(set (match_operand:SI 0 "register_operand" "=D")
2518 (minus:SI (match_operand:SI 1 "register_operand" "0")
2519 (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
2520 (clobber (match_scratch:HI 3 "=X"))]
2526 if (A_REG_P (operands[2]))
2529 ops[0] = gen_rtx_MEM (HImode,
2530 gen_rtx_PRE_DEC (HImode,
2531 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2533 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2535 ops[1] = operands[2];
2536 m68hc11_gen_movhi (insn, ops);
2538 operands[2] = gen_rtx_MEM (HImode,
2539 gen_rtx_POST_INC (HImode,
2540 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2542 operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2544 ops[0] = gen_label_rtx ();
2545 output_asm_insn (\"subd\\t%2\", operands);
2546 output_asm_insn (\"bcc\\t%l0\", ops);
2547 output_asm_insn (\"dex\", ops);
2548 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2553 (define_insn "*subsi3_zero_extendqi"
2554 [(set (match_operand:SI 0 "register_operand" "=D")
2555 (minus:SI (match_operand:SI 1 "register_operand" "0")
2556 (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
2557 (clobber (match_scratch:HI 3 "=X"))]
2563 if (A_REG_P (operands[2]))
2565 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2566 ops[1] = operands[2];
2567 m68hc11_gen_movhi (insn, ops);
2568 operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2570 ops[0] = gen_label_rtx ();
2571 output_asm_insn (\"subb\\t%b2\", operands);
2572 output_asm_insn (\"sbca\\t#0\", operands);
2573 output_asm_insn (\"bcc\\t%l0\", ops);
2574 output_asm_insn (\"dex\", ops);
2575 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2581 ;; reg:HI 1 -> d reg:QI 6 -> B
2582 ;; reg:QI 7 -> ccr reg:QI 5 -> A
2584 (define_split /* "*subsi3" */
2585 [(set (match_operand:SI 0 "register_operand" "")
2586 (minus:SI (match_operand:SI 1 "register_operand" "")
2587 (match_operand:SI 2 "general_operand" "")))
2588 (clobber (match_scratch:HI 3 "=X"))]
2589 "reload_completed && z_replacement_completed == 2
2590 && X_REG_P (operands[1])"
2591 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2592 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2593 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2594 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2595 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2596 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2597 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2598 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2599 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2600 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2601 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2603 (define_split /* "*subsi3" */
2604 [(set (match_operand:SI 0 "register_operand" "")
2605 (minus:SI (match_operand:SI 1 "general_operand" "")
2606 (match_operand:SI 2 "register_operand" "")))
2607 (clobber (match_scratch:HI 3 "=X"))]
2608 "reload_completed && z_replacement_completed == 2
2609 && X_REG_P (operands[2])"
2610 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2611 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2612 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2613 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2614 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2615 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2616 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2617 (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2618 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2619 operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2620 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2621 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2623 (define_split /* "*subsi3" */
2624 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2625 (minus:SI (match_operand:SI 1 "general_operand" "")
2626 (match_operand:SI 2 "general_operand" "")))
2627 (clobber (match_scratch:HI 3 "=d"))]
2628 "reload_completed && z_replacement_completed == 2
2629 && !X_REG_P (operands[0])"
2630 [(set (match_dup 3) (match_dup 4))
2631 (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2632 (set (match_dup 4) (match_dup 3))
2633 (set (match_dup 3) (match_dup 6))
2634 (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2635 (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2636 (set (match_dup 6) (match_dup 3))]
2637 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2638 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2639 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2640 operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2641 operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2642 operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2645 ;; - 16-bit Subtract.
2647 (define_expand "subhi3"
2648 [(set (match_operand:HI 0 "register_operand" "=r")
2649 (minus:HI (match_operand:HI 1 "register_operand" "0")
2650 (match_operand:HI 2 "general_operand" "g")))]
2655 ;; Subtract from stack. This is better if we provide a pattern.
2657 (define_insn "*subhi3_sp"
2658 [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2659 (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2660 (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2661 (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2665 if (X_REG_P (operands[2]))
2667 operands[2] = m68hc11_soft_tmp_reg;
2668 output_asm_insn (\"stx\\t%2\", operands);
2670 else if (Y_REG_P (operands[2]))
2672 operands[2] = m68hc11_soft_tmp_reg;
2673 output_asm_insn (\"sty\\t%2\", operands);
2675 else if (D_REG_P (operands[2]))
2677 operands[2] = m68hc11_soft_tmp_reg;
2678 output_asm_insn (\"std\\t%2\", operands);
2681 if (D_REG_P (operands[3]))
2685 save_x = !dead_register_here (insn, ix_reg);
2687 output_asm_insn (\"xgdx\", operands);
2688 output_asm_insn (\"tsx\", operands);
2689 output_asm_insn (\"xgdx\", operands);
2690 output_asm_insn (\"subd\\t%2\", operands);
2691 output_asm_insn (\"xgdx\", operands);
2693 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2694 modify the flags. */
2695 output_asm_insn (\"txs\", operands);
2702 /* Need to transfer to SP to X,Y and then to D register.
2703 Register X,Y is lost, this is specified by the (clobber) statement. */
2704 output_asm_insn (\"ts%3\", operands);
2705 output_asm_insn (\"xgd%3\", operands);
2706 output_asm_insn (\"subd\\t%2\", operands);
2707 output_asm_insn (\"xgd%3\", operands);
2709 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2710 modify the flags. */
2715 (define_insn "*subhi3"
2716 [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
2717 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0")
2718 (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
2722 /* Adding to an address register or with another/same register
2723 is not possible. This must be replaced. */
2724 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2727 return \"subd\\t%2\";
2730 (define_insn "*subhi3_zext"
2731 [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2732 (minus:HI (match_operand:HI 1 "hard_reg_operand" "0,0")
2733 (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2738 if (A_REG_P (operands[2]))
2742 ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2743 ops[1] = operands[2];
2744 m68hc11_gen_movqi (insn, ops);
2745 return \"subb\\t%T0\\n\\tsbca\\t#0\";
2747 return \"subb\\t%b2\\n\\tsbca\\t#0\";
2750 (define_insn "subqi3"
2751 [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2752 (minus:QI (match_operand:QI 1 "hard_reg_operand" "0,0")
2753 (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2757 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2759 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2760 return \"subb\\t%b2\";
2762 return \"suba\\t%b2\";
2766 ;; subtract with carry is used for 32-bit subtract.
2768 (define_insn "*subcq"
2769 [(set (match_operand:QI 0 "register_operand" "=q")
2770 (minus:QI (minus:QI (reg:QI CC_REGNUM)
2771 (match_operand:QI 1 "register_operand" "0"))
2772 (match_operand:QI 2 "general_operand" "ium")))]
2776 ;;--------------------------------------------------------------------
2777 ;;- Multiply instructions.
2778 ;;--------------------------------------------------------------------
2780 ;; 32 and 64-bit multiply are handled by the library
2783 (define_expand "mulsi3"
2784 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2785 (mult:SI (match_operand:SI 1 "general_operand" "")
2786 (match_operand:SI 2 "general_operand" "")))]
2788 "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2791 (define_expand "mulhi3"
2792 [(parallel [(set (match_operand:HI 0 "register_operand" "")
2793 (mult:HI (match_operand:HI 1 "register_operand" "")
2794 (match_operand:HI 2 "register_operand" "")))
2795 (clobber (match_scratch:HI 3 ""))])]
2799 (define_insn "mulhi3_m68hc11"
2800 [(set (match_operand:HI 0 "register_operand" "=d")
2801 (mult:HI (match_operand:HI 1 "register_operand" "%0")
2802 (match_operand:HI 2 "register_operand" "x")))
2803 (clobber (match_scratch:HI 3 "=X"))]
2808 /* D * X -> D (X and Y are preserved by this function call). */
2809 return \"jsr\\t___mulhi3\";
2812 (define_insn "mulhi3_m68hc12"
2813 [(set (match_operand:HI 0 "register_operand" "=d,d")
2814 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2815 (match_operand:HI 2 "register_operand" "y,x")))
2816 (clobber (match_scratch:HI 3 "=2,2"))]
2821 if (X_REG_P (operands[2]))
2822 return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2827 (define_insn "umulhisi3"
2828 [(set (match_operand:SI 0 "register_operand" "=D,D")
2829 (mult:SI (zero_extend:SI
2830 (match_operand:HI 1 "register_operand" "%d,d"))
2832 (match_operand:HI 2 "register_operand" "y,x"))))
2833 (clobber (match_scratch:HI 3 "=2,X"))]
2837 if (X_REG_P (operands [2]))
2838 output_asm_insn (\"exg\\tx,y\", operands);
2840 /* Can't use the carry after that; other flags are ok when testing
2841 the 32-bit result. */
2842 cc_status.flags |= CC_NO_OVERFLOW;
2843 return \"emul\\n\\texg\\tx,y\";
2846 (define_insn "mulhisi3"
2847 [(set (match_operand:SI 0 "register_operand" "=D,D")
2848 (mult:SI (sign_extend:SI
2849 (match_operand:HI 1 "register_operand" "%d,d"))
2851 (match_operand:HI 2 "register_operand" "y,x"))))
2852 (clobber (match_scratch:HI 3 "=2,X"))]
2856 if (X_REG_P (operands [2]))
2857 output_asm_insn (\"exg\\tx,y\", operands);
2859 /* Can't use the carry after that; other flags are ok when testing
2860 the 32-bit result. */
2861 cc_status.flags |= CC_NO_OVERFLOW;
2862 return \"emuls\\n\\texg\\tx,y\";
2865 (define_insn "umulqihi3"
2866 [(set (match_operand:HI 0 "register_operand" "=d")
2867 (mult:HI (zero_extend:HI
2868 (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2870 (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2874 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2876 output_asm_insn (\"tba\", operands);
2882 if (D_REG_P (operands[2]))
2884 rtx temp = operands[2];
2885 operands[2] = operands[1];
2889 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2890 ops[1] = operands[2];
2891 m68hc11_gen_movqi (insn, ops);
2893 if (!D_REG_P (operands[1]))
2895 output_asm_insn (\"ldab\\t%b1\", operands);
2903 (define_insn "mulqi3"
2904 [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
2905 (mult:QI (match_operand:QI 1 "nonimmediate_operand" "%dum,0,0")
2906 (match_operand:QI 2 "general_operand" "dium,*xium,*yium")))]
2910 if (A_REG_P (operands[0]))
2913 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2915 output_asm_insn (\"tba\", operands);
2919 if (D_REG_P (operands[2]))
2921 rtx temp = operands[2];
2922 operands[2] = operands[1];
2926 output_asm_insn (\"ldaa\\t%b2\", operands);
2928 if (!D_REG_P (operands[1]))
2930 output_asm_insn (\"ldab\\t%b1\", operands);
2939 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
2940 (mult:QI (match_operand:QI 1 "general_operand" "")
2941 (match_operand:QI 2 "general_operand" "")))]
2942 "z_replacement_completed == 2"
2943 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2944 (set (match_dup 3) (reg:HI D_REGNUM))])
2945 (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
2946 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2947 (set (match_dup 3) (reg:HI D_REGNUM))])]
2949 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
2950 if (A_REG_P (operands[1]))
2951 operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2953 operands[5] = operands[1];
2954 if (A_REG_P (operands[2]))
2955 operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2957 operands[6] = operands[2];
2960 (define_insn "mulqihi3"
2961 [(set (match_operand:HI 0 "register_operand" "=d,d")
2962 (mult:HI (sign_extend:HI
2963 (match_operand:QI 1 "register_operand" "%0,0"))
2965 (match_operand:QI 2 "nonimmediate_operand" "dm,*A"))))]
2971 /* Special case when multiplying the register with itself. */
2972 if (D_REG_P (operands[2]))
2974 output_asm_insn (\"tba\", operands);
2978 if (!H_REG_P (operands[2]))
2980 output_asm_insn (\"ldaa\\t%b2\", operands);
2986 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2987 ops[1] = operands[2];
2988 m68hc11_gen_movqi (insn, ops);
2990 return \"jsr\\t___mulqi3\";
2993 ;;--------------------------------------------------------------------
2994 ;;- Divide instructions.
2995 ;;--------------------------------------------------------------------
2997 (define_insn "divmodhi4"
2998 [(set (match_operand:HI 0 "register_operand" "=d,d")
2999 (div:HI (match_operand:HI 1 "register_operand" "0,0")
3000 (match_operand:HI 2 "general_operand" "A,ium")))
3001 (set (match_operand:HI 3 "register_operand" "=&x,&x")
3002 (mod:HI (match_dup 1) (match_dup 2)))]
3006 if (!X_REG_P (operands[2]))
3008 if (Y_REG_P (operands[2]))
3010 output_asm_insn (\"sty\\t%t1\", operands);
3011 output_asm_insn (\"ldx\\t%t1\", operands);
3015 output_asm_insn (\"ldx\\t%2\", operands);
3020 /* Flags are ok after that. */
3021 return \"idivs\\n\\txgdx\";
3026 return \"bsr\\t__divmodhi4\";
3030 (define_insn "udivmodhi4"
3031 [(set (match_operand:HI 0 "register_operand" "=d,d")
3032 (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
3033 (match_operand:HI 2 "general_operand" "A,ium")))
3034 (set (match_operand:HI 3 "register_operand" "=x,x")
3035 (umod:HI (match_dup 1) (match_dup 2)))]
3039 if (!X_REG_P (operands[2]))
3041 if (Y_REG_P (operands[2]))
3043 output_asm_insn (\"sty\\t%t1\", operands);
3044 output_asm_insn (\"ldx\\t%t1\", operands);
3048 output_asm_insn (\"ldx\\t%2\", operands);
3052 /* Z V and C flags are set but N is unchanged.
3053 Since this is an unsigned divide, we can probably keep the flags
3054 and indicate this. */
3055 cc_status.flags |= CC_NOT_NEGATIVE;
3056 return \"idiv\\n\\txgdx\";
3059 ;;--------------------------------------------------------------------
3060 ;;- and instructions.
3061 ;;--------------------------------------------------------------------
3063 (define_insn_and_split "anddi3"
3064 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3065 (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3066 (match_operand:DI 2 "general_operand" "imu,imu")))
3067 (clobber (match_scratch:HI 3 "=d,d"))]
3072 "m68hc11_split_logical (SImode, AND, operands);
3075 (define_insn_and_split "andsi3"
3076 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3077 (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3078 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3079 (clobber (match_scratch:HI 3 "=X,d"))]
3084 "m68hc11_split_logical (HImode, AND, operands);
3087 (define_expand "andhi3"
3088 [(set (match_operand:HI 0 "register_operand" "")
3089 (and:HI (match_operand:HI 1 "register_operand" "")
3090 (match_operand:HI 2 "general_operand" "")))]
3094 (define_insn "*andhi3_mem"
3095 [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3096 (and:HI (match_dup 0)
3097 (match_operand:HI 1 "immediate_operand" "i,i")))
3098 (clobber (match_scratch:HI 2 "=X,xy"))]
3099 "TARGET_RELAX && !TARGET_M6812"
3102 int val = INTVAL (operands[1]) & 0x0FFFF;
3106 cc_status = cc_prev_status;
3112 /* The bclr instruction uses an inverted mask. */
3113 operands[1] = GEN_INT ((~val) & 0x0FFFF);
3115 /* When destination is a global variable, generate a .relax instruction
3116 and load the address in the clobber register. That load can be
3117 eliminated by the linker if the address is in page0. */
3118 if (which_alternative == 1)
3122 ops[0] = operands[2];
3123 ops[1] = XEXP (operands[0], 0);
3124 ops[2] = gen_label_rtx ();
3125 output_asm_insn (\".relax\\t%l2\", ops);
3126 m68hc11_gen_movhi (insn, ops);
3127 if ((val & 0x0FF) != 0x0FF)
3128 output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
3130 if ((val & 0x0FF00) != 0x0FF00)
3131 output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
3133 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3134 CODE_LABEL_NUMBER (ops[2]));
3138 if ((val & 0x0FF) != 0x0FF)
3139 output_asm_insn (\"bclr\\t%b0, %b1\", operands);
3141 if ((val & 0x0FF00) != 0x0FF00)
3142 output_asm_insn (\"bclr\\t%h0, %h1\", operands);
3147 (define_insn "*andhi3_const"
3148 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3149 (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3150 (match_operand:HI 2 "const_int_operand" "")))]
3154 int val = INTVAL (operands[2]) & 0x0FFFF;
3155 int lowpart_zero = 0;
3156 int highpart_zero = 0;
3157 int lowpart_unknown = 0;
3158 int highpart_unknown = 0;
3160 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3165 cc_status = cc_prev_status;
3169 /* First, try to clear the low and high part.
3170 If that's possible, the second 'and' will give
3171 the good status flags and we can avoid a tsthi. */
3172 if ((val & 0x0FF) == 0)
3174 if (D_REG_P (operands[0]))
3175 output_asm_insn (\"clrb\", operands);
3177 output_asm_insn (\"clr\\t%b0\", operands);
3180 if ((val & 0x0FF00) == 0)
3182 if (D_REG_P (operands[0]))
3183 output_asm_insn (\"clra\", operands);
3185 output_asm_insn (\"clr\\t%h0\", operands);
3189 if ((val & 0x0FF) == 0x0FF)
3191 lowpart_unknown = 1;
3193 else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3197 ops[0] = operands[0];
3198 ops[1] = GEN_INT ((~val) & 0x0FF);
3199 output_asm_insn (\"bclr\\t%b0, %1\", ops);
3201 else if ((val & 0x0FF) != 0)
3203 output_asm_insn (\"andb\\t%b2\", operands);
3206 if ((val & 0x0FF00) == 0x0FF00)
3208 highpart_unknown = 1;
3210 else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3214 ops[0] = operands[0];
3215 ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
3216 output_asm_insn (\"bclr\\t%h0, %1\", ops);
3218 else if ((val & 0x0FF00) != 0)
3220 output_asm_insn (\"anda\\t%h2\", operands);
3223 if (highpart_unknown || lowpart_unknown)
3225 else if (highpart_zero == 0 && lowpart_zero == 0)
3231 (define_insn "*andhi3_gen"
3232 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3233 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
3234 (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))]
3238 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3242 return \"anda\\t%h2\\n\\tandb\\t%b2\";
3245 (define_expand "andqi3"
3246 [(set (match_operand:QI 0 "register_operand" "")
3247 (and:QI (match_operand:QI 1 "register_operand" "")
3248 (match_operand:QI 2 "general_operand" "")))]
3252 (define_insn "*andqi3_mem"
3253 [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3254 (and:QI (match_dup 0)
3255 (match_operand:QI 1 "const_int_operand" "i,i")))
3256 (clobber (match_scratch:HI 2 "=X,xy"))]
3257 "TARGET_RELAX && !TARGET_M6812"
3260 int val = INTVAL (operands[1]) & 0x0FF;
3264 cc_status = cc_prev_status;
3268 /* The bclr instruction uses an inverted mask. */
3269 operands[1] = GEN_INT ((~val) & 0x0FF);
3271 /* When destination is a global variable, generate a .relax instruction
3272 and load the address in the clobber register. That load can be
3273 eliminated by the linker if the address is in page0. */
3274 if (which_alternative == 1)
3278 ops[0] = operands[2];
3279 ops[1] = XEXP (operands[0], 0);
3280 ops[2] = gen_label_rtx ();
3281 output_asm_insn (\".relax\\t%l2\", ops);
3282 m68hc11_gen_movhi (insn, ops);
3283 output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3284 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3285 CODE_LABEL_NUMBER (ops[2]));
3288 return \"bclr\\t%b0, %1\";
3291 (define_insn "*andqi3_const"
3292 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3293 (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3294 (match_operand:QI 2 "const_int_operand" "")))]
3298 int val = INTVAL (operands[2]) & 0x0FF;
3300 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3305 cc_status = cc_prev_status;
3308 if (!H_REG_P (operands[0]))
3312 ops[0] = operands[0];
3313 ops[1] = GEN_INT ((~val) & 0x0FF);
3314 output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3317 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3318 return \"andb\\t%b2\";
3319 else if (DA_REG_P (operands[0]))
3320 return \"anda\\t%b2\";
3322 fatal_insn (\"Invalid operand in the instruction\", insn);
3325 (define_insn "*andqi3_gen"
3326 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3327 (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
3328 (match_operand:QI 2 "general_operand" "mi,!u,?*A,!um,?*A*d,!um*A")))]
3332 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3335 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3336 return \"andb\\t%b2\";
3337 else if (DA_REG_P (operands[0]))
3338 return \"anda\\t%b2\";
3340 fatal_insn (\"Invalid operand in the instruction\", insn);
3343 ;;--------------------------------------------------------------------
3344 ;;- Bit set or instructions.
3345 ;;--------------------------------------------------------------------
3347 (define_insn_and_split "iordi3"
3348 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3349 (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3350 (match_operand:DI 2 "general_operand" "imu,imu")))
3351 (clobber (match_scratch:HI 3 "=d,d"))]
3356 "m68hc11_split_logical (SImode, IOR, operands);
3359 (define_insn_and_split "iorsi3"
3360 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3361 (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3362 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3363 (clobber (match_scratch:HI 3 "=X,d"))]
3368 "m68hc11_split_logical (HImode, IOR, operands);
3371 (define_expand "iorhi3"
3372 [(set (match_operand:HI 0 "register_operand" "")
3373 (ior:HI (match_operand:HI 1 "register_operand" "")
3374 (match_operand:HI 2 "general_operand" "")))]
3378 (define_insn "*iorhi3_mem"
3379 [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3380 (ior:HI (match_dup 0)
3381 (match_operand:HI 1 "const_int_operand" "")))
3382 (clobber (match_scratch:HI 2 "=X,xy"))]
3383 "TARGET_RELAX && !TARGET_M6812"
3386 int val = INTVAL (operands[1]) & 0x0FFFF;
3390 cc_status = cc_prev_status;
3394 if (which_alternative == 1)
3398 ops[0] = operands[2];
3399 ops[1] = XEXP (operands[0], 0);
3400 ops[2] = gen_label_rtx ();
3401 output_asm_insn (\".relax\\t%l2\", ops);
3402 m68hc11_gen_movhi (insn, ops);
3403 if ((val & 0x0FF) != 0)
3404 output_asm_insn (\"bset\\t1,%2, %b1\", operands);
3406 if ((val & 0x0FF00) != 0)
3407 output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3408 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3409 CODE_LABEL_NUMBER (ops[2]));
3413 if ((val & 0x0FF) != 0)
3414 output_asm_insn (\"bset\\t%b0, %b1\", operands);
3416 if ((val & 0x0FF00) != 0)
3417 output_asm_insn (\"bset\\t%h0, %h1\", operands);
3422 (define_insn "*iorhi3_const"
3423 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3424 (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3425 (match_operand:HI 2 "const_int_operand" "")))]
3429 int val = INTVAL (operands[2]) & 0x0FFFF;
3431 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3436 cc_status = cc_prev_status;
3440 if ((val & 0x0FF) != 0)
3442 if (!H_REG_P (operands[0]))
3443 output_asm_insn (\"bset\\t%b0, %b2\", operands);
3445 output_asm_insn (\"orab\\t%b2\", operands);
3448 if ((val & 0x0FF00) != 0)
3450 if (!H_REG_P (operands[0]))
3451 output_asm_insn (\"bset\\t%h0, %h2\", operands);
3453 output_asm_insn (\"oraa\\t%h2\", operands);
3460 (define_insn "*iorhi3_gen"
3461 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3462 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0")
3463 (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))]
3467 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3471 return \"oraa\\t%h2\\n\\torab\\t%b2\";
3474 (define_expand "iorqi3"
3475 [(set (match_operand:QI 0 "register_operand" "")
3476 (ior:QI (match_operand:QI 1 "register_operand" "")
3477 (match_operand:QI 2 "general_operand" "")))]
3481 (define_insn "*iorqi3_mem"
3482 [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3483 (ior:QI (match_dup 0)
3484 (match_operand:QI 1 "const_int_operand" "")))
3485 (clobber (match_scratch:HI 2 "=X,xy"))]
3486 "TARGET_RELAX && !TARGET_M6812"
3489 int val = INTVAL (operands[1]) & 0x0FF;
3493 cc_status = cc_prev_status;
3496 if (which_alternative == 1)
3500 ops[0] = operands[2];
3501 ops[1] = XEXP (operands[0], 0);
3502 ops[2] = gen_label_rtx ();
3503 output_asm_insn (\".relax\\t%l2\", ops);
3504 m68hc11_gen_movhi (insn, ops);
3505 output_asm_insn (\"bset\\t0,%2, %1\", operands);
3506 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3507 CODE_LABEL_NUMBER (ops[2]));
3510 return \"bset\\t%b0, %1\";
3513 (define_insn "*iorqi3_const"
3514 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3515 (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3516 (match_operand:QI 2 "const_int_operand" "")))]
3520 int val = INTVAL (operands[2]) & 0x0FF;
3522 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3527 cc_status = cc_prev_status;
3530 if (!H_REG_P (operands[0]))
3532 return \"bset\\t%b0, %2\";
3535 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3536 return \"orab\\t%b2\";
3537 else if (DA_REG_P (operands[0]))
3538 return \"oraa\\t%b2\";
3540 fatal_insn (\"Invalid operand in the instruction\", insn);
3543 (define_insn "*iorqi3_gen"
3544 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3545 (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
3546 (match_operand:QI 2 "general_operand" "mi,!u,!*A,!um,?*A*d,!um*A")))]
3550 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3553 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3554 return \"orab\\t%b2\";
3555 else if (DA_REG_P (operands[0]))
3556 return \"oraa\\t%b2\";
3558 fatal_insn (\"Invalid operand in the instruction\", insn);
3562 ;;--------------------------------------------------------------------
3563 ;;- xor instructions.
3564 ;;--------------------------------------------------------------------
3566 (define_insn_and_split "xordi3"
3567 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3568 (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3569 (match_operand:DI 2 "general_operand" "imu,imu")))
3570 (clobber (match_scratch:HI 3 "=d,d"))]
3575 "m68hc11_split_logical (SImode, XOR, operands);
3578 (define_insn_and_split "xorsi3"
3579 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3580 (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3581 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3582 (clobber (match_scratch:HI 3 "=X,d"))]
3587 "m68hc11_split_logical (HImode, XOR, operands);
3590 (define_insn "xorhi3"
3591 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3592 (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
3593 (match_operand:HI 2 "general_operand" "im,!u*A,!ium*A")))]
3597 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3600 if (GET_CODE (operands[2]) == CONST_INT)
3602 int val = INTVAL (operands[2]) & 0x0FFFF;
3606 cc_status = cc_prev_status;
3609 if ((val & 0x0FF) != 0)
3611 output_asm_insn (\"eorb\\t%b2\", operands);
3613 else if ((val & 0x0FF) == 0x0FF)
3615 output_asm_insn (\"comb\", operands);
3618 if ((val & 0x0FF00) != 0)
3620 output_asm_insn (\"eora\\t%h2\", operands);
3622 else if ((val & 0x0FF00) == 0x0FF00)
3624 output_asm_insn (\"coma\", operands);
3632 return \"eora\\t%h2\\n\\teorb\\t%b2\";
3635 (define_insn "xorqi3"
3636 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3637 (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
3638 (match_operand:QI 2 "general_operand" "im,!u,!*A,!ium,?*A*d,!ium*A")))]
3642 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3645 if (GET_CODE (operands[2]) == CONST_INT)
3647 int val = INTVAL (operands[2]) & 0x0FF;
3651 cc_status = cc_prev_status;
3656 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3662 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3663 return \"eorb\\t%b2\";
3664 else if (DA_REG_P (operands[0]))
3665 return \"eora\\t%b2\";
3667 fatal_insn (\"Invalid operand in the instruction\", insn);
3670 ;;--------------------------------------------------------------------
3671 ;;- Bit set or instructions.
3672 ;;--------------------------------------------------------------------
3674 (define_insn_and_split "*logicalsi3_zexthi"
3675 [(set (match_operand:SI 0 "register_operand" "=D")
3676 (match_operator:SI 3 "m68hc11_logical_operator"
3678 (match_operand:HI 1 "general_operand" "imudA"))
3679 (match_operand:SI 2 "general_operand" "Dimu")]))]
3683 [(set (reg:HI D_REGNUM) (match_dup 4))
3684 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3685 (set (reg:HI X_REGNUM) (match_dup 6))]
3686 "PUT_MODE (operands[3], HImode);
3687 if (X_REG_P (operands[2]))
3689 operands[5] = operands[1];
3690 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3691 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3692 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3696 operands[4] = operands[1];
3697 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3698 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3700 /* For an AND, make sure the high 16-bit part is cleared. */
3701 if (GET_CODE (operands[3]) == AND)
3703 operands[6] = const0_rtx;
3707 (define_insn_and_split "*logicalsi3_zextqi"
3708 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3709 (match_operator:SI 3 "m68hc11_logical_operator"
3711 (match_operand:QI 1 "general_operand" "d,*A,imu"))
3712 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3715 "z_replacement_completed == 2"
3716 [(set (reg:QI A_REGNUM) (match_dup 4))
3717 (set (reg:QI D_REGNUM) (match_dup 7))
3718 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3719 (set (reg:HI X_REGNUM) (match_dup 6))]
3720 "PUT_MODE (operands[3], QImode);
3721 if (X_REG_P (operands[2]))
3723 operands[5] = operands[1];
3724 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3725 operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3726 operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
3727 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3731 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3732 operands[7] = operands[1];
3733 operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3734 operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3735 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3737 /* For an AND, make sure the high 24-bit part is cleared. */
3738 if (GET_CODE (operands[3]) == AND)
3740 operands[4] = const0_rtx;
3741 operands[6] = const0_rtx;
3745 (define_insn_and_split "*logicalhi3_zexthi_ashift8"
3746 [(set (match_operand:HI 0 "register_operand" "=d")
3747 (match_operator:HI 3 "m68hc11_logical_operator"
3749 (match_operand:QI 1 "general_operand" "imud*A"))
3751 (match_operand:HI 2 "general_operand" "imud*A")
3755 "z_replacement_completed == 2"
3756 [(set (reg:QI A_REGNUM) (match_dup 4))
3757 (set (reg:QI B_REGNUM) (match_dup 5))]
3759 if (GET_CODE (operands[3]) == AND)
3761 emit_insn (gen_movhi (operands[0], const0_rtx));
3766 operands[5] = operands[1];
3767 if (D_REG_P (operands[2]))
3769 operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3773 operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3778 (define_insn_and_split "*logicalhi3_zexthi"
3779 [(set (match_operand:HI 0 "register_operand" "=d,d")
3780 (match_operator:HI 3 "m68hc11_logical_operator"
3782 (match_operand:QI 1 "general_operand" "imd*A,?u"))
3783 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3786 "z_replacement_completed == 2"
3787 [(set (reg:QI B_REGNUM) (match_dup 6))
3788 (set (reg:QI A_REGNUM) (match_dup 4))
3789 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3791 PUT_MODE (operands[3], QImode);
3792 if (D_REG_P (operands[2]))
3794 operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3795 operands[5] = operands[1];
3796 operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3800 operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3801 operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3802 if (D_REG_P (operands[1]))
3803 operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3805 operands[6] = operands[1];
3807 /* For an AND, make sure the high 8-bit part is cleared. */
3808 if (GET_CODE (operands[3]) == AND)
3810 operands[4] = const0_rtx;
3815 (define_insn_and_split "*logicalsi3_silshr16"
3816 [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
3817 (match_operator:SI 3 "m68hc11_logical_operator"
3819 (match_operand:SI 1 "general_operand" "uim,uim,0,0")
3821 (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
3825 [(set (reg:HI D_REGNUM) (match_dup 4))
3826 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3827 (set (reg:HI X_REGNUM) (match_dup 6))]
3828 "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3829 if (X_REG_P (operands[2]))
3831 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3832 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3836 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3837 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3839 PUT_MODE (operands[3], HImode);
3841 /* For an AND, make sure the high 16-bit part is cleared. */
3842 if (GET_CODE (operands[3]) == AND)
3844 operands[6] = const0_rtx;
3848 (define_insn_and_split "*logicalsi3_silshl16"
3849 [(set (match_operand:SI 0 "register_operand" "=D,D")
3850 (match_operator:SI 3 "m68hc11_logical_operator"
3852 (match_operand:SI 1 "general_operand" "uim,?D")
3854 (match_operand:SI 2 "general_operand" "0,0")]))]
3857 "z_replacement_completed == 2"
3858 [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3859 (set (reg:HI D_REGNUM) (match_dup 5))]
3860 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3861 PUT_MODE (operands[3], HImode);
3863 if (GET_CODE (operands[3]) == AND)
3864 operands[5] = const0_rtx;
3866 operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3869 (define_insn_and_split "*logicalsi3_silshl16_zext"
3870 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3871 (match_operator:SI 3 "m68hc11_logical_operator"
3874 (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
3876 (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
3879 ;; Must split before z register replacement
3881 [(set (match_dup 4) (match_dup 5))
3882 (set (match_dup 6) (match_dup 7))]
3884 /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
3885 if (GET_CODE (operands[1]) == HARD_D_REGNUM
3886 && GET_CODE (operands[3]) != AND)
3888 /* This particular case is too early to be split before
3889 Z register replacement because the cse-reg pass we do
3890 does not recognize the 'swap_areg'. It is ok to handle
3892 if (z_replacement_completed != 2)
3896 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), operands[2]);
3897 emit_insn (gen_swap_areg (gen_rtx (REG, HImode, HARD_D_REGNUM),
3898 gen_rtx (REG, HImode, HARD_X_REGNUM)));
3900 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3901 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3902 operands[5] = operands[2];
3903 operands[7] = operands[1];
3905 if (GET_CODE (operands[3]) == AND)
3906 operands[5] = operands[7] = const0_rtx;
3909 ;;--------------------------------------------------------------------
3910 ;; 16-bit Arithmetic and logical operations on X and Y:
3912 ;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3914 ;; Operations on X or Y registers are split here. Instructions are
3916 ;; - xgdx/xgdy instruction pattern,
3917 ;; - The same operation on register D,
3918 ;; - xgdx/xgdy instruction pattern.
3919 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3920 ;; We also handle the case were the address register is used in both source
3921 ;; operands, such as:
3923 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3925 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3929 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3930 (match_operator:HI 3 "m68hc11_arith_operator"
3931 [(match_operand:HI 1 "hard_addr_reg_operand" "")
3932 (match_operand:HI 2 "general_operand" "")]))]
3933 "z_replacement_completed == 2
3934 /* If we are adding a small constant to X or Y, it's
3935 better to use one or several inx/iny instructions. */
3936 && !(GET_CODE (operands[3]) == PLUS
3938 && (immediate_operand (operands[2], HImode)
3939 || hard_reg_operand (operands[2], HImode)))
3940 || (GET_CODE (operands[2]) == CONST_INT
3941 && INTVAL (operands[2]) >= -4
3942 && INTVAL (operands[2]) <= 4)))"
3943 [(set (match_dup 9) (match_dup 0))
3944 (set (match_dup 4) (match_dup 5))
3945 (set (match_dup 8) (match_dup 7))
3946 (set (match_dup 0) (match_dup 1))
3947 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3948 (set (match_dup 0) (reg:HI D_REGNUM))])
3949 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3950 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3951 (set (match_dup 0) (reg:HI D_REGNUM))])]
3953 operands[9] = operands[0];
3954 /* For 68HC12, push the value on the stack and do the operation
3957 && m68hc11_non_shift_operator (operands[3], HImode)
3958 && (H_REG_P (operands[2])
3959 || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3960 && reg_mentioned_p (operands[0], operands[2]))))
3962 operands[4] = gen_rtx_MEM (HImode,
3963 gen_rtx_PRE_DEC (HImode,
3964 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3965 operands[6] = gen_rtx_MEM (HImode,
3966 gen_rtx_POST_INC (HImode,
3967 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3968 operands[5] = operands[2];
3969 operands[8] = operands[7] = operands[0];
3971 /* Save the operand2 in a temporary location and use it. */
3972 else if ((H_REG_P (operands[2])
3973 || reg_mentioned_p (operands[0], operands[2]))
3974 && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3976 if (GET_CODE (operands[3]) == MINUS
3977 && reg_mentioned_p (operands[0], operands[2]))
3979 operands[9] = gen_rtx_MEM (HImode,
3980 gen_rtx_PRE_DEC (HImode,
3981 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3982 operands[1] = gen_rtx_MEM (HImode,
3983 gen_rtx_POST_INC (HImode,
3984 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3985 operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3986 operands[4] = operands[7] = operands[0];
3987 operands[6] = operands[8];
3988 operands[5] = operands[2];
3992 operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3993 operands[6] = operands[4];
3994 if (!H_REG_P (operands[2]))
3996 operands[5] = operands[0];
3997 operands[7] = operands[2];
3998 operands[8] = operands[0];
4002 operands[5] = operands[2];
4003 operands[8] = operands[7] = operands[0];
4009 operands[4] = operands[5] = operands[0];
4010 operands[6] = operands[2];
4011 operands[8] = operands[7] = operands[0];
4016 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4017 (match_operator:HI 3 "m68hc11_arith_operator"
4018 [(match_operand:HI 1 "general_operand" "")
4019 (match_operand:HI 2 "general_operand" "")]))]
4020 "z_replacement_completed == 2
4021 /* If we are adding a small constant to X or Y, it's
4022 better to use one or several inx/iny instructions. */
4023 && !(GET_CODE (operands[3]) == PLUS
4025 && (immediate_operand (operands[2], HImode)
4026 || hard_reg_operand (operands[2], HImode)))
4027 || (GET_CODE (operands[2]) == CONST_INT
4028 && INTVAL (operands[2]) >= -4
4029 && INTVAL (operands[2]) <= 4)))"
4030 [(set (match_dup 0) (match_dup 1))
4031 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4032 (set (match_dup 0) (reg:HI D_REGNUM))])
4033 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
4034 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4035 (set (match_dup 0) (reg:HI D_REGNUM))])]
4040 ;; Next split handles the logical operations on D register with
4041 ;; another hard register for the second operand. For this, we
4042 ;; have to save the second operand in a scratch location and use
4043 ;; it instead. This must be supported because in some (rare) cases
4044 ;; the second operand can come in a hard register and the reload
4045 ;; pass doesn't know how to reload it in a memory location.
4047 ;; PLUS MINUS AND IOR XOR
4049 ;; The shift operators are special and must not appear here.
4052 [(set (match_operand:HI 0 "d_register_operand" "")
4053 (match_operator:HI 3 "m68hc11_non_shift_operator"
4054 [(match_operand:HI 1 "d_register_operand" "")
4055 (match_operand:HI 2 "hard_reg_operand" "")]))]
4057 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4058 [(set (match_dup 4) (match_dup 2))
4059 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4060 "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
4063 ;; For 68HC12, push the operand[2] value on the stack and do the
4064 ;; logical/arithmetic operation with a pop.
4067 [(set (match_operand:HI 0 "d_register_operand" "")
4068 (match_operator:HI 3 "m68hc11_non_shift_operator"
4069 [(match_operand:HI 1 "d_register_operand" "")
4070 (match_operand:HI 2 "hard_reg_operand" "")]))]
4072 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4073 [(set (match_dup 4) (match_dup 2))
4074 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4075 "operands[4] = gen_rtx_MEM (HImode,
4076 gen_rtx_PRE_DEC (HImode,
4077 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4078 operands[5] = gen_rtx_MEM (HImode,
4079 gen_rtx_POST_INC (HImode,
4080 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4083 ;;--------------------------------------------------------------------
4084 ;; 16-bit Unary operations on X and Y:
4088 ;; Operations on X or Y registers are split here. Instructions are
4090 ;; - xgdx/xgdy instruction pattern,
4091 ;; - The same operation on register D,
4092 ;; - xgdx/xgdy instruction pattern.
4093 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4094 ;; We also handle the case were the address register is used in both source
4095 ;; operands, such as:
4097 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4099 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4102 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4103 (match_operator:HI 2 "m68hc11_unary_operator"
4104 [(match_operand 1 "general_operand" "")]))]
4105 "z_replacement_completed == 2"
4106 [(set (match_dup 4) (match_dup 5))
4107 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4108 (set (match_dup 0) (reg:HI D_REGNUM))])
4109 (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4110 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4111 (set (match_dup 0) (reg:HI D_REGNUM))])]
4114 if ((H_REG_P (operands[1])
4115 && !rtx_equal_p (operands[0], operands[1]))
4116 || reg_mentioned_p (operands[0], operands[1]))
4118 /* Move to the destination register, before the xgdx. */
4119 operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
4120 REGNO (operands[0]));
4121 operands[5] = operands[1];
4123 /* Apply the operation on D. */
4124 operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
4128 /* Generate a copy to same register (nop). */
4129 operands[4] = operands[5] = operands[0];
4130 operands[3] = operands[1];
4135 ;; 8-bit operations on address registers.
4137 ;; We have to take care that the address register is not used for the
4138 ;; source of operand2. If operand2 is the D register, we have to save
4139 ;; that register in a temporary location.
4141 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4144 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4145 (match_operator:QI 3 "m68hc11_arith_operator"
4146 [(match_operand:QI 1 "hard_addr_reg_operand" "")
4147 (match_operand:QI 2 "general_operand" "")]))]
4148 "z_replacement_completed == 2
4149 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
4150 incqi pattern generates a better code. */
4151 && !(GET_CODE (operands[3]) == PLUS
4152 && GET_CODE (operands[2]) == CONST_INT
4153 && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4154 [(set (match_dup 5) (match_dup 6))
4155 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4156 (set (match_dup 4) (reg:HI D_REGNUM))])
4157 (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4158 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4159 (set (match_dup 4) (reg:HI D_REGNUM))])]
4160 "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
4162 /* For the second operand is a hard register or if the address
4163 register appears in the source, we have to save the operand[2]
4164 value in a temporary location and then use that temp.
4165 Otherwise, it's ok and we generate a (set (D) (D)) that
4166 will result in a nop. */
4167 if (H_REG_P (operands[2]))
4169 operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4170 operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
4171 operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4173 else if (reg_mentioned_p (operands[0], operands[2]))
4175 operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4176 operands[6] = operands[2];
4177 operands[7] = operands[5];
4181 operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4182 operands[7] = operands[2];
4187 ;; Next split handles the logical operations on D register with
4188 ;; another hard register for the second operand. For this, we
4189 ;; have to save the second operand in a scratch location and use
4190 ;; it instead. This must be supported because in some (rare) cases
4191 ;; the second operand can come in a hard register and the reload
4192 ;; pass doesn't know how to reload it in a memory location.
4194 ;; PLUS MINUS AND IOR XOR
4196 ;; The shift operators are special and must not appear here.
4199 [(set (match_operand:QI 0 "d_register_operand" "")
4200 (match_operator:QI 3 "m68hc11_non_shift_operator"
4201 [(match_operand:QI 1 "d_register_operand" "")
4202 (match_operand:QI 2 "hard_reg_operand" "")]))]
4204 [(set (match_dup 5) (match_dup 6))
4205 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4206 "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4207 operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4208 operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
4210 ;;--------------------------------------------------------------------
4211 ;; 8-bit Unary operations on X and Y:
4215 ;; Operations on X or Y registers are split here. Instructions are
4217 ;; - xgdx/xgdy instruction pattern,
4218 ;; - The same operation on register D,
4219 ;; - xgdx/xgdy instruction pattern.
4220 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4221 ;; We also handle the case were the address register is used in both source
4222 ;; operands, such as:
4224 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4226 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4229 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4230 (match_operator:QI 2 "m68hc11_unary_operator"
4231 [(match_operand:QI 1 "general_operand" "")]))]
4232 "z_replacement_completed == 2"
4233 [(set (match_dup 4) (match_dup 5))
4234 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4235 (set (match_dup 3) (reg:HI D_REGNUM))])
4236 (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4237 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4238 (set (match_dup 3) (reg:HI D_REGNUM))])]
4241 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4242 if ((H_REG_P (operands[1])
4243 && !rtx_equal_p (operands[0], operands[1]))
4244 || reg_mentioned_p (operands[0], operands[1]))
4246 /* Move to the destination register, before the xgdx. */
4247 operands[4] = operands[0];
4248 operands[5] = operands[1];
4250 /* Apply the operation on D. */
4251 operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4255 operands[4] = operands[5] = operands[0];
4256 operands[6] = operands[1];
4261 ;;--------------------------------------------------------------------
4263 ;;--------------------------------------------------------------------
4265 (define_expand "negdi2"
4266 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4267 (neg:DI (match_operand:DI 1 "general_operand" "")))]
4269 "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4273 (define_insn "negsi2"
4274 [(set (match_operand:SI 0 "register_operand" "=D")
4275 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
4283 /* With -Os or without -O, use a special library call. */
4284 if (optimize_size || optimize == 0)
4285 return \"bsr\\t___negsi2\";
4287 ops[0] = gen_label_rtx ();
4289 /* 32-bit complement and add 1. */
4290 output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4291 output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4292 output_asm_insn (\"bne\\t%l0\", ops);
4293 output_asm_insn (\"inx\", operands);
4294 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4298 (define_insn "neghi2"
4299 [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
4300 (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4303 coma\\n\\tcomb\\n\\taddd\\t#1
4304 clra\\n\\tclrb\\n\\tsubd\\t%1
4305 xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4307 (define_insn "negqi2"
4308 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4309 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
4318 ;; - 32-bit complement. GCC knows how to translate them but providing a
4319 ;; pattern generates better/smaller code.
4321 (define_expand "one_cmpldi2"
4322 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4323 (not:DI (match_operand:DI 1 "general_operand" "")))]
4325 "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4328 (define_insn "one_cmplsi2"
4329 [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4330 (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4331 (clobber (match_scratch:HI 2 "=X,d,X"))]
4334 bsr\\t___one_cmplsi2
4338 (define_insn "one_cmplhi2"
4339 [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
4340 (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
4344 com\\t%b0\\n\\tcom\\t%h0
4346 com\\t%b0\\n\\tcom\\t%h0")
4348 (define_insn "one_cmplqi2"
4349 [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
4350 (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
4358 (define_split /* "*one_cmplsi2" */
4359 [(set (match_operand:SI 0 "non_push_operand" "")
4360 (not:SI (match_dup 0)))
4361 (clobber (match_scratch:HI 1 ""))]
4362 "z_replacement_completed == 2
4363 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4364 [(set (match_dup 2) (not:HI (match_dup 2)))
4365 (set (match_dup 3) (not:HI (match_dup 3)))]
4366 "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4367 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
4369 (define_split /* "*one_cmplsi2" */
4370 [(set (match_operand:SI 0 "non_push_operand" "")
4371 (not:SI (match_operand:SI 1 "non_push_operand" "")))
4372 (clobber (match_operand:HI 2 "d_register_operand" ""))]
4373 "z_replacement_completed == 2
4374 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4375 [(set (match_dup 2) (match_dup 3))
4376 (set (match_dup 2) (not:HI (match_dup 2)))
4377 (set (match_dup 4) (match_dup 2))
4378 (set (match_dup 2) (match_dup 5))
4379 (set (match_dup 2) (not:HI (match_dup 2)))
4380 (set (match_dup 6) (match_dup 2))]
4381 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4382 operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4383 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4384 operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
4386 ;;--------------------------------------------------------------------
4387 ;;- arithmetic shifts
4388 ;;--------------------------------------------------------------------
4390 ;; Provide some 64-bit shift patterns.
4391 (define_expand "ashldi3"
4392 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4393 (ashift:DI (match_operand:DI 1 "general_operand" "")
4394 (match_operand:HI 2 "general_operand" "")))
4395 (clobber (match_scratch:HI 3 ""))])]
4399 if (GET_CODE (operands[2]) != CONST_INT
4400 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4406 (define_insn_and_split "*ashldi3_const32"
4407 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4408 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4410 (clobber (match_scratch:HI 2 "=&A,d,d"))]
4415 "/* Move the lowpart in the highpart first in case the shift
4416 is applied on the source. */
4417 if (IS_STACK_PUSH (operands[0]))
4419 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4420 const0_rtx, operands[2]);
4422 /* Adjust first operand if it uses SP so that we take into
4423 account the above push. Can occur only for 68HC12. */
4424 if (reg_mentioned_p (gen_rtx (REG, HImode, HARD_SP_REGNUM),
4426 operands[1] = adjust_address (operands[1],
4427 GET_MODE (operands[0]), 4);
4429 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4430 m68hc11_gen_lowpart (SImode, operands[1]),
4432 if (!IS_STACK_PUSH (operands[0]))
4434 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4435 const0_rtx, operands[2]);
4439 (define_insn_and_split "*ashldi3_const1"
4440 [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4441 (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4443 (clobber (match_scratch:HI 2 "=d,d,d"))]
4446 "z_replacement_completed == 2"
4447 [(set (match_dup 2) (match_dup 3))
4448 (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4449 (set (match_dup 4) (match_dup 2))
4451 (set (match_dup 2) (match_dup 5))
4452 (parallel [(set (match_dup 2)
4453 (rotate:HI (match_dup 2) (const_int 1)))
4454 (clobber (reg:HI CC_REGNUM))])
4455 (set (match_dup 6) (match_dup 2))
4457 (set (match_dup 2) (match_dup 7))
4458 (parallel [(set (match_dup 2)
4459 (rotate:HI (match_dup 2) (const_int 1)))
4460 (clobber (reg:HI CC_REGNUM))])
4461 (set (match_dup 8) (match_dup 2))
4463 (set (match_dup 2) (match_dup 9))
4464 (parallel [(set (match_dup 2)
4465 (rotate:HI (match_dup 2) (const_int 1)))
4466 (clobber (reg:HI CC_REGNUM))])
4467 (set (match_dup 10) (match_dup 2))]
4468 "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4469 operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4470 operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4472 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4473 operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4474 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4476 operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4477 operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4478 operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4480 operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4481 operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4482 operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4484 (define_insn "addsi_silshr16"
4485 [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
4486 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
4488 (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
4493 [(set (match_operand:SI 0 "register_operand" "")
4494 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4496 (match_operand:SI 2 "general_operand" "")))]
4497 "z_replacement_completed == 2 && !X_REG_P (operands[1])"
4498 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4499 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4501 (reg:HI CC_REGNUM)))]
4502 "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4505 [(set (match_operand:SI 0 "register_operand" "")
4506 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4508 (match_operand:SI 2 "general_operand" "")))]
4509 "z_replacement_completed == 2 && X_REG_P (operands[1])"
4510 [(set (reg:HI D_REGNUM) (match_dup 5))
4511 (set (reg:HI X_REGNUM) (match_dup 3))
4512 (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4513 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4515 (reg:HI CC_REGNUM)))]
4516 "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4517 if (X_REG_P (operands[2]))
4519 operands[4] = gen_rtx (REG, HImode, HARD_X_REGNUM);
4520 operands[5] = gen_rtx (REG, HImode, HARD_D_REGNUM);
4524 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4525 operands[5] = gen_rtx (REG, HImode, HARD_X_REGNUM);
4529 (define_insn "addsi_ashift16"
4530 [(set (match_operand:SI 0 "register_operand" "=D")
4532 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4534 (match_operand:SI 1 "general_operand" "0")))
4535 (clobber (match_scratch:HI 3 "=X"))]
4540 [(set (match_operand:SI 0 "register_operand" "")
4542 (mult:SI (match_operand:SI 2 "general_operand" "")
4544 (match_operand:SI 1 "general_operand" "")))
4545 (clobber (match_scratch:HI 3 "=X"))]
4546 "0 && reload_completed && z_replacement_completed == 2"
4547 [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4550 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4553 (define_insn_and_split "addsi_andshr16"
4554 [(set (match_operand:SI 0 "register_operand" "=D")
4555 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4557 (match_operand:SI 2 "general_operand" "0")))]
4560 "z_replacement_completed == 2"
4561 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4562 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4563 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4566 ;; 32-bit shifts are made by a small library routine that uses
4567 ;; a specific passing convention for parameters (for efficiency reasons).
4569 ;; [D + X] -> Value to be shifted
4572 ;; The shift count is clobbered by the routine.
4574 (define_expand "ashlsi3"
4576 [(set (match_operand:SI 0 "register_operand" "")
4577 (match_operand:SI 1 "general_operand" ""))
4578 (clobber (scratch:HI))])
4580 [(set (match_dup 0) (ashift:SI (match_dup 0)
4581 (match_operand:HI 2 "nonmemory_operand" "")))
4582 (clobber (scratch:HI))])]
4587 [(set (match_operand:SI 0 "nonimmediate_operand" "")
4588 (ashift:SI (match_operand:SI 1 "general_operand" "")
4590 (clobber (match_scratch:HI 3 ""))]
4592 [(set (match_dup 2) (match_dup 3))
4593 (set (match_dup 4) (const_int 0))]
4594 "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4595 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4596 operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4598 (define_insn "*ashlsi3_const16"
4599 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4600 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4602 (clobber (match_scratch:HI 2 "=X,X,X"))]
4606 (define_insn_and_split "*ashlsi3_const16_zexthi"
4607 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4608 (ashift:SI (zero_extend:HI
4609 (match_operand:HI 1 "general_operand" "duim*A"))
4611 (clobber (match_scratch:HI 2 "=X"))]
4615 [(set (reg:HI X_REGNUM) (match_dup 1))
4616 (set (reg:HI D_REGNUM) (const_int 0))]
4619 (define_insn "*ashlsi3_const1"
4620 [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
4621 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
4623 (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
4628 if (X_REG_P (operands[1]))
4630 return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4636 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4637 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4638 m68hc11_gen_movhi (insn, ops);
4639 output_asm_insn (\"lsld\", ops);
4640 if (!X_REG_P (operands[0]))
4643 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4644 m68hc11_gen_movhi (insn, ops);
4646 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4647 m68hc11_gen_movhi (insn, ops);
4651 /* Load the high part in X in case the source operand
4652 uses X as a memory pointer. */
4653 ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4654 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4655 m68hc11_gen_movhi (insn, ops);
4656 output_asm_insn (\"xgdx\", ops);
4658 output_asm_insn (\"rolb\", ops);
4659 output_asm_insn (\"rola\", ops);
4660 if (!X_REG_P (operands[0]))
4663 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4664 m68hc11_gen_movhi (insn, ops);
4668 output_asm_insn (\"xgdx\", ops);
4674 (define_insn "*ashlsi3_const"
4675 [(set (match_operand:SI 0 "register_operand" "+D")
4676 (ashift:SI (match_dup 0)
4677 (match_operand:HI 1 "const_int_operand" "")))
4678 (clobber (match_scratch:HI 2 "=y"))]
4679 "TARGET_M6811 /* See *ashlsi3 note. */"
4683 return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4686 (define_insn "*ashlsi3"
4687 [(set (match_operand:SI 0 "register_operand" "+D,D")
4688 (ashift:SI (match_dup 0)
4689 (match_operand:HI 1 "general_operand" "y,mi")))
4690 (clobber (match_scratch:HI 2 "=1,X"))]
4696 /* There is a reload problem if we don't accept 'm' for the shift value.
4697 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4698 and this conflicts with all reloads. Since X, Y, Z are used there
4699 is not enough register in class A_REGS.
4701 Assuming that 'operands[1]' does not refer to the stack (which
4702 is true for 68hc11 only, we save temporary the value of Y.
4704 For 68HC12 we must also accept a constant because Z register is
4705 disabled when compiling with -fomit-frame-pointer. We can come up
4706 with a reload problem and the *lshrsi3_const pattern was disabled
4708 if (!Y_REG_P (operands[2]))
4711 int y_dead = dead_register_here (insn, iy_reg);
4713 ops[0] = operands[1];
4716 output_asm_insn (\"pshy\", operands);
4717 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4718 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4720 output_asm_insn (\"ldy\\t%0\", ops);
4721 output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4722 return y_dead == 0 ? \"puly\" : \"\";
4724 return \"bsr\\t___ashlsi3\";
4727 (define_expand "ashlhi3"
4728 [(set (match_operand:HI 0 "register_operand" "")
4729 (ashift:HI (match_operand:HI 1 "register_operand" "")
4730 (match_operand:HI 2 "general_operand" "")))]
4734 if (GET_CODE (operands[2]) != CONST_INT)
4736 rtx scratch = gen_reg_rtx (HImode);
4737 emit_move_insn (scratch, operands[2]);
4738 emit_insn (gen_rtx_PARALLEL (VOIDmode,
4739 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4741 gen_rtx_ASHIFT (HImode,
4742 operand1, scratch)),
4743 gen_rtx_CLOBBER (VOIDmode, scratch))));
4748 (define_insn "*ashlhi3_const1"
4749 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4750 (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4755 if (A_REG_P (operands[0]))
4758 if (D_REG_P (operands[0]))
4763 output_asm_insn (\"asl\\t%b0\", operands);
4764 output_asm_insn (\"rol\\t%h0\", operands);
4770 (define_insn "*ashlhi3_2"
4771 [(set (match_operand:HI 0 "register_operand" "=d,*x")
4772 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4773 (match_operand:HI 2 "register_operand" "+x,+d")))
4774 (clobber (match_dup 2))]
4778 if (A_REG_P (operands[0]))
4782 return \"bsr\\t___lshlhi3\";
4785 (define_insn "*ashlhi3"
4786 [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4787 (ashift:HI (match_dup 0)
4788 (match_operand:HI 1 "register_operand" "+x")))
4789 (clobber (match_dup 1))]
4794 return \"bsr\\t___lshlhi3\";
4797 (define_insn "*ashlhi3"
4798 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4799 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4800 (match_operand:HI 2 "const_int_operand" "")))]
4806 if (A_REG_P (operands[0]))
4809 i = INTVAL (operands[2]);
4813 output_asm_insn (\"tba\", operands);
4816 output_asm_insn (\"rora\", operands);
4817 output_asm_insn (\"anda\\t#0\", operands);
4818 output_asm_insn (\"rora\", operands);
4823 output_asm_insn (\"asla\", operands);
4828 for (i = 0; i < INTVAL (operands[2]) - 1; i++)
4830 output_asm_insn (\"asld\", operands);
4835 (define_expand "ashlqi3"
4836 [(set (match_operand:QI 0 "register_operand" "")
4837 (ashift:QI (match_operand:QI 1 "register_operand" "")
4838 (match_operand:QI 2 "general_operand" "")))]
4842 (define_insn "*ashlqi3_const1"
4843 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4844 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4854 (define_insn "*ashlqi3_const"
4855 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4856 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4857 (match_operand:QI 2 "const_int_operand" "")))]
4862 const char* insn_code;
4864 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4865 insn_code = \"aslb\";
4866 else if (DA_REG_P (operands[0]))
4867 insn_code = \"asla\";
4871 i = INTVAL (operands[2]);
4874 if (DA_REG_P (operands[0]))
4881 if (DA_REG_P (operands[0]))
4883 output_asm_insn (\"rora\", operands);
4884 output_asm_insn (\"ldaa\\t#0\", operands);
4889 output_asm_insn (\"rorb\", operands);
4890 output_asm_insn (\"ldab\\t#0\", operands);
4896 if (DA_REG_P (operands[0]))
4898 output_asm_insn (\"rora\", operands);
4899 output_asm_insn (\"rora\", operands);
4900 output_asm_insn (\"rora\", operands);
4901 return \"anda\\t#0xC0\";
4905 output_asm_insn (\"rorb\", operands);
4906 output_asm_insn (\"rorb\", operands);
4907 output_asm_insn (\"rorb\", operands);
4908 return \"andb\\t#0xC0\";
4913 output_asm_insn (insn_code, operands);
4918 (define_insn "*ashlqi3"
4919 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4920 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4921 (match_operand:QI 2 "nonimmediate_operand"
4922 "m*u*d*A,m*u*d*A,m*u")))]
4928 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4931 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
4932 ops[1] = operands[2];
4933 m68hc11_gen_movqi (insn, ops);
4936 return \"bsr\\t___lshlqi3\";
4939 (define_expand "ashrhi3"
4940 [(set (match_operand:HI 0 "register_operand" "")
4941 (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4942 (match_operand:HI 2 "general_operand" "")))]
4946 if (GET_CODE (operands[2]) != CONST_INT)
4948 rtx scratch = gen_reg_rtx (HImode);
4950 emit_move_insn (scratch, operands[2]);
4951 emit_insn (gen_rtx_PARALLEL (VOIDmode,
4952 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4954 gen_rtx_ASHIFTRT (HImode,
4955 operand1, scratch)),
4956 gen_rtx_CLOBBER (VOIDmode, scratch))));
4961 (define_insn "*ashrhi3_const1"
4962 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4963 (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4968 if (A_REG_P (operands[0]))
4972 if (D_REG_P (operands[0]))
4974 return \"asra\\n\\trorb\";
4977 output_asm_insn (\"asr\\t%h0\", operands);
4978 output_asm_insn (\"ror\\t%b0\", operands);
4983 (define_insn "*ashrhi3_const"
4984 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4985 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4986 (match_operand:HI 2 "const_int_operand" "")))]
4991 int val = INTVAL (operands[2]);
4993 if (A_REG_P (operands[0]))
4998 ops[0] = gen_label_rtx ();
5000 output_asm_insn (\"clrb\", operands);
5001 output_asm_insn (\"rola\", operands);
5003 /* Clear A without clearing the carry flag. */
5004 output_asm_insn (\"tba\", operands);
5005 output_asm_insn (\"bcc\\t%l0\", ops);
5006 output_asm_insn (\"coma\", operands);
5007 output_asm_insn (\"comb\", operands);
5010 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5011 CODE_LABEL_NUMBER (ops[0]));
5016 ops[0] = gen_label_rtx ();
5018 output_asm_insn (\"tab\", operands);
5019 output_asm_insn (\"clra\", operands);
5020 output_asm_insn (\"tstb\", operands);
5021 output_asm_insn (\"bge\\t%l0\", ops);
5022 output_asm_insn (\"deca\", operands);
5024 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5025 CODE_LABEL_NUMBER (ops[0]));
5031 output_asm_insn (\"asrb\", operands);
5039 ops[0] = gen_label_rtx ();
5040 output_asm_insn (\"rolb\", operands);
5041 output_asm_insn (\"rola\", operands);
5042 output_asm_insn (\"tab\", operands);
5043 output_asm_insn (\"anda\\t#0\", operands);
5044 output_asm_insn (\"bcc\\t%l0\", ops);
5045 output_asm_insn (\"coma\", ops);
5047 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5048 CODE_LABEL_NUMBER (ops[0]));
5053 output_asm_insn (\"asra\", operands);
5054 output_asm_insn (\"rorb\", operands);
5062 (define_insn "*ashrhi3"
5063 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5064 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5065 (match_operand:HI 2 "register_operand" "+x,+d")))
5066 (clobber (match_dup 2))]
5070 if (A_REG_P (operands[0]))
5073 output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5077 (define_expand "ashrsi3"
5079 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5080 (clobber (scratch:HI))])
5082 [(set (match_operand:SI 0 "register_operand" "")
5083 (ashiftrt:SI (match_dup 0)
5084 (match_operand:HI 2 "general_operand" "")))
5085 (clobber (scratch:HI))])]
5089 (define_insn "*ashrsi3_const"
5090 [(set (match_operand:SI 0 "register_operand" "+D")
5091 (ashiftrt:SI (match_dup 0)
5092 (match_operand:HI 1 "const_int_operand" "")))
5093 (clobber (match_scratch:HI 2 "=y"))]
5094 "TARGET_M6811 /* See *ashrsi3 note. */"
5098 return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
5101 (define_insn "*ashrsi3"
5102 [(set (match_operand:SI 0 "register_operand" "+D,D")
5103 (ashiftrt:SI (match_dup 0)
5104 (match_operand:HI 1 "general_operand" "y,mi")))
5105 (clobber (match_scratch:HI 2 "=1,X"))]
5110 /* There is a reload problem if we don't accept 'm' for the shift value.
5111 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5112 and this conflicts with all reloads. Since X, Y, Z are used there
5113 is not enough register in class A_REGS.
5115 Assuming that 'operands[1]' does not refer to the stack (which
5116 is true for 68hc11 only, we save temporary the value of Y.
5118 For 68HC12 we must also accept a constant because Z register is
5119 disabled when compiling with -fomit-frame-pointer. We can come up
5120 with a reload problem and the *lshrsi3_const pattern was disabled
5122 if (!Y_REG_P (operands[2]))
5125 int y_dead = dead_register_here (insn, iy_reg);
5127 ops[0] = operands[1];
5130 output_asm_insn (\"pshy\", operands);
5131 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5132 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5134 output_asm_insn (\"ldy\\t%0\", ops);
5135 output_asm_insn (\"bsr\\t___ashrsi3\", operands);
5136 return y_dead == 0 ? \"puly\" : \"\";
5138 return \"bsr\\t___ashrsi3\";
5141 (define_expand "ashrqi3"
5142 [(set (match_operand:QI 0 "register_operand" "")
5143 (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5144 (match_operand:QI 2 "general_operand" "")))]
5148 (define_insn "*ashrqi3_const1"
5149 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5150 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5160 (define_insn "*ashrqi3_const"
5161 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5162 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5163 (match_operand:QI 2 "const_int_operand" "")))]
5168 const char* insn_code;
5170 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5171 insn_code = \"asrb\";
5172 else if (DA_REG_P (operands[0]))
5173 insn_code = \"asra\";
5177 i = INTVAL (operands[2]);
5182 output_asm_insn (insn_code, operands);
5187 (define_insn "*ashrqi3"
5188 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5189 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5190 (match_operand:QI 2 "nonimmediate_operand"
5191 "m*u*d*A,m*u*d*A,m*u")))]
5197 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5200 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5201 ops[1] = operands[2];
5202 m68hc11_gen_movqi (insn, ops);
5205 return \"bsr\\t___ashrqi3\";
5208 ;;--------------------------------------------------------------------
5209 ;; logical shift instructions
5210 ;;--------------------------------------------------------------------
5211 (define_expand "lshrdi3"
5212 [(parallel [(set (match_operand:DI 0 "general_operand" "")
5213 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5214 (match_operand:HI 2 "general_operand" "")))
5215 (clobber (match_scratch:HI 3 ""))])]
5219 if (GET_CODE (operands[2]) != CONST_INT
5220 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5221 && INTVAL (operands[2]) != 1))
5227 (define_insn_and_split "*lshrdi3_const32"
5228 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5229 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
5231 (clobber (match_scratch:HI 2 "=&A,d,d"))]
5236 "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5237 m68hc11_gen_highpart (SImode, operands[1]),
5239 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5240 const0_rtx, operands[2]);
5243 (define_insn "*lshrdi3_const63"
5244 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5245 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5246 (match_operand:DI 2 "const_int_operand" "")))
5247 (clobber (match_scratch:HI 3 "=d,d"))]
5248 "INTVAL (operands[2]) >= 48"
5252 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5253 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5254 (match_operand:DI 2 "const_int_operand" "")))
5255 (clobber (match_scratch:HI 3 "=d"))]
5256 "z_replacement_completed && INTVAL (operands[2]) >= 56"
5257 [(set (reg:QI D_REGNUM) (match_dup 9))
5258 (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5259 (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5260 (set (match_dup 4) (reg:HI D_REGNUM))
5261 (set (reg:QI D_REGNUM) (const_int 0))
5262 (set (match_dup 5) (reg:HI D_REGNUM))
5263 (set (match_dup 6) (reg:HI D_REGNUM))
5264 (set (match_dup 7) (reg:HI D_REGNUM))]
5265 "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
5266 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5267 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5268 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5270 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5271 operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5272 operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5274 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5275 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5276 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5279 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5280 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5281 (match_operand:DI 2 "const_int_operand" "")))
5282 (clobber (match_scratch:HI 3 "=d"))]
5283 "z_replacement_completed && INTVAL (operands[2]) >= 48
5284 && INTVAL (operands[2]) < 56"
5285 [(set (reg:HI D_REGNUM) (match_dup 9))
5286 (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5287 (set (match_dup 4) (reg:HI D_REGNUM))
5288 (set (reg:HI D_REGNUM) (const_int 0))
5289 (set (match_dup 5) (reg:HI D_REGNUM))
5290 (set (match_dup 6) (reg:HI D_REGNUM))
5291 (set (match_dup 7) (reg:HI D_REGNUM))]
5292 "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
5293 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5294 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5295 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5297 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5298 operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5299 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5300 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5301 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5303 (define_insn_and_split "*lshrdi_const1"
5304 [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5305 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5307 (clobber (match_scratch:HI 2 "=d,d"))]
5310 "z_replacement_completed == 2"
5311 [(set (match_dup 2) (match_dup 3))
5312 (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5313 (set (match_dup 4) (match_dup 2))
5315 (set (match_dup 2) (match_dup 5))
5316 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5317 (clobber (reg:HI CC_REGNUM))])
5318 (set (match_dup 6) (match_dup 2))
5320 (set (match_dup 2) (match_dup 7))
5321 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5322 (clobber (reg:HI CC_REGNUM))])
5323 (set (match_dup 8) (match_dup 2))
5325 (set (match_dup 2) (match_dup 9))
5326 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5327 (clobber (reg:HI CC_REGNUM))])
5328 (set (match_dup 10) (match_dup 2))]
5329 "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5330 operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5331 operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5333 operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5334 operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5335 operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5337 operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5338 operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5339 operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5341 operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5342 operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5343 operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5345 (define_expand "lshrsi3"
5347 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5348 (clobber (scratch:HI))])
5350 [(set (match_operand:SI 0 "register_operand" "")
5351 (lshiftrt:SI (match_dup 0)
5352 (match_operand:HI 2 "general_operand" "")))
5353 (clobber (scratch:HI))])]
5358 [(set (match_operand:SI 0 "non_push_operand" "")
5359 (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
5361 (clobber (match_scratch:HI 3 ""))]
5362 "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5363 [(set (match_dup 2) (match_dup 3))
5364 (set (match_dup 4) (const_int 0))]
5365 "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5366 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5367 operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5369 (define_insn "*lshrsi3_const16"
5370 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5371 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
5373 (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5381 (define_insn "*lshrsi3_const1"
5382 [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
5383 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
5385 (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
5390 if (X_REG_P (operands[1]))
5392 return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5398 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5399 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
5400 m68hc11_gen_movhi (insn, ops);
5401 output_asm_insn (\"lsrd\", ops);
5402 if (!X_REG_P (operands[0]))
5405 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5406 m68hc11_gen_movhi (insn, ops);
5408 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5409 m68hc11_gen_movhi (insn, ops);
5413 /* Load the lowpart in X in case the operands is some N,x. */
5414 ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
5415 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5416 m68hc11_gen_movhi (insn, ops);
5417 output_asm_insn (\"xgdx\", ops);
5419 output_asm_insn (\"rora\", ops);
5420 output_asm_insn (\"rorb\", ops);
5421 if (!X_REG_P (operands[0]))
5424 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5425 m68hc11_gen_movhi (insn, ops);
5431 (define_insn "*lshrsi3_const"
5432 [(set (match_operand:SI 0 "register_operand" "+D")
5433 (lshiftrt:SI (match_dup 0)
5434 (match_operand:HI 1 "const_int_operand" "")))
5435 (clobber (match_scratch:HI 2 "=y"))]
5436 "TARGET_M6811 /* See *lshrsi3 note. */"
5440 return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5443 (define_insn "*lshrsi3"
5444 [(set (match_operand:SI 0 "register_operand" "+D,D")
5445 (lshiftrt:SI (match_dup 0)
5446 (match_operand:HI 1 "general_operand" "y,mi")))
5447 (clobber (match_scratch:HI 2 "=1,X"))]
5452 /* There is a reload problem if we don't accept 'm' for the shift value.
5453 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5454 and this conflicts with all reloads. Since X, Y, Z are used there
5455 is not enough register in class A_REGS.
5457 Assuming that 'operands[1]' does not refer to the stack (which
5458 is true for 68hc11 only, we save temporary the value of Y.
5460 For 68HC12 we must also accept a constant because Z register is
5461 disabled when compiling with -fomit-frame-pointer. We can come up
5462 with a reload problem and the *lshrsi3_const pattern was disabled
5464 if (!Y_REG_P (operands[2]))
5467 int y_dead = dead_register_here (insn, iy_reg);
5469 ops[0] = operands[1];
5472 output_asm_insn (\"pshy\", operands);
5473 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5474 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5476 output_asm_insn (\"ldy\\t%0\", ops);
5477 output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5478 return y_dead == 0 ? \"puly\" : \"\";
5480 return \"bsr\\t___lshrsi3\";
5483 (define_expand "lshrhi3"
5484 [(set (match_operand:HI 0 "register_operand" "")
5485 (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5486 (match_operand:HI 2 "general_operand" "")))]
5490 if (GET_CODE (operands[2]) != CONST_INT)
5492 rtx scratch = gen_reg_rtx (HImode);
5493 operand1 = force_reg (HImode, operand1);
5495 emit_move_insn (scratch, operands[2]);
5496 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5497 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5499 gen_rtx_LSHIFTRT (HImode,
5500 operand1, scratch)),
5501 gen_rtx_CLOBBER (VOIDmode, scratch))));
5506 (define_insn "lshrhi3_const1"
5507 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5508 (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5513 if (A_REG_P (operands[0]))
5516 if (D_REG_P (operands[0]))
5520 return \"lsr\\t%h0\\n\\tror\\t%b0\";
5523 (define_insn "lshrhi3_const"
5524 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5525 (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5526 (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5530 int val = INTVAL (operands[2]);
5532 if (A_REG_P (operands[0]))
5540 if (!H_REG_P (operands[1]))
5542 output_asm_insn (\"clra\", operands);
5543 output_asm_insn (\"ldab\\t%h1\", operands);
5545 else if (A_REG_P (operands[1]))
5547 output_asm_insn (\"st%1\\t%t0\", operands);
5548 output_asm_insn (\"ldab\\t%t0\", operands);
5549 output_asm_insn (\"clra\", operands);
5553 output_asm_insn (\"tab\", operands);
5554 output_asm_insn (\"clra\", operands);
5560 output_asm_insn (\"rolb\", operands);
5561 output_asm_insn (\"tab\", operands);
5562 output_asm_insn (\"rolb\", operands);
5566 output_asm_insn (\"rolb\", operands);
5567 output_asm_insn (\"rolb\", operands);
5568 output_asm_insn (\"rolb\", operands);
5569 output_asm_insn (\"andb\\t#3\", operands);
5576 output_asm_insn (\"lsrb\", operands);
5583 if (!D_REG_P (operands[1]))
5584 m68hc11_gen_movhi (insn, operands);
5588 output_asm_insn (\"rolb\", operands);
5589 output_asm_insn (\"tab\", operands);
5590 output_asm_insn (\"rolb\", operands);
5591 output_asm_insn (\"rola\", operands);
5592 output_asm_insn (\"rola\", operands);
5593 output_asm_insn (\"anda\\t#1\", operands);
5601 output_asm_insn (\"lsrd\", operands);
5607 (define_insn "*lshrhi3"
5608 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5609 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5610 (match_operand:HI 2 "register_operand" "+x,+d")))
5611 (clobber (match_dup 2))]
5615 if (A_REG_P (operands[0]))
5618 return \"bsr\\t___lshrhi3\";
5621 (define_expand "lshrqi3"
5622 [(set (match_operand:QI 0 "register_operand" "")
5623 (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5624 (match_operand:QI 2 "general_operand" "")))]
5628 (define_insn "*lshrqi3_const1"
5629 [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5630 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5640 (define_insn "*lshrqi3_const"
5641 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5642 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5643 (match_operand:QI 2 "const_int_operand" "")))]
5648 const char* insn_code;
5650 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5651 insn_code = \"lsrb\";
5652 else if (DA_REG_P (operands[0]))
5653 insn_code = \"lsra\";
5657 i = INTVAL (operands[2]);
5660 if (DA_REG_P (operands[0]))
5667 if (DA_REG_P (operands[0]))
5669 output_asm_insn (\"rola\", operands);
5670 output_asm_insn (\"ldaa\\t#0\", operands);
5675 output_asm_insn (\"rolb\", operands);
5676 output_asm_insn (\"ldab\\t#0\", operands);
5682 if (DA_REG_P (operands[0]))
5684 output_asm_insn (\"rola\", operands);
5685 output_asm_insn (\"rola\", operands);
5686 output_asm_insn (\"rola\", operands);
5687 return \"anda\\t#3\";
5691 output_asm_insn (\"rolb\", operands);
5692 output_asm_insn (\"rolb\", operands);
5693 output_asm_insn (\"rolb\", operands);
5694 return \"andb\\t#3\";
5699 output_asm_insn (insn_code, operands);
5704 (define_insn "*lshrqi3"
5705 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5706 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5707 (match_operand:QI 2 "nonimmediate_operand"
5708 "m*u*d*A,m*u*d*A,m*u")))]
5714 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5718 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5719 ops[1] = operands[2];
5720 m68hc11_gen_movqi (insn, ops);
5722 if (!optimize || optimize_size)
5724 return \"bsr\\t___lshrqi3\";
5727 ops[0] = gen_label_rtx ();
5728 ops[1] = gen_label_rtx ();
5729 output_asm_insn (\"ble\\t%l1\", ops);
5731 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5732 CODE_LABEL_NUMBER (ops[0]));
5734 output_asm_insn (\"lsrb\", operands);
5735 output_asm_insn (\"deca\", operands);
5736 output_asm_insn (\"bne\\t%l0\", ops);
5738 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5739 CODE_LABEL_NUMBER (ops[1]));
5743 (define_insn "*rotlqi3_with_carry"
5744 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5745 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5746 (reg:QI CC_REGNUM)))]
5750 if (DA_REG_P (operands[0]))
5756 (define_insn "*rotlhi3_with_carry"
5757 [(set (match_operand:HI 0 "register_operand" "=d")
5758 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5760 (clobber (reg:HI CC_REGNUM))]
5765 return \"rolb\\n\\trola\";
5768 (define_insn "*rotrhi3_with_carry"
5769 [(set (match_operand:HI 0 "register_operand" "=d")
5770 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5772 (clobber (reg:HI CC_REGNUM))]
5777 return \"rora\\n\\trorb\";
5780 (define_insn "rotlqi3"
5781 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5782 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5783 (match_operand:QI 2 "const_int_operand" "i,i")))]
5787 m68hc11_gen_rotate (ROTATE, insn, operands);
5791 (define_insn "rotrqi3"
5792 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5793 (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5794 (match_operand:QI 2 "const_int_operand" "i,i")))]
5798 m68hc11_gen_rotate (ROTATERT, insn, operands);
5802 (define_expand "rotlhi3"
5803 [(set (match_operand:HI 0 "register_operand" "")
5804 (rotate:HI (match_operand:HI 1 "register_operand" "")
5805 (match_operand:HI 2 "general_operand" "")))]
5809 if (GET_CODE (operands[2]) != CONST_INT)
5811 rtx scratch = gen_reg_rtx (HImode);
5812 operand1 = force_reg (HImode, operand1);
5814 emit_move_insn (scratch, operands[2]);
5815 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5816 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5818 gen_rtx_ROTATE (HImode,
5819 operand1, scratch)),
5820 gen_rtx_CLOBBER (VOIDmode, scratch))));
5825 (define_insn "rotlhi3_const"
5826 [(set (match_operand:HI 0 "register_operand" "=d")
5827 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5828 (match_operand:HI 2 "const_int_operand" "i")))]
5832 m68hc11_gen_rotate (ROTATE, insn, operands);
5836 (define_insn "*rotlhi3"
5837 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5838 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
5839 (match_operand:HI 2 "general_operand" "+x,+d")))
5840 (clobber (match_dup 2))]
5844 if (A_REG_P (operands[0]))
5847 return \"bsr\\t___rotlhi3\";
5850 (define_expand "rotrhi3"
5851 [(set (match_operand:HI 0 "register_operand" "")
5852 (rotatert:HI (match_operand:HI 1 "general_operand" "")
5853 (match_operand:HI 2 "general_operand" "")))]
5857 if (GET_CODE (operands[2]) != CONST_INT)
5859 rtx scratch = gen_reg_rtx (HImode);
5860 operand1 = force_reg (HImode, operand1);
5862 emit_move_insn (scratch, operands[2]);
5863 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5864 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5866 gen_rtx_ROTATERT (HImode,
5867 operand1, scratch)),
5868 gen_rtx_CLOBBER (VOIDmode, scratch))));
5873 (define_insn "rotrhi3_const"
5874 [(set (match_operand:HI 0 "register_operand" "=d")
5875 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5876 (match_operand:HI 2 "const_int_operand" "i")))]
5880 m68hc11_gen_rotate (ROTATERT, insn, operands);
5884 (define_insn "*rotrhi3"
5885 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5886 (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
5887 (match_operand:HI 2 "general_operand" "+x,+d")))
5888 (clobber (match_dup 2))]
5892 if (A_REG_P (operands[0]))
5895 return \"bsr\\t___rotrhi3\";
5898 ;; Split a shift operation on an address register in a shift
5900 (define_split /* "*rotrhi3_addr" */
5901 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
5902 (match_operator:HI 3 "m68hc11_shift_operator"
5903 [(match_operand:HI 1 "register_operand" "")
5904 (match_operand:HI 2 "register_operand" "")]))
5905 (clobber (match_dup 2))]
5906 "z_replacement_completed == 2"
5907 [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5908 (set (match_dup 0) (reg:HI D_REGNUM))])
5909 (parallel [(set (reg:HI D_REGNUM)
5910 (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
5911 (clobber (match_dup 0))])
5912 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5913 (set (match_dup 0) (reg:HI D_REGNUM))])]
5916 ;;--------------------------------------------------------------------
5917 ;;- 68HC12 Decrement/Increment and branch
5918 ;;--------------------------------------------------------------------
5919 ;; These patterns are used by loop optimization as well as peephole2
5920 ;; They must handle reloading themselves and the scratch register
5921 ;; is used for that. Even if we accept memory operand, we must not
5922 ;; accept them on the predicate because it might create too many reloads.
5923 ;; (specially on HC12 due to its auto-incdec addressing modes).
5925 (define_expand "decrement_and_branch_until_zero"
5926 [(parallel [(set (pc)
5928 (ne (plus:HI (match_operand:HI 0 "register_operand" "")
5931 (label_ref (match_operand 1 "" ""))
5934 (plus:HI (match_dup 0)
5936 (clobber (match_scratch:HI 2 ""))])]
5940 (define_expand "doloop_end"
5941 [(use (match_operand 0 "" "")) ; loop pseudo
5942 (use (match_operand 1 "" "")) ; iterations; zero if unknown
5943 (use (match_operand 2 "" "")) ; max iterations
5944 (use (match_operand 3 "" "")) ; loop level
5945 (use (match_operand 4 "" ""))] ; label
5949 /* Reject non-constant loops as it generates bigger code due to
5950 the handling of the loop register. We can do better by using
5951 the peephole2 dbcc/ibcc patterns. */
5952 if (INTVAL (operands[1]) == 0)
5957 /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
5958 the operator and its operands are not relevant. */
5959 if (GET_MODE (operands[0]) == HImode)
5961 emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
5968 if (GET_MODE (operands[0]) == QImode)
5970 emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
5981 ;; Decrement-and-branch insns.
5982 (define_insn "m68hc12_dbcc_dec_hi"
5985 (match_operator 1 "m68hc11_eq_compare_operator"
5986 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5988 (label_ref (match_operand 2 "" ""))
5991 (plus:HI (match_dup 0) (const_int -1)))
5992 (clobber (match_scratch:HI 3 "=X,dxy"))]
5996 if (!H_REG_P (operands[0]))
6000 if (GET_CODE (operands[1]) == EQ)
6001 return \"dbeq\\t%0,%l2\";
6003 return \"dbne\\t%0,%l2\";
6006 ;; Decrement-and-branch insns.
6007 (define_insn "m68hc12_dbcc_inc_hi"
6010 (match_operator 1 "m68hc11_eq_compare_operator"
6011 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
6013 (label_ref (match_operand 2 "" ""))
6016 (plus:HI (match_dup 0) (const_int 1)))
6017 (clobber (match_scratch:HI 3 "=X,dxy"))]
6021 if (!H_REG_P (operands[0]))
6025 if (GET_CODE (operands[1]) == EQ)
6026 return \"ibeq\\t%0,%l2\";
6028 return \"ibeq\\t%0,%l2\";
6031 ;; Decrement-and-branch (QImode).
6032 (define_insn "m68hc12_dbcc_dec_qi"
6035 (match_operator 1 "m68hc11_eq_compare_operator"
6036 [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6038 (label_ref (match_operand 2 "" ""))
6041 (plus:QI (match_dup 0) (const_int -1)))
6042 (clobber (match_scratch:QI 3 "=X,d"))]
6046 if (!D_REG_P (operands[0]))
6050 if (GET_CODE (operands[1]) == EQ)
6051 return \"dbeq\\tb,%l2\";
6053 return \"dbne\\tb,%l2\";
6056 ;; Increment-and-branch (QImode).
6057 (define_insn "m68hc12_dbcc_inc_qi"
6060 (match_operator 1 "m68hc11_eq_compare_operator"
6061 [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6063 (label_ref (match_operand 2 "" ""))
6066 (plus:QI (match_dup 0) (const_int 1)))
6067 (clobber (match_scratch:QI 3 "=X,d"))]
6071 if (!D_REG_P (operands[0]))
6075 if (GET_CODE (operands[1]) == EQ)
6076 return \"ibeq\\tb,%l2\";
6078 return \"ibeq\\tb,%l2\";
6081 ;; Split the above to handle the case where operand 0 is in memory
6082 ;; (a register that couldn't get a hard register)
6086 (match_operator 3 "m68hc11_eq_compare_operator"
6087 [(match_operand:HI 0 "general_operand" "")
6088 (match_operand:HI 1 "const_int_operand" "")])
6089 (label_ref (match_operand 4 "" ""))
6092 (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6093 (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
6094 "TARGET_M6812 && reload_completed"
6095 [(set (match_dup 5) (match_dup 0))
6096 (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
6097 (set (match_dup 0) (match_dup 5))
6099 (if_then_else (match_op_dup 3
6100 [(match_dup 5) (const_int 0)])
6101 (label_ref (match_dup 4)) (pc)))]
6104 ;; Split the above to handle the case where operand 0 is in memory
6105 ;; (a register that couldn't get a hard register)
6109 (match_operator 3 "m68hc11_eq_compare_operator"
6110 [(match_operand:QI 0 "general_operand" "")
6111 (match_operand:QI 1 "const_int_operand" "")])
6112 (label_ref (match_operand 4 "" ""))
6115 (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6116 (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
6117 "TARGET_M6812 && reload_completed"
6118 [(set (match_dup 5) (match_dup 0))
6119 (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
6120 (set (match_dup 0) (match_dup 5))
6122 (if_then_else (match_op_dup 3
6123 [(match_dup 5) (const_int 0)])
6124 (label_ref (match_dup 4)) (pc)))]
6127 ;;--------------------------------------------------------------------
6128 ;;- Jumps and transfers
6129 ;;--------------------------------------------------------------------
6132 (label_ref (match_operand 0 "" "")))]
6136 (define_expand "beq"
6138 (if_then_else (eq (cc0)
6140 (label_ref (match_operand 0 "" ""))
6145 m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
6146 m68hc11_compare_op1,
6151 (define_expand "bne"
6153 (if_then_else (ne (cc0)
6155 (label_ref (match_operand 0 "" ""))
6160 m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
6161 m68hc11_compare_op1,
6166 (define_expand "bgt"
6168 (if_then_else (gt (cc0)
6170 (label_ref (match_operand 0 "" ""))
6175 m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
6176 m68hc11_compare_op1,
6181 (define_expand "bgtu"
6183 (if_then_else (gtu (cc0)
6185 (label_ref (match_operand 0 "" ""))
6190 m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
6191 m68hc11_compare_op1,
6196 (define_expand "blt"
6198 (if_then_else (lt (cc0)
6200 (label_ref (match_operand 0 "" ""))
6205 m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
6206 m68hc11_compare_op1,
6211 (define_expand "bltu"
6213 (if_then_else (ltu (cc0)
6215 (label_ref (match_operand 0 "" ""))
6220 m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
6221 m68hc11_compare_op1,
6226 (define_expand "bge"
6228 (if_then_else (ge (cc0)
6230 (label_ref (match_operand 0 "" ""))
6235 m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
6236 m68hc11_compare_op1,
6241 (define_expand "bgeu"
6243 (if_then_else (geu (cc0)
6245 (label_ref (match_operand 0 "" ""))
6250 m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
6251 m68hc11_compare_op1,
6256 (define_expand "ble"
6258 (if_then_else (le (cc0)
6260 (label_ref (match_operand 0 "" ""))
6265 m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
6266 m68hc11_compare_op1,
6271 (define_expand "bleu"
6273 (if_then_else (leu (cc0)
6275 (label_ref (match_operand 0 "" ""))
6280 m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
6281 m68hc11_compare_op1,
6287 ;; Test and branch instructions for 68HC12 for EQ and NE.
6288 ;; 'z' must not appear in the constraints because the z replacement
6289 ;; pass does not know how to restore the replacement register.
6291 (define_insn "*tbeq"
6293 (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
6295 (label_ref (match_operand 1 "" ""))
6300 /* If the flags are already set correctly, use 'bne/beq' which are
6301 smaller and a little bit faster. This happens quite often due
6302 to reloading of operands[0]. In that case, flags are set correctly
6303 due to the load instruction. */
6304 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6305 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6306 return \"beq\\t%l1\";
6308 return \"tbeq\\t%0,%l1\";
6311 (define_insn "*tbne"
6313 (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6315 (label_ref (match_operand 1 "" ""))
6320 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6321 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6322 return \"bne\\t%l1\";
6324 return \"tbne\\t%0,%l1\";
6328 ;; Test and branch with 8-bit register. Register must be B (or A).
6330 (define_insn "*tbeq8"
6332 (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6334 (label_ref (match_operand 1 "" ""))
6339 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6340 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6341 return \"beq\\t%l1\";
6343 return \"tbeq\\tb,%l1\";
6346 (define_insn "*tbne8"
6348 (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6350 (label_ref (match_operand 1 "" ""))
6355 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6356 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6357 return \"bne\\t%l1\";
6359 return \"tbne\\tb,%l1\";
6364 (if_then_else (eq (cc0)
6366 (label_ref (match_operand 0 "" ""))
6373 (if_then_else (ne (cc0)
6375 (label_ref (match_operand 0 "" ""))
6382 (if_then_else (gt (cc0)
6384 (label_ref (match_operand 0 "" ""))
6389 (define_insn "*bgtu"
6391 (if_then_else (gtu (cc0)
6393 (label_ref (match_operand 0 "" ""))
6400 (if_then_else (lt (cc0)
6402 (label_ref (match_operand 0 "" ""))
6407 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6408 return \"bmi\\t%l0\";
6410 return \"blt\\t%l0\";
6413 (define_insn "*bltu"
6415 (if_then_else (ltu (cc0)
6417 (label_ref (match_operand 0 "" ""))
6424 (if_then_else (ge (cc0)
6426 (label_ref (match_operand 0 "" ""))
6431 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6432 return \"bpl\\t%l0\";
6434 return \"bge\\t%l0\";
6437 (define_insn "*bgeu"
6439 (if_then_else (geu (cc0)
6441 (label_ref (match_operand 0 "" ""))
6448 (if_then_else (le (cc0)
6450 (label_ref (match_operand 0 "" ""))
6455 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6456 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6458 return \"ble\\t%l0\";
6461 (define_insn "*bleu"
6463 (if_then_else (leu (cc0)
6465 (label_ref (match_operand 0 "" ""))
6470 ;;--------------------------------------------------------------------
6471 ;;- Negative test and branch
6472 ;;--------------------------------------------------------------------
6475 (if_then_else (eq (cc0)
6478 (label_ref (match_operand 0 "" ""))))]
6484 (if_then_else (ne (cc0)
6487 (label_ref (match_operand 0 "" ""))))]
6493 (if_then_else (gt (cc0)
6496 (label_ref (match_operand 0 "" ""))))]
6500 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6501 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6503 return \"ble\\t%l0\";
6508 (if_then_else (gtu (cc0)
6511 (label_ref (match_operand 0 "" ""))))]
6517 (if_then_else (lt (cc0)
6520 (label_ref (match_operand 0 "" ""))))]
6524 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6525 return \"bpl\\t%l0\";
6527 return \"bge\\t%l0\";
6532 (if_then_else (ltu (cc0)
6535 (label_ref (match_operand 0 "" ""))))]
6541 (if_then_else (ge (cc0)
6544 (label_ref (match_operand 0 "" ""))))]
6548 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6549 return \"bmi\\t%l0\";
6551 return \"blt\\t%l0\";
6556 (if_then_else (geu (cc0)
6559 (label_ref (match_operand 0 "" ""))))]
6565 (if_then_else (le (cc0)
6568 (label_ref (match_operand 0 "" ""))))]
6574 (if_then_else (leu (cc0)
6577 (label_ref (match_operand 0 "" ""))))]
6581 ;;--------------------------------------------------------------------
6583 ;;--------------------------------------------------------------------
6585 ;;- Call a function that returns no value.
6587 [(call (match_operand:QI 0 "memory_operand" "m")
6588 (match_operand:SI 1 "general_operand" "g"))]
6589 ;; Operand 1 not really used on the m68hc11.
6593 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6595 if (m68hc11_is_far_symbol (operands[0]))
6599 output_asm_insn (\"call\\t%0\", operands);
6604 output_asm_insn (\"pshb\", operands);
6605 output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
6606 output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
6607 return \"jsr\\t__call_a32\";
6610 if (m68hc11_is_trap_symbol (operands[0]))
6613 return \"bsr\\t%0\";
6617 return \"jsr\\t%0\";
6621 (define_insn "call_value"
6622 [(set (match_operand 0 "" "=g")
6623 (call (match_operand:QI 1 "memory_operand" "m")
6624 (match_operand:SI 2 "general_operand" "g")))]
6628 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6630 if (m68hc11_is_far_symbol (operands[1]))
6634 output_asm_insn (\"call\\t%1\", operands);
6639 output_asm_insn (\"pshb\", operands);
6640 output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
6641 output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
6642 return \"jsr\\t__call_a32\";
6645 if (m68hc11_is_trap_symbol (operands[1]))
6648 return \"bsr\\t%1\";
6652 return \"jsr\\t%1\";
6656 ;; Call subroutine returning any type.
6658 (define_expand "untyped_call"
6659 [(parallel [(call (match_operand 0 "" "")
6661 (match_operand 1 "" "")
6662 (match_operand 2 "" "")])]
6668 emit_call_insn (gen_call (operands[0], const0_rtx));
6670 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6672 rtx set = XVECEXP (operands[2], 0, i);
6673 emit_move_insn (SET_DEST (set), SET_SRC (set));
6676 /* The optimizer does not know that the call sets the function value
6677 registers we stored in the result block. We avoid problems by
6678 claiming that all hard registers are used and clobbered at this
6680 emit_insn (gen_blockage ());
6685 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6686 ;; all of memory. This blocks insns from being moved across this point.
6688 (define_insn "blockage"
6689 [(unspec_volatile [(const_int 0)] 0)]
6698 (define_expand "prologue"
6707 (define_expand "epilogue"
6716 ;; Used for frameless functions which save no regs and allocate no locals.
6717 (define_expand "return"
6719 "reload_completed && m68hc11_total_frame_size () == 0"
6724 if (current_function_return_rtx)
6725 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6727 /* Emit use notes only when HAVE_return is true. */
6728 if (m68hc11_total_frame_size () != 0)
6731 if (ret_size && ret_size <= 2)
6733 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6734 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6735 gen_rtx_USE (VOIDmode,
6736 gen_rtx_REG (HImode, 1)))));
6741 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6742 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6743 gen_rtx_USE (VOIDmode,
6744 gen_rtx_REG (SImode, 0)))));
6749 (define_insn "*return_void"
6754 rtx next = next_active_insn (insn);
6757 && GET_CODE (next) == JUMP_INSN
6758 && GET_CODE (PATTERN (next)) == RETURN)
6760 if (current_function_interrupt || current_function_trap)
6762 else if (!current_function_far)
6764 else if (TARGET_M6812)
6770 if (current_function_return_rtx)
6771 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6774 return \"jmp\\t__return_void\";
6776 return \"jmp\\t__return_16\";
6778 return \"jmp\\t__return_32\";
6779 return \"jmp\\t__return_16\";
6783 (define_insn "*return_16bit"
6785 (use (reg:HI D_REGNUM))]
6786 "reload_completed && m68hc11_total_frame_size () == 0"
6789 rtx next = next_active_insn (insn);
6792 && GET_CODE (next) == JUMP_INSN
6793 && GET_CODE (PATTERN (next)) == RETURN)
6795 if (current_function_interrupt || current_function_trap)
6797 else if (!current_function_far)
6799 else if (TARGET_M6812)
6802 return \"jmp\\t__return_16\";
6805 (define_insn "*return_32bit"
6808 "reload_completed && m68hc11_total_frame_size () == 0"
6811 rtx next = next_active_insn (insn);
6814 && GET_CODE (next) == JUMP_INSN
6815 && GET_CODE (PATTERN (next)) == RETURN)
6817 if (current_function_interrupt || current_function_trap)
6819 else if (!current_function_far)
6821 else if (TARGET_M6812)
6824 return \"jmp\\t__return_32\";
6827 (define_insn "indirect_jump"
6828 [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6832 ;;--------------------------------------------------------------------
6834 ;;--------------------------------------------------------------------
6836 ;; Operand 0 is the address of the table element to use
6837 ;; operand 1 is the CODE_LABEL for the table
6838 ;;--------------------------------------------------------------------
6839 (define_expand "tablejump"
6840 [(parallel [(set (pc) (match_operand 0 "" ""))
6841 (use (label_ref (match_operand 1 "" "")))])]
6845 (define_insn "*jump_indirect"
6847 (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6848 (use (label_ref (match_operand 1 "" "")))])]
6852 ;;--------------------------------------------------------------------
6854 ;;--------------------------------------------------------------------
6856 ;;--------------------------------------------------------------------
6857 ;;- 68HC12 dbcc/ibcc peepholes
6858 ;;--------------------------------------------------------------------
6860 ;; Replace: "addd #-1; bne L1" into "dbne d,L1"
6861 ;; "addd #-1; beq L1" into "dbeq d,L1"
6862 ;; "addd #1; bne L1" into "ibne d,L1"
6863 ;; "addd #1; beq L1" into "ibeq d,L1"
6866 [(set (match_operand:HI 0 "hard_reg_operand" "")
6867 (plus:HI (match_dup 0)
6868 (match_operand:HI 1 "const_int_operand" "")))
6870 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6873 (label_ref (match_operand 3 "" "")) (pc)))]
6874 "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6876 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6877 (label_ref (match_dup 3)) (pc)))
6878 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
6879 (clobber (match_dup 4))])]
6880 "operands[4] = gen_rtx_SCRATCH(HImode);
6881 operands[5] = GEN_INT (-INTVAL (operands[1]));")
6885 ;; Replace: "addb #-1; bne L1" into "dbne b,L1"
6886 ;; "addb #-1; beq L1" into "dbeq b,L1"
6889 [(set (match_operand:QI 0 "hard_reg_operand" "")
6890 (plus:QI (match_dup 0)
6891 (match_operand:QI 1 "const_int_operand" "")))
6893 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6896 (label_ref (match_operand 3 "" "")) (pc)))]
6897 "TARGET_M6812 && D_REG_P (operands[0])
6898 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6900 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6901 (label_ref (match_dup 3)) (pc)))
6902 (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
6903 (clobber (match_dup 4))])]
6904 "operands[4] = gen_rtx_SCRATCH(QImode);
6905 operands[5] = GEN_INT (-INTVAL (operands[1]));")
6908 ;;--------------------------------------------------------------------
6910 ;;--------------------------------------------------------------------
6913 ;; Replace "leas 2,sp" with a "pulx" or a "puly".
6914 ;; On 68HC12, this is one cycle slower but one byte smaller.
6915 ;; pr target/6899: This peephole is not valid because a register CSE
6916 ;; pass removes the pulx/puly.
6919 [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6920 (match_scratch:HI 0 "xy")]
6921 "0 && TARGET_M6812 && optimize_size"
6922 [(set (match_dup 0) (match_dup 1))]
6923 "operands[1] = gen_rtx_MEM (HImode,
6924 gen_rtx_POST_INC (HImode,
6925 gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
6927 ;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
6929 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6930 (match_operand:HI 0 "hard_reg_operand" ""))
6932 (match_operand:HI 1 "hard_reg_operand" ""))
6933 (set (mem:HI (reg:HI SP_REGNUM))
6936 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6938 (set (match_dup 0) (match_dup 1))]
6942 ;; Change: "ldd 0,sp; pulx" into "puld"
6943 ;; This sequence usually appears at end a functions.
6945 [(set (match_operand:HI 0 "hard_reg_operand" "")
6946 (mem:HI (reg:HI SP_REGNUM)))
6948 (set (match_operand:HI 1 "hard_reg_operand" "")
6949 (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
6950 "peep2_reg_dead_p (2, operands[1])"
6951 [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
6952 (use (match_dup 0))]
6955 ;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
6956 ;; Appears to allocate local variables.
6958 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6959 (match_operand:HI 0 "hard_reg_operand" ""))
6960 (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
6962 (set (mem:QI (reg:HI SP_REGNUM))
6965 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6969 ;; Likewise for HI mode
6971 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6972 (match_operand:HI 0 "hard_reg_operand" ""))
6973 (set (mem:HI (reg:HI SP_REGNUM))
6976 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6979 ;;--------------------------------------------------------------------
6981 ;;--------------------------------------------------------------------
6983 ;; Optimize memory<->memory moves when the value is also loaded in
6987 [(set (match_operand:QI 0 "memory_operand" "")
6988 (match_operand:QI 1 "memory_operand" ""))
6989 (set (reg:QI D_REGNUM)
6990 (match_operand:QI 2 "memory_operand" ""))]
6991 "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
6992 || (GET_CODE (XEXP (operands[0], 0)) == REG
6993 && GET_CODE (XEXP (operands[2], 0)) == POST_INC
6994 && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
6995 [(set (reg:QI D_REGNUM) (match_dup 1))
6996 (set (match_dup 2) (reg:QI D_REGNUM))]
7000 ;; Remove a possible move before a compare instruction when that
7001 ;; move will go in a dead register. Compare with the source then.
7004 [(set (match_operand:HI 0 "hard_reg_operand" "")
7005 (match_operand:HI 1 "hard_reg_operand" ""))
7007 (compare (match_dup 0)
7008 (match_operand:HI 2 "cmp_operand" "")))]
7009 "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
7010 && peep2_reg_dead_p (2, operands[0])
7011 && !reg_mentioned_p (operands[0], operands[2])"
7012 [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
7016 ;; Optimize loading a constant to memory when that same constant
7017 ;; is loaded to a hard register. Switch the two to use the register
7018 ;; for memory initialization. In most cases, the constant is 0.
7021 [(set (match_operand:HI 0 "memory_operand" "")
7022 (match_operand:HI 1 "immediate_operand" ""))
7023 (set (match_operand:HI 2 "hard_reg_operand" "")
7025 "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
7026 && !reg_mentioned_p (operands[2], operands[0])"
7027 [(set (match_dup 2) (match_dup 1))
7028 (set (match_dup 0) (match_dup 2))]
7032 ;; Reorganize to optimize address computations.
7035 [(set (match_operand:HI 0 "hard_reg_operand" "")
7036 (match_operand:HI 1 "const_int_operand" ""))
7038 (plus:HI (match_dup 0)
7039 (match_operand:HI 2 "general_operand" "")))]
7040 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7041 [(set (match_dup 0) (match_dup 2))
7042 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7046 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7049 [(set (match_operand:HI 0 "hard_reg_operand" "")
7050 (match_operand:HI 1 "const_int_operand" ""))
7052 (plus:HI (match_dup 0)
7053 (match_operand:HI 2 "general_operand" "")))
7054 (match_scratch:QI 3 "d")]
7055 "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
7056 [(set (match_dup 3) (match_dup 4))
7057 (set (match_dup 0) (match_dup 2))
7058 (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
7059 "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
7062 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7065 [(set (match_operand:HI 0 "hard_reg_operand" "")
7066 (match_operand:HI 1 "const_int_operand" ""))
7068 (plus:HI (match_dup 0)
7069 (match_operand:HI 2 "general_operand" "")))]
7071 [(set (match_dup 0) (match_dup 2))
7072 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7076 ;; Optimize an address register increment and a compare to use
7077 ;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
7078 ;; before reload, but can be enabled after).
7081 [(set (match_operand:HI 0 "hard_reg_operand" "")
7082 (plus:HI (match_dup 0)
7083 (match_operand:HI 1 "const_int_operand" "")))
7085 (match_operand:QI 2 "memory_operand" ""))]
7086 "TARGET_AUTO_INC_DEC
7087 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7088 && reg_mentioned_p (operands[0], operands[2])"
7089 [(set (cc0) (match_dup 3))]
7090 "if (INTVAL (operands[1]) == 1)
7091 operands[3] = gen_rtx_MEM (QImode,
7092 gen_rtx_PRE_INC (HImode, operands[0]));
7094 operands[3] = gen_rtx_MEM (QImode,
7095 gen_rtx_PRE_DEC (HImode, operands[0]));
7099 ;; Likewise for compare.
7102 [(set (match_operand:HI 0 "hard_reg_operand" "")
7103 (plus:HI (match_dup 0)
7104 (match_operand:HI 1 "const_int_operand" "")))
7106 (compare (match_operand:QI 2 "hard_reg_operand" "")
7107 (match_operand:QI 3 "memory_operand" "")))]
7108 "TARGET_AUTO_INC_DEC
7109 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7110 && reg_mentioned_p (operands[0], operands[3])"
7111 [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
7112 "if (INTVAL (operands[1]) == 1)
7113 operands[4] = gen_rtx_MEM (QImode,
7114 gen_rtx_PRE_INC (HImode, operands[0]));
7116 operands[4] = gen_rtx_MEM (QImode,
7117 gen_rtx_PRE_DEC (HImode, operands[0]));
7121 [(set (match_operand:HI 0 "hard_reg_operand" "")
7122 (plus:HI (match_dup 0)
7123 (match_operand:HI 1 "const_int_operand" "")))
7125 (compare (match_operand:QI 2 "memory_operand" "")
7126 (match_operand:QI 3 "hard_reg_operand" "")))]
7127 "TARGET_AUTO_INC_DEC
7128 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7129 && reg_mentioned_p (operands[0], operands[2])"
7130 [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
7131 "if (INTVAL (operands[1]) == 1)
7132 operands[4] = gen_rtx_MEM (QImode,
7133 gen_rtx_PRE_INC (HImode, operands[0]));
7135 operands[4] = gen_rtx_MEM (QImode,
7136 gen_rtx_PRE_DEC (HImode, operands[0]));
7140 ;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
7141 ;; (avoids many temporary moves because we can't add sp to another reg easily)
7144 [(set (match_operand:HI 0 "hard_reg_operand" "")
7145 (match_operand:HI 1 "const_int_operand" ""))
7146 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7148 [(set (match_dup 0) (reg:HI SP_REGNUM))
7149 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7153 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7156 [(set (match_operand:HI 0 "hard_reg_operand" "")
7157 (match_operand:HI 1 "const_int_operand" ""))
7159 (plus:HI (match_dup 0)
7160 (match_operand:HI 2 "general_operand" "")))]
7161 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7162 [(set (match_dup 0) (match_dup 2))
7163 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7171 [(set (match_operand:SI 0 "hard_reg_operand" "")
7172 (ashift:SI (match_operand:SI 1 "general_operand" "")
7174 (clobber (match_scratch:HI 2 ""))])
7175 (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
7176 (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
7177 "!X_REG_P (operands[1])
7178 && peep2_reg_dead_p (2, gen_rtx (REG, HImode, D_REGNUM))
7179 && peep2_reg_dead_p (3, gen_rtx (REG, HImode, X_REGNUM))"
7180 [(set (reg:HI D_REGNUM) (match_dup 5))
7181 (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
7182 (set (match_dup 3) (reg:HI D_REGNUM))
7183 (set (reg:HI D_REGNUM) (match_dup 6))
7184 (parallel [(set (reg:HI D_REGNUM)
7185 (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
7186 (clobber (reg:HI CC_REGNUM))])
7187 (set (match_dup 4) (reg:HI D_REGNUM))]
7188 "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
7189 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
7192 ;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
7195 [(set (match_operand:HI 0 "hard_reg_operand" "")
7196 (match_operand:HI 1 "memory_operand" ""))
7197 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
7199 (match_scratch:HI 2 "x")]
7200 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
7201 [(set (match_dup 2) (match_dup 1))
7202 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
7206 ;; Remove one load when copying a value to/from memory and also
7207 ;; to a register. Take care not clobbering a possible register used
7209 ;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
7212 [(set (match_operand:HI 0 "hard_reg_operand" "")
7213 (match_operand:HI 1 "general_operand" ""))
7214 (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
7215 (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
7216 "peep2_reg_dead_p (2, operands[0])
7217 && !side_effects_p (operands[1])
7218 && !side_effects_p (operands[2])
7219 && !reg_mentioned_p (operands[3], operands[2])"
7220 [(set (match_dup 3) (match_dup 1))
7221 (set (match_dup 2) (match_dup 3))]
7225 ;; Replace a "ldd <mem>; addd #N; std <mem>" into a
7226 ;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
7227 ;; and the constant is small.
7230 [(set (match_operand:HI 0 "hard_reg_operand" "")
7231 (match_operand:HI 1 "general_operand" ""))
7232 (set (match_dup 0) (plus:HI (match_dup 0)
7233 (match_operand:HI 2 "const_int_operand" "")))
7234 (set (match_operand:HI 3 "nonimmediate_operand" "")
7236 (match_scratch:HI 4 "xy")]
7237 "D_REG_P (operands[0])
7239 || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
7240 && peep2_reg_dead_p (3, operands[0])"
7241 [(set (match_dup 4) (match_dup 1))
7242 (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
7243 (set (match_dup 3) (match_dup 4))]
7244 "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
7245 if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
7247 ;;--------------------------------------------------------------------
7249 ;;--------------------------------------------------------------------
7250 ;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
7252 ;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
7253 ;; Register D must be dead and there must be no register side effects for mem.
7254 ;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
7255 ;; The good side effect is that it makes the sequence atomic.
7258 [(set (match_operand:QI 0 "hard_reg_operand" "")
7259 (match_operand:QI 1 "nonimmediate_operand" ""))
7260 (set (match_dup 0) (ior:QI (match_dup 0)
7261 (match_operand:QI 2 "const_int_operand" "")))
7262 (set (match_dup 1) (match_dup 0))]
7263 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7264 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7265 && peep2_reg_dead_p (3, operands[0])"
7266 [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
7270 [(set (match_operand:HI 0 "hard_reg_operand" "")
7271 (match_operand:HI 1 "nonimmediate_operand" ""))
7272 (set (match_dup 0) (ior:HI (match_dup 0)
7273 (match_operand:HI 2 "const_int_operand" "")))
7274 (set (match_dup 1) (match_dup 0))]
7275 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7276 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7277 && peep2_reg_dead_p (3, operands[0])"
7278 [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
7281 ;;--------------------------------------------------------------------
7283 ;;--------------------------------------------------------------------
7284 ;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
7285 ;; See Bset peephole2.
7288 [(set (match_operand:QI 0 "hard_reg_operand" "")
7289 (match_operand:QI 1 "nonimmediate_operand" ""))
7290 (set (match_dup 0) (and:QI (match_dup 0)
7291 (match_operand:QI 2 "const_int_operand" "")))
7292 (set (match_dup 1) (match_dup 0))]
7293 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7294 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7295 && peep2_reg_dead_p (3, operands[0])"
7296 [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
7300 [(set (match_operand:HI 0 "hard_reg_operand" "")
7301 (match_operand:HI 1 "nonimmediate_operand" ""))
7302 (set (match_dup 0) (and:HI (match_dup 0)
7303 (match_operand:HI 2 "const_int_operand" "")))
7304 (set (match_dup 1) (match_dup 0))]
7305 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7306 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7307 && peep2_reg_dead_p (3, operands[0])"
7308 [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
7312 ;;--------------------------------------------------------------------
7313 ;;- Compare peephole2
7314 ;;--------------------------------------------------------------------
7316 [(set (match_operand:HI 0 "hard_reg_operand" "")
7317 (match_operand:HI 1 "hard_reg_operand" ""))
7318 (set (match_dup 1) (plus:HI (match_dup 1)
7319 (match_operand:HI 2 "const_int_operand" "")))
7320 (set (cc0) (match_dup 0))]
7321 "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
7322 [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
7323 (set (cc0) (compare (match_dup 1) (match_dup 2)))]
7327 [(set (match_operand:HI 0 "hard_reg_operand" "")
7328 (match_operand:HI 1 "hard_reg_operand" ""))
7329 (set (match_operand:HI 2 "hard_reg_operand" "")
7330 (plus:HI (match_dup 2)
7331 (match_operand:HI 3 "const_int_operand" "")))
7332 (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
7333 (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
7334 "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
7335 && !reg_mentioned_p (operands[2], operands[4])
7337 && ((rtx_equal_p (operands[5], operands[0])
7338 && rtx_equal_p (operands[2], operands[1]))
7340 || (rtx_equal_p (operands[5], operands[1])
7341 && rtx_equal_p (operands[2], operands[0])))"
7342 [(set (match_dup 2) (match_dup 1))
7343 (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
7344 (set (match_dup 4) (match_dup 2))
7345 (set (cc0) (compare (match_dup 2) (match_dup 3)))]
7349 ;;--------------------------------------------------------------------
7351 ;;--------------------------------------------------------------------
7353 ;; Optimize initialization of 2 hard regs from the same memory location
7354 ;; Since we can't copy easily X, Y and D to each other, load the 2 registers
7355 ;; from the same memory location.
7358 [(set (match_operand:HI 0 "hard_reg_operand" "")
7359 (match_operand:HI 1 "memory_operand" ""))
7360 (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7362 && !side_effects_p (operands[1])
7363 && !reg_mentioned_p (operands[0], operands[1])"
7364 [(set (match_dup 0) (match_dup 1))
7365 (set (match_dup 2) (match_dup 1))]
7368 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7371 [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7372 (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7373 (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7374 (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
7375 (match_scratch:HI 4 "d")]
7377 [(set (match_dup 4) (const_int 0))
7378 (set (match_dup 0) (match_dup 4))
7379 (set (match_dup 1) (match_dup 4))
7380 (set (match_dup 2) (match_dup 4))
7381 (set (match_dup 3) (match_dup 4))]
7385 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7388 [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7389 (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7390 (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7391 (match_scratch:HI 3 "d")]
7393 [(set (match_dup 3) (const_int 0))
7394 (set (match_dup 0) (match_dup 3))
7395 (set (match_dup 1) (match_dup 3))
7396 (set (match_dup 2) (match_dup 3))]
7400 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7403 [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
7404 (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
7405 (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
7406 (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
7407 (match_scratch:HI 4 "x")]
7408 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
7409 [(set (match_dup 4) (const_int 0))
7410 (set (match_dup 1) (match_dup 4))
7411 (set (match_dup 2) (match_dup 4))
7412 (set (match_dup 3) (match_dup 4))]
7416 ;; This peephole catches the address computations generated by the reload
7419 [(set (match_operand:HI 0 "hard_reg_operand" "xy")
7420 (match_operand:HI 1 "const_int_operand" ""))
7421 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7422 (set (match_dup 0) (reg:HI D_REGNUM))])
7423 (set (reg:HI D_REGNUM)
7424 (plus (reg:HI D_REGNUM)
7425 (match_operand:HI 2 "general_operand" "")))
7426 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7427 (set (match_dup 0) (reg:HI D_REGNUM))])]
7428 "(INTVAL (operands[1]) & 0x0FF) == 0"
7431 int value_loaded = 1;
7433 if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
7437 ops[0] = operands[0];
7438 ops[1] = operands[2];
7439 m68hc11_gen_movhi (insn, ops);
7440 output_asm_insn (\"xgd%0\", operands);
7442 else if (Y_REG_P (operands[0]))
7444 if (reg_mentioned_p (iy_reg, operands[2]))
7445 output_asm_insn (\"ldy\\t%2\", operands);
7448 output_asm_insn (\"xgdy\", operands);
7452 output_asm_insn (\"ldd\\t%2\", operands);
7455 if (value_loaded == 0)
7456 output_asm_insn (\"ldd\\t%2\", operands);
7457 if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
7458 output_asm_insn (\"inca\", operands);
7459 else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
7460 output_asm_insn (\"deca\", operands);
7461 else if (INTVAL (operands[1]) != 0)
7462 output_asm_insn (\"adda\\t%h1\", operands);
7464 if (X_REG_P (operands[0]))
7466 else if (Y_REG_P (operands[0]))
7474 [(set (match_operand:HI 0 "hard_reg_operand" "h")
7475 (match_operand:HI 1 "non_push_operand" "g"))
7476 (set (match_operand:HI 2 "hard_reg_operand" "h")
7478 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7479 && !S_REG_P (operands[2])"
7484 ops[0] = operands[2];
7485 ops[1] = operands[1];
7486 m68hc11_gen_movhi (insn, ops);
7492 [(set (match_operand:HI 0 "hard_reg_operand" "h")
7493 (match_operand:HI 1 "hard_reg_operand" "h"))
7494 (set (match_operand:HI 2 "non_push_operand" "g")
7496 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7497 && !S_REG_P (operands[2])"
7502 ops[0] = operands[2];
7503 ops[1] = operands[1];
7504 m68hc11_gen_movhi (insn, ops);
7510 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
7511 ;; the set, so we don't need to emit anything. 'ins1' refers to the
7515 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7516 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7517 (set (match_dup 0) (reg:HI D_REGNUM))])]
7518 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7521 cc_status = cc_prev_status;
7526 ;; Same as above but due to some split, there may be a noop set
7529 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7530 (set (match_dup 0) (match_dup 0))
7531 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7532 (set (match_dup 0) (reg:HI D_REGNUM))])]
7533 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7536 cc_status = cc_prev_status;
7542 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
7543 ;; and we must, at least, setup X/Y with value of D.
7546 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7547 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7548 (set (match_dup 0) (reg:HI D_REGNUM))])]
7554 ops[0] = operands[0];
7555 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7556 m68hc11_gen_movhi (insn, ops);
7562 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7563 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7566 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7567 (set (match_dup 0) (reg:HI D_REGNUM))])
7568 (set (reg:HI D_REGNUM) (match_dup 0))]
7569 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7572 cc_status = cc_prev_status;
7578 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7579 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7582 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7583 (set (match_dup 0) (reg:HI D_REGNUM))])
7584 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7585 "REGNO (operands[0]) == REGNO (operands[1])
7586 && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7589 cc_status = cc_prev_status;
7595 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7596 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7599 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7600 (set (match_dup 0) (reg:HI D_REGNUM))])
7601 (set (reg:HI D_REGNUM) (match_dup 0))]
7607 ops[0] = operands[0];
7608 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7609 m68hc11_gen_movhi (insn, ops);
7615 ;;; Same peephole with a QI set. The copy is made as 16-bit to comply
7619 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7620 (set (match_dup 0) (reg:HI D_REGNUM))])
7621 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7622 "REGNO (operands[0]) == REGNO (operands[1])"
7627 ops[0] = operands[0];
7628 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7629 m68hc11_gen_movhi (insn, ops);
7635 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
7638 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7639 (set (match_dup 0) (reg:HI D_REGNUM))])
7640 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7641 (set (match_dup 0) (reg:HI D_REGNUM))])]
7645 cc_status = cc_prev_status;
7651 [(set (match_operand:HI 0 "hard_reg_operand" "")
7652 (match_operand:HI 1 "stack_register_operand" ""))
7653 (set (match_operand:HI 2 "hard_reg_operand" "")
7654 (match_operand:HI 3 "memory_operand" "m"))
7656 (match_operand:HI 4 "memory_operand" "m"))]
7657 "IS_STACK_POP (operands[4])
7658 && (GET_CODE (operands[3]) == MEM &&
7659 rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
7664 ops[0] = operands[2];
7665 ops[1] = gen_rtx_MEM (HImode,
7666 gen_rtx_POST_INC (HImode, stack_pointer_rtx));
7667 m68hc11_gen_movhi (insn, ops);
7673 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
7676 [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
7677 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7681 return \"sts\\t%t0\\n\\tld%0\\t%t0\";
7686 [(set (match_operand:HI 0 "hard_reg_operand" "")
7687 (match_operand:HI 1 "memory_operand" ""))
7688 (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7690 && !side_effects_p (operands[1])
7691 && !reg_mentioned_p (operands[0], operands[1])"
7696 ops[0] = operands[0];
7697 ops[1] = operands[1];
7698 m68hc11_gen_movhi (insn, ops);
7699 ops[0] = operands[2];
7700 m68hc11_gen_movhi (insn, ops);
7704 ;; Peephole for Z register replacement.
7705 ;; Avoid to use _.tmp register when comparing D and X if we can compare
7706 ;; with soft register
7708 [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
7709 (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
7710 (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
7711 (reg:HI SOFT_TMP_REGNUM)))]
7712 "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
7717 ops[0] = operands[0];
7718 ops[1] = operands[1];
7719 m68hc11_gen_movhi (insn, ops);
7720 return \"cp%2\\t%1\";