1 ;;- Machine description file for Motorola 68HC11 and 68HC12.
2 ;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
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 3, 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 COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
23 ;; A first 68HC11 port was made by Otto Lind (otto@coactive.com)
24 ;; on gcc 2.6.3. I have used it as a starting point for this port.
25 ;; However, this new port is a complete re-write. Its internal
26 ;; design is completely different. The generated code is not
27 ;; compatible with the gcc 2.6.3 port.
29 ;; The gcc 2.6.3 port is available at:
31 ;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
34 ;;- Instruction patterns. When multiple patterns apply,
35 ;;- the first one in the file is chosen.
37 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
39 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
40 ;;- updates for most instructions.
43 ;; The following constraints are used:
45 ;; Single pair registers:
46 ;; a register 'a' 8-bit
47 ;; b register 'b' 8-bit
48 ;; d register 'd' 16-bit
49 ;; t pseudo soft register 'TMP' 16-bit
50 ;; v register 'd' for 68hc11, 16-bit
52 ;; (used for scratch register)
53 ;; w register 'sp' 16-bit
54 ;; x register 'x' 16-bit
55 ;; y register 'y' 16-bit
56 ;; z register 'z' 16-bit (fake r for 68HC11 and 68HC12)
57 ;; D register 'd+x' 32-bit
59 ;; Group of registers:
60 ;; q register 'a' or 'b' or 'd' 8-bit
61 ;; u pseudo soft register 16-bit
62 ;; A register 'x', 'y', 'z' 16-bit
63 ;; B register 'x', 'y' 16-bit
64 ;; h register 'd', 'x', 'y', 'z' 16-bit
68 ;; Q an operand which is in memory but whose address is constant
69 ;; (i.e., a (MEM (SYMBOL_REF x))). This constraint is used by
70 ;; bset/bclr instructions together with linker relaxation. The
71 ;; operand can be translated to a page0 addressing mode if the
72 ;; symbol address is in page0 (0..255).
74 ;; R an operand which is in memory and whose address is expressed
75 ;; with 68HC11/68HC12 indexed addressing mode. In general this
76 ;; is any valid (MEM) except a (MEM (SYMBOL_REF x)).
78 ;; U an operand which is in memory and if it uses the 68HC12 indexed
79 ;; addressing mode, the offset is in the range -16..+15. This is
80 ;; used by 68HC12 movb/movw instructions since they do not accept
81 ;; the full 16-bit offset range (as other insn do).
84 ;; Immediate integer operand constraints:
85 ;; `L' is for range -65536 to 65536
86 ;; `M' is for values whose 16-bit low part is 0
87 ;; 'N' is for +1 or -1.
88 ;; 'O' is for 16 (for rotate using swap).
89 ;; 'P' is for range -8 to 2 (used by addhi_sp)
91 ;; In many cases, it's not possible to use the 'g' or 'r' constraints.
93 ;; Operands modifiers:
95 ;; %b Get the low part of the operand (to obtain a QImode)
96 ;; This modifier must always be used for QImode operations
97 ;; because a correction must be applied when the operand
98 ;; is a soft register (ex: *ZD1). Otherwise, we generate
99 ;; *ZD1 and this is the high part of the register. For other
100 ;; kinds of operands, if the operand is already QImode, no
101 ;; additional correction is made.
102 ;; %h Get the high part of the operand (to obtain a QImode)
103 ;; %t Represents the temporary/scratch register *_.tmp
104 ;; The scratch register is used in some cases when GCC puts
105 ;; some values in bad registers.
107 ;; 32/64-bit Patterns:
108 ;; The 68HC11 does not support 32/64-bit operations. Most of the
109 ;; 32/64-bit patterns are defined to split the instruction in
110 ;; 16-bits patterns. Providing split patterns generates better code
111 ;; than letting GCC implement the 32/64-bit operation itself.
116 ;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
117 ;; otherwise some insn are not satisfied.
119 ;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
120 ;; be valid only when z_replacement_completed == 2 because once these
121 ;; swap instructions are generated, a flow/cse pass fails to handle
122 ;; them correctly (it would treat the X, Y or D register as dead sometimes).
124 ;; o Some split pattern generate instructions that operate on 'a' or 'b'
125 ;; register directly (high part and low part of D respectively).
126 ;; Such split pattern must also be valid when z_replacement_completed == 2
127 ;; because flow/cse is not aware that D is composed of {a, b}.
129 ;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
130 ;; the high part of a soft register must be expanded after z_replacement
133 ;;---------------------------------------------------------------------------
138 (X_REGNUM 0) ; Index X register
139 (D_REGNUM 1) ; Data register
140 (Y_REGNUM 2) ; Index Y register
141 (SP_REGNUM 3) ; Stack pointer
142 (PC_REGNUM 4) ; Program counter
143 (A_REGNUM 5) ; A (high part of D)
144 (B_REGNUM 6) ; B (low part of D)
145 (CC_REGNUM 7) ; Condition code register
146 (SOFT_TMP_REGNUM 10) ; TMP soft register
147 (SOFT_Z_REGNUM 11) ; Z soft register
148 (SOFT_XY_REGNUM 12) ; XY soft register
151 (include "predicates.md")
153 ;;--------------------------------------------------------------------
155 ;;--------------------------------------------------------------------
157 ;; The test and compare insn must not accept a memory operand with
158 ;; an auto-inc mode. If we do this, the reload can emit move insns
159 ;; after the test or compare. Such move will set the flags and therefore
160 ;; break the comparison. This can happen if the auto-inc register
161 ;; does not happen to be a hard register (i.e., reloading occurs).
162 ;; An offsetable memory operand should be ok. The 'tst_operand' and
163 ;; 'cmp_operand' predicates take care of this rule.
165 (define_expand "tstsi"
167 (match_operand:SI 0 "tst_operand" ""))]
171 m68hc11_compare_op0 = operands[0];
172 m68hc11_compare_op1 = const0_rtx;
176 (define_expand "tsthi"
178 (match_operand:HI 0 "tst_operand" ""))]
182 m68hc11_compare_op0 = operands[0];
183 m68hc11_compare_op1 = const0_rtx;
187 (define_insn "tsthi_1"
189 (match_operand:HI 0 "tst_operand" "dx,*y"))]
193 if (D_REG_P (operands[0]) && !TARGET_M6812)
194 return \"std\\t%t0\";
196 return \"cp%0\\t#0\";
199 (define_expand "tstqi"
201 (match_operand:QI 0 "tst_operand" ""))]
205 m68hc11_compare_op0 = operands[0];
206 m68hc11_compare_op1 = const0_rtx;
211 ;; Split pattern for (tst:QI) on an address register.
215 (match_operand:QI 0 "hard_addr_reg_operand" ""))]
216 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
217 [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
218 (set (match_dup 1) (reg:HI D_REGNUM))])
219 (set (cc0) (reg:QI D_REGNUM))
220 (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
221 (set (match_dup 1) (reg:HI D_REGNUM))])]
222 "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
224 (define_insn "tstqi_1"
226 (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
230 if (A_REG_P (operands[0]))
233 else if (D_REG_P (operands[0]))
236 else if (dead_register_here (insn, d_reg))
237 return \"ldab\\t%b0\";
240 return \"tst\\t%b0\";
244 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
245 ;; during the Z register replacement. They are used when an operand
246 ;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
247 ;; In that case, we have to preserve the values of the replacement
248 ;; register (as well as the CC0 since the insns are compare insns).
249 ;; To do this, the replacement register is pushed on the stack and
250 ;; restored after the real compare. A pattern+split is defined to
251 ;; avoid problems with the flow+cse register pass which are made
252 ;; after Z register replacement.
254 (define_insn_and_split "tstqi_z_used"
256 (match_operand:QI 0 "tst_operand" "m"))
257 (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
258 (use (reg:HI SOFT_Z_REGNUM))]
261 "z_replacement_completed == 2"
262 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
263 (set (match_dup 1) (match_dup 2))
264 (set (cc0) (match_dup 0))
265 (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
266 "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
269 ;;--------------------------------------------------------------------
271 ;;--------------------------------------------------------------------
273 (define_expand "cmpsi"
275 (compare (match_operand:SI 0 "tst_operand" "")
276 (match_operand:SI 1 "cmp_operand" "")))]
280 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
281 operands[0] = force_reg (SImode, operands[0]);
283 m68hc11_compare_op0 = operands[0];
284 m68hc11_compare_op1 = operands[1];
289 ;; Comparison of a hard register with another one is provided because
290 ;; it helps GCC to avoid to spill a pseudo hard register.
291 ;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
292 ;; (except that we loose the information that the value is saved in it).
294 ;; The split pattern transforms the comparison into a save of one hard
295 ;; register and a comparison with the temporary.
299 (compare (match_operand:HI 0 "hard_reg_operand" "")
300 (match_operand:HI 1 "hard_reg_operand" "")))]
302 && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
303 [(set (match_dup 2) (match_dup 1))
305 (compare (match_dup 0) (match_dup 2)))]
306 "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
310 (compare (match_operand:HI 0 "hard_reg_operand" "")
311 (match_operand:HI 1 "hard_reg_operand" "")))]
313 && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
314 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
316 (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
319 (define_expand "cmphi"
321 (compare (match_operand:HI 0 "tst_operand" "")
322 (match_operand:HI 1 "cmp_operand" "")))]
326 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
327 operands[0] = force_reg (HImode, operands[0]);
329 m68hc11_compare_op0 = operands[0];
330 m68hc11_compare_op1 = operands[1];
334 (define_insn "cmphi_1_hc12"
336 (compare (match_operand:HI 0 "tst_operand"
337 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
338 (match_operand:HI 1 "general_operand"
339 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
343 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
345 cc_status.flags |= CC_REVERSED;
346 return \"cp%1\\t%0\";
348 else if (SP_REG_P (operands[1]))
349 return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
350 else if (H_REG_P (operands[1]))
351 return \"psh%1\n\\tcp%0\\t2,sp+\";
353 return \"cp%0\\t%1\";
356 (define_insn "cmphi_1_hc11"
358 (compare (match_operand:HI 0 "tst_operand"
359 "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
360 (match_operand:HI 1 "cmp_operand"
361 "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
365 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
367 cc_status.flags |= CC_REVERSED;
368 return \"cp%1\\t%0\";
370 else if (H_REG_P (operands[1]))
373 return \"cp%0\\t%1\";
376 (define_insn_and_split "cmphi_z_used"
378 (compare (match_operand:HI 0 "tst_operand" "dxy,m")
379 (match_operand:HI 1 "cmp_operand" "mi,dxy")))
380 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
381 (use (reg:HI SOFT_Z_REGNUM))]
384 "z_replacement_completed == 2"
385 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
386 (set (match_dup 2) (match_dup 3))
387 (set (cc0) (compare (match_dup 0) (match_dup 1)))
388 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
389 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
392 ;; 8-bit comparison with address register.
393 ;; There is no such comparison instruction, we have to temporarily switch
394 ;; the address register and the D register and do the comparison with D.
395 ;; The xgdx and xgdy instructions preserve the flags.
399 (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
400 (match_operand:QI 1 "cmp_operand" "")))]
401 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
402 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
403 (set (match_dup 3) (reg:HI D_REGNUM))])
405 (compare (reg:QI D_REGNUM) (match_dup 1)))
406 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
407 (set (match_dup 3) (reg:HI D_REGNUM))])]
408 "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
412 (compare (match_operand:QI 0 "hard_reg_operand" "")
413 (match_operand:QI 1 "hard_reg_operand" "")))]
415 [(set (match_dup 3) (match_dup 4))
417 (compare (match_dup 0) (match_dup 2)))]
418 "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
419 operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
420 operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
422 (define_expand "cmpqi"
424 (compare (match_operand:QI 0 "tst_operand" "")
425 (match_operand:QI 1 "cmp_operand" "")))]
429 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
430 operands[0] = force_reg (QImode, operands[0]);
432 m68hc11_compare_op0 = operands[0];
433 m68hc11_compare_op1 = operands[1];
437 (define_insn "bitcmpqi"
439 (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
440 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
449 (define_split /* "bitcmpqi" */
451 (and:QI (match_operand:QI 0 "tst_operand" "")
452 (match_operand:QI 1 "hard_addr_reg_operand" "")))]
453 "z_replacement_completed == 2"
454 [(set (match_dup 3) (match_dup 2))
455 (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
456 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
457 operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
458 operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
460 (define_insn_and_split "bitcmpqi_z_used"
462 (and:QI (match_operand:QI 0 "tst_operand" "d,m")
463 (match_operand:QI 1 "cmp_operand" "m,d")))
464 (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
465 (use (reg:HI SOFT_Z_REGNUM))]
468 "z_replacement_completed == 2"
469 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
470 (set (match_dup 2) (match_dup 3))
471 (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
472 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
473 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
475 (define_insn "bitcmphi"
477 (and:HI (match_operand:HI 0 "tst_operand" "d")
478 (match_operand:HI 1 "const_int_operand" "i")))]
479 "(INTVAL (operands[1]) & 0x0ff) == 0
480 || (INTVAL (operands[1]) & 0x0ff00) == 0"
483 if ((INTVAL (operands[1]) & 0x0ff) == 0)
484 return \"bita\\t%h1\";
486 return \"bitb\\t%1\";
489 (define_insn "bitcmpqi_12"
491 (zero_extract (match_operand:HI 0 "tst_operand" "d")
492 (match_operand:HI 1 "const_int_operand" "i")
493 (match_operand:HI 2 "const_int_operand" "i")))]
494 "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
495 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
496 && (unsigned) INTVAL (operands[2]) >= 8)"
501 int startpos = INTVAL (operands[2]);
502 int bitsize = INTVAL (operands[1]);
507 mask = (1 << (startpos + bitsize)) - 1;
508 mask &= ~((1 << startpos) - 1);
510 ops[0] = GEN_INT (mask);
511 output_asm_insn (\"bita\\t%0\", ops);
515 mask = (1 << (startpos + bitsize)) - 1;
516 mask &= ~((1 << startpos) - 1);
518 ops[0] = GEN_INT (mask);
519 output_asm_insn (\"bitb\\t%0\", ops);
524 (define_insn "cmpqi_1"
526 (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
527 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
531 if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
535 else if (D_REG_P (operands[0]))
537 return \"cmpb\\t%b1\";
539 cc_status.flags |= CC_REVERSED;
540 return \"cmpb\\t%b0\";
543 (define_insn_and_split "cmpqi_z_used"
545 (compare (match_operand:QI 0 "tst_operand" "dxy,m")
546 (match_operand:QI 1 "cmp_operand" "m,dxy")))
547 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
548 (use (reg:HI SOFT_Z_REGNUM))]
551 "z_replacement_completed == 2"
552 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
553 (set (match_dup 2) (match_dup 3))
554 (set (cc0) (compare (match_dup 0) (match_dup 1)))
555 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
556 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
558 ;;--------------------------------------------------------------------
559 ;;- Move strict_low_part
560 ;;--------------------------------------------------------------------
562 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
563 ;; The replacement must be made at the very end because we loose the
564 ;; (strict_low_part ...) information. This is correct for our machine
565 ;; description but not for GCC optimization passes.
567 (define_insn_and_split "movstrictsi"
568 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
569 (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
572 "z_replacement_completed == 2"
573 [(set (match_dup 0) (match_dup 1))]
576 (define_insn_and_split "movstricthi"
577 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
578 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
581 "z_replacement_completed == 2"
582 [(set (match_dup 0) (match_dup 1))]
585 (define_insn_and_split "movstrictqi"
586 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
587 (match_operand:QI 1 "general_operand" "d,imudA"))]
590 "z_replacement_completed == 2"
591 [(set (match_dup 0) (match_dup 1))]
594 ;;--------------------------------------------------------------------
595 ;;- 64-bit Move Operations.
596 ;; The movdi and movdf patterns are identical except for the mode.
597 ;; They are also very similar to those for movsi and movsf.
599 ;; For 68HC11, we need a scratch register (either D, X, Y)
600 ;; because there is no memory->memory moves. It must be defined with
601 ;; earlyclobber (&) so that it does not appear in the source or destination
602 ;; address. Providing patterns for movdi/movdf allows GCC to generate
603 ;; better code. [Until now, the scratch register is limited to D because
604 ;; otherwise we can run out of registers in the A_REGS class for reload].
606 ;; For 68HC12, the scratch register is not necessary. To use the same
607 ;; pattern and same split, we use the 'v' constraint. This tells the
608 ;; reload to use the _.tmp register (which is not used at all).
609 ;; The insn will be split in one or several memory moves (movw).
610 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
611 ;;--------------------------------------------------------------------
612 (define_expand "movdi"
613 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
614 (match_operand:DI 1 "general_operand" ""))
615 (clobber (match_scratch:HI 2 ""))])]
618 /* For push/pop, emit a REG_INC note to make sure the reload
619 inheritance and reload CSE pass notice the change of the stack
621 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
625 insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
626 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
633 ;; Separate push from normal moves to avoid reloading problems
634 ;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
635 ;; We can also accept more scratch registers.
636 (define_insn_and_split "*pushdi_internal"
637 [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
638 (match_operand:DI 1 "general_operand" "i,U,m,!u"))
639 (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
644 "m68hc11_split_move (operands[0], operands[1], operands[2]);
647 (define_insn_and_split "movdi_internal"
648 [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
649 (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
650 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
655 "m68hc11_split_move (operands[0], operands[1], operands[2]);
658 (define_expand "movdf"
659 [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
660 (match_operand:DF 1 "general_operand" ""))
661 (clobber (match_scratch:HI 2 ""))])]
663 "/* For push/pop, emit a REG_INC note to make sure the reload
664 inheritance and reload CSE pass notice the change of the stack
666 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
670 insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
671 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
678 ;; See pushdi_internal
679 (define_insn_and_split "*pushdf_internal"
680 [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
681 (match_operand:DF 1 "general_operand" "i,U,m,!u"))
682 (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
687 "m68hc11_split_move (operands[0], operands[1], operands[2]);
690 (define_insn_and_split "movdf_internal"
691 [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
692 (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
693 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
698 "m68hc11_split_move (operands[0], operands[1], operands[2]);
701 ;;--------------------------------------------------------------------
702 ;;- 32-bit Move Operations.
703 ;; The movsi and movsf patterns are identical except for the mode.
704 ;; When we move to/from a hard register (d+x), we don't need a scratch.
705 ;; Otherwise, a scratch register is used as intermediate register for
706 ;; the move. The '&' constraint is necessary to make sure the reload
707 ;; pass does not give us a register that dies in the insn and is used
708 ;; for input/output operands.
709 ;;--------------------------------------------------------------------
710 (define_expand "movsi"
711 [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
712 (match_operand:SI 1 "general_operand" ""))
713 (clobber (match_scratch:HI 2 ""))])]
715 "/* For push/pop, emit a REG_INC note to make sure the reload
716 inheritance and reload CSE pass notice the change of the stack
718 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
722 insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
723 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
730 (define_insn_and_split "*pushsi_internal"
731 [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
732 (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
733 (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
738 "m68hc11_split_move (operands[0], operands[1], operands[2]);
741 (define_insn_and_split "movsi_internal"
742 [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
743 (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
744 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
749 "m68hc11_split_move (operands[0], operands[1], operands[2]);
752 (define_expand "movsf"
753 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
754 (match_operand:SF 1 "general_operand" ""))
755 (clobber (match_scratch:HI 2 ""))])]
757 "/* For push/pop, emit a REG_INC note to make sure the reload
758 inheritance and reload CSE pass notice the change of the stack
760 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
764 insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
765 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
772 (define_insn_and_split "*pushsf_internal"
773 [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
774 (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
775 (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
780 "m68hc11_split_move (operands[0], operands[1], operands[2]);
783 (define_insn_and_split "movsf_internal"
784 [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
785 (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
786 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
791 "m68hc11_split_move (operands[0], operands[1], operands[2]);
795 ;;--------------------------------------------------------------------
796 ;;- 16-bit Move Operations.
797 ;; We don't need a scratch register.
798 ;;--------------------------------------------------------------------
800 (define_insn "*movhi2_push"
801 [(set (match_operand:HI 0 "push_operand" "=<,<,<")
802 (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
803 "TARGET_M6811 && !TARGET_M6812"
806 cc_status = cc_prev_status;
807 if (D_REG_P (operands[1]))
809 output_asm_insn (\"pshb\", operands);
812 else if (X_REG_P (operands[1]))
816 else if (Y_REG_P (operands[1]))
820 fatal_insn (\"Invalid register in the instruction\", insn);
823 (define_insn "*movhi2_pop"
824 [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
825 (match_operand:HI 1 "pop_operand" ">,>"))]
829 cc_status = cc_prev_status;
830 if (D_REG_P (operands[0]))
832 output_asm_insn (\"pula\", operands);
835 else if (X_REG_P (operands[0]))
839 else if (Y_REG_P (operands[0]))
843 fatal_insn (\"Invalid register in the instruction\", insn);
846 (define_expand "movhi"
847 [(set (match_operand:HI 0 "nonimmediate_operand" "")
848 (match_operand:HI 1 "general_operand" ""))]
852 if (reload_in_progress)
854 if (m68hc11_reload_operands (operands))
859 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
861 if (GET_CODE (operands[0]) == MEM &&
862 (GET_CODE (operands[1]) == MEM
863 || GET_CODE (operands[1]) == CONST_INT))
865 operands[1] = force_reg (HImode, operands[1]);
867 else if (IS_STACK_PUSH (operands[0])
868 && GET_CODE (operands[1]) != REG)
870 operands[1] = force_reg (HImode, operands[1]);
873 /* For push/pop, emit a REG_INC note to make sure the reload
874 inheritance and reload CSE pass notice the change of the stack
876 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
880 insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
881 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
888 (define_insn "*movhi_68hc12"
889 [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
890 (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
894 m68hc11_gen_movhi (insn, operands);
898 (define_insn "movhi_const0"
899 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
905 clr\\t%b0\\n\\tclr\\t%h0")
907 (define_insn "*movhi_m68hc11"
908 [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
909 (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
913 m68hc11_gen_movhi (insn, operands);
917 ;;--------------------------------------------------------------------
918 ;;- 8-bit Move Operations.
919 ;; We don't need a scratch register.
920 ;;--------------------------------------------------------------------
922 ;; The *a alternative also clears the high part of the register.
923 ;; This should be ok since this is not the (strict_low_part) set.
925 (define_insn "movqi_const0"
926 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
937 ;; 8-bit operations on address registers.
939 ;; Switch temporary to the D register and load the value in B.
940 ;; This is possible as long as the address register does not
941 ;; appear in the source operand.
944 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
945 (match_operand:QI 1 "general_operand" ""))]
946 "z_replacement_completed == 2
947 && !reg_mentioned_p (operands[0], operands[1])
948 && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
949 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
950 (set (match_dup 2) (reg:HI D_REGNUM))])
951 (set (reg:QI D_REGNUM) (match_dup 1))
952 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
953 (set (match_dup 2) (reg:HI D_REGNUM))])]
954 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
957 ;; 8-bit operations on address registers.
960 [(set (match_operand:QI 0 "nonimmediate_operand" "")
961 (match_operand:QI 1 "hard_addr_reg_operand" ""))]
962 "z_replacement_completed == 2
963 && !reg_mentioned_p (operands[1], operands[0])
964 && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
965 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
966 (set (match_dup 2) (reg:HI D_REGNUM))])
967 (set (match_dup 0) (reg:QI D_REGNUM))
968 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
969 (set (match_dup 2) (reg:HI D_REGNUM))])]
970 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
972 (define_insn "*movqi2_push"
973 [(set (match_operand:QI 0 "push_operand" "=<,<")
974 (match_operand:QI 1 "general_operand" "d,!*A"))]
978 if (A_REG_P (operands[1]))
981 cc_status = cc_prev_status;
986 (define_expand "movqi"
987 [(set (match_operand:QI 0 "nonimmediate_operand" "")
988 (match_operand:QI 1 "general_operand" ""))]
992 if (reload_in_progress)
994 if (m68hc11_reload_operands (operands))
999 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
1001 if (GET_CODE (operands[0]) == MEM
1002 && (GET_CODE (operands[1]) == MEM
1003 || GET_CODE (operands[1]) == CONST_INT))
1005 operands[1] = force_reg (QImode, operands[1]);
1007 else if (IS_STACK_PUSH (operands[0])
1008 && GET_CODE (operands[1]) != REG)
1010 operands[1] = force_reg (QImode, operands[1]);
1013 /* For push/pop, emit a REG_INC note to make sure the reload
1014 inheritance and reload CSE pass notice the change of the stack
1016 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
1020 insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
1021 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
1028 (define_insn "*movqi_68hc12"
1029 [(set (match_operand:QI 0 "nonimmediate_operand"
1030 "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
1031 (match_operand:QI 1 "general_operand"
1032 "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
1036 m68hc11_gen_movqi (insn, operands);
1040 (define_insn "*movqi_m68hc11"
1041 [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
1042 (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
1046 m68hc11_gen_movqi (insn, operands);
1050 ;;--------------------------------------------------------------------
1052 ;;--------------------------------------------------------------------
1053 ;; Swapping registers is used for split patterns.
1054 (define_insn "swap_areg"
1055 [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1056 (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1057 (set (match_dup 1) (match_dup 0))]
1061 m68hc11_output_swap (insn, operands);
1065 ;;--------------------------------------------------------------------
1066 ;;- Truncation insns.
1067 ;;--------------------------------------------------------------------
1069 ;; Truncation are not necessary because GCC knows how to truncate,
1070 ;; specially when values lie in consecutive registers.
1073 (define_expand "floatunssisf2"
1074 [(set (match_operand:SF 0 "nonimmediate_operand" "")
1075 (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1077 "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
1078 SFmode, SImode, 2, operands);
1081 (define_expand "floatunssidf2"
1082 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1083 (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1085 "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
1086 DFmode, SImode, 2, operands);
1089 ;;--------------------------------------------------------------------
1090 ;;- Zero extension insns.
1091 ;;--------------------------------------------------------------------
1094 ;; 64-bit extend. The insn will be split into 16-bit instructions just
1095 ;; before the final pass. We need a scratch register for the split.
1096 ;; The final value can be generated on the stack directly. This is more
1097 ;; efficient and useful for conversions made during parameter passing rules.
1099 (define_insn "zero_extendqidi2"
1100 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1102 (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1103 (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1108 [(set (match_operand:DI 0 "push_operand" "")
1109 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1110 (clobber (match_scratch:HI 2 "=&dB"))]
1111 "z_replacement_completed == 2"
1115 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1116 rtx push = m68hc11_gen_lowpart (HImode, low);
1117 rtx src = operands[1];
1119 /* Source operand must be in a hard register. */
1122 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1123 emit_move_insn (src, operands[1]);
1126 /* Source is in D, we can push B then one word of 0 and we do
1127 a correction on the stack pointer. */
1130 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1131 emit_move_insn (operands[2], const0_rtx);
1132 if (D_REG_P (operands[2]))
1134 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1138 emit_move_insn (push, operands[2]);
1139 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1140 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1146 /* Source is in X or Y. It's better to push the 16-bit register
1147 and then to some stack adjustment. */
1148 src = gen_rtx_REG (HImode, REGNO (src));
1149 emit_move_insn (push, src);
1150 emit_move_insn (operands[2], const0_rtx);
1151 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1152 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1154 emit_move_insn (push, operands[2]);
1155 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1156 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1159 emit_move_insn (push, operands[2]);
1160 emit_move_insn (push, operands[2]);
1161 emit_move_insn (push, operands[2]);
1166 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1167 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1168 (clobber (match_scratch:HI 2 "=&dB"))]
1169 "z_replacement_completed == 2"
1173 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1174 rtx low2 = m68hc11_gen_lowpart (HImode, low);
1175 rtx src = operands[1];
1177 /* Source operand must be in a hard register. */
1180 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1181 emit_move_insn (src, operands[1]);
1184 emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1185 emit_move_insn (operands[2], const0_rtx);
1186 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1187 emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1189 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1190 low = m68hc11_gen_highpart (SImode, operands[0]);
1191 emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1192 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1196 (define_insn "zero_extendhidi2"
1197 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1199 (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1200 (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1205 [(set (match_operand:DI 0 "non_push_operand" "")
1207 (match_operand:HI 1 "nonimmediate_operand" "")))
1208 (clobber (match_scratch:HI 2 ""))]
1209 "z_replacement_completed == 2"
1213 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1214 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1215 rtx src = operands[1];
1217 /* Make sure the source is in a hard register. */
1221 emit_move_insn (src, operands[1]);
1224 /* Move the low part first for the push. */
1225 emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1227 /* Now, use the scratch register to fill in the zeros. */
1228 emit_move_insn (operands[2], const0_rtx);
1229 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1230 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1231 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1235 (define_insn "zero_extendsidi2"
1236 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1238 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1239 (clobber (match_scratch:HI 2 "=d,d,d,d"))]
1244 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1246 (match_operand:SI 1 "nonimmediate_operand" "")))
1247 (clobber (match_scratch:HI 2 ""))]
1248 "z_replacement_completed == 2"
1252 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1253 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1255 /* Move the low part first so that this is ok for a push. */
1256 m68hc11_split_move (low, operands[1], operands[2]);
1258 /* Use the scratch register to clear the high part of the destination. */
1259 emit_move_insn (operands[2], const0_rtx);
1260 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1261 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1266 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1267 ;; because it's less efficient.
1269 (define_insn "zero_extendhisi2"
1270 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1272 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1273 (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1278 [(set (match_operand:SI 0 "non_push_operand" "")
1280 (match_operand:HI 1 "nonimmediate_operand" "")))
1281 (clobber (match_scratch:HI 2 ""))]
1286 rtx src = operands[1];
1288 if (!H_REG_P (src) && !H_REG_P (operands[0]))
1291 emit_move_insn (src, operands[1]);
1293 emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1294 emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1298 (define_insn "zero_extendqisi2"
1299 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1301 (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1306 [(set (match_operand:SI 0 "non_push_operand" "")
1307 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1308 "reload_completed && !X_REG_P (operands[0])"
1309 [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1310 (set (match_dup 3) (const_int 0))]
1312 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1313 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1316 [(set (match_operand:SI 0 "hard_reg_operand" "")
1317 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1318 "z_replacement_completed == 2 && X_REG_P (operands[0])"
1319 [(set (match_dup 2) (match_dup 3))
1320 (set (match_dup 4) (const_int 0))
1321 (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1323 if (X_REG_P (operands[1]))
1325 emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
1326 gen_rtx_REG (HImode, HARD_X_REGNUM)));
1327 emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
1328 gen_rtx_REG (QImode, HARD_D_REGNUM)));
1329 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
1334 if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
1336 emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1339 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
1342 operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1343 operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1344 if (A_REG_P (operands[1]))
1346 operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1347 operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
1348 operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
1352 operands[5] = operands[2] =
1353 operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1354 operands[6] = operands[1];
1358 (define_insn "zero_extendqihi2"
1359 [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
1361 (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1365 if (A_REG_P (operands[0]))
1368 if (H_REG_P (operands[0]))
1370 output_asm_insn (\"clra\", operands);
1371 if (operands[0] != operands[1]
1372 && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1374 if (X_REG_P (operands[1])
1375 || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1377 output_asm_insn (\"stx\\t%t1\", operands);
1378 output_asm_insn (\"ldab\\t%T0\", operands);
1380 else if (Y_REG_P (operands[1])
1381 || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1383 output_asm_insn (\"sty\\t%t1\", operands);
1384 output_asm_insn (\"ldab\\t%T0\", operands);
1388 output_asm_insn (\"ldab\\t%b1\", operands);
1390 cc_status.flags |= CC_NOT_NEGATIVE;
1394 /* Status refers to the clra insn. Status is ok for others
1395 * since we have loaded the value in B.
1402 if (A_REG_P (operands[1]))
1404 output_asm_insn (\"st%1\\t%0\", operands);
1405 output_asm_insn (\"clr\\t%h0\", operands);
1410 output_asm_insn (\"clr\\t%h0\", operands);
1411 output_asm_insn (\"stab\\t%b0\", operands);
1412 cc_status.flags |= CC_NOT_NEGATIVE;
1419 ;;--------------------------------------------------------------------
1420 ;;- Sign extension insns.
1421 ;;--------------------------------------------------------------------
1423 (define_insn "extendqisi2"
1424 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1425 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1432 /* The 68HC12 has a sign-extension instruction. Use it when the
1433 destination is the register (X,D). First sign-extend the low
1434 part and fill X with the sign-extension of the high part. */
1435 if (TARGET_M6812 && X_REG_P (operands[0]))
1437 if (!D_REG_P (operands[1]))
1439 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1440 ops[1] = operands[1];
1441 m68hc11_gen_movqi (insn, ops);
1443 return \"sex\\tb,d\\n\\tsex\\ta,x\";
1446 ops[2] = gen_label_rtx ();
1448 if (X_REG_P (operands[1]))
1450 output_asm_insn (\"xgdx\", operands);
1453 else if (X_REG_P (operands[0]))
1455 /* X can be used as an indexed addressing in the source.
1456 Get the value before clearing it. */
1457 if (reg_mentioned_p (ix_reg, operands[1]))
1459 output_asm_insn (\"ldab\\t%b1\", operands);
1462 output_asm_insn (\"ldx\\t#0\", operands);
1465 output_asm_insn (\"clra\", operands);
1466 if (!X_REG_P (operands[0]))
1468 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1469 ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1471 if (IS_STACK_PUSH (operands[0]))
1473 output_asm_insn (\"pshb\", ops);
1474 output_asm_insn (\"tstb\", ops);
1478 output_asm_insn (\"stab\\t%b1\", ops);
1481 else if (D_REG_P (operands[1]) || need_tst)
1483 output_asm_insn (\"tstb\", operands);
1487 output_asm_insn (\"ldab\\t%b1\", operands);
1489 output_asm_insn (\"bpl\\t%l2\", ops);
1490 output_asm_insn (\"deca\", operands);
1491 if (X_REG_P (operands[0]))
1492 output_asm_insn (\"dex\", operands);
1494 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1496 if (!X_REG_P (operands[0]))
1498 if (IS_STACK_PUSH (operands[0]))
1500 output_asm_insn (\"psha\", ops);
1501 output_asm_insn (\"psha\", ops);
1502 output_asm_insn (\"psha\", ops);
1506 output_asm_insn (\"staa\\t%h0\", ops);
1508 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1509 if (dead_register_here (insn, d_reg))
1511 output_asm_insn (\"tab\", ops);
1512 output_asm_insn (\"std\\t%0\", ops);
1516 output_asm_insn (\"staa\\t%b0\", ops);
1517 output_asm_insn (\"staa\\t%h0\", ops);
1527 (define_insn "extendqihi2"
1528 [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1529 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1535 if (A_REG_P (operands[0]))
1538 ops[0] = gen_label_rtx ();
1539 if (D_REG_P (operands[0]))
1543 if (!D_REG_P (operands[1]))
1545 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1546 ops[1] = operands[1];
1547 m68hc11_gen_movqi (insn, ops);
1549 return \"sex\\tb,d\";
1551 output_asm_insn (\"clra\", operands);
1552 if (H_REG_P (operands[1]))
1554 output_asm_insn (\"tstb\", operands);
1558 output_asm_insn (\"ldab\\t%b1\", operands);
1560 output_asm_insn (\"bpl\\t%l0\", ops);
1561 output_asm_insn (\"deca\", operands);
1563 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1564 CODE_LABEL_NUMBER (ops[0]));
1568 output_asm_insn (\"clr\\t%h0\", operands);
1569 if (m68hc11_register_indirect_p (operands[1], HImode))
1571 ops[1] = operands[1];
1572 output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1577 output_asm_insn (\"tst\\t%b1\", operands);
1578 output_asm_insn (\"bpl\\t%l0\", ops);
1580 output_asm_insn (\"dec\\t%h0\", operands);
1581 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1582 CODE_LABEL_NUMBER (ops[0]));
1589 ;; Split the special case where the source of the sign extend is
1590 ;; either Y or Z. In that case, we can't move the source in the D
1591 ;; register directly. The movhi pattern handles this move by using
1592 ;; a temporary scratch memory location.
1595 [(set (match_operand:SI 0 "register_operand" "")
1596 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1597 "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1598 [(set (reg:HI D_REGNUM) (match_dup 1))
1599 (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1602 (define_insn "extendhisi2"
1603 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1604 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1611 if (Y_REG_P (operands[1]))
1614 if (X_REG_P (operands[1]))
1616 output_asm_insn (\"xgdx\", operands);
1621 /* X can be used as an indexed addressing in the source.
1622 Get the value before clearing it. */
1623 x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1626 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1627 ops[1] = operands[1];
1628 m68hc11_gen_movhi (insn, ops);
1633 if (TARGET_M6812 && 0)
1635 /* This sequence of code is larger than the one for 68HC11.
1636 Don't use it; keep it for documentation. */
1637 if (!D_REG_P (operands[1]) && !x_reg_used)
1639 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1640 ops[1] = operands[1];
1641 m68hc11_gen_movhi (insn, ops);
1643 output_asm_insn (\"sex\\ta,x\", operands);
1644 output_asm_insn (\"xgdx\", operands);
1645 output_asm_insn (\"sex\\ta,d\", operands);
1649 output_asm_insn (\"ldx\\t#0\", operands);
1650 if (D_REG_P (operands[1]) || x_reg_used)
1652 output_asm_insn (\"tsta\", operands);
1656 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1657 ops[1] = operands[1];
1658 m68hc11_gen_movhi (insn, ops);
1661 ops[0] = gen_label_rtx ();
1662 output_asm_insn (\"bpl\\t%l0\", ops);
1663 output_asm_insn (\"dex\", operands);
1664 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1670 ;;--------------------------------------------------------------------
1671 ;;- Min and Max instructions (68HC12).
1672 ;;--------------------------------------------------------------------
1673 (define_insn "uminqi3"
1674 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1675 (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1676 (match_operand:QI 2 "general_operand" "m,d")))]
1677 "TARGET_M6812 && TARGET_MIN_MAX"
1680 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1681 The mina/minm use A as the source or destination. This is the
1682 high part of D. There is no way to express that in the pattern
1683 so we must use 'exg a,b' to put the operand in the good register. */
1685 if (D_REG_P (operands[0]))
1687 return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1691 return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1695 (define_insn "umaxqi3"
1696 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1697 (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1698 (match_operand:QI 2 "general_operand" "m,d")))]
1699 "TARGET_M6812 && TARGET_MIN_MAX"
1702 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1703 The maxa/maxm use A as the source or destination. This is the
1704 high part of D. There is no way to express that in the pattern
1705 so we must use 'exg a,b' to put the operand in the good register. */
1707 if (D_REG_P (operands[0]))
1709 return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1713 return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1717 (define_insn "uminhi3"
1718 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1719 (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1720 (match_operand:HI 2 "general_operand" "m,d")))]
1721 "TARGET_M6812 && TARGET_MIN_MAX"
1724 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1726 if (D_REG_P (operands[0]))
1728 return \"emind\\t%2\";
1732 return \"eminm\\t%0\";
1736 (define_insn "umaxhi3"
1737 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1738 (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1739 (match_operand:HI 2 "general_operand" "m,d")))]
1740 "TARGET_M6812 && TARGET_MIN_MAX"
1743 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1745 if (D_REG_P (operands[0]))
1747 return \"emaxd\\t%2\";
1751 return \"emaxm\\t%0\";
1756 ;;--------------------------------------------------------------------
1757 ;;- Add instructions.
1758 ;;--------------------------------------------------------------------
1759 ;; 64-bit: Use a library call because what GCC generates is huge.
1761 (define_expand "adddi3"
1762 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1763 (plus:DI (match_operand:DI 1 "general_operand" "")
1764 (match_operand:DI 2 "general_operand" "")))]
1766 "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1772 (define_expand "addsi3"
1773 [(parallel [(set (match_operand:SI 0 "register_operand" "")
1774 (plus:SI (match_operand:SI 1 "general_operand" "")
1775 (match_operand:SI 2 "general_operand" "")))
1776 (clobber (match_scratch:HI 3 ""))])]
1780 (define_insn "*addsi3_zero_extendhi"
1781 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1782 (plus:SI (zero_extend:SI
1783 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1784 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1785 (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1791 if (X_REG_P (operands[2]))
1793 ops[0] = operands[1];
1797 if (X_REG_P (operands[1]))
1799 output_asm_insn (\"xgdx\", ops);
1801 else if (!D_REG_P (operands[1]))
1803 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1804 ops[1] = operands[1];
1805 m68hc11_gen_movhi (insn, ops);
1807 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1808 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1810 ops[2] = gen_label_rtx ();
1812 /* ldx preserves the carry, propagate it by incrementing X directly. */
1813 output_asm_insn (\"addd\\t%0\", ops);
1814 if (!X_REG_P (operands[2]))
1815 output_asm_insn (\"ldx\\t%1\", ops);
1817 output_asm_insn (\"bcc\\t%l2\", ops);
1818 output_asm_insn (\"inx\", ops);
1821 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1826 (define_split /* "*addsi3_zero_extendqi" */
1827 [(set (match_operand:SI 0 "register_operand" "")
1828 (plus:SI (zero_extend:SI
1829 (match_operand:QI 1 "general_operand" ""))
1830 (match_operand:SI 2 "memory_operand" "")))
1831 (clobber (match_scratch:HI 3 "=X,X"))]
1833 [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1834 (parallel [(set (match_dup 0)
1835 (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1836 (clobber (match_dup 3))])]
1839 (define_insn "*addsi3_zero_extendqi"
1840 [(set (match_operand:SI 0 "register_operand" "=D,D")
1841 (plus:SI (zero_extend:SI
1842 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1843 (match_operand:SI 2 "general_operand" "miD,!muiD")))
1844 (clobber (match_scratch:HI 3 "=X,X"))]
1850 if (GET_CODE (operands[2]) == MEM)
1853 if (X_REG_P (operands[2]))
1855 if (H_REG_P (operands[1]))
1857 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1858 ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1859 m68hc11_gen_movhi (insn, ops);
1863 ops[0] = operands[1];
1865 ops[1] = const0_rtx;
1869 if (X_REG_P (operands[1]))
1871 output_asm_insn (\"xgdx\", ops);
1873 else if (!D_REG_P (operands[1]))
1875 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1876 ops[1] = operands[1];
1877 m68hc11_gen_movqi (insn, ops);
1880 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1882 ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1883 output_asm_insn (\"clra\", ops);
1886 /* ldx preserves the carry, propagate it by incrementing X directly. */
1887 output_asm_insn (\"addb\\t%b0\", ops);
1888 output_asm_insn (\"adca\\t%h1\", ops);
1889 if (!X_REG_P (operands[2]))
1890 output_asm_insn (\"ldx\\t%2\", ops);
1892 /* If the above adca was adding some constant, we don't need to propagate
1893 the carry unless the constant was 0xff. */
1894 if (X_REG_P (operands[2])
1895 || GET_CODE (ops[1]) != CONST_INT
1896 || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1898 ops[3] = gen_label_rtx ();
1900 output_asm_insn (\"bcc\\t%l3\", ops);
1901 output_asm_insn (\"inx\", ops);
1903 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1904 CODE_LABEL_NUMBER (ops[3]));
1910 (define_insn "*addsi3"
1911 [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
1912 (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1913 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
1914 (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1919 const char* add_insn;
1920 const char* inc_insn;
1921 const char* incb_mem;
1922 const char* inch_mem;
1925 if (which_alternative > 2)
1930 val = INTVAL (operands[2]);
1931 if ((val & 0x0ffffL) == 0)
1933 if (!H_REG_P (operands[0]))
1935 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1936 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1937 output_asm_insn (\"ldd\\t%0\", ops);
1938 output_asm_insn (\"addd\\t%1\", ops);
1939 output_asm_insn (\"std\\t%0\", ops);
1951 if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1958 ops[1] = operands[2];
1959 add_insn = \"addd\\t%1\";
1960 inc_insn = \"inx\\t\";
1961 incb_mem = \"inc\\t%b1\";
1962 inch_mem = \"inc\\t%h1\";
1966 ops[1] = GEN_INT (- val);
1967 add_insn = \"subd\\t%1\";
1969 incb_mem = \"dec\\t%b1\";
1970 inch_mem = \"dec\\t%h1\";
1973 ops[2] = gen_label_rtx ();
1974 if (!H_REG_P (operands[0]))
1976 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1977 output_asm_insn (\"ldd\\t%0\", ops);
1979 output_asm_insn (add_insn, ops);
1980 if (!H_REG_P (operands[0]))
1982 output_asm_insn (\"std\\t%0\", ops);
1984 output_asm_insn (\"bcc\\t%l2\", ops);
1985 if (H_REG_P (operands[0]))
1987 output_asm_insn (inc_insn, ops);
1991 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1993 if (INTVAL (operands[2]) < 0)
1995 output_asm_insn (\"ldd\\t%1\", ops);
1996 output_asm_insn (\"addd\\t#-1\", ops);
1997 output_asm_insn (\"std\\t%1\", ops);
2001 output_asm_insn (incb_mem, ops);
2002 output_asm_insn (\"bne\\t%l2\", ops);
2003 output_asm_insn (inch_mem, ops);
2006 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
2013 [(set (match_operand:SI 0 "register_operand" "")
2014 (plus:SI (match_operand:SI 1 "register_operand" "")
2015 (match_operand:SI 2 "const_int_operand" "")))
2016 (clobber (match_scratch:HI 3 ""))]
2017 "reload_completed && z_replacement_completed == 2
2018 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
2019 [(set (match_dup 5) (match_dup 6))
2020 (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
2021 (set (match_dup 6) (match_dup 5))]
2022 "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2023 if (X_REG_P (operands[0]))
2025 operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
2029 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2030 operands[5] = operands[3];
2035 [(set (match_operand:SI 0 "register_operand" "")
2036 (plus:SI (match_operand:SI 1 "register_operand" "")
2037 (match_operand:SI 2 "general_operand" "")))
2038 (clobber (match_scratch:HI 3 "=X"))]
2039 "reload_completed && z_replacement_completed == 2
2040 && (GET_CODE (operands[2]) != CONST_INT ||
2041 (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
2042 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2043 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2044 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2045 (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2046 (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2047 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2048 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
2049 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2050 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2051 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2052 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2055 ;; Instruction generated to propagate the carry of a 16-bit add
2056 ;; to the upper 16-bit part (in register X).
2058 (define_insn "*addsi_carry"
2059 [(set (match_operand:HI 0 "register_operand" "=x")
2060 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2062 (reg:HI CC_REGNUM)))]
2068 ops[0] = gen_label_rtx ();
2069 output_asm_insn (\"bcc\\t%l0\", ops);
2070 output_asm_insn (\"in%0\", operands);
2071 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2079 (define_expand "addhi3"
2080 [(set (match_operand:HI 0 "register_operand" "")
2081 (plus:HI (match_operand:HI 1 "register_operand" "")
2082 (match_operand:HI 2 "general_operand" "")))]
2086 if (TARGET_M6811 && SP_REG_P (operands[0]))
2088 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
2089 gen_rtx_SET (VOIDmode,
2091 gen_rtx_PLUS (HImode,
2092 operand1, operand2)),
2093 gen_rtx_CLOBBER (VOIDmode,
2094 gen_rtx_SCRATCH (HImode)))));
2099 (define_insn "*addhi3_68hc12"
2100 [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
2101 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
2102 (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
2107 const char* insn_code;
2109 if (which_alternative >= 4)
2111 if (A_REG_P (operands[2]))
2114 output_asm_insn (\"xgd%2\", operands);
2115 output_asm_insn (\"lea%0 d,%0\", operands);
2121 if (D_REG_P (operands[0]))
2123 if (X_REG_P (operands[2]))
2125 m68hc11_notice_keep_cc (operands[0]);
2126 output_asm_insn (\"xgdx\", operands);
2127 output_asm_insn (\"leax\\td,%2\", operands);
2130 else if (Y_REG_P (operands[2]))
2132 m68hc11_notice_keep_cc (operands[0]);
2133 output_asm_insn (\"xgdy\", operands);
2134 output_asm_insn (\"leay\\td,%2\", operands);
2137 else if (SP_REG_P (operands[2]))
2139 output_asm_insn (\"sts\\t%t0\", operands);
2140 return \"addd\\t%t0\";
2142 return \"addd\\t%2\";
2145 if (GET_CODE (operands[2]) == CONST_INT)
2146 val = INTVAL (operands[2]);
2150 if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
2152 m68hc11_notice_keep_cc (operands[0]);
2153 switch (REGNO (operands[0]))
2156 return \"leax\\t%i2,%1\";
2159 return \"leay\\t%i2,%1\";
2161 case HARD_SP_REGNUM:
2162 return \"leas\\t%i2,%1\";
2165 fatal_insn (\"Invalid operands in the instruction\", insn);
2170 insn_code = X_REG_P (operands[0]) ? \"inx\"
2171 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2176 insn_code = X_REG_P (operands[0]) ? \"dex\"
2177 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2180 /* For X and Y increment, the flags are not complete. Only the Z flag
2181 is updated. For SP increment, flags are not changed. */
2182 if (SP_REG_P (operands[0]))
2184 cc_status = cc_prev_status;
2185 if (INTVAL (operands[2]) < 0)
2189 output_asm_insn (\"pshx\", operands);
2203 output_asm_insn (insn_code, operands);
2210 ;; Specific pattern to add to the stack pointer.
2211 ;; We also take care of the clobbering of the IY register.
2213 (define_insn "addhi_sp"
2214 [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2215 (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2216 (match_operand:HI 2 "general_operand" "P,im,u,im")))
2217 (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2223 if (optimize && Y_REG_P (operands[3])
2224 && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
2225 operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
2227 if (GET_CODE (operands[2]) == CONST_INT
2228 && (val = INTVAL (operands[2])) != 0
2229 && (CONST_OK_FOR_LETTER_P (val, 'P')
2230 || (val > 0 && val <= 8)))
2232 while (val > 1 || val < -1)
2236 if (!H_REG_P (operands[3]))
2239 output_asm_insn (\"pul%3\", operands);
2244 output_asm_insn (\"pshx\", operands);
2252 output_asm_insn (\"ins\", operands);
2257 output_asm_insn (\"des\", operands);
2261 cc_status = cc_prev_status;
2265 /* Need to transfer to SP to X/Y and then to D register.
2266 Register X/Y is lost, this is specified by the (clobber) statement. */
2267 output_asm_insn (\"ts%3\", operands);
2268 if (GET_CODE (operands[2]) == CONST_INT
2269 && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
2270 && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
2272 output_asm_insn (\"ldab\\t%2\", operands);
2273 output_asm_insn (\"ab%3\", operands);
2278 output_asm_insn (\"xgd%3\", operands);
2279 output_asm_insn (\"addd\\t%2\", operands);
2280 output_asm_insn (\"xgd%3\", operands);
2283 /* The status flags correspond to the addd. xgdy and tys do not
2284 modify the flags. */
2288 (define_insn "*addhi3"
2289 [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
2290 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
2291 (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
2295 const char* insn_code;
2298 if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2300 output_asm_insn (\"sts\\t%t0\", operands);
2301 output_asm_insn (\"addd\\t%t0\", operands);
2302 return \"addd\\t#1\";
2304 if (GET_CODE (operands[2]) != CONST_INT)
2306 /* Adding to an address register or with another/same register
2307 is not possible. This must be replaced. */
2308 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2311 return \"addd\\t%2\";
2313 val = INTVAL (operands[2]);
2314 if (!SP_REG_P (operands[0]))
2316 if (D_REG_P (operands[0]))
2318 if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2321 return \"adda\\t%h2\";
2325 return \"addd\\t%2\";
2328 else if (GET_CODE (operands[2]) != CONST_INT
2329 || INTVAL (operands[2]) < -4
2330 || INTVAL (operands[2]) > 4)
2335 insn_code = X_REG_P (operands[0]) ? \"inx\"
2336 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2341 insn_code = X_REG_P (operands[0]) ? \"dex\"
2342 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2345 /* For X and Y increment, the flags are not complete. Only the Z flag
2346 is updated. For SP increment, flags are not changed. */
2347 if (SP_REG_P (operands[0]))
2349 cc_status = cc_prev_status;
2350 if (INTVAL (operands[2]) < 0)
2354 output_asm_insn (\"pshx\", operands);
2358 else if (optimize && dead_register_here (insn, ix_reg))
2362 output_asm_insn (\"pulx\", operands);
2374 output_asm_insn (insn_code, operands);
2380 (define_insn "*addhi3_zext"
2381 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2382 (plus:HI (zero_extend:HI
2383 (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2384 (match_operand:HI 2 "general_operand" "0,0")))]
2389 if (A_REG_P (operands[0]))
2391 else if (A_REG_P (operands[1]))
2392 return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2394 return \"addb\\t%b1\\n\\tadca\\t#0\";
2398 ;; Translate d = d + d into d = << 1
2399 ;; We have to do this because adding a register to itself is not possible.
2400 ;; ??? It's not clear whether this is really necessary.
2403 [(set (match_operand:QI 0 "hard_reg_operand" "")
2404 (plus:QI (match_dup 0)
2406 "0 && reload_completed"
2407 [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2410 (define_insn "addqi3"
2411 [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2412 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2413 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2417 if (GET_CODE (operands[2]) == CONST_INT)
2419 if (INTVAL (operands[2]) == 1)
2421 if (DA_REG_P (operands[0]))
2425 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2430 else if (A_REG_P (operands[0]))
2432 /* This applies on the 16-bit register. This should be ok since
2433 this is not a strict_low_part increment. */
2438 return \"inc\\t%b0\";
2441 else if (INTVAL (operands[2]) == -1)
2443 if (DA_REG_P (operands[0]))
2447 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2451 else if (A_REG_P (operands[0]))
2453 /* This applies on the 16-bit register. This should be ok since
2454 this is not a strict_low_part decrement. */
2459 return \"dec\\t%b0\";
2463 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2465 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2466 return \"addb\\t%b2\";
2468 return \"adda\\t%b2\";
2472 ;; add with carry is used for 32-bit add.
2474 (define_insn "*adcq"
2475 [(set (match_operand:QI 0 "register_operand" "=q")
2476 (plus:QI (plus:QI (reg:QI CC_REGNUM)
2477 (match_operand:QI 1 "register_operand" "%0"))
2478 (match_operand:QI 2 "general_operand" "ium")))]
2482 ;;--------------------------------------------------------------------
2483 ;;- Subtract instructions.
2484 ;;--------------------------------------------------------------------
2486 (define_expand "subdi3"
2487 [(set (match_operand:DI 0 "nonimmediate_operand" "")
2488 (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2489 (match_operand:DI 2 "general_operand" "")))]
2491 "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2495 ;; 32-bit Subtract (see addsi3)
2496 ;; Subtract with a constant are handled by addsi3.
2501 (define_expand "subsi3"
2502 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2503 (minus:SI (match_operand:SI 1 "register_operand" "")
2504 (match_operand:SI 2 "general_operand" "")))
2505 (clobber (match_scratch:HI 3 ""))])]
2509 (define_insn "*subsi3"
2510 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
2511 (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2512 (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
2513 (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
2517 (define_insn "*subsi3_zero_extendhi"
2518 [(set (match_operand:SI 0 "register_operand" "=D")
2519 (minus:SI (match_operand:SI 1 "register_operand" "0")
2520 (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
2521 (clobber (match_scratch:HI 3 "=X"))]
2527 if (A_REG_P (operands[2]))
2530 ops[0] = gen_rtx_MEM (HImode,
2531 gen_rtx_PRE_DEC (HImode,
2532 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2534 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2536 ops[1] = operands[2];
2537 m68hc11_gen_movhi (insn, ops);
2539 operands[2] = gen_rtx_MEM (HImode,
2540 gen_rtx_POST_INC (HImode,
2541 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2543 operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2545 ops[0] = gen_label_rtx ();
2546 output_asm_insn (\"subd\\t%2\", operands);
2547 output_asm_insn (\"bcc\\t%l0\", ops);
2548 output_asm_insn (\"dex\", ops);
2549 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2554 (define_insn "*subsi3_zero_extendqi"
2555 [(set (match_operand:SI 0 "register_operand" "=D")
2556 (minus:SI (match_operand:SI 1 "register_operand" "0")
2557 (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
2558 (clobber (match_scratch:HI 3 "=X"))]
2564 if (A_REG_P (operands[2]))
2566 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2567 ops[1] = operands[2];
2568 m68hc11_gen_movhi (insn, ops);
2569 operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2571 ops[0] = gen_label_rtx ();
2572 output_asm_insn (\"subb\\t%b2\", operands);
2573 output_asm_insn (\"sbca\\t#0\", operands);
2574 output_asm_insn (\"bcc\\t%l0\", ops);
2575 output_asm_insn (\"dex\", ops);
2576 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2582 ;; reg:HI 1 -> d reg:QI 6 -> B
2583 ;; reg:QI 7 -> ccr reg:QI 5 -> A
2585 (define_split /* "*subsi3" */
2586 [(set (match_operand:SI 0 "register_operand" "")
2587 (minus:SI (match_operand:SI 1 "register_operand" "")
2588 (match_operand:SI 2 "general_operand" "")))
2589 (clobber (match_scratch:HI 3 "=X"))]
2590 "reload_completed && z_replacement_completed == 2
2591 && X_REG_P (operands[1])"
2592 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2593 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2594 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2595 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2596 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2597 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2598 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2599 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2600 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2601 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2602 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2604 (define_split /* "*subsi3" */
2605 [(set (match_operand:SI 0 "register_operand" "")
2606 (minus:SI (match_operand:SI 1 "general_operand" "")
2607 (match_operand:SI 2 "register_operand" "")))
2608 (clobber (match_scratch:HI 3 "=X"))]
2609 "reload_completed && z_replacement_completed == 2
2610 && X_REG_P (operands[2])"
2611 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2612 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2613 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2614 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2615 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2616 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2617 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2618 (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2619 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2620 operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2621 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2622 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2624 (define_split /* "*subsi3" */
2625 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2626 (minus:SI (match_operand:SI 1 "general_operand" "")
2627 (match_operand:SI 2 "general_operand" "")))
2628 (clobber (match_scratch:HI 3 "=d"))]
2629 "reload_completed && z_replacement_completed == 2
2630 && !X_REG_P (operands[0])"
2631 [(set (match_dup 3) (match_dup 4))
2632 (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2633 (set (match_dup 4) (match_dup 3))
2634 (set (match_dup 3) (match_dup 6))
2635 (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2636 (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2637 (set (match_dup 6) (match_dup 3))]
2638 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2639 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2640 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2641 operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2642 operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2643 operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2646 ;; - 16-bit Subtract.
2648 (define_expand "subhi3"
2649 [(set (match_operand:HI 0 "register_operand" "=r")
2650 (minus:HI (match_operand:HI 1 "register_operand" "0")
2651 (match_operand:HI 2 "general_operand" "g")))]
2656 ;; Subtract from stack. This is better if we provide a pattern.
2658 (define_insn "*subhi3_sp"
2659 [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2660 (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2661 (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2662 (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2666 if (X_REG_P (operands[2]))
2668 operands[2] = m68hc11_soft_tmp_reg;
2669 output_asm_insn (\"stx\\t%2\", operands);
2671 else if (Y_REG_P (operands[2]))
2673 operands[2] = m68hc11_soft_tmp_reg;
2674 output_asm_insn (\"sty\\t%2\", operands);
2676 else if (D_REG_P (operands[2]))
2678 operands[2] = m68hc11_soft_tmp_reg;
2679 output_asm_insn (\"std\\t%2\", operands);
2682 if (D_REG_P (operands[3]))
2686 save_x = !dead_register_here (insn, ix_reg);
2688 output_asm_insn (\"xgdx\", operands);
2689 output_asm_insn (\"tsx\", operands);
2690 output_asm_insn (\"xgdx\", operands);
2691 output_asm_insn (\"subd\\t%2\", operands);
2692 output_asm_insn (\"xgdx\", operands);
2694 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2695 modify the flags. */
2696 output_asm_insn (\"txs\", operands);
2703 /* Need to transfer to SP to X,Y and then to D register.
2704 Register X,Y is lost, this is specified by the (clobber) statement. */
2705 output_asm_insn (\"ts%3\", operands);
2706 output_asm_insn (\"xgd%3\", operands);
2707 output_asm_insn (\"subd\\t%2\", operands);
2708 output_asm_insn (\"xgd%3\", operands);
2710 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2711 modify the flags. */
2716 (define_insn "*subhi3"
2717 [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
2718 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
2719 (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
2723 /* Adding to an address register or with another/same register
2724 is not possible. This must be replaced. */
2725 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2728 return \"subd\\t%2\";
2731 (define_insn "*subhi3_zext"
2732 [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2733 (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2734 (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2739 if (A_REG_P (operands[2]))
2743 ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2744 ops[1] = operands[2];
2745 m68hc11_gen_movqi (insn, ops);
2746 return \"subb\\t%T0\\n\\tsbca\\t#0\";
2748 return \"subb\\t%b2\\n\\tsbca\\t#0\";
2751 (define_insn "subqi3"
2752 [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2753 (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2754 (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2758 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2760 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2761 return \"subb\\t%b2\";
2763 return \"suba\\t%b2\";
2767 ;; subtract with carry is used for 32-bit subtract.
2769 (define_insn "*subcq"
2770 [(set (match_operand:QI 0 "register_operand" "=q")
2771 (minus:QI (minus:QI (reg:QI CC_REGNUM)
2772 (match_operand:QI 1 "register_operand" "0"))
2773 (match_operand:QI 2 "general_operand" "ium")))]
2777 ;;--------------------------------------------------------------------
2778 ;;- Multiply instructions.
2779 ;;--------------------------------------------------------------------
2781 ;; 32 and 64-bit multiply are handled by the library
2784 (define_expand "mulsi3"
2785 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2786 (mult:SI (match_operand:SI 1 "general_operand" "")
2787 (match_operand:SI 2 "general_operand" "")))]
2789 "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2792 (define_expand "mulhi3"
2793 [(parallel [(set (match_operand:HI 0 "register_operand" "")
2794 (mult:HI (match_operand:HI 1 "register_operand" "")
2795 (match_operand:HI 2 "register_operand" "")))
2796 (clobber (match_scratch:HI 3 ""))])]
2800 (define_insn "mulhi3_m68hc11"
2801 [(set (match_operand:HI 0 "register_operand" "=d")
2802 (mult:HI (match_operand:HI 1 "register_operand" "%0")
2803 (match_operand:HI 2 "register_operand" "x")))
2804 (clobber (match_scratch:HI 3 "=X"))]
2809 /* D * X -> D (X and Y are preserved by this function call). */
2810 return \"jsr\\t___mulhi3\";
2813 (define_insn "mulhi3_m68hc12"
2814 [(set (match_operand:HI 0 "register_operand" "=d,d")
2815 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2816 (match_operand:HI 2 "register_operand" "y,x")))
2817 (clobber (match_scratch:HI 3 "=2,2"))]
2822 if (X_REG_P (operands[2]))
2823 return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2828 (define_insn "umulhisi3"
2829 [(set (match_operand:SI 0 "register_operand" "=D,D")
2830 (mult:SI (zero_extend:SI
2831 (match_operand:HI 1 "register_operand" "%d,d"))
2833 (match_operand:HI 2 "register_operand" "y,x"))))
2834 (clobber (match_scratch:HI 3 "=2,X"))]
2838 if (X_REG_P (operands [2]))
2839 output_asm_insn (\"exg\\tx,y\", operands);
2841 /* Can't use the carry after that; other flags are ok when testing
2842 the 32-bit result. */
2843 cc_status.flags |= CC_NO_OVERFLOW;
2844 return \"emul\\n\\texg\\tx,y\";
2847 (define_insn "mulhisi3"
2848 [(set (match_operand:SI 0 "register_operand" "=D,D")
2849 (mult:SI (sign_extend:SI
2850 (match_operand:HI 1 "register_operand" "%d,d"))
2852 (match_operand:HI 2 "register_operand" "y,x"))))
2853 (clobber (match_scratch:HI 3 "=2,X"))]
2857 if (X_REG_P (operands [2]))
2858 output_asm_insn (\"exg\\tx,y\", operands);
2860 /* Can't use the carry after that; other flags are ok when testing
2861 the 32-bit result. */
2862 cc_status.flags |= CC_NO_OVERFLOW;
2863 return \"emuls\\n\\texg\\tx,y\";
2866 (define_insn "umulqihi3"
2867 [(set (match_operand:HI 0 "register_operand" "=d")
2868 (mult:HI (zero_extend:HI
2869 (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2871 (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2875 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2877 output_asm_insn (\"tba\", operands);
2883 if (D_REG_P (operands[2]))
2885 rtx temp = operands[2];
2886 operands[2] = operands[1];
2890 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2891 ops[1] = operands[2];
2892 m68hc11_gen_movqi (insn, ops);
2894 if (!D_REG_P (operands[1]))
2896 output_asm_insn (\"ldab\\t%b1\", operands);
2904 (define_insn "mulqi3"
2905 [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
2906 (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
2907 (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
2911 if (A_REG_P (operands[0]))
2914 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2916 output_asm_insn (\"tba\", operands);
2920 if (D_REG_P (operands[2]))
2922 rtx temp = operands[2];
2923 operands[2] = operands[1];
2927 output_asm_insn (\"ldaa\\t%b2\", operands);
2929 if (!D_REG_P (operands[1]))
2931 output_asm_insn (\"ldab\\t%b1\", operands);
2940 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
2941 (mult:QI (match_operand:QI 1 "general_operand" "")
2942 (match_operand:QI 2 "general_operand" "")))]
2943 "z_replacement_completed == 2"
2944 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2945 (set (match_dup 3) (reg:HI D_REGNUM))])
2946 (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
2947 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2948 (set (match_dup 3) (reg:HI D_REGNUM))])]
2950 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
2951 if (A_REG_P (operands[1]))
2952 operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2954 operands[5] = operands[1];
2955 if (A_REG_P (operands[2]))
2956 operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2958 operands[6] = operands[2];
2961 (define_insn "mulqihi3"
2962 [(set (match_operand:HI 0 "register_operand" "=d,d,d")
2963 (mult:HI (sign_extend:HI
2964 (match_operand:QI 1 "register_operand" "%0,0,0"))
2966 (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
2972 /* Special case when multiplying the register with itself. */
2973 if (D_REG_P (operands[2]))
2975 output_asm_insn (\"tba\", operands);
2979 if (!H_REG_P (operands[2]))
2981 output_asm_insn (\"ldaa\\t%b2\", operands);
2987 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2988 ops[1] = operands[2];
2989 m68hc11_gen_movqi (insn, ops);
2991 return \"jsr\\t___mulqi3\";
2994 ;;--------------------------------------------------------------------
2995 ;;- Divide instructions.
2996 ;;--------------------------------------------------------------------
2998 (define_insn "divmodhi4"
2999 [(set (match_operand:HI 0 "register_operand" "=d,d")
3000 (div:HI (match_operand:HI 1 "register_operand" "0,0")
3001 (match_operand:HI 2 "general_operand" "A,ium")))
3002 (set (match_operand:HI 3 "register_operand" "=&x,&x")
3003 (mod:HI (match_dup 1) (match_dup 2)))]
3007 if (!X_REG_P (operands[2]))
3009 if (Y_REG_P (operands[2]))
3011 output_asm_insn (\"sty\\t%t1\", operands);
3012 output_asm_insn (\"ldx\\t%t1\", operands);
3016 output_asm_insn (\"ldx\\t%2\", operands);
3021 /* Flags are ok after that. */
3022 return \"idivs\\n\\txgdx\";
3027 return \"bsr\\t__divmodhi4\";
3031 (define_insn "udivmodhi4"
3032 [(set (match_operand:HI 0 "register_operand" "=d,d")
3033 (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
3034 (match_operand:HI 2 "general_operand" "A,ium")))
3035 (set (match_operand:HI 3 "register_operand" "=x,x")
3036 (umod:HI (match_dup 1) (match_dup 2)))]
3040 if (!X_REG_P (operands[2]))
3042 if (Y_REG_P (operands[2]))
3044 output_asm_insn (\"sty\\t%t1\", operands);
3045 output_asm_insn (\"ldx\\t%t1\", operands);
3049 output_asm_insn (\"ldx\\t%2\", operands);
3053 /* Z V and C flags are set but N is unchanged.
3054 Since this is an unsigned divide, we can probably keep the flags
3055 and indicate this. */
3056 cc_status.flags |= CC_NOT_NEGATIVE;
3057 return \"idiv\\n\\txgdx\";
3060 ;;--------------------------------------------------------------------
3061 ;;- and instructions.
3062 ;;--------------------------------------------------------------------
3064 (define_insn_and_split "anddi3"
3065 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3066 (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3067 (match_operand:DI 2 "general_operand" "imu,imu")))
3068 (clobber (match_scratch:HI 3 "=d,d"))]
3073 "m68hc11_split_logical (SImode, AND, operands);
3076 (define_insn_and_split "andsi3"
3077 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3078 (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3079 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3080 (clobber (match_scratch:HI 3 "=X,d"))]
3085 "m68hc11_split_logical (HImode, AND, operands);
3088 (define_expand "andhi3"
3089 [(set (match_operand:HI 0 "register_operand" "")
3090 (and:HI (match_operand:HI 1 "register_operand" "")
3091 (match_operand:HI 2 "general_operand" "")))]
3095 (define_insn "*andhi3_mem"
3096 [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3097 (and:HI (match_dup 0)
3098 (match_operand:HI 1 "immediate_operand" "i,i")))
3099 (clobber (match_scratch:HI 2 "=X,xy"))]
3100 "TARGET_RELAX && !TARGET_M6812"
3103 int val = INTVAL (operands[1]) & 0x0FFFF;
3107 cc_status = cc_prev_status;
3113 /* The bclr instruction uses an inverted mask. */
3114 operands[1] = GEN_INT ((~val) & 0x0FFFF);
3116 /* When destination is a global variable, generate a .relax instruction
3117 and load the address in the clobber register. That load can be
3118 eliminated by the linker if the address is in page0. */
3119 if (which_alternative == 1)
3123 ops[0] = operands[2];
3124 ops[1] = XEXP (operands[0], 0);
3125 ops[2] = gen_label_rtx ();
3126 output_asm_insn (\".relax\\t%l2\", ops);
3127 m68hc11_gen_movhi (insn, ops);
3128 if ((val & 0x0FF) != 0x0FF)
3129 output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
3131 if ((val & 0x0FF00) != 0x0FF00)
3132 output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
3134 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3135 CODE_LABEL_NUMBER (ops[2]));
3139 if ((val & 0x0FF) != 0x0FF)
3140 output_asm_insn (\"bclr\\t%b0, %b1\", operands);
3142 if ((val & 0x0FF00) != 0x0FF00)
3143 output_asm_insn (\"bclr\\t%h0, %h1\", operands);
3148 (define_insn "*andhi3_const"
3149 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3150 (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3151 (match_operand:HI 2 "const_int_operand" "")))]
3155 int val = INTVAL (operands[2]) & 0x0FFFF;
3156 int lowpart_zero = 0;
3157 int highpart_zero = 0;
3158 int lowpart_unknown = 0;
3159 int highpart_unknown = 0;
3161 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3166 cc_status = cc_prev_status;
3170 /* First, try to clear the low and high part.
3171 If that's possible, the second 'and' will give
3172 the good status flags and we can avoid a tsthi. */
3173 if ((val & 0x0FF) == 0)
3175 if (D_REG_P (operands[0]))
3176 output_asm_insn (\"clrb\", operands);
3178 output_asm_insn (\"clr\\t%b0\", operands);
3181 if ((val & 0x0FF00) == 0)
3183 if (D_REG_P (operands[0]))
3184 output_asm_insn (\"clra\", operands);
3186 output_asm_insn (\"clr\\t%h0\", operands);
3190 if ((val & 0x0FF) == 0x0FF)
3192 lowpart_unknown = 1;
3194 else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3198 ops[0] = operands[0];
3199 ops[1] = GEN_INT ((~val) & 0x0FF);
3200 output_asm_insn (\"bclr\\t%b0, %1\", ops);
3202 else if ((val & 0x0FF) != 0)
3204 output_asm_insn (\"andb\\t%b2\", operands);
3207 if ((val & 0x0FF00) == 0x0FF00)
3209 highpart_unknown = 1;
3211 else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3215 ops[0] = operands[0];
3216 ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
3217 output_asm_insn (\"bclr\\t%h0, %1\", ops);
3219 else if ((val & 0x0FF00) != 0)
3221 output_asm_insn (\"anda\\t%h2\", operands);
3224 if (highpart_unknown || lowpart_unknown)
3226 else if (highpart_zero == 0 && lowpart_zero == 0)
3232 (define_insn "*andhi3_gen"
3233 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3234 (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3235 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3239 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3243 return \"anda\\t%h2\\n\\tandb\\t%b2\";
3246 (define_expand "andqi3"
3247 [(set (match_operand:QI 0 "register_operand" "")
3248 (and:QI (match_operand:QI 1 "register_operand" "")
3249 (match_operand:QI 2 "general_operand" "")))]
3253 (define_insn "*andqi3_mem"
3254 [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3255 (and:QI (match_dup 0)
3256 (match_operand:QI 1 "const_int_operand" "i,i")))
3257 (clobber (match_scratch:HI 2 "=X,xy"))]
3258 "TARGET_RELAX && !TARGET_M6812"
3261 int val = INTVAL (operands[1]) & 0x0FF;
3265 cc_status = cc_prev_status;
3269 /* The bclr instruction uses an inverted mask. */
3270 operands[1] = GEN_INT ((~val) & 0x0FF);
3272 /* When destination is a global variable, generate a .relax instruction
3273 and load the address in the clobber register. That load can be
3274 eliminated by the linker if the address is in page0. */
3275 if (which_alternative == 1)
3279 ops[0] = operands[2];
3280 ops[1] = XEXP (operands[0], 0);
3281 ops[2] = gen_label_rtx ();
3282 output_asm_insn (\".relax\\t%l2\", ops);
3283 m68hc11_gen_movhi (insn, ops);
3284 output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3285 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3286 CODE_LABEL_NUMBER (ops[2]));
3289 return \"bclr\\t%b0, %1\";
3292 (define_insn "*andqi3_const"
3293 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3294 (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3295 (match_operand:QI 2 "const_int_operand" "")))]
3299 int val = INTVAL (operands[2]) & 0x0FF;
3301 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3306 cc_status = cc_prev_status;
3309 if (!H_REG_P (operands[0]))
3313 ops[0] = operands[0];
3314 ops[1] = GEN_INT ((~val) & 0x0FF);
3315 output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3318 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3319 return \"andb\\t%b2\";
3320 else if (DA_REG_P (operands[0]))
3321 return \"anda\\t%b2\";
3323 fatal_insn (\"Invalid operand in the instruction\", insn);
3326 (define_insn "*andqi3_gen"
3327 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3328 (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3329 (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
3333 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3336 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3337 return \"andb\\t%b2\";
3338 else if (DA_REG_P (operands[0]))
3339 return \"anda\\t%b2\";
3341 fatal_insn (\"Invalid operand in the instruction\", insn);
3344 ;;--------------------------------------------------------------------
3345 ;;- Bit set or instructions.
3346 ;;--------------------------------------------------------------------
3348 (define_insn_and_split "iordi3"
3349 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3350 (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3351 (match_operand:DI 2 "general_operand" "imu,imu")))
3352 (clobber (match_scratch:HI 3 "=d,d"))]
3357 "m68hc11_split_logical (SImode, IOR, operands);
3360 (define_insn_and_split "iorsi3"
3361 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3362 (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3363 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3364 (clobber (match_scratch:HI 3 "=X,d"))]
3369 "m68hc11_split_logical (HImode, IOR, operands);
3372 (define_expand "iorhi3"
3373 [(set (match_operand:HI 0 "register_operand" "")
3374 (ior:HI (match_operand:HI 1 "register_operand" "")
3375 (match_operand:HI 2 "splitable_operand" "")))]
3379 (define_insn "*iorhi3_mem"
3380 [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3381 (ior:HI (match_dup 0)
3382 (match_operand:HI 1 "const_int_operand" "")))
3383 (clobber (match_scratch:HI 2 "=X,xy"))]
3384 "TARGET_RELAX && !TARGET_M6812"
3387 int val = INTVAL (operands[1]) & 0x0FFFF;
3391 cc_status = cc_prev_status;
3395 if (which_alternative == 1)
3399 ops[0] = operands[2];
3400 ops[1] = XEXP (operands[0], 0);
3401 ops[2] = gen_label_rtx ();
3402 output_asm_insn (\".relax\\t%l2\", ops);
3403 m68hc11_gen_movhi (insn, ops);
3404 if ((val & 0x0FF) != 0)
3405 output_asm_insn (\"bset\\t1,%2, %b1\", operands);
3407 if ((val & 0x0FF00) != 0)
3408 output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3409 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3410 CODE_LABEL_NUMBER (ops[2]));
3414 if ((val & 0x0FF) != 0)
3415 output_asm_insn (\"bset\\t%b0, %b1\", operands);
3417 if ((val & 0x0FF00) != 0)
3418 output_asm_insn (\"bset\\t%h0, %h1\", operands);
3423 (define_insn "*iorhi3_const"
3424 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3425 (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3426 (match_operand:HI 2 "const_int_operand" "")))]
3430 int val = INTVAL (operands[2]) & 0x0FFFF;
3432 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3437 cc_status = cc_prev_status;
3441 if ((val & 0x0FF) != 0)
3443 if (!H_REG_P (operands[0]))
3444 output_asm_insn (\"bset\\t%b0, %b2\", operands);
3446 output_asm_insn (\"orab\\t%b2\", operands);
3449 if ((val & 0x0FF00) != 0)
3451 if (!H_REG_P (operands[0]))
3452 output_asm_insn (\"bset\\t%h0, %h2\", operands);
3454 output_asm_insn (\"oraa\\t%h2\", operands);
3461 (define_insn "*iorhi3_gen"
3462 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3463 (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3464 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3468 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3472 return \"oraa\\t%h2\\n\\torab\\t%b2\";
3475 (define_expand "iorqi3"
3476 [(set (match_operand:QI 0 "register_operand" "")
3477 (ior:QI (match_operand:QI 1 "register_operand" "")
3478 (match_operand:QI 2 "general_operand" "")))]
3482 (define_insn "*iorqi3_mem"
3483 [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3484 (ior:QI (match_dup 0)
3485 (match_operand:QI 1 "const_int_operand" "")))
3486 (clobber (match_scratch:HI 2 "=X,xy"))]
3487 "TARGET_RELAX && !TARGET_M6812"
3490 int val = INTVAL (operands[1]) & 0x0FF;
3494 cc_status = cc_prev_status;
3497 if (which_alternative == 1)
3501 ops[0] = operands[2];
3502 ops[1] = XEXP (operands[0], 0);
3503 ops[2] = gen_label_rtx ();
3504 output_asm_insn (\".relax\\t%l2\", ops);
3505 m68hc11_gen_movhi (insn, ops);
3506 output_asm_insn (\"bset\\t0,%2, %1\", operands);
3507 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3508 CODE_LABEL_NUMBER (ops[2]));
3511 return \"bset\\t%b0, %1\";
3514 (define_insn "*iorqi3_const"
3515 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3516 (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3517 (match_operand:QI 2 "const_int_operand" "")))]
3521 int val = INTVAL (operands[2]) & 0x0FF;
3523 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3528 cc_status = cc_prev_status;
3531 if (!H_REG_P (operands[0]))
3533 return \"bset\\t%b0, %2\";
3536 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3537 return \"orab\\t%b2\";
3538 else if (DA_REG_P (operands[0]))
3539 return \"oraa\\t%b2\";
3541 fatal_insn (\"Invalid operand in the instruction\", insn);
3544 (define_insn "*iorqi3_gen"
3545 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3546 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3547 (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
3551 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3554 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3555 return \"orab\\t%b2\";
3556 else if (DA_REG_P (operands[0]))
3557 return \"oraa\\t%b2\";
3559 fatal_insn (\"Invalid operand in the instruction\", insn);
3563 ;;--------------------------------------------------------------------
3564 ;;- xor instructions.
3565 ;;--------------------------------------------------------------------
3567 (define_insn_and_split "xordi3"
3568 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3569 (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3570 (match_operand:DI 2 "general_operand" "imu,imu")))
3571 (clobber (match_scratch:HI 3 "=d,d"))]
3576 "m68hc11_split_logical (SImode, XOR, operands);
3579 (define_insn_and_split "xorsi3"
3580 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3581 (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3582 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3583 (clobber (match_scratch:HI 3 "=X,d"))]
3588 "m68hc11_split_logical (HImode, XOR, operands);
3591 (define_insn "xorhi3"
3592 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3593 (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3594 (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
3598 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3601 if (GET_CODE (operands[2]) == CONST_INT)
3603 int val = INTVAL (operands[2]) & 0x0FFFF;
3607 cc_status = cc_prev_status;
3610 if ((val & 0x0FF) != 0)
3612 output_asm_insn (\"eorb\\t%b2\", operands);
3614 else if ((val & 0x0FF) == 0x0FF)
3616 output_asm_insn (\"comb\", operands);
3619 if ((val & 0x0FF00) != 0)
3621 output_asm_insn (\"eora\\t%h2\", operands);
3623 else if ((val & 0x0FF00) == 0x0FF00)
3625 output_asm_insn (\"coma\", operands);
3633 return \"eora\\t%h2\\n\\teorb\\t%b2\";
3636 (define_insn "xorqi3"
3637 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3638 (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3639 (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
3643 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3646 if (GET_CODE (operands[2]) == CONST_INT)
3648 int val = INTVAL (operands[2]) & 0x0FF;
3652 cc_status = cc_prev_status;
3657 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3663 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3664 return \"eorb\\t%b2\";
3665 else if (DA_REG_P (operands[0]))
3666 return \"eora\\t%b2\";
3668 fatal_insn (\"Invalid operand in the instruction\", insn);
3671 ;;--------------------------------------------------------------------
3672 ;;- Bit set or instructions.
3673 ;;--------------------------------------------------------------------
3675 (define_insn_and_split "*logicalsi3_zexthi"
3676 [(set (match_operand:SI 0 "register_operand" "=D")
3677 (match_operator:SI 3 "m68hc11_logical_operator"
3679 (match_operand:HI 1 "general_operand" "imudA"))
3680 (match_operand:SI 2 "general_operand" "Dimu")]))]
3684 [(set (reg:HI D_REGNUM) (match_dup 4))
3685 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3686 (set (reg:HI X_REGNUM) (match_dup 6))]
3687 "PUT_MODE (operands[3], HImode);
3688 if (X_REG_P (operands[2]))
3690 operands[5] = operands[1];
3691 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3692 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3693 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3697 operands[4] = operands[1];
3698 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3699 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3701 /* For an AND, make sure the high 16-bit part is cleared. */
3702 if (GET_CODE (operands[3]) == AND)
3704 operands[6] = const0_rtx;
3708 (define_insn_and_split "*logicalsi3_zextqi"
3709 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3710 (match_operator:SI 3 "m68hc11_logical_operator"
3712 (match_operand:QI 1 "general_operand" "d,*A,imu"))
3713 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3716 "z_replacement_completed == 2"
3717 [(set (reg:QI A_REGNUM) (match_dup 4))
3718 (set (reg:QI D_REGNUM) (match_dup 7))
3719 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3720 (set (reg:HI X_REGNUM) (match_dup 6))]
3721 "PUT_MODE (operands[3], QImode);
3722 if (X_REG_P (operands[2]))
3724 operands[5] = operands[1];
3725 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3726 operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3727 operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
3728 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3732 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3733 operands[7] = operands[1];
3734 operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3735 operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3736 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3738 /* For an AND, make sure the high 24-bit part is cleared. */
3739 if (GET_CODE (operands[3]) == AND)
3741 operands[4] = const0_rtx;
3742 operands[6] = const0_rtx;
3746 (define_insn_and_split "*logicalhi3_zexthi_ashift8"
3747 [(set (match_operand:HI 0 "register_operand" "=d")
3748 (match_operator:HI 3 "m68hc11_logical_operator"
3750 (match_operand:QI 1 "general_operand" "imud*A"))
3752 (match_operand:HI 2 "general_operand" "imud*A")
3756 "z_replacement_completed == 2"
3757 [(set (reg:QI A_REGNUM) (match_dup 4))
3758 (set (reg:QI B_REGNUM) (match_dup 5))]
3760 if (GET_CODE (operands[3]) == AND)
3762 emit_insn (gen_movhi (operands[0], const0_rtx));
3767 operands[5] = operands[1];
3768 if (D_REG_P (operands[2]))
3770 operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3774 operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3779 (define_insn_and_split "*logicalhi3_zexthi"
3780 [(set (match_operand:HI 0 "register_operand" "=d,d")
3781 (match_operator:HI 3 "m68hc11_logical_operator"
3783 (match_operand:QI 1 "general_operand" "imd*A,?u"))
3784 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3787 "z_replacement_completed == 2"
3788 [(set (reg:QI B_REGNUM) (match_dup 6))
3789 (set (reg:QI A_REGNUM) (match_dup 4))
3790 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3792 PUT_MODE (operands[3], QImode);
3793 if (D_REG_P (operands[2]))
3795 operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3796 operands[5] = operands[1];
3797 operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3801 operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3802 operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3803 if (D_REG_P (operands[1]))
3804 operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3806 operands[6] = operands[1];
3808 /* For an AND, make sure the high 8-bit part is cleared. */
3809 if (GET_CODE (operands[3]) == AND)
3811 operands[4] = const0_rtx;
3816 (define_insn_and_split "*logicalsi3_silshr16"
3817 [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
3818 (match_operator:SI 3 "m68hc11_logical_operator"
3820 (match_operand:SI 1 "general_operand" "uim,uim,0,0")
3822 (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
3826 [(set (reg:HI D_REGNUM) (match_dup 4))
3827 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3828 (set (reg:HI X_REGNUM) (match_dup 6))]
3829 "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3830 if (X_REG_P (operands[2]))
3832 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3833 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3837 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3838 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3840 PUT_MODE (operands[3], HImode);
3842 /* For an AND, make sure the high 16-bit part is cleared. */
3843 if (GET_CODE (operands[3]) == AND)
3845 operands[6] = const0_rtx;
3849 (define_insn_and_split "*logicalsi3_silshl16"
3850 [(set (match_operand:SI 0 "register_operand" "=D,D")
3851 (match_operator:SI 3 "m68hc11_logical_operator"
3853 (match_operand:SI 1 "general_operand" "uim,?D")
3855 (match_operand:SI 2 "general_operand" "0,0")]))]
3858 "z_replacement_completed == 2"
3859 [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3860 (set (reg:HI D_REGNUM) (match_dup 5))]
3861 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3862 PUT_MODE (operands[3], HImode);
3864 if (GET_CODE (operands[3]) == AND)
3865 operands[5] = const0_rtx;
3867 operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3870 (define_insn_and_split "*logicalsi3_silshl16_zext"
3871 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3872 (match_operator:SI 3 "m68hc11_logical_operator"
3875 (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
3877 (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
3880 ;; Must split before z register replacement
3882 [(set (match_dup 4) (match_dup 5))
3883 (set (match_dup 6) (match_dup 7))]
3885 /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
3886 if (GET_CODE (operands[1]) == HARD_D_REGNUM
3887 && GET_CODE (operands[3]) != AND)
3889 /* This particular case is too early to be split before
3890 Z register replacement because the cse-reg pass we do
3891 does not recognize the 'swap_areg'. It is ok to handle
3893 if (z_replacement_completed != 2)
3897 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
3898 emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
3899 gen_rtx_REG (HImode, HARD_X_REGNUM)));
3901 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3902 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3903 operands[5] = operands[2];
3904 operands[7] = operands[1];
3906 if (GET_CODE (operands[3]) == AND)
3907 operands[5] = operands[7] = const0_rtx;
3910 ;;--------------------------------------------------------------------
3911 ;; 16-bit Arithmetic and logical operations on X and Y:
3913 ;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3915 ;; Operations on X or Y registers are split here. Instructions are
3917 ;; - xgdx/xgdy instruction pattern,
3918 ;; - The same operation on register D,
3919 ;; - xgdx/xgdy instruction pattern.
3920 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3921 ;; We also handle the case were the address register is used in both source
3922 ;; operands, such as:
3924 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3926 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3930 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3931 (match_operator:HI 3 "m68hc11_arith_operator"
3932 [(match_operand:HI 1 "hard_addr_reg_operand" "")
3933 (match_operand:HI 2 "general_operand" "")]))]
3934 "z_replacement_completed == 2
3935 /* If we are adding a small constant to X or Y, it's
3936 better to use one or several inx/iny instructions. */
3937 && !(GET_CODE (operands[3]) == PLUS
3939 && (immediate_operand (operands[2], HImode)
3940 || hard_reg_operand (operands[2], HImode)))
3941 || (GET_CODE (operands[2]) == CONST_INT
3942 && INTVAL (operands[2]) >= -4
3943 && INTVAL (operands[2]) <= 4)))"
3944 [(set (match_dup 9) (match_dup 0))
3945 (set (match_dup 4) (match_dup 5))
3946 (set (match_dup 8) (match_dup 7))
3947 (set (match_dup 0) (match_dup 1))
3948 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3949 (set (match_dup 0) (reg:HI D_REGNUM))])
3950 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3951 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3952 (set (match_dup 0) (reg:HI D_REGNUM))])]
3954 operands[9] = operands[0];
3955 /* For 68HC12, push the value on the stack and do the operation
3958 && m68hc11_non_shift_operator (operands[3], HImode)
3959 && (H_REG_P (operands[2])
3960 || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3961 && reg_mentioned_p (operands[0], operands[2]))))
3963 operands[4] = gen_rtx_MEM (HImode,
3964 gen_rtx_PRE_DEC (HImode,
3965 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3966 operands[6] = gen_rtx_MEM (HImode,
3967 gen_rtx_POST_INC (HImode,
3968 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3969 operands[5] = operands[2];
3970 operands[8] = operands[7] = operands[0];
3972 /* Save the operand2 in a temporary location and use it. */
3973 else if ((H_REG_P (operands[2])
3974 || reg_mentioned_p (operands[0], operands[2]))
3975 && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3977 if (GET_CODE (operands[3]) == MINUS
3978 && reg_mentioned_p (operands[0], operands[2]))
3980 operands[9] = gen_rtx_MEM (HImode,
3981 gen_rtx_PRE_DEC (HImode,
3982 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3983 operands[1] = gen_rtx_MEM (HImode,
3984 gen_rtx_POST_INC (HImode,
3985 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3986 operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3987 operands[4] = operands[7] = operands[0];
3988 operands[6] = operands[8];
3989 operands[5] = operands[2];
3993 operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3994 operands[6] = operands[4];
3995 if (!H_REG_P (operands[2]))
3997 operands[5] = operands[0];
3998 operands[7] = operands[2];
3999 operands[8] = operands[0];
4003 operands[5] = operands[2];
4004 operands[8] = operands[7] = operands[0];
4010 operands[4] = operands[5] = operands[0];
4011 operands[6] = operands[2];
4012 operands[8] = operands[7] = operands[0];
4017 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4018 (match_operator:HI 3 "m68hc11_arith_operator"
4019 [(match_operand:HI 1 "general_operand" "")
4020 (match_operand:HI 2 "general_operand" "")]))]
4021 "z_replacement_completed == 2
4022 /* If we are adding a small constant to X or Y, it's
4023 better to use one or several inx/iny instructions. */
4024 && !(GET_CODE (operands[3]) == PLUS
4026 && (immediate_operand (operands[2], HImode)
4027 || hard_reg_operand (operands[2], HImode)))
4028 || (GET_CODE (operands[2]) == CONST_INT
4029 && INTVAL (operands[2]) >= -4
4030 && INTVAL (operands[2]) <= 4)))"
4031 [(set (match_dup 0) (match_dup 1))
4032 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4033 (set (match_dup 0) (reg:HI D_REGNUM))])
4034 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
4035 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4036 (set (match_dup 0) (reg:HI D_REGNUM))])]
4041 ;; Next split handles the logical operations on D register with
4042 ;; another hard register for the second operand. For this, we
4043 ;; have to save the second operand in a scratch location and use
4044 ;; it instead. This must be supported because in some (rare) cases
4045 ;; the second operand can come in a hard register and the reload
4046 ;; pass doesn't know how to reload it in a memory location.
4048 ;; PLUS MINUS AND IOR XOR
4050 ;; The shift operators are special and must not appear here.
4053 [(set (match_operand:HI 0 "d_register_operand" "")
4054 (match_operator:HI 3 "m68hc11_non_shift_operator"
4055 [(match_operand:HI 1 "d_register_operand" "")
4056 (match_operand:HI 2 "hard_reg_operand" "")]))]
4058 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4059 [(set (match_dup 4) (match_dup 2))
4060 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4061 "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
4064 ;; For 68HC12, push the operand[2] value on the stack and do the
4065 ;; logical/arithmetic operation with a pop.
4068 [(set (match_operand:HI 0 "d_register_operand" "")
4069 (match_operator:HI 3 "m68hc11_non_shift_operator"
4070 [(match_operand:HI 1 "d_register_operand" "")
4071 (match_operand:HI 2 "hard_reg_operand" "")]))]
4073 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4074 [(set (match_dup 4) (match_dup 2))
4075 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4076 "operands[4] = gen_rtx_MEM (HImode,
4077 gen_rtx_PRE_DEC (HImode,
4078 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4079 operands[5] = gen_rtx_MEM (HImode,
4080 gen_rtx_POST_INC (HImode,
4081 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4084 ;;--------------------------------------------------------------------
4085 ;; 16-bit Unary operations on X and Y:
4089 ;; Operations on X or Y registers are split here. Instructions are
4091 ;; - xgdx/xgdy instruction pattern,
4092 ;; - The same operation on register D,
4093 ;; - xgdx/xgdy instruction pattern.
4094 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4095 ;; We also handle the case were the address register is used in both source
4096 ;; operands, such as:
4098 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4100 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4103 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4104 (match_operator:HI 2 "m68hc11_unary_operator"
4105 [(match_operand 1 "general_operand" "")]))]
4106 "z_replacement_completed == 2"
4107 [(set (match_dup 4) (match_dup 5))
4108 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4109 (set (match_dup 0) (reg:HI D_REGNUM))])
4110 (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4111 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4112 (set (match_dup 0) (reg:HI D_REGNUM))])]
4115 if ((H_REG_P (operands[1])
4116 && !rtx_equal_p (operands[0], operands[1]))
4117 || reg_mentioned_p (operands[0], operands[1]))
4119 /* Move to the destination register, before the xgdx. */
4120 operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
4121 REGNO (operands[0]));
4122 operands[5] = operands[1];
4124 /* Apply the operation on D. */
4125 operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
4129 /* Generate a copy to same register (nop). */
4130 operands[4] = operands[5] = operands[0];
4131 operands[3] = operands[1];
4136 ;; 8-bit operations on address registers.
4138 ;; We have to take care that the address register is not used for the
4139 ;; source of operand2. If operand2 is the D register, we have to save
4140 ;; that register in a temporary location.
4142 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4145 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4146 (match_operator:QI 3 "m68hc11_arith_operator"
4147 [(match_operand:QI 1 "hard_addr_reg_operand" "")
4148 (match_operand:QI 2 "general_operand" "")]))]
4149 "z_replacement_completed == 2
4150 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
4151 incqi pattern generates a better code. */
4152 && !(GET_CODE (operands[3]) == PLUS
4153 && GET_CODE (operands[2]) == CONST_INT
4154 && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4155 [(set (match_dup 5) (match_dup 6))
4156 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4157 (set (match_dup 4) (reg:HI D_REGNUM))])
4158 (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4159 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4160 (set (match_dup 4) (reg:HI D_REGNUM))])]
4161 "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
4163 /* For the second operand is a hard register or if the address
4164 register appears in the source, we have to save the operand[2]
4165 value in a temporary location and then use that temp.
4166 Otherwise, it's ok and we generate a (set (D) (D)) that
4167 will result in a nop. */
4168 if (H_REG_P (operands[2]))
4170 operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4171 operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
4172 operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4174 else if (reg_mentioned_p (operands[0], operands[2]))
4176 operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4177 operands[6] = operands[2];
4178 operands[7] = operands[5];
4182 operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4183 operands[7] = operands[2];
4188 ;; Next split handles the logical operations on D register with
4189 ;; another hard register for the second operand. For this, we
4190 ;; have to save the second operand in a scratch location and use
4191 ;; it instead. This must be supported because in some (rare) cases
4192 ;; the second operand can come in a hard register and the reload
4193 ;; pass doesn't know how to reload it in a memory location.
4195 ;; PLUS MINUS AND IOR XOR
4197 ;; The shift operators are special and must not appear here.
4200 [(set (match_operand:QI 0 "d_register_operand" "")
4201 (match_operator:QI 3 "m68hc11_non_shift_operator"
4202 [(match_operand:QI 1 "d_register_operand" "")
4203 (match_operand:QI 2 "hard_reg_operand" "")]))]
4205 [(set (match_dup 5) (match_dup 6))
4206 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4207 "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4208 operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4209 operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
4211 ;;--------------------------------------------------------------------
4212 ;; 8-bit Unary operations on X and Y:
4216 ;; Operations on X or Y registers are split here. Instructions are
4218 ;; - xgdx/xgdy instruction pattern,
4219 ;; - The same operation on register D,
4220 ;; - xgdx/xgdy instruction pattern.
4221 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4222 ;; We also handle the case were the address register is used in both source
4223 ;; operands, such as:
4225 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4227 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4230 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4231 (match_operator:QI 2 "m68hc11_unary_operator"
4232 [(match_operand:QI 1 "general_operand" "")]))]
4233 "z_replacement_completed == 2"
4234 [(set (match_dup 4) (match_dup 5))
4235 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4236 (set (match_dup 3) (reg:HI D_REGNUM))])
4237 (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4238 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4239 (set (match_dup 3) (reg:HI D_REGNUM))])]
4242 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4243 if ((H_REG_P (operands[1])
4244 && !rtx_equal_p (operands[0], operands[1]))
4245 || reg_mentioned_p (operands[0], operands[1]))
4247 /* Move to the destination register, before the xgdx. */
4248 operands[4] = operands[0];
4249 operands[5] = operands[1];
4251 /* Apply the operation on D. */
4252 operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4256 operands[4] = operands[5] = operands[0];
4257 operands[6] = operands[1];
4262 ;;--------------------------------------------------------------------
4264 ;;--------------------------------------------------------------------
4266 (define_expand "negdi2"
4267 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4268 (neg:DI (match_operand:DI 1 "general_operand" "")))]
4270 "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4274 (define_insn "negsi2"
4275 [(set (match_operand:SI 0 "register_operand" "=D")
4276 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
4284 /* With -Os or without -O, use a special library call. */
4285 if (optimize_size || optimize == 0)
4286 return \"bsr\\t___negsi2\";
4288 ops[0] = gen_label_rtx ();
4290 /* 32-bit complement and add 1. */
4291 output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4292 output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4293 output_asm_insn (\"bne\\t%l0\", ops);
4294 output_asm_insn (\"inx\", operands);
4295 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4299 (define_insn "neghi2"
4300 [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
4301 (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4304 coma\\n\\tcomb\\n\\taddd\\t#1
4305 clra\\n\\tclrb\\n\\tsubd\\t%1
4306 xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4308 (define_insn "negqi2"
4309 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4310 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
4319 ;; - 32-bit complement. GCC knows how to translate them but providing a
4320 ;; pattern generates better/smaller code.
4322 (define_expand "one_cmpldi2"
4323 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4324 (not:DI (match_operand:DI 1 "general_operand" "")))]
4326 "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4329 (define_insn "one_cmplsi2"
4330 [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4331 (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4332 (clobber (match_scratch:HI 2 "=X,d,X"))]
4335 bsr\\t___one_cmplsi2
4339 (define_insn "one_cmplhi2"
4340 [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
4341 (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
4345 com\\t%b0\\n\\tcom\\t%h0
4347 com\\t%b0\\n\\tcom\\t%h0")
4349 (define_insn "one_cmplqi2"
4350 [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
4351 (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
4359 (define_split /* "*one_cmplsi2" */
4360 [(set (match_operand:SI 0 "non_push_operand" "")
4361 (not:SI (match_dup 0)))
4362 (clobber (match_scratch:HI 1 ""))]
4363 "z_replacement_completed == 2
4364 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4365 [(set (match_dup 2) (not:HI (match_dup 2)))
4366 (set (match_dup 3) (not:HI (match_dup 3)))]
4367 "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4368 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
4370 (define_split /* "*one_cmplsi2" */
4371 [(set (match_operand:SI 0 "non_push_operand" "")
4372 (not:SI (match_operand:SI 1 "non_push_operand" "")))
4373 (clobber (match_operand:HI 2 "d_register_operand" ""))]
4374 "z_replacement_completed == 2
4375 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4376 [(set (match_dup 2) (match_dup 3))
4377 (set (match_dup 2) (not:HI (match_dup 2)))
4378 (set (match_dup 4) (match_dup 2))
4379 (set (match_dup 2) (match_dup 5))
4380 (set (match_dup 2) (not:HI (match_dup 2)))
4381 (set (match_dup 6) (match_dup 2))]
4382 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4383 operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4384 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4385 operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
4387 ;;--------------------------------------------------------------------
4388 ;;- arithmetic shifts
4389 ;;--------------------------------------------------------------------
4391 ;; Provide some 64-bit shift patterns.
4392 (define_expand "ashldi3"
4393 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4394 (ashift:DI (match_operand:DI 1 "general_operand" "")
4395 (match_operand:HI 2 "general_operand" "")))
4396 (clobber (match_scratch:HI 3 ""))])]
4400 if (GET_CODE (operands[2]) != CONST_INT
4401 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4407 (define_insn_and_split "*ashldi3_const32"
4408 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4409 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4411 (clobber (match_scratch:HI 2 "=&A,d,d"))]
4416 "/* Move the lowpart in the highpart first in case the shift
4417 is applied on the source. */
4418 if (IS_STACK_PUSH (operands[0]))
4420 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4421 const0_rtx, operands[2]);
4423 /* Adjust first operand if it uses SP so that we take into
4424 account the above push. Can occur only for 68HC12. */
4425 if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
4427 operands[1] = adjust_address (operands[1],
4428 GET_MODE (operands[0]), 4);
4430 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4431 m68hc11_gen_lowpart (SImode, operands[1]),
4433 if (!IS_STACK_PUSH (operands[0]))
4435 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4436 const0_rtx, operands[2]);
4440 (define_insn_and_split "*ashldi3_const1"
4441 [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4442 (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4444 (clobber (match_scratch:HI 2 "=d,d,d"))]
4447 "z_replacement_completed == 2"
4448 [(set (match_dup 2) (match_dup 3))
4449 (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4450 (set (match_dup 4) (match_dup 2))
4452 (set (match_dup 2) (match_dup 5))
4453 (parallel [(set (match_dup 2)
4454 (rotate:HI (match_dup 2) (const_int 1)))
4455 (clobber (reg:HI CC_REGNUM))])
4456 (set (match_dup 6) (match_dup 2))
4458 (set (match_dup 2) (match_dup 7))
4459 (parallel [(set (match_dup 2)
4460 (rotate:HI (match_dup 2) (const_int 1)))
4461 (clobber (reg:HI CC_REGNUM))])
4462 (set (match_dup 8) (match_dup 2))
4464 (set (match_dup 2) (match_dup 9))
4465 (parallel [(set (match_dup 2)
4466 (rotate:HI (match_dup 2) (const_int 1)))
4467 (clobber (reg:HI CC_REGNUM))])
4468 (set (match_dup 10) (match_dup 2))]
4469 "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4470 operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4471 operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4473 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4474 operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4475 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4477 operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4478 operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4479 operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4481 operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4482 operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4483 operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4485 (define_insn "addsi_silshr16"
4486 [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
4487 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
4489 (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
4494 [(set (match_operand:SI 0 "register_operand" "")
4495 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4497 (match_operand:SI 2 "general_operand" "")))]
4498 "z_replacement_completed == 2 && !X_REG_P (operands[1])"
4499 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4500 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4502 (reg:HI CC_REGNUM)))]
4503 "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4506 [(set (match_operand:SI 0 "register_operand" "")
4507 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4509 (match_operand:SI 2 "general_operand" "")))]
4510 "z_replacement_completed == 2 && X_REG_P (operands[1])"
4511 [(set (reg:HI D_REGNUM) (match_dup 5))
4512 (set (reg:HI X_REGNUM) (match_dup 3))
4513 (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4514 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4516 (reg:HI CC_REGNUM)))]
4517 "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4518 if (X_REG_P (operands[2]))
4520 operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4521 operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4525 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4526 operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4530 (define_insn "addsi_ashift16"
4531 [(set (match_operand:SI 0 "register_operand" "=D")
4533 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4535 (match_operand:SI 1 "general_operand" "0")))
4536 (clobber (match_scratch:HI 3 "=X"))]
4541 [(set (match_operand:SI 0 "register_operand" "")
4543 (mult:SI (match_operand:SI 2 "general_operand" "")
4545 (match_operand:SI 1 "general_operand" "")))
4546 (clobber (match_scratch:HI 3 "=X"))]
4547 "0 && reload_completed && z_replacement_completed == 2"
4548 [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4551 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4554 (define_insn_and_split "addsi_andshr16"
4555 [(set (match_operand:SI 0 "register_operand" "=D")
4556 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4558 (match_operand:SI 2 "general_operand" "0")))]
4561 "z_replacement_completed == 2"
4562 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4563 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4564 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4567 ;; 32-bit shifts are made by a small library routine that uses
4568 ;; a specific passing convention for parameters (for efficiency reasons).
4570 ;; [D + X] -> Value to be shifted
4573 ;; The shift count is clobbered by the routine.
4575 (define_expand "ashlsi3"
4577 [(set (match_operand:SI 0 "register_operand" "")
4578 (match_operand:SI 1 "general_operand" ""))
4579 (clobber (scratch:HI))])
4581 [(set (match_dup 0) (ashift:SI (match_dup 0)
4582 (match_operand:HI 2 "nonmemory_operand" "")))
4583 (clobber (scratch:HI))])]
4588 [(set (match_operand:SI 0 "nonimmediate_operand" "")
4589 (ashift:SI (match_operand:SI 1 "general_operand" "")
4591 (clobber (match_scratch:HI 3 ""))]
4593 [(set (match_dup 2) (match_dup 3))
4594 (set (match_dup 4) (const_int 0))]
4595 "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4596 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4597 operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4599 (define_insn "*ashlsi3_const16"
4600 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4601 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4603 (clobber (match_scratch:HI 2 "=X,X,X"))]
4607 (define_insn_and_split "*ashlsi3_const16_zexthi"
4608 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4609 (ashift:SI (zero_extend:HI
4610 (match_operand:HI 1 "general_operand" "duim*A"))
4612 (clobber (match_scratch:HI 2 "=X"))]
4616 [(set (reg:HI X_REGNUM) (match_dup 1))
4617 (set (reg:HI D_REGNUM) (const_int 0))]
4620 (define_insn "*ashlsi3_const1"
4621 [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
4622 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
4624 (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
4629 if (X_REG_P (operands[1]))
4631 return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4637 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4638 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4639 m68hc11_gen_movhi (insn, ops);
4640 output_asm_insn (\"lsld\", ops);
4641 if (!X_REG_P (operands[0]))
4644 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4645 m68hc11_gen_movhi (insn, ops);
4647 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4648 m68hc11_gen_movhi (insn, ops);
4652 /* Load the high part in X in case the source operand
4653 uses X as a memory pointer. */
4654 ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4655 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4656 m68hc11_gen_movhi (insn, ops);
4657 output_asm_insn (\"xgdx\", ops);
4659 output_asm_insn (\"rolb\", ops);
4660 output_asm_insn (\"rola\", ops);
4661 if (!X_REG_P (operands[0]))
4664 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4665 m68hc11_gen_movhi (insn, ops);
4669 output_asm_insn (\"xgdx\", ops);
4675 (define_insn "*ashlsi3_const"
4676 [(set (match_operand:SI 0 "register_operand" "+D")
4677 (ashift:SI (match_dup 0)
4678 (match_operand:HI 1 "const_int_operand" "")))
4679 (clobber (match_scratch:HI 2 "=y"))]
4680 "TARGET_M6811 /* See *ashlsi3 note. */"
4684 return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4687 (define_insn "*ashlsi3"
4688 [(set (match_operand:SI 0 "register_operand" "+D,D")
4689 (ashift:SI (match_dup 0)
4690 (match_operand:HI 1 "general_operand" "y,mi")))
4691 (clobber (match_scratch:HI 2 "=1,X"))]
4697 /* There is a reload problem if we don't accept 'm' for the shift value.
4698 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4699 and this conflicts with all reloads. Since X, Y, Z are used there
4700 is not enough register in class A_REGS.
4702 Assuming that 'operands[1]' does not refer to the stack (which
4703 is true for 68hc11 only, we save temporary the value of Y.
4705 For 68HC12 we must also accept a constant because Z register is
4706 disabled when compiling with -fomit-frame-pointer. We can come up
4707 with a reload problem and the *lshrsi3_const pattern was disabled
4709 if (!Y_REG_P (operands[2]))
4712 int y_dead = dead_register_here (insn, iy_reg);
4714 ops[0] = operands[1];
4717 output_asm_insn (\"pshy\", operands);
4718 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4719 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4721 output_asm_insn (\"ldy\\t%0\", ops);
4722 output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4723 return y_dead == 0 ? \"puly\" : \"\";
4725 return \"bsr\\t___ashlsi3\";
4728 (define_expand "ashlhi3"
4729 [(set (match_operand:HI 0 "register_operand" "")
4730 (ashift:HI (match_operand:HI 1 "register_operand" "")
4731 (match_operand:HI 2 "general_operand" "")))]
4735 if (GET_CODE (operands[2]) != CONST_INT)
4737 rtx scratch = gen_reg_rtx (HImode);
4738 emit_move_insn (scratch, operands[2]);
4739 emit_insn (gen_rtx_PARALLEL (VOIDmode,
4740 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4742 gen_rtx_ASHIFT (HImode,
4743 operand1, scratch)),
4744 gen_rtx_CLOBBER (VOIDmode, scratch))));
4749 (define_insn "*ashlhi3_const1"
4750 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4751 (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4756 if (A_REG_P (operands[0]))
4759 if (D_REG_P (operands[0]))
4764 output_asm_insn (\"asl\\t%b0\", operands);
4765 output_asm_insn (\"rol\\t%h0\", operands);
4771 (define_insn "*ashlhi3_2"
4772 [(set (match_operand:HI 0 "register_operand" "=d,*x")
4773 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4774 (match_operand:HI 2 "register_operand" "+x,+d")))
4775 (clobber (match_dup 2))]
4779 if (A_REG_P (operands[0]))
4783 return \"bsr\\t___lshlhi3\";
4786 (define_insn "*ashlhi3"
4787 [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4788 (ashift:HI (match_dup 0)
4789 (match_operand:HI 1 "register_operand" "+x")))
4790 (clobber (match_dup 1))]
4795 return \"bsr\\t___lshlhi3\";
4798 (define_insn "*ashlhi3"
4799 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4800 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4801 (match_operand:HI 2 "const_int_operand" "")))]
4807 if (A_REG_P (operands[0]))
4810 i = INTVAL (operands[2]);
4814 output_asm_insn (\"tba\", operands);
4817 output_asm_insn (\"rora\", operands);
4818 output_asm_insn (\"anda\\t#0\", operands);
4819 output_asm_insn (\"rora\", operands);
4824 output_asm_insn (\"asla\", operands);
4829 for (i = 0; i < INTVAL (operands[2]) - 1; i++)
4831 output_asm_insn (\"asld\", operands);
4836 (define_expand "ashlqi3"
4837 [(set (match_operand:QI 0 "register_operand" "")
4838 (ashift:QI (match_operand:QI 1 "register_operand" "")
4839 (match_operand:QI 2 "general_operand" "")))]
4843 (define_insn "*ashlqi3_const1"
4844 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4845 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4855 (define_insn "*ashlqi3_const"
4856 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4857 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4858 (match_operand:QI 2 "const_int_operand" "")))]
4863 const char* insn_code;
4865 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4866 insn_code = \"aslb\";
4867 else if (DA_REG_P (operands[0]))
4868 insn_code = \"asla\";
4872 i = INTVAL (operands[2]);
4875 if (DA_REG_P (operands[0]))
4882 if (DA_REG_P (operands[0]))
4884 output_asm_insn (\"rora\", operands);
4885 output_asm_insn (\"ldaa\\t#0\", operands);
4890 output_asm_insn (\"rorb\", operands);
4891 output_asm_insn (\"ldab\\t#0\", operands);
4897 if (DA_REG_P (operands[0]))
4899 output_asm_insn (\"rora\", operands);
4900 output_asm_insn (\"rora\", operands);
4901 output_asm_insn (\"rora\", operands);
4902 return \"anda\\t#0xC0\";
4906 output_asm_insn (\"rorb\", operands);
4907 output_asm_insn (\"rorb\", operands);
4908 output_asm_insn (\"rorb\", operands);
4909 return \"andb\\t#0xC0\";
4914 output_asm_insn (insn_code, operands);
4919 (define_insn "*ashlqi3"
4920 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4921 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4922 (match_operand:QI 2 "nonimmediate_operand"
4923 "m*u*d*A,m*u*d*A,m*u")))]
4929 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4932 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
4933 ops[1] = operands[2];
4934 m68hc11_gen_movqi (insn, ops);
4937 return \"bsr\\t___lshlqi3\";
4940 (define_expand "ashrhi3"
4941 [(set (match_operand:HI 0 "register_operand" "")
4942 (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4943 (match_operand:HI 2 "general_operand" "")))]
4947 if (GET_CODE (operands[2]) != CONST_INT)
4949 rtx scratch = gen_reg_rtx (HImode);
4951 emit_move_insn (scratch, operands[2]);
4952 emit_insn (gen_rtx_PARALLEL (VOIDmode,
4953 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4955 gen_rtx_ASHIFTRT (HImode,
4956 operand1, scratch)),
4957 gen_rtx_CLOBBER (VOIDmode, scratch))));
4962 (define_insn "*ashrhi3_const1"
4963 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4964 (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4969 if (A_REG_P (operands[0]))
4973 if (D_REG_P (operands[0]))
4975 return \"asra\\n\\trorb\";
4978 output_asm_insn (\"asr\\t%h0\", operands);
4979 output_asm_insn (\"ror\\t%b0\", operands);
4984 (define_insn "*ashrhi3_const"
4985 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4986 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4987 (match_operand:HI 2 "const_int_operand" "")))]
4992 int val = INTVAL (operands[2]);
4994 if (A_REG_P (operands[0]))
4999 ops[0] = gen_label_rtx ();
5001 output_asm_insn (\"clrb\", operands);
5002 output_asm_insn (\"rola\", operands);
5004 /* Clear A without clearing the carry flag. */
5005 output_asm_insn (\"tba\", operands);
5006 output_asm_insn (\"bcc\\t%l0\", ops);
5007 output_asm_insn (\"coma\", operands);
5008 output_asm_insn (\"comb\", operands);
5011 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5012 CODE_LABEL_NUMBER (ops[0]));
5017 ops[0] = gen_label_rtx ();
5019 output_asm_insn (\"tab\", operands);
5020 output_asm_insn (\"clra\", operands);
5021 output_asm_insn (\"tstb\", operands);
5022 output_asm_insn (\"bge\\t%l0\", ops);
5023 output_asm_insn (\"deca\", operands);
5025 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5026 CODE_LABEL_NUMBER (ops[0]));
5032 output_asm_insn (\"asrb\", operands);
5040 ops[0] = gen_label_rtx ();
5041 output_asm_insn (\"rolb\", operands);
5042 output_asm_insn (\"rola\", operands);
5043 output_asm_insn (\"tab\", operands);
5044 output_asm_insn (\"anda\\t#0\", operands);
5045 output_asm_insn (\"bcc\\t%l0\", ops);
5046 output_asm_insn (\"coma\", ops);
5048 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5049 CODE_LABEL_NUMBER (ops[0]));
5054 output_asm_insn (\"asra\", operands);
5055 output_asm_insn (\"rorb\", operands);
5063 (define_insn "*ashrhi3"
5064 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5065 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5066 (match_operand:HI 2 "register_operand" "+x,+d")))
5067 (clobber (match_dup 2))]
5071 if (A_REG_P (operands[0]))
5074 output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5078 (define_expand "ashrsi3"
5080 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5081 (clobber (scratch:HI))])
5083 [(set (match_operand:SI 0 "register_operand" "")
5084 (ashiftrt:SI (match_dup 0)
5085 (match_operand:HI 2 "general_operand" "")))
5086 (clobber (scratch:HI))])]
5090 (define_insn "*ashrsi3_const"
5091 [(set (match_operand:SI 0 "register_operand" "+D")
5092 (ashiftrt:SI (match_dup 0)
5093 (match_operand:HI 1 "const_int_operand" "")))
5094 (clobber (match_scratch:HI 2 "=y"))]
5095 "TARGET_M6811 /* See *ashrsi3 note. */"
5099 return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
5102 (define_insn "*ashrsi3"
5103 [(set (match_operand:SI 0 "register_operand" "+D,D")
5104 (ashiftrt:SI (match_dup 0)
5105 (match_operand:HI 1 "general_operand" "y,mi")))
5106 (clobber (match_scratch:HI 2 "=1,X"))]
5111 /* There is a reload problem if we don't accept 'm' for the shift value.
5112 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5113 and this conflicts with all reloads. Since X, Y, Z are used there
5114 is not enough register in class A_REGS.
5116 Assuming that 'operands[1]' does not refer to the stack (which
5117 is true for 68hc11 only, we save temporary the value of Y.
5119 For 68HC12 we must also accept a constant because Z register is
5120 disabled when compiling with -fomit-frame-pointer. We can come up
5121 with a reload problem and the *lshrsi3_const pattern was disabled
5123 if (!Y_REG_P (operands[2]))
5126 int y_dead = dead_register_here (insn, iy_reg);
5128 ops[0] = operands[1];
5131 output_asm_insn (\"pshy\", operands);
5132 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5133 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5135 output_asm_insn (\"ldy\\t%0\", ops);
5136 output_asm_insn (\"bsr\\t___ashrsi3\", operands);
5137 return y_dead == 0 ? \"puly\" : \"\";
5139 return \"bsr\\t___ashrsi3\";
5142 (define_expand "ashrqi3"
5143 [(set (match_operand:QI 0 "register_operand" "")
5144 (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5145 (match_operand:QI 2 "general_operand" "")))]
5149 (define_insn "*ashrqi3_const1"
5150 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5151 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5161 (define_insn "*ashrqi3_const"
5162 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5163 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5164 (match_operand:QI 2 "const_int_operand" "")))]
5169 const char* insn_code;
5171 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5172 insn_code = \"asrb\";
5173 else if (DA_REG_P (operands[0]))
5174 insn_code = \"asra\";
5178 i = INTVAL (operands[2]);
5183 output_asm_insn (insn_code, operands);
5188 (define_insn "*ashrqi3"
5189 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5190 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5191 (match_operand:QI 2 "nonimmediate_operand"
5192 "m*u*d*A,m*u*d*A,m*u")))]
5198 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5201 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5202 ops[1] = operands[2];
5203 m68hc11_gen_movqi (insn, ops);
5206 return \"bsr\\t___ashrqi3\";
5209 ;;--------------------------------------------------------------------
5210 ;; logical shift instructions
5211 ;;--------------------------------------------------------------------
5212 (define_expand "lshrdi3"
5213 [(parallel [(set (match_operand:DI 0 "general_operand" "")
5214 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5215 (match_operand:HI 2 "general_operand" "")))
5216 (clobber (match_scratch:HI 3 ""))])]
5220 if (GET_CODE (operands[2]) != CONST_INT
5221 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5222 && INTVAL (operands[2]) != 1))
5228 (define_insn_and_split "*lshrdi3_const32"
5229 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5230 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
5232 (clobber (match_scratch:HI 2 "=&A,d,d"))]
5237 "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5238 m68hc11_gen_highpart (SImode, operands[1]),
5240 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5241 const0_rtx, operands[2]);
5244 (define_insn "*lshrdi3_const63"
5245 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5246 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5247 (match_operand:DI 2 "const_int_operand" "")))
5248 (clobber (match_scratch:HI 3 "=d,d"))]
5249 "INTVAL (operands[2]) >= 48"
5253 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5254 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5255 (match_operand:DI 2 "const_int_operand" "")))
5256 (clobber (match_scratch:HI 3 "=d"))]
5257 "z_replacement_completed && INTVAL (operands[2]) >= 56"
5258 [(set (reg:QI D_REGNUM) (match_dup 9))
5259 (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5260 (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5261 (set (match_dup 4) (reg:HI D_REGNUM))
5262 (set (reg:QI D_REGNUM) (const_int 0))
5263 (set (match_dup 5) (reg:HI D_REGNUM))
5264 (set (match_dup 6) (reg:HI D_REGNUM))
5265 (set (match_dup 7) (reg:HI D_REGNUM))]
5266 "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
5267 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5268 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5269 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5271 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5272 operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5273 operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5275 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5276 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5277 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5280 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5281 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5282 (match_operand:DI 2 "const_int_operand" "")))
5283 (clobber (match_scratch:HI 3 "=d"))]
5284 "z_replacement_completed && INTVAL (operands[2]) >= 48
5285 && INTVAL (operands[2]) < 56"
5286 [(set (reg:HI D_REGNUM) (match_dup 9))
5287 (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5288 (set (match_dup 4) (reg:HI D_REGNUM))
5289 (set (reg:HI D_REGNUM) (const_int 0))
5290 (set (match_dup 5) (reg:HI D_REGNUM))
5291 (set (match_dup 6) (reg:HI D_REGNUM))
5292 (set (match_dup 7) (reg:HI D_REGNUM))]
5293 "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
5294 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5295 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5296 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5298 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5299 operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5300 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5301 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5302 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5304 (define_insn_and_split "*lshrdi_const1"
5305 [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5306 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5308 (clobber (match_scratch:HI 2 "=d,d"))]
5311 "z_replacement_completed == 2"
5312 [(set (match_dup 2) (match_dup 3))
5313 (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5314 (set (match_dup 4) (match_dup 2))
5316 (set (match_dup 2) (match_dup 5))
5317 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5318 (clobber (reg:HI CC_REGNUM))])
5319 (set (match_dup 6) (match_dup 2))
5321 (set (match_dup 2) (match_dup 7))
5322 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5323 (clobber (reg:HI CC_REGNUM))])
5324 (set (match_dup 8) (match_dup 2))
5326 (set (match_dup 2) (match_dup 9))
5327 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5328 (clobber (reg:HI CC_REGNUM))])
5329 (set (match_dup 10) (match_dup 2))]
5330 "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5331 operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5332 operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5334 operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5335 operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5336 operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5338 operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5339 operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5340 operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5342 operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5343 operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5344 operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5346 (define_expand "lshrsi3"
5348 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5349 (clobber (scratch:HI))])
5351 [(set (match_operand:SI 0 "register_operand" "")
5352 (lshiftrt:SI (match_dup 0)
5353 (match_operand:HI 2 "general_operand" "")))
5354 (clobber (scratch:HI))])]
5359 [(set (match_operand:SI 0 "non_push_operand" "")
5360 (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
5362 (clobber (match_scratch:HI 3 ""))]
5363 "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5364 [(set (match_dup 2) (match_dup 3))
5365 (set (match_dup 4) (const_int 0))]
5366 "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5367 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5368 operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5370 (define_insn "*lshrsi3_const16"
5371 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5372 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
5374 (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5382 (define_insn "*lshrsi3_const1"
5383 [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
5384 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
5386 (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
5391 if (X_REG_P (operands[1]))
5393 return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5399 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5400 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
5401 m68hc11_gen_movhi (insn, ops);
5402 output_asm_insn (\"lsrd\", ops);
5403 if (!X_REG_P (operands[0]))
5406 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5407 m68hc11_gen_movhi (insn, ops);
5409 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5410 m68hc11_gen_movhi (insn, ops);
5414 /* Load the lowpart in X in case the operands is some N,x. */
5415 ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
5416 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5417 m68hc11_gen_movhi (insn, ops);
5418 output_asm_insn (\"xgdx\", ops);
5420 output_asm_insn (\"rora\", ops);
5421 output_asm_insn (\"rorb\", ops);
5422 if (!X_REG_P (operands[0]))
5425 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5426 m68hc11_gen_movhi (insn, ops);
5432 (define_insn "*lshrsi3_const"
5433 [(set (match_operand:SI 0 "register_operand" "+D")
5434 (lshiftrt:SI (match_dup 0)
5435 (match_operand:HI 1 "const_int_operand" "")))
5436 (clobber (match_scratch:HI 2 "=y"))]
5437 "TARGET_M6811 /* See *lshrsi3 note. */"
5441 return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5444 (define_insn "*lshrsi3"
5445 [(set (match_operand:SI 0 "register_operand" "+D,D")
5446 (lshiftrt:SI (match_dup 0)
5447 (match_operand:HI 1 "general_operand" "y,mi")))
5448 (clobber (match_scratch:HI 2 "=1,X"))]
5453 /* There is a reload problem if we don't accept 'm' for the shift value.
5454 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5455 and this conflicts with all reloads. Since X, Y, Z are used there
5456 is not enough register in class A_REGS.
5458 Assuming that 'operands[1]' does not refer to the stack (which
5459 is true for 68hc11 only, we save temporary the value of Y.
5461 For 68HC12 we must also accept a constant because Z register is
5462 disabled when compiling with -fomit-frame-pointer. We can come up
5463 with a reload problem and the *lshrsi3_const pattern was disabled
5465 if (!Y_REG_P (operands[2]))
5468 int y_dead = dead_register_here (insn, iy_reg);
5470 ops[0] = operands[1];
5473 output_asm_insn (\"pshy\", operands);
5474 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5475 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5477 output_asm_insn (\"ldy\\t%0\", ops);
5478 output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5479 return y_dead == 0 ? \"puly\" : \"\";
5481 return \"bsr\\t___lshrsi3\";
5484 (define_expand "lshrhi3"
5485 [(set (match_operand:HI 0 "register_operand" "")
5486 (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5487 (match_operand:HI 2 "general_operand" "")))]
5491 if (GET_CODE (operands[2]) != CONST_INT)
5493 rtx scratch = gen_reg_rtx (HImode);
5494 operand1 = force_reg (HImode, operand1);
5496 emit_move_insn (scratch, operands[2]);
5497 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5498 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5500 gen_rtx_LSHIFTRT (HImode,
5501 operand1, scratch)),
5502 gen_rtx_CLOBBER (VOIDmode, scratch))));
5507 (define_insn "lshrhi3_const1"
5508 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5509 (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5514 if (A_REG_P (operands[0]))
5517 if (D_REG_P (operands[0]))
5521 return \"lsr\\t%h0\\n\\tror\\t%b0\";
5524 (define_insn "lshrhi3_const"
5525 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5526 (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5527 (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5531 int val = INTVAL (operands[2]);
5533 if (A_REG_P (operands[0]))
5541 if (!H_REG_P (operands[1]))
5543 output_asm_insn (\"clra\", operands);
5544 output_asm_insn (\"ldab\\t%h1\", operands);
5546 else if (A_REG_P (operands[1]))
5548 output_asm_insn (\"st%1\\t%t0\", operands);
5549 output_asm_insn (\"ldab\\t%t0\", operands);
5550 output_asm_insn (\"clra\", operands);
5554 output_asm_insn (\"tab\", operands);
5555 output_asm_insn (\"clra\", operands);
5561 output_asm_insn (\"rolb\", operands);
5562 output_asm_insn (\"tab\", operands);
5563 output_asm_insn (\"rolb\", operands);
5567 output_asm_insn (\"rolb\", operands);
5568 output_asm_insn (\"rolb\", operands);
5569 output_asm_insn (\"rolb\", operands);
5570 output_asm_insn (\"andb\\t#3\", operands);
5577 output_asm_insn (\"lsrb\", operands);
5584 if (!D_REG_P (operands[1]))
5585 m68hc11_gen_movhi (insn, operands);
5589 output_asm_insn (\"rolb\", operands);
5590 output_asm_insn (\"tab\", operands);
5591 output_asm_insn (\"rolb\", operands);
5592 output_asm_insn (\"rola\", operands);
5593 output_asm_insn (\"rola\", operands);
5594 output_asm_insn (\"anda\\t#1\", operands);
5602 output_asm_insn (\"lsrd\", operands);
5608 (define_insn "*lshrhi3"
5609 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5610 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5611 (match_operand:HI 2 "register_operand" "+x,+d")))
5612 (clobber (match_dup 2))]
5616 if (A_REG_P (operands[0]))
5619 return \"bsr\\t___lshrhi3\";
5622 (define_expand "lshrqi3"
5623 [(set (match_operand:QI 0 "register_operand" "")
5624 (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5625 (match_operand:QI 2 "general_operand" "")))]
5629 (define_insn "*lshrqi3_const1"
5630 [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5631 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5641 (define_insn "*lshrqi3_const"
5642 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5643 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5644 (match_operand:QI 2 "const_int_operand" "")))]
5649 const char* insn_code;
5651 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5652 insn_code = \"lsrb\";
5653 else if (DA_REG_P (operands[0]))
5654 insn_code = \"lsra\";
5658 i = INTVAL (operands[2]);
5661 if (DA_REG_P (operands[0]))
5668 if (DA_REG_P (operands[0]))
5670 output_asm_insn (\"rola\", operands);
5671 output_asm_insn (\"ldaa\\t#0\", operands);
5676 output_asm_insn (\"rolb\", operands);
5677 output_asm_insn (\"ldab\\t#0\", operands);
5683 if (DA_REG_P (operands[0]))
5685 output_asm_insn (\"rola\", operands);
5686 output_asm_insn (\"rola\", operands);
5687 output_asm_insn (\"rola\", operands);
5688 return \"anda\\t#3\";
5692 output_asm_insn (\"rolb\", operands);
5693 output_asm_insn (\"rolb\", operands);
5694 output_asm_insn (\"rolb\", operands);
5695 return \"andb\\t#3\";
5700 output_asm_insn (insn_code, operands);
5705 (define_insn "*lshrqi3"
5706 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5707 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5708 (match_operand:QI 2 "nonimmediate_operand"
5709 "m*u*d*A,m*u*d*A,m*u")))]
5715 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5719 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5720 ops[1] = operands[2];
5721 m68hc11_gen_movqi (insn, ops);
5723 if (!optimize || optimize_size)
5725 return \"bsr\\t___lshrqi3\";
5728 ops[0] = gen_label_rtx ();
5729 ops[1] = gen_label_rtx ();
5730 output_asm_insn (\"ble\\t%l1\", ops);
5732 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5733 CODE_LABEL_NUMBER (ops[0]));
5735 output_asm_insn (\"lsrb\", operands);
5736 output_asm_insn (\"deca\", operands);
5737 output_asm_insn (\"bne\\t%l0\", ops);
5739 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5740 CODE_LABEL_NUMBER (ops[1]));
5744 (define_insn "*rotlqi3_with_carry"
5745 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5746 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5747 (reg:QI CC_REGNUM)))]
5751 if (DA_REG_P (operands[0]))
5757 (define_insn "*rotlhi3_with_carry"
5758 [(set (match_operand:HI 0 "register_operand" "=d")
5759 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5761 (clobber (reg:HI CC_REGNUM))]
5766 return \"rolb\\n\\trola\";
5769 (define_insn "*rotrhi3_with_carry"
5770 [(set (match_operand:HI 0 "register_operand" "=d")
5771 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5773 (clobber (reg:HI CC_REGNUM))]
5778 return \"rora\\n\\trorb\";
5781 (define_insn "rotlqi3"
5782 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5783 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5784 (match_operand:QI 2 "const_int_operand" "i,i")))]
5788 m68hc11_gen_rotate (ROTATE, insn, operands);
5792 (define_insn "rotrqi3"
5793 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5794 (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5795 (match_operand:QI 2 "const_int_operand" "i,i")))]
5799 m68hc11_gen_rotate (ROTATERT, insn, operands);
5803 (define_expand "rotlhi3"
5804 [(set (match_operand:HI 0 "register_operand" "")
5805 (rotate:HI (match_operand:HI 1 "register_operand" "")
5806 (match_operand:HI 2 "general_operand" "")))]
5810 if (GET_CODE (operands[2]) != CONST_INT)
5812 rtx scratch = gen_reg_rtx (HImode);
5813 operand1 = force_reg (HImode, operand1);
5815 emit_move_insn (scratch, operands[2]);
5816 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5817 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5819 gen_rtx_ROTATE (HImode,
5820 operand1, scratch)),
5821 gen_rtx_CLOBBER (VOIDmode, scratch))));
5826 (define_insn "rotlhi3_const"
5827 [(set (match_operand:HI 0 "register_operand" "=d")
5828 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5829 (match_operand:HI 2 "const_int_operand" "i")))]
5833 m68hc11_gen_rotate (ROTATE, insn, operands);
5837 (define_insn "*rotlhi3"
5838 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5839 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
5840 (match_operand:HI 2 "general_operand" "+x,+d")))
5841 (clobber (match_dup 2))]
5845 if (A_REG_P (operands[0]))
5848 return \"bsr\\t___rotlhi3\";
5851 (define_expand "rotrhi3"
5852 [(set (match_operand:HI 0 "register_operand" "")
5853 (rotatert:HI (match_operand:HI 1 "general_operand" "")
5854 (match_operand:HI 2 "general_operand" "")))]
5858 if (GET_CODE (operands[2]) != CONST_INT)
5860 rtx scratch = gen_reg_rtx (HImode);
5861 operand1 = force_reg (HImode, operand1);
5863 emit_move_insn (scratch, operands[2]);
5864 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5865 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5867 gen_rtx_ROTATERT (HImode,
5868 operand1, scratch)),
5869 gen_rtx_CLOBBER (VOIDmode, scratch))));
5874 (define_insn "rotrhi3_const"
5875 [(set (match_operand:HI 0 "register_operand" "=d")
5876 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5877 (match_operand:HI 2 "const_int_operand" "i")))]
5881 m68hc11_gen_rotate (ROTATERT, insn, operands);
5885 (define_insn "*rotrhi3"
5886 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5887 (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
5888 (match_operand:HI 2 "general_operand" "+x,+d")))
5889 (clobber (match_dup 2))]
5893 if (A_REG_P (operands[0]))
5896 return \"bsr\\t___rotrhi3\";
5899 ;; Split a shift operation on an address register in a shift
5901 (define_split /* "*rotrhi3_addr" */
5902 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
5903 (match_operator:HI 3 "m68hc11_shift_operator"
5904 [(match_operand:HI 1 "register_operand" "")
5905 (match_operand:HI 2 "register_operand" "")]))
5906 (clobber (match_dup 2))]
5907 "z_replacement_completed == 2"
5908 [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5909 (set (match_dup 0) (reg:HI D_REGNUM))])
5910 (parallel [(set (reg:HI D_REGNUM)
5911 (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
5912 (clobber (match_dup 0))])
5913 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5914 (set (match_dup 0) (reg:HI D_REGNUM))])]
5917 ;;--------------------------------------------------------------------
5918 ;;- 68HC12 Decrement/Increment and branch
5919 ;;--------------------------------------------------------------------
5920 ;; These patterns are used by loop optimization as well as peephole2
5921 ;; They must handle reloading themselves and the scratch register
5922 ;; is used for that. Even if we accept memory operand, we must not
5923 ;; accept them on the predicate because it might create too many reloads.
5924 ;; (specially on HC12 due to its auto-incdec addressing modes).
5926 (define_expand "decrement_and_branch_until_zero"
5927 [(parallel [(set (pc)
5929 (ne (plus:HI (match_operand:HI 0 "register_operand" "")
5932 (label_ref (match_operand 1 "" ""))
5935 (plus:HI (match_dup 0)
5937 (clobber (match_scratch:HI 2 ""))])]
5941 (define_expand "doloop_end"
5942 [(use (match_operand 0 "" "")) ; loop pseudo
5943 (use (match_operand 1 "" "")) ; iterations; zero if unknown
5944 (use (match_operand 2 "" "")) ; max iterations
5945 (use (match_operand 3 "" "")) ; loop level
5946 (use (match_operand 4 "" ""))] ; label
5950 /* Reject non-constant loops as it generates bigger code due to
5951 the handling of the loop register. We can do better by using
5952 the peephole2 dbcc/ibcc patterns. */
5953 if (INTVAL (operands[1]) == 0)
5958 /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
5959 the operator and its operands are not relevant. */
5960 if (GET_MODE (operands[0]) == HImode)
5962 emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
5969 if (GET_MODE (operands[0]) == QImode)
5971 emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
5982 ;; Decrement-and-branch insns.
5983 (define_insn "m68hc12_dbcc_dec_hi"
5986 (match_operator 1 "m68hc11_eq_compare_operator"
5987 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5989 (label_ref (match_operand 2 "" ""))
5992 (plus:HI (match_dup 0) (const_int -1)))
5993 (clobber (match_scratch:HI 3 "=X,dxy"))]
5997 if (!H_REG_P (operands[0]))
6001 if (GET_CODE (operands[1]) == EQ)
6002 return \"dbeq\\t%0,%l2\";
6004 return \"dbne\\t%0,%l2\";
6007 ;; Decrement-and-branch insns.
6008 (define_insn "m68hc12_dbcc_inc_hi"
6011 (match_operator 1 "m68hc11_eq_compare_operator"
6012 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
6014 (label_ref (match_operand 2 "" ""))
6017 (plus:HI (match_dup 0) (const_int 1)))
6018 (clobber (match_scratch:HI 3 "=X,dxy"))]
6022 if (!H_REG_P (operands[0]))
6026 if (GET_CODE (operands[1]) == EQ)
6027 return \"ibeq\\t%0,%l2\";
6029 return \"ibeq\\t%0,%l2\";
6032 ;; Decrement-and-branch (QImode).
6033 (define_insn "m68hc12_dbcc_dec_qi"
6036 (match_operator 1 "m68hc11_eq_compare_operator"
6037 [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6039 (label_ref (match_operand 2 "" ""))
6042 (plus:QI (match_dup 0) (const_int -1)))
6043 (clobber (match_scratch:QI 3 "=X,d"))]
6047 if (!D_REG_P (operands[0]))
6051 if (GET_CODE (operands[1]) == EQ)
6052 return \"dbeq\\tb,%l2\";
6054 return \"dbne\\tb,%l2\";
6057 ;; Increment-and-branch (QImode).
6058 (define_insn "m68hc12_dbcc_inc_qi"
6061 (match_operator 1 "m68hc11_eq_compare_operator"
6062 [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6064 (label_ref (match_operand 2 "" ""))
6067 (plus:QI (match_dup 0) (const_int 1)))
6068 (clobber (match_scratch:QI 3 "=X,d"))]
6072 if (!D_REG_P (operands[0]))
6076 if (GET_CODE (operands[1]) == EQ)
6077 return \"ibeq\\tb,%l2\";
6079 return \"ibeq\\tb,%l2\";
6082 ;; Split the above to handle the case where operand 0 is in memory
6083 ;; (a register that couldn't get a hard register)
6087 (match_operator 3 "m68hc11_eq_compare_operator"
6088 [(match_operand:HI 0 "general_operand" "")
6089 (match_operand:HI 1 "const_int_operand" "")])
6090 (label_ref (match_operand 4 "" ""))
6093 (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6094 (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
6095 "TARGET_M6812 && reload_completed"
6096 [(set (match_dup 5) (match_dup 0))
6097 (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
6098 (set (match_dup 0) (match_dup 5))
6100 (if_then_else (match_op_dup 3
6101 [(match_dup 5) (const_int 0)])
6102 (label_ref (match_dup 4)) (pc)))]
6105 ;; Split the above to handle the case where operand 0 is in memory
6106 ;; (a register that couldn't get a hard register)
6110 (match_operator 3 "m68hc11_eq_compare_operator"
6111 [(match_operand:QI 0 "general_operand" "")
6112 (match_operand:QI 1 "const_int_operand" "")])
6113 (label_ref (match_operand 4 "" ""))
6116 (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6117 (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
6118 "TARGET_M6812 && reload_completed"
6119 [(set (match_dup 5) (match_dup 0))
6120 (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
6121 (set (match_dup 0) (match_dup 5))
6123 (if_then_else (match_op_dup 3
6124 [(match_dup 5) (const_int 0)])
6125 (label_ref (match_dup 4)) (pc)))]
6128 ;;--------------------------------------------------------------------
6129 ;;- Jumps and transfers
6130 ;;--------------------------------------------------------------------
6133 (label_ref (match_operand 0 "" "")))]
6137 (define_expand "beq"
6139 (if_then_else (eq (cc0)
6141 (label_ref (match_operand 0 "" ""))
6146 m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
6147 m68hc11_compare_op1,
6152 (define_expand "bne"
6154 (if_then_else (ne (cc0)
6156 (label_ref (match_operand 0 "" ""))
6161 m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
6162 m68hc11_compare_op1,
6167 (define_expand "bgt"
6169 (if_then_else (gt (cc0)
6171 (label_ref (match_operand 0 "" ""))
6176 m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
6177 m68hc11_compare_op1,
6182 (define_expand "bgtu"
6184 (if_then_else (gtu (cc0)
6186 (label_ref (match_operand 0 "" ""))
6191 m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
6192 m68hc11_compare_op1,
6197 (define_expand "blt"
6199 (if_then_else (lt (cc0)
6201 (label_ref (match_operand 0 "" ""))
6206 m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
6207 m68hc11_compare_op1,
6212 (define_expand "bltu"
6214 (if_then_else (ltu (cc0)
6216 (label_ref (match_operand 0 "" ""))
6221 m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
6222 m68hc11_compare_op1,
6227 (define_expand "bge"
6229 (if_then_else (ge (cc0)
6231 (label_ref (match_operand 0 "" ""))
6236 m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
6237 m68hc11_compare_op1,
6242 (define_expand "bgeu"
6244 (if_then_else (geu (cc0)
6246 (label_ref (match_operand 0 "" ""))
6251 m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
6252 m68hc11_compare_op1,
6257 (define_expand "ble"
6259 (if_then_else (le (cc0)
6261 (label_ref (match_operand 0 "" ""))
6266 m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
6267 m68hc11_compare_op1,
6272 (define_expand "bleu"
6274 (if_then_else (leu (cc0)
6276 (label_ref (match_operand 0 "" ""))
6281 m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
6282 m68hc11_compare_op1,
6288 ;; Test and branch instructions for 68HC12 for EQ and NE.
6289 ;; 'z' must not appear in the constraints because the z replacement
6290 ;; pass does not know how to restore the replacement register.
6292 (define_insn "*tbeq"
6294 (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
6296 (label_ref (match_operand 1 "" ""))
6301 /* If the flags are already set correctly, use 'bne/beq' which are
6302 smaller and a little bit faster. This happens quite often due
6303 to reloading of operands[0]. In that case, flags are set correctly
6304 due to the load instruction. */
6305 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6306 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6307 return \"beq\\t%l1\";
6309 return \"tbeq\\t%0,%l1\";
6312 (define_insn "*tbne"
6314 (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6316 (label_ref (match_operand 1 "" ""))
6321 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6322 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6323 return \"bne\\t%l1\";
6325 return \"tbne\\t%0,%l1\";
6329 ;; Test and branch with 8-bit register. Register must be B (or A).
6331 (define_insn "*tbeq8"
6333 (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6335 (label_ref (match_operand 1 "" ""))
6340 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6341 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6342 return \"beq\\t%l1\";
6344 return \"tbeq\\tb,%l1\";
6347 (define_insn "*tbne8"
6349 (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6351 (label_ref (match_operand 1 "" ""))
6356 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6357 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6358 return \"bne\\t%l1\";
6360 return \"tbne\\tb,%l1\";
6365 (if_then_else (eq (cc0)
6367 (label_ref (match_operand 0 "" ""))
6374 (if_then_else (ne (cc0)
6376 (label_ref (match_operand 0 "" ""))
6383 (if_then_else (gt (cc0)
6385 (label_ref (match_operand 0 "" ""))
6390 (define_insn "*bgtu"
6392 (if_then_else (gtu (cc0)
6394 (label_ref (match_operand 0 "" ""))
6401 (if_then_else (lt (cc0)
6403 (label_ref (match_operand 0 "" ""))
6408 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6409 return \"bmi\\t%l0\";
6411 return \"blt\\t%l0\";
6414 (define_insn "*bltu"
6416 (if_then_else (ltu (cc0)
6418 (label_ref (match_operand 0 "" ""))
6425 (if_then_else (ge (cc0)
6427 (label_ref (match_operand 0 "" ""))
6432 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6433 return \"bpl\\t%l0\";
6435 return \"bge\\t%l0\";
6438 (define_insn "*bgeu"
6440 (if_then_else (geu (cc0)
6442 (label_ref (match_operand 0 "" ""))
6449 (if_then_else (le (cc0)
6451 (label_ref (match_operand 0 "" ""))
6456 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6457 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6459 return \"ble\\t%l0\";
6462 (define_insn "*bleu"
6464 (if_then_else (leu (cc0)
6466 (label_ref (match_operand 0 "" ""))
6471 ;;--------------------------------------------------------------------
6472 ;;- Negative test and branch
6473 ;;--------------------------------------------------------------------
6476 (if_then_else (eq (cc0)
6479 (label_ref (match_operand 0 "" ""))))]
6485 (if_then_else (ne (cc0)
6488 (label_ref (match_operand 0 "" ""))))]
6494 (if_then_else (gt (cc0)
6497 (label_ref (match_operand 0 "" ""))))]
6501 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6502 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6504 return \"ble\\t%l0\";
6509 (if_then_else (gtu (cc0)
6512 (label_ref (match_operand 0 "" ""))))]
6518 (if_then_else (lt (cc0)
6521 (label_ref (match_operand 0 "" ""))))]
6525 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6526 return \"bpl\\t%l0\";
6528 return \"bge\\t%l0\";
6533 (if_then_else (ltu (cc0)
6536 (label_ref (match_operand 0 "" ""))))]
6542 (if_then_else (ge (cc0)
6545 (label_ref (match_operand 0 "" ""))))]
6549 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6550 return \"bmi\\t%l0\";
6552 return \"blt\\t%l0\";
6557 (if_then_else (geu (cc0)
6560 (label_ref (match_operand 0 "" ""))))]
6566 (if_then_else (le (cc0)
6569 (label_ref (match_operand 0 "" ""))))]
6575 (if_then_else (leu (cc0)
6578 (label_ref (match_operand 0 "" ""))))]
6582 ;;--------------------------------------------------------------------
6584 ;;--------------------------------------------------------------------
6586 ;;- Call a function that returns no value.
6588 [(call (match_operand:QI 0 "memory_operand" "m")
6589 (match_operand:SI 1 "general_operand" "g"))]
6590 ;; Operand 1 not really used on the m68hc11.
6594 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6596 if (m68hc11_is_far_symbol (operands[0]))
6600 output_asm_insn (\"call\\t%0\", operands);
6605 output_asm_insn (\"pshb\", operands);
6606 output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
6607 output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
6608 return \"jsr\\t__call_a32\";
6611 if (m68hc11_is_trap_symbol (operands[0]))
6614 return \"bsr\\t%0\";
6618 return \"jsr\\t%0\";
6622 (define_insn "call_value"
6623 [(set (match_operand 0 "" "=g")
6624 (call (match_operand:QI 1 "memory_operand" "m")
6625 (match_operand:SI 2 "general_operand" "g")))]
6629 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6631 if (m68hc11_is_far_symbol (operands[1]))
6635 output_asm_insn (\"call\\t%1\", operands);
6640 output_asm_insn (\"pshb\", operands);
6641 output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
6642 output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
6643 return \"jsr\\t__call_a32\";
6646 if (m68hc11_is_trap_symbol (operands[1]))
6649 return \"bsr\\t%1\";
6653 return \"jsr\\t%1\";
6657 ;; Call subroutine returning any type.
6659 (define_expand "untyped_call"
6660 [(parallel [(call (match_operand 0 "" "")
6662 (match_operand 1 "" "")
6663 (match_operand 2 "" "")])]
6669 emit_call_insn (gen_call (operands[0], const0_rtx));
6671 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6673 rtx set = XVECEXP (operands[2], 0, i);
6674 emit_move_insn (SET_DEST (set), SET_SRC (set));
6677 /* The optimizer does not know that the call sets the function value
6678 registers we stored in the result block. We avoid problems by
6679 claiming that all hard registers are used and clobbered at this
6681 emit_insn (gen_blockage ());
6686 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6687 ;; all of memory. This blocks insns from being moved across this point.
6689 (define_insn "blockage"
6690 [(unspec_volatile [(const_int 0)] 0)]
6699 (define_expand "prologue"
6708 (define_expand "epilogue"
6717 ;; Used for frameless functions which save no regs and allocate no locals.
6718 (define_expand "return"
6720 "reload_completed && m68hc11_total_frame_size () == 0"
6725 if (crtl->return_rtx)
6726 ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
6728 /* Emit use notes only when HAVE_return is true. */
6729 if (m68hc11_total_frame_size () != 0)
6732 if (ret_size && ret_size <= 2)
6734 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6735 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6736 gen_rtx_USE (VOIDmode,
6737 gen_rtx_REG (HImode, 1)))));
6742 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6743 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6744 gen_rtx_USE (VOIDmode,
6745 gen_rtx_REG (SImode, 0)))));
6750 (define_insn "*return_void"
6755 rtx next = next_active_insn (insn);
6758 && GET_CODE (next) == JUMP_INSN
6759 && GET_CODE (PATTERN (next)) == RETURN)
6761 if (current_function_interrupt || current_function_trap)
6763 else if (!current_function_far)
6765 else if (TARGET_M6812)
6771 if (crtl->return_rtx)
6772 ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
6775 return \"jmp\\t__return_void\";
6777 return \"jmp\\t__return_16\";
6779 return \"jmp\\t__return_32\";
6780 return \"jmp\\t__return_16\";
6784 (define_insn "*return_16bit"
6786 (use (reg:HI D_REGNUM))]
6787 "reload_completed && m68hc11_total_frame_size () == 0"
6790 rtx next = next_active_insn (insn);
6793 && GET_CODE (next) == JUMP_INSN
6794 && GET_CODE (PATTERN (next)) == RETURN)
6796 if (current_function_interrupt || current_function_trap)
6798 else if (!current_function_far)
6800 else if (TARGET_M6812)
6803 return \"jmp\\t__return_16\";
6806 (define_insn "*return_32bit"
6809 "reload_completed && m68hc11_total_frame_size () == 0"
6812 rtx next = next_active_insn (insn);
6815 && GET_CODE (next) == JUMP_INSN
6816 && GET_CODE (PATTERN (next)) == RETURN)
6818 if (current_function_interrupt || current_function_trap)
6820 else if (!current_function_far)
6822 else if (TARGET_M6812)
6825 return \"jmp\\t__return_32\";
6828 (define_insn "indirect_jump"
6829 [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6833 ;;--------------------------------------------------------------------
6835 ;;--------------------------------------------------------------------
6837 ;; Operand 0 is the address of the table element to use
6838 ;; operand 1 is the CODE_LABEL for the table
6839 ;;--------------------------------------------------------------------
6840 (define_expand "tablejump"
6841 [(parallel [(set (pc) (match_operand 0 "" ""))
6842 (use (label_ref (match_operand 1 "" "")))])]
6846 (define_insn "*jump_indirect"
6848 (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6849 (use (label_ref (match_operand 1 "" "")))])]
6853 ;;--------------------------------------------------------------------
6855 ;;--------------------------------------------------------------------
6857 ;;--------------------------------------------------------------------
6858 ;;- 68HC12 dbcc/ibcc peepholes
6859 ;;--------------------------------------------------------------------
6861 ;; Replace: "addd #-1; bne L1" into "dbne d,L1"
6862 ;; "addd #-1; beq L1" into "dbeq d,L1"
6863 ;; "addd #1; bne L1" into "ibne d,L1"
6864 ;; "addd #1; beq L1" into "ibeq d,L1"
6867 [(set (match_operand:HI 0 "hard_reg_operand" "")
6868 (plus:HI (match_dup 0)
6869 (match_operand:HI 1 "const_int_operand" "")))
6871 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6874 (label_ref (match_operand 3 "" "")) (pc)))]
6875 "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6877 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6878 (label_ref (match_dup 3)) (pc)))
6879 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
6880 (clobber (match_dup 4))])]
6881 "operands[4] = gen_rtx_SCRATCH(HImode);
6882 operands[5] = GEN_INT (-INTVAL (operands[1]));")
6886 ;; Replace: "addb #-1; bne L1" into "dbne b,L1"
6887 ;; "addb #-1; beq L1" into "dbeq b,L1"
6890 [(set (match_operand:QI 0 "hard_reg_operand" "")
6891 (plus:QI (match_dup 0)
6892 (match_operand:QI 1 "const_int_operand" "")))
6894 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6897 (label_ref (match_operand 3 "" "")) (pc)))]
6898 "TARGET_M6812 && D_REG_P (operands[0])
6899 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6901 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6902 (label_ref (match_dup 3)) (pc)))
6903 (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
6904 (clobber (match_dup 4))])]
6905 "operands[4] = gen_rtx_SCRATCH(QImode);
6906 operands[5] = GEN_INT (-INTVAL (operands[1]));")
6909 ;;--------------------------------------------------------------------
6911 ;;--------------------------------------------------------------------
6914 ;; Replace "leas 2,sp" with a "pulx" or a "puly".
6915 ;; On 68HC12, this is one cycle slower but one byte smaller.
6916 ;; pr target/6899: This peephole was not valid because a register CSE
6917 ;; pass removes the pulx/puly. The 'use' clause ensure that the pulx is
6921 [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6922 (match_scratch:HI 0 "xy")]
6923 "TARGET_M6812 && optimize_size"
6924 [(set (match_dup 0) (match_dup 1))
6925 (use (match_dup 0))]
6926 "operands[1] = gen_rtx_MEM (HImode,
6927 gen_rtx_POST_INC (HImode,
6928 gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
6930 ;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
6932 ;; PR 14542: emit a use to pretend we need the value of initial register.
6933 ;; Otherwise verify_local_live_at_start will die due to a live change
6934 ;; of that register.
6937 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6938 (match_operand:HI 0 "hard_reg_operand" ""))
6940 (match_operand:HI 1 "hard_reg_operand" ""))
6941 (set (mem:HI (reg:HI SP_REGNUM))
6944 [(use (match_dup 0))
6945 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6947 (set (match_dup 0) (match_dup 1))]
6951 ;; Change: "ldd 0,sp; pulx" into "puld"
6952 ;; This sequence usually appears at end a functions.
6954 [(set (match_operand:HI 0 "hard_reg_operand" "")
6955 (mem:HI (reg:HI SP_REGNUM)))
6957 (set (match_operand:HI 1 "hard_reg_operand" "")
6958 (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
6959 "peep2_reg_dead_p (2, operands[1])"
6960 [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
6961 (use (match_dup 0))]
6964 ;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
6965 ;; Appears to allocate local variables.
6967 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6968 (match_operand:HI 0 "hard_reg_operand" ""))
6969 (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
6971 (set (mem:QI (reg:HI SP_REGNUM))
6974 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6978 ;; Likewise for HI mode
6980 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6981 (match_operand:HI 0 "hard_reg_operand" ""))
6982 (set (mem:HI (reg:HI SP_REGNUM))
6985 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6988 ;;--------------------------------------------------------------------
6990 ;;--------------------------------------------------------------------
6992 ;; Optimize memory<->memory moves when the value is also loaded in
6996 [(set (match_operand:QI 0 "memory_operand" "")
6997 (match_operand:QI 1 "memory_operand" ""))
6998 (set (reg:QI D_REGNUM)
6999 (match_operand:QI 2 "memory_operand" ""))]
7000 "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
7001 || (GET_CODE (XEXP (operands[0], 0)) == REG
7002 && GET_CODE (XEXP (operands[2], 0)) == POST_INC
7003 && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
7004 [(set (reg:QI D_REGNUM) (match_dup 1))
7005 (set (match_dup 2) (reg:QI D_REGNUM))]
7009 ;; Remove a possible move before a compare instruction when that
7010 ;; move will go in a dead register. Compare with the source then.
7013 [(set (match_operand:HI 0 "hard_reg_operand" "")
7014 (match_operand:HI 1 "hard_reg_operand" ""))
7016 (compare (match_dup 0)
7017 (match_operand:HI 2 "cmp_operand" "")))]
7018 "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
7019 && peep2_reg_dead_p (2, operands[0])
7020 && !reg_mentioned_p (operands[0], operands[2])"
7021 [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
7025 ;; Optimize loading a constant to memory when that same constant
7026 ;; is loaded to a hard register. Switch the two to use the register
7027 ;; for memory initialization. In most cases, the constant is 0.
7030 [(set (match_operand:HI 0 "memory_operand" "")
7031 (match_operand:HI 1 "immediate_operand" ""))
7032 (set (match_operand:HI 2 "hard_reg_operand" "")
7034 "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
7035 && !reg_mentioned_p (operands[2], operands[0])"
7036 [(set (match_dup 2) (match_dup 1))
7037 (set (match_dup 0) (match_dup 2))]
7041 ;; Reorganize to optimize address computations.
7044 [(set (match_operand:HI 0 "hard_reg_operand" "")
7045 (match_operand:HI 1 "const_int_operand" ""))
7047 (plus:HI (match_dup 0)
7048 (match_operand:HI 2 "general_operand" "")))]
7049 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7050 [(set (match_dup 0) (match_dup 2))
7051 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7055 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7058 [(set (match_operand:HI 0 "hard_reg_operand" "")
7059 (match_operand:HI 1 "const_int_operand" ""))
7061 (plus:HI (match_dup 0)
7062 (match_operand:HI 2 "general_operand" "")))
7063 (match_scratch:QI 3 "d")]
7064 "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
7065 [(set (match_dup 3) (match_dup 4))
7066 (set (match_dup 0) (match_dup 2))
7067 (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
7068 "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
7071 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7074 [(set (match_operand:HI 0 "hard_reg_operand" "")
7075 (match_operand:HI 1 "const_int_operand" ""))
7077 (plus:HI (match_dup 0)
7078 (match_operand:HI 2 "general_operand" "")))]
7080 [(set (match_dup 0) (match_dup 2))
7081 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7085 ;; Optimize an address register increment and a compare to use
7086 ;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
7087 ;; before reload, but can be enabled after).
7090 [(set (match_operand:HI 0 "hard_reg_operand" "")
7091 (plus:HI (match_dup 0)
7092 (match_operand:HI 1 "const_int_operand" "")))
7094 (match_operand:QI 2 "memory_operand" ""))]
7095 "TARGET_AUTO_INC_DEC
7096 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7097 && reg_mentioned_p (operands[0], operands[2])"
7098 [(set (cc0) (match_dup 3))]
7099 "if (INTVAL (operands[1]) == 1)
7100 operands[3] = gen_rtx_MEM (QImode,
7101 gen_rtx_PRE_INC (HImode, operands[0]));
7103 operands[3] = gen_rtx_MEM (QImode,
7104 gen_rtx_PRE_DEC (HImode, operands[0]));
7108 ;; Likewise for compare.
7111 [(set (match_operand:HI 0 "hard_reg_operand" "")
7112 (plus:HI (match_dup 0)
7113 (match_operand:HI 1 "const_int_operand" "")))
7115 (compare (match_operand:QI 2 "hard_reg_operand" "")
7116 (match_operand:QI 3 "memory_operand" "")))]
7117 "TARGET_AUTO_INC_DEC
7118 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7119 && reg_mentioned_p (operands[0], operands[3])"
7120 [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
7121 "if (INTVAL (operands[1]) == 1)
7122 operands[4] = gen_rtx_MEM (QImode,
7123 gen_rtx_PRE_INC (HImode, operands[0]));
7125 operands[4] = gen_rtx_MEM (QImode,
7126 gen_rtx_PRE_DEC (HImode, operands[0]));
7130 [(set (match_operand:HI 0 "hard_reg_operand" "")
7131 (plus:HI (match_dup 0)
7132 (match_operand:HI 1 "const_int_operand" "")))
7134 (compare (match_operand:QI 2 "memory_operand" "")
7135 (match_operand:QI 3 "hard_reg_operand" "")))]
7136 "TARGET_AUTO_INC_DEC
7137 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7138 && reg_mentioned_p (operands[0], operands[2])"
7139 [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
7140 "if (INTVAL (operands[1]) == 1)
7141 operands[4] = gen_rtx_MEM (QImode,
7142 gen_rtx_PRE_INC (HImode, operands[0]));
7144 operands[4] = gen_rtx_MEM (QImode,
7145 gen_rtx_PRE_DEC (HImode, operands[0]));
7149 ;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
7150 ;; (avoids many temporary moves because we can't add sp to another reg easily)
7153 [(set (match_operand:HI 0 "hard_reg_operand" "")
7154 (match_operand:HI 1 "const_int_operand" ""))
7155 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7157 [(set (match_dup 0) (reg:HI SP_REGNUM))
7158 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7162 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7165 [(set (match_operand:HI 0 "hard_reg_operand" "")
7166 (match_operand:HI 1 "const_int_operand" ""))
7168 (plus:HI (match_dup 0)
7169 (match_operand:HI 2 "general_operand" "")))]
7170 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7171 [(set (match_dup 0) (match_dup 2))
7172 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7180 [(set (match_operand:SI 0 "hard_reg_operand" "")
7181 (ashift:SI (match_operand:SI 1 "general_operand" "")
7183 (clobber (match_scratch:HI 2 ""))])
7184 (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
7185 (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
7186 "!X_REG_P (operands[1])
7187 && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
7188 && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
7189 [(set (reg:HI D_REGNUM) (match_dup 5))
7190 (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
7191 (set (match_dup 3) (reg:HI D_REGNUM))
7192 (set (reg:HI D_REGNUM) (match_dup 6))
7193 (parallel [(set (reg:HI D_REGNUM)
7194 (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
7195 (clobber (reg:HI CC_REGNUM))])
7196 (set (match_dup 4) (reg:HI D_REGNUM))]
7197 "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
7198 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
7201 ;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
7204 [(set (match_operand:HI 0 "hard_reg_operand" "")
7205 (match_operand:HI 1 "memory_operand" ""))
7206 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
7208 (match_scratch:HI 2 "x")]
7209 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
7210 [(set (match_dup 2) (match_dup 1))
7211 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
7215 ;; Remove one load when copying a value to/from memory and also
7216 ;; to a register. Take care not clobbering a possible register used
7218 ;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
7221 [(set (match_operand:HI 0 "hard_reg_operand" "")
7222 (match_operand:HI 1 "general_operand" ""))
7223 (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
7224 (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
7225 "peep2_reg_dead_p (2, operands[0])
7226 && !side_effects_p (operands[1])
7227 && !side_effects_p (operands[2])
7228 && !reg_mentioned_p (operands[3], operands[2])"
7229 [(set (match_dup 3) (match_dup 1))
7230 (set (match_dup 2) (match_dup 3))]
7234 ;; Replace a "ldd <mem>; addd #N; std <mem>" into a
7235 ;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
7236 ;; and the constant is small.
7239 [(set (match_operand:HI 0 "hard_reg_operand" "")
7240 (match_operand:HI 1 "general_operand" ""))
7241 (set (match_dup 0) (plus:HI (match_dup 0)
7242 (match_operand:HI 2 "const_int_operand" "")))
7243 (set (match_operand:HI 3 "nonimmediate_operand" "")
7245 (match_scratch:HI 4 "xy")]
7246 "D_REG_P (operands[0])
7248 || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
7249 && peep2_reg_dead_p (3, operands[0])"
7250 [(set (match_dup 4) (match_dup 1))
7251 (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
7252 (set (match_dup 3) (match_dup 4))]
7253 "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
7254 if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
7256 ;;--------------------------------------------------------------------
7258 ;;--------------------------------------------------------------------
7259 ;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
7261 ;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
7262 ;; Register D must be dead and there must be no register side effects for mem.
7263 ;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
7264 ;; The good side effect is that it makes the sequence atomic.
7267 [(set (match_operand:QI 0 "hard_reg_operand" "")
7268 (match_operand:QI 1 "nonimmediate_operand" ""))
7269 (set (match_dup 0) (ior:QI (match_dup 0)
7270 (match_operand:QI 2 "const_int_operand" "")))
7271 (set (match_dup 1) (match_dup 0))]
7272 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7273 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7274 && peep2_reg_dead_p (3, operands[0])"
7275 [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
7279 [(set (match_operand:HI 0 "hard_reg_operand" "")
7280 (match_operand:HI 1 "nonimmediate_operand" ""))
7281 (set (match_dup 0) (ior:HI (match_dup 0)
7282 (match_operand:HI 2 "const_int_operand" "")))
7283 (set (match_dup 1) (match_dup 0))]
7284 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7285 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7286 && peep2_reg_dead_p (3, operands[0])"
7287 [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
7290 ;;--------------------------------------------------------------------
7292 ;;--------------------------------------------------------------------
7293 ;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
7294 ;; See Bset peephole2.
7297 [(set (match_operand:QI 0 "hard_reg_operand" "")
7298 (match_operand:QI 1 "nonimmediate_operand" ""))
7299 (set (match_dup 0) (and:QI (match_dup 0)
7300 (match_operand:QI 2 "const_int_operand" "")))
7301 (set (match_dup 1) (match_dup 0))]
7302 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7303 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7304 && peep2_reg_dead_p (3, operands[0])"
7305 [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
7309 [(set (match_operand:HI 0 "hard_reg_operand" "")
7310 (match_operand:HI 1 "nonimmediate_operand" ""))
7311 (set (match_dup 0) (and:HI (match_dup 0)
7312 (match_operand:HI 2 "const_int_operand" "")))
7313 (set (match_dup 1) (match_dup 0))]
7314 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7315 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7316 && peep2_reg_dead_p (3, operands[0])"
7317 [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
7321 ;;--------------------------------------------------------------------
7322 ;;- Compare peephole2
7323 ;;--------------------------------------------------------------------
7325 [(set (match_operand:HI 0 "hard_reg_operand" "")
7326 (match_operand:HI 1 "hard_reg_operand" ""))
7327 (set (match_dup 1) (plus:HI (match_dup 1)
7328 (match_operand:HI 2 "const_int_operand" "")))
7329 (set (cc0) (match_dup 0))]
7330 "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
7331 [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
7332 (set (cc0) (compare (match_dup 1) (match_dup 2)))]
7336 [(set (match_operand:HI 0 "hard_reg_operand" "")
7337 (match_operand:HI 1 "hard_reg_operand" ""))
7338 (set (match_operand:HI 2 "hard_reg_operand" "")
7339 (plus:HI (match_dup 2)
7340 (match_operand:HI 3 "const_int_operand" "")))
7341 (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
7342 (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
7343 "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
7344 && !reg_mentioned_p (operands[2], operands[4])
7346 && ((rtx_equal_p (operands[5], operands[0])
7347 && rtx_equal_p (operands[2], operands[1]))
7349 || (rtx_equal_p (operands[5], operands[1])
7350 && rtx_equal_p (operands[2], operands[0])))"
7351 [(set (match_dup 2) (match_dup 1))
7352 (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
7353 (set (match_dup 4) (match_dup 2))
7354 (set (cc0) (compare (match_dup 2) (match_dup 3)))]
7358 ;;--------------------------------------------------------------------
7360 ;;--------------------------------------------------------------------
7362 ;; Optimize initialization of 2 hard regs from the same memory location
7363 ;; Since we can't copy easily X, Y and D to each other, load the 2 registers
7364 ;; from the same memory location.
7367 [(set (match_operand:HI 0 "hard_reg_operand" "")
7368 (match_operand:HI 1 "memory_operand" ""))
7369 (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7371 && !side_effects_p (operands[1])
7372 && !reg_mentioned_p (operands[0], operands[1])"
7373 [(set (match_dup 0) (match_dup 1))
7374 (set (match_dup 2) (match_dup 1))]
7377 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7380 [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7381 (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7382 (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7383 (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
7384 (match_scratch:HI 4 "d")]
7386 [(set (match_dup 4) (const_int 0))
7387 (set (match_dup 0) (match_dup 4))
7388 (set (match_dup 1) (match_dup 4))
7389 (set (match_dup 2) (match_dup 4))
7390 (set (match_dup 3) (match_dup 4))]
7394 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7397 [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7398 (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7399 (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7400 (match_scratch:HI 3 "d")]
7402 [(set (match_dup 3) (const_int 0))
7403 (set (match_dup 0) (match_dup 3))
7404 (set (match_dup 1) (match_dup 3))
7405 (set (match_dup 2) (match_dup 3))]
7409 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7412 [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
7413 (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
7414 (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
7415 (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
7416 (match_scratch:HI 4 "x")]
7417 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
7418 [(set (match_dup 4) (const_int 0))
7419 (set (match_dup 1) (match_dup 4))
7420 (set (match_dup 2) (match_dup 4))
7421 (set (match_dup 3) (match_dup 4))]
7425 ;; This peephole catches the address computations generated by the reload
7428 [(set (match_operand:HI 0 "hard_reg_operand" "xy")
7429 (match_operand:HI 1 "const_int_operand" ""))
7430 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7431 (set (match_dup 0) (reg:HI D_REGNUM))])
7432 (set (reg:HI D_REGNUM)
7433 (plus (reg:HI D_REGNUM)
7434 (match_operand:HI 2 "general_operand" "")))
7435 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7436 (set (match_dup 0) (reg:HI D_REGNUM))])]
7437 "(INTVAL (operands[1]) & 0x0FF) == 0"
7440 int value_loaded = 1;
7442 if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
7446 ops[0] = operands[0];
7447 ops[1] = operands[2];
7448 m68hc11_gen_movhi (insn, ops);
7449 output_asm_insn (\"xgd%0\", operands);
7451 else if (Y_REG_P (operands[0]))
7453 if (reg_mentioned_p (iy_reg, operands[2]))
7454 output_asm_insn (\"ldy\\t%2\", operands);
7457 output_asm_insn (\"xgdy\", operands);
7461 output_asm_insn (\"ldd\\t%2\", operands);
7464 if (value_loaded == 0)
7465 output_asm_insn (\"ldd\\t%2\", operands);
7466 if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
7467 output_asm_insn (\"inca\", operands);
7468 else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
7469 output_asm_insn (\"deca\", operands);
7470 else if (INTVAL (operands[1]) != 0)
7471 output_asm_insn (\"adda\\t%h1\", operands);
7473 if (X_REG_P (operands[0]))
7475 else if (Y_REG_P (operands[0]))
7483 [(set (match_operand:HI 0 "hard_reg_operand" "h")
7484 (match_operand:HI 1 "non_push_operand" "g"))
7485 (set (match_operand:HI 2 "hard_reg_operand" "h")
7487 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7488 && !S_REG_P (operands[2])"
7493 ops[0] = operands[2];
7494 ops[1] = operands[1];
7495 m68hc11_gen_movhi (insn, ops);
7501 [(set (match_operand:HI 0 "hard_reg_operand" "h")
7502 (match_operand:HI 1 "hard_reg_operand" "h"))
7503 (set (match_operand:HI 2 "non_push_operand" "g")
7505 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7506 && !S_REG_P (operands[2])"
7511 ops[0] = operands[2];
7512 ops[1] = operands[1];
7513 m68hc11_gen_movhi (insn, ops);
7519 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
7520 ;; the set, so we don't need to emit anything. 'ins1' refers to the
7524 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7525 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7526 (set (match_dup 0) (reg:HI D_REGNUM))])]
7527 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7530 cc_status = cc_prev_status;
7535 ;; Same as above but due to some split, there may be a noop set
7538 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7539 (set (match_dup 0) (match_dup 0))
7540 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7541 (set (match_dup 0) (reg:HI D_REGNUM))])]
7542 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7545 cc_status = cc_prev_status;
7551 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
7552 ;; and we must, at least, setup X/Y with value of D.
7555 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7556 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7557 (set (match_dup 0) (reg:HI D_REGNUM))])]
7563 ops[0] = operands[0];
7564 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7565 m68hc11_gen_movhi (insn, ops);
7571 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7572 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7575 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7576 (set (match_dup 0) (reg:HI D_REGNUM))])
7577 (set (reg:HI D_REGNUM) (match_dup 0))]
7578 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7581 cc_status = cc_prev_status;
7587 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7588 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7591 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7592 (set (match_dup 0) (reg:HI D_REGNUM))])
7593 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7594 "REGNO (operands[0]) == REGNO (operands[1])
7595 && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7598 cc_status = cc_prev_status;
7604 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7605 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7608 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7609 (set (match_dup 0) (reg:HI D_REGNUM))])
7610 (set (reg:HI D_REGNUM) (match_dup 0))]
7616 ops[0] = operands[0];
7617 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7618 m68hc11_gen_movhi (insn, ops);
7624 ;;; Same peephole with a QI set. The copy is made as 16-bit to comply
7628 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7629 (set (match_dup 0) (reg:HI D_REGNUM))])
7630 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7631 "REGNO (operands[0]) == REGNO (operands[1])"
7636 ops[0] = operands[0];
7637 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7638 m68hc11_gen_movhi (insn, ops);
7644 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
7647 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7648 (set (match_dup 0) (reg:HI D_REGNUM))])
7649 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7650 (set (match_dup 0) (reg:HI D_REGNUM))])]
7654 cc_status = cc_prev_status;
7660 [(set (match_operand:HI 0 "hard_reg_operand" "")
7661 (match_operand:HI 1 "stack_register_operand" ""))
7662 (set (match_operand:HI 2 "hard_reg_operand" "")
7663 (match_operand:HI 3 "memory_operand" "m"))
7665 (match_operand:HI 4 "memory_operand" "m"))]
7666 "IS_STACK_POP (operands[4])
7667 && (GET_CODE (operands[3]) == MEM &&
7668 rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
7673 ops[0] = operands[2];
7674 ops[1] = gen_rtx_MEM (HImode,
7675 gen_rtx_POST_INC (HImode, stack_pointer_rtx));
7676 m68hc11_gen_movhi (insn, ops);
7682 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
7685 [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
7686 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7690 return \"sts\\t%t0\\n\\tld%0\\t%t0\";
7695 [(set (match_operand:HI 0 "hard_reg_operand" "")
7696 (match_operand:HI 1 "memory_operand" ""))
7697 (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7699 && !side_effects_p (operands[1])
7700 && !reg_mentioned_p (operands[0], operands[1])"
7705 ops[0] = operands[0];
7706 ops[1] = operands[1];
7707 m68hc11_gen_movhi (insn, ops);
7708 ops[0] = operands[2];
7709 m68hc11_gen_movhi (insn, ops);
7713 ;; Peephole for Z register replacement.
7714 ;; Avoid to use _.tmp register when comparing D and X if we can compare
7715 ;; with soft register
7717 [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
7718 (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
7719 (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
7720 (reg:HI SOFT_TMP_REGNUM)))]
7721 "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
7726 ops[0] = operands[0];
7727 ops[1] = operands[1];
7728 m68hc11_gen_movhi (insn, ops);
7729 return \"cp%2\\t%1\";