1 ;;- Machine description file for Motorola 68HC11 and 68HC12.
2 ;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
3 ;;- Free Software Foundation, Inc.
4 ;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING. If not, write to
20 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 ;; Boston, MA 02110-1301, USA.
24 ;; A first 68HC11 port was made by Otto Lind (otto@coactive.com)
25 ;; on gcc 2.6.3. I have used it as a starting point for this port.
26 ;; However, this new port is a complete re-write. Its internal
27 ;; design is completely different. The generated code is not
28 ;; compatible with the gcc 2.6.3 port.
30 ;; The gcc 2.6.3 port is available at:
32 ;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
35 ;;- Instruction patterns. When multiple patterns apply,
36 ;;- the first one in the file is chosen.
38 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
40 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
41 ;;- updates for most instructions.
44 ;; The following constraints are used:
46 ;; Single pair registers:
47 ;; a register 'a' 8-bit
48 ;; b register 'b' 8-bit
49 ;; d register 'd' 16-bit
50 ;; t pseudo soft register 'TMP' 16-bit
51 ;; v register 'd' for 68hc11, 16-bit
53 ;; (used for scratch register)
54 ;; w register 'sp' 16-bit
55 ;; x register 'x' 16-bit
56 ;; y register 'y' 16-bit
57 ;; z register 'z' 16-bit (fake r for 68HC11 and 68HC12)
58 ;; D register 'd+x' 32-bit
60 ;; Group of registers:
61 ;; q register 'a' or 'b' or 'd' 8-bit
62 ;; u pseudo soft register 16-bit
63 ;; A register 'x', 'y', 'z' 16-bit
64 ;; B register 'x', 'y' 16-bit
65 ;; h register 'd', 'x', 'y', 'z' 16-bit
69 ;; Q an operand which is in memory but whose address is constant
70 ;; (i.e., a (MEM (SYMBOL_REF x))). This constraint is used by
71 ;; bset/bclr instructions together with linker relaxation. The
72 ;; operand can be translated to a page0 addressing mode if the
73 ;; symbol address is in page0 (0..255).
75 ;; R an operand which is in memory and whose address is expressed
76 ;; with 68HC11/68HC12 indexed addressing mode. In general this
77 ;; is any valid (MEM) except a (MEM (SYMBOL_REF x)).
79 ;; U an operand which is in memory and if it uses the 68HC12 indexed
80 ;; addressing mode, the offset is in the range -16..+15. This is
81 ;; used by 68HC12 movb/movw instructions since they do not accept
82 ;; the full 16-bit offset range (as other insn do).
85 ;; Immediate integer operand constraints:
86 ;; `L' is for range -65536 to 65536
87 ;; `M' is for values whose 16-bit low part is 0
88 ;; 'N' is for +1 or -1.
89 ;; 'O' is for 16 (for rotate using swap).
90 ;; 'P' is for range -8 to 2 (used by addhi_sp)
92 ;; In many cases, it's not possible to use the 'g' or 'r' constraints.
94 ;; Operands modifiers:
96 ;; %b Get the low part of the operand (to obtain a QImode)
97 ;; This modifier must always be used for QImode operations
98 ;; because a correction must be applied when the operand
99 ;; is a soft register (ex: *ZD1). Otherwise, we generate
100 ;; *ZD1 and this is the high part of the register. For other
101 ;; kinds of operands, if the operand is already QImode, no
102 ;; additional correction is made.
103 ;; %h Get the high part of the operand (to obtain a QImode)
104 ;; %t Represents the temporary/scratch register *_.tmp
105 ;; The scratch register is used in some cases when GCC puts
106 ;; some values in bad registers.
108 ;; 32/64-bit Patterns:
109 ;; The 68HC11 does not support 32/64-bit operations. Most of the
110 ;; 32/64-bit patterns are defined to split the instruction in
111 ;; 16-bits patterns. Providing split patterns generates better code
112 ;; than letting GCC implement the 32/64-bit operation itself.
117 ;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
118 ;; otherwise some insn are not satisfied.
120 ;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
121 ;; be valid only when z_replacement_completed == 2 because once these
122 ;; swap instructions are generated, a flow/cse pass fails to handle
123 ;; them correctly (it would treat the X, Y or D register as dead sometimes).
125 ;; o Some split pattern generate instructions that operate on 'a' or 'b'
126 ;; register directly (high part and low part of D respectively).
127 ;; Such split pattern must also be valid when z_replacement_completed == 2
128 ;; because flow/cse is not aware that D is composed of {a, b}.
130 ;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
131 ;; the high part of a soft register must be expanded after z_replacement
134 ;;---------------------------------------------------------------------------
139 (X_REGNUM 0) ; Index X register
140 (D_REGNUM 1) ; Data register
141 (Y_REGNUM 2) ; Index Y register
142 (SP_REGNUM 3) ; Stack pointer
143 (PC_REGNUM 4) ; Program counter
144 (A_REGNUM 5) ; A (high part of D)
145 (B_REGNUM 6) ; B (low part of D)
146 (CC_REGNUM 7) ; Condition code register
147 (SOFT_TMP_REGNUM 10) ; TMP soft register
148 (SOFT_Z_REGNUM 11) ; Z soft register
149 (SOFT_XY_REGNUM 12) ; XY soft register
152 (include "predicates.md")
154 ;;--------------------------------------------------------------------
156 ;;--------------------------------------------------------------------
158 ;; The test and compare insn must not accept a memory operand with
159 ;; an auto-inc mode. If we do this, the reload can emit move insns
160 ;; after the test or compare. Such move will set the flags and therefore
161 ;; break the comparison. This can happen if the auto-inc register
162 ;; does not happen to be a hard register (i.e., reloading occurs).
163 ;; An offsetable memory operand should be ok. The 'tst_operand' and
164 ;; 'cmp_operand' predicates take care of this rule.
166 (define_expand "tstsi"
168 (match_operand:SI 0 "tst_operand" ""))]
172 m68hc11_compare_op0 = operands[0];
173 m68hc11_compare_op1 = const0_rtx;
177 (define_expand "tsthi"
179 (match_operand:HI 0 "tst_operand" ""))]
183 m68hc11_compare_op0 = operands[0];
184 m68hc11_compare_op1 = const0_rtx;
188 (define_insn "tsthi_1"
190 (match_operand:HI 0 "tst_operand" "dx,*y"))]
194 if (D_REG_P (operands[0]) && !TARGET_M6812)
195 return \"std\\t%t0\";
197 return \"cp%0\\t#0\";
200 (define_expand "tstqi"
202 (match_operand:QI 0 "tst_operand" ""))]
206 m68hc11_compare_op0 = operands[0];
207 m68hc11_compare_op1 = const0_rtx;
212 ;; Split pattern for (tst:QI) on an address register.
216 (match_operand:QI 0 "hard_addr_reg_operand" ""))]
217 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
218 [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
219 (set (match_dup 1) (reg:HI D_REGNUM))])
220 (set (cc0) (reg:QI D_REGNUM))
221 (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
222 (set (match_dup 1) (reg:HI D_REGNUM))])]
223 "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
225 (define_insn "tstqi_1"
227 (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
231 if (A_REG_P (operands[0]))
234 else if (D_REG_P (operands[0]))
237 else if (dead_register_here (insn, d_reg))
238 return \"ldab\\t%b0\";
241 return \"tst\\t%b0\";
245 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
246 ;; during the Z register replacement. They are used when an operand
247 ;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
248 ;; In that case, we have to preserve the values of the replacement
249 ;; register (as well as the CC0 since the insns are compare insns).
250 ;; To do this, the replacement register is pushed on the stack and
251 ;; restored after the real compare. A pattern+split is defined to
252 ;; avoid problems with the flow+cse register pass which are made
253 ;; after Z register replacement.
255 (define_insn_and_split "tstqi_z_used"
257 (match_operand:QI 0 "tst_operand" "m"))
258 (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
259 (use (reg:HI SOFT_Z_REGNUM))]
262 "z_replacement_completed == 2"
263 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
264 (set (match_dup 1) (match_dup 2))
265 (set (cc0) (match_dup 0))
266 (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
267 "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
270 ;;--------------------------------------------------------------------
272 ;;--------------------------------------------------------------------
274 (define_expand "cmpsi"
276 (compare (match_operand:SI 0 "tst_operand" "")
277 (match_operand:SI 1 "cmp_operand" "")))]
281 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
282 operands[0] = force_reg (SImode, operands[0]);
284 m68hc11_compare_op0 = operands[0];
285 m68hc11_compare_op1 = operands[1];
290 ;; Comparison of a hard register with another one is provided because
291 ;; it helps GCC to avoid to spill a pseudo hard register.
292 ;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
293 ;; (except that we loose the information that the value is saved in it).
295 ;; The split pattern transforms the comparison into a save of one hard
296 ;; register and a comparison with the temporary.
300 (compare (match_operand:HI 0 "hard_reg_operand" "")
301 (match_operand:HI 1 "hard_reg_operand" "")))]
303 && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
304 [(set (match_dup 2) (match_dup 1))
306 (compare (match_dup 0) (match_dup 2)))]
307 "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
311 (compare (match_operand:HI 0 "hard_reg_operand" "")
312 (match_operand:HI 1 "hard_reg_operand" "")))]
314 && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
315 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
317 (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
320 (define_expand "cmphi"
322 (compare (match_operand:HI 0 "tst_operand" "")
323 (match_operand:HI 1 "cmp_operand" "")))]
327 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
328 operands[0] = force_reg (HImode, operands[0]);
330 m68hc11_compare_op0 = operands[0];
331 m68hc11_compare_op1 = operands[1];
335 (define_insn "cmphi_1_hc12"
337 (compare (match_operand:HI 0 "tst_operand"
338 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
339 (match_operand:HI 1 "general_operand"
340 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
344 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
346 cc_status.flags |= CC_REVERSED;
347 return \"cp%1\\t%0\";
349 else if (SP_REG_P (operands[1]))
350 return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
351 else if (H_REG_P (operands[1]))
352 return \"psh%1\n\\tcp%0\\t2,sp+\";
354 return \"cp%0\\t%1\";
357 (define_insn "cmphi_1_hc11"
359 (compare (match_operand:HI 0 "tst_operand"
360 "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
361 (match_operand:HI 1 "cmp_operand"
362 "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
366 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
368 cc_status.flags |= CC_REVERSED;
369 return \"cp%1\\t%0\";
371 else if (H_REG_P (operands[1]))
374 return \"cp%0\\t%1\";
377 (define_insn_and_split "cmphi_z_used"
379 (compare (match_operand:HI 0 "tst_operand" "dxy,m")
380 (match_operand:HI 1 "cmp_operand" "mi,dxy")))
381 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
382 (use (reg:HI SOFT_Z_REGNUM))]
385 "z_replacement_completed == 2"
386 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
387 (set (match_dup 2) (match_dup 3))
388 (set (cc0) (compare (match_dup 0) (match_dup 1)))
389 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
390 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
393 ;; 8-bit comparison with address register.
394 ;; There is no such comparison instruction, we have to temporarily switch
395 ;; the address register and the D register and do the comparison with D.
396 ;; The xgdx and xgdy instructions preserve the flags.
400 (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
401 (match_operand:QI 1 "cmp_operand" "")))]
402 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
403 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
404 (set (match_dup 3) (reg:HI D_REGNUM))])
406 (compare (reg:QI D_REGNUM) (match_dup 1)))
407 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
408 (set (match_dup 3) (reg:HI D_REGNUM))])]
409 "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
413 (compare (match_operand:QI 0 "hard_reg_operand" "")
414 (match_operand:QI 1 "hard_reg_operand" "")))]
416 [(set (match_dup 3) (match_dup 4))
418 (compare (match_dup 0) (match_dup 2)))]
419 "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
420 operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
421 operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
423 (define_expand "cmpqi"
425 (compare (match_operand:QI 0 "tst_operand" "")
426 (match_operand:QI 1 "cmp_operand" "")))]
430 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
431 operands[0] = force_reg (QImode, operands[0]);
433 m68hc11_compare_op0 = operands[0];
434 m68hc11_compare_op1 = operands[1];
438 (define_insn "bitcmpqi"
440 (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
441 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
450 (define_split /* "bitcmpqi" */
452 (and:QI (match_operand:QI 0 "tst_operand" "")
453 (match_operand:QI 1 "hard_addr_reg_operand" "")))]
454 "z_replacement_completed == 2"
455 [(set (match_dup 3) (match_dup 2))
456 (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
457 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
458 operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
459 operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
461 (define_insn_and_split "bitcmpqi_z_used"
463 (and:QI (match_operand:QI 0 "tst_operand" "d,m")
464 (match_operand:QI 1 "cmp_operand" "m,d")))
465 (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
466 (use (reg:HI SOFT_Z_REGNUM))]
469 "z_replacement_completed == 2"
470 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
471 (set (match_dup 2) (match_dup 3))
472 (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
473 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
474 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
476 (define_insn "bitcmphi"
478 (and:HI (match_operand:HI 0 "tst_operand" "d")
479 (match_operand:HI 1 "const_int_operand" "i")))]
480 "(INTVAL (operands[1]) & 0x0ff) == 0
481 || (INTVAL (operands[1]) & 0x0ff00) == 0"
484 if ((INTVAL (operands[1]) & 0x0ff) == 0)
485 return \"bita\\t%h1\";
487 return \"bitb\\t%1\";
490 (define_insn "bitcmpqi_12"
492 (zero_extract (match_operand:HI 0 "tst_operand" "d")
493 (match_operand:HI 1 "const_int_operand" "i")
494 (match_operand:HI 2 "const_int_operand" "i")))]
495 "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
496 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
497 && (unsigned) INTVAL (operands[2]) >= 8)"
502 int startpos = INTVAL (operands[2]);
503 int bitsize = INTVAL (operands[1]);
508 mask = (1 << (startpos + bitsize)) - 1;
509 mask &= ~((1 << startpos) - 1);
511 ops[0] = GEN_INT (mask);
512 output_asm_insn (\"bita\\t%0\", ops);
516 mask = (1 << (startpos + bitsize)) - 1;
517 mask &= ~((1 << startpos) - 1);
519 ops[0] = GEN_INT (mask);
520 output_asm_insn (\"bitb\\t%0\", ops);
525 (define_insn "cmpqi_1"
527 (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
528 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
532 if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
536 else if (D_REG_P (operands[0]))
538 return \"cmpb\\t%b1\";
540 cc_status.flags |= CC_REVERSED;
541 return \"cmpb\\t%b0\";
544 (define_insn_and_split "cmpqi_z_used"
546 (compare (match_operand:QI 0 "tst_operand" "dxy,m")
547 (match_operand:QI 1 "cmp_operand" "m,dxy")))
548 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
549 (use (reg:HI SOFT_Z_REGNUM))]
552 "z_replacement_completed == 2"
553 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
554 (set (match_dup 2) (match_dup 3))
555 (set (cc0) (compare (match_dup 0) (match_dup 1)))
556 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
557 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
559 ;;--------------------------------------------------------------------
560 ;;- Move strict_low_part
561 ;;--------------------------------------------------------------------
563 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
564 ;; The replacement must be made at the very end because we loose the
565 ;; (strict_low_part ...) information. This is correct for our machine
566 ;; description but not for GCC optimization passes.
568 (define_insn_and_split "movstrictsi"
569 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
570 (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
573 "z_replacement_completed == 2"
574 [(set (match_dup 0) (match_dup 1))]
577 (define_insn_and_split "movstricthi"
578 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
579 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
582 "z_replacement_completed == 2"
583 [(set (match_dup 0) (match_dup 1))]
586 (define_insn_and_split "movstrictqi"
587 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
588 (match_operand:QI 1 "general_operand" "d,imudA"))]
591 "z_replacement_completed == 2"
592 [(set (match_dup 0) (match_dup 1))]
595 ;;--------------------------------------------------------------------
596 ;;- 64-bit Move Operations.
597 ;; The movdi and movdf patterns are identical except for the mode.
598 ;; They are also very similar to those for movsi and movsf.
600 ;; For 68HC11, we need a scratch register (either D, X, Y)
601 ;; because there is no memory->memory moves. It must be defined with
602 ;; earlyclobber (&) so that it does not appear in the source or destination
603 ;; address. Providing patterns for movdi/movdf allows GCC to generate
604 ;; better code. [Until now, the scratch register is limited to D because
605 ;; otherwise we can run out of registers in the A_REGS class for reload].
607 ;; For 68HC12, the scratch register is not necessary. To use the same
608 ;; pattern and same split, we use the 'v' constraint. This tells the
609 ;; reload to use the _.tmp register (which is not used at all).
610 ;; The insn will be split in one or several memory moves (movw).
611 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
612 ;;--------------------------------------------------------------------
613 (define_expand "movdi"
614 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
615 (match_operand:DI 1 "general_operand" ""))
616 (clobber (match_scratch:HI 2 ""))])]
619 /* For push/pop, emit a REG_INC note to make sure the reload
620 inheritance and reload CSE pass notice the change of the stack
622 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
626 insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
627 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
634 ;; Separate push from normal moves to avoid reloading problems
635 ;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
636 ;; We can also accept more scratch registers.
637 (define_insn_and_split "*pushdi_internal"
638 [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
639 (match_operand:DI 1 "general_operand" "i,U,m,!u"))
640 (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
645 "m68hc11_split_move (operands[0], operands[1], operands[2]);
648 (define_insn_and_split "movdi_internal"
649 [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
650 (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
651 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
656 "m68hc11_split_move (operands[0], operands[1], operands[2]);
659 (define_expand "movdf"
660 [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
661 (match_operand:DF 1 "general_operand" ""))
662 (clobber (match_scratch:HI 2 ""))])]
664 "/* For push/pop, emit a REG_INC note to make sure the reload
665 inheritance and reload CSE pass notice the change of the stack
667 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
671 insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
672 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
679 ;; See pushdi_internal
680 (define_insn_and_split "*pushdf_internal"
681 [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
682 (match_operand:DF 1 "general_operand" "i,U,m,!u"))
683 (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
688 "m68hc11_split_move (operands[0], operands[1], operands[2]);
691 (define_insn_and_split "movdf_internal"
692 [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
693 (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
694 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
699 "m68hc11_split_move (operands[0], operands[1], operands[2]);
702 ;;--------------------------------------------------------------------
703 ;;- 32-bit Move Operations.
704 ;; The movsi and movsf patterns are identical except for the mode.
705 ;; When we move to/from a hard register (d+x), we don't need a scratch.
706 ;; Otherwise, a scratch register is used as intermediate register for
707 ;; the move. The '&' constraint is necessary to make sure the reload
708 ;; pass does not give us a register that dies in the insn and is used
709 ;; for input/output operands.
710 ;;--------------------------------------------------------------------
711 (define_expand "movsi"
712 [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
713 (match_operand:SI 1 "general_operand" ""))
714 (clobber (match_scratch:HI 2 ""))])]
716 "/* For push/pop, emit a REG_INC note to make sure the reload
717 inheritance and reload CSE pass notice the change of the stack
719 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
723 insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
724 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
731 (define_insn_and_split "*pushsi_internal"
732 [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
733 (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
734 (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
739 "m68hc11_split_move (operands[0], operands[1], operands[2]);
742 (define_insn_and_split "movsi_internal"
743 [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
744 (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
745 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
750 "m68hc11_split_move (operands[0], operands[1], operands[2]);
753 (define_expand "movsf"
754 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
755 (match_operand:SF 1 "general_operand" ""))
756 (clobber (match_scratch:HI 2 ""))])]
758 "/* For push/pop, emit a REG_INC note to make sure the reload
759 inheritance and reload CSE pass notice the change of the stack
761 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
765 insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
766 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
773 (define_insn_and_split "*pushsf_internal"
774 [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
775 (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
776 (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
781 "m68hc11_split_move (operands[0], operands[1], operands[2]);
784 (define_insn_and_split "movsf_internal"
785 [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
786 (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
787 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
792 "m68hc11_split_move (operands[0], operands[1], operands[2]);
796 ;;--------------------------------------------------------------------
797 ;;- 16-bit Move Operations.
798 ;; We don't need a scratch register.
799 ;;--------------------------------------------------------------------
801 (define_insn "*movhi2_push"
802 [(set (match_operand:HI 0 "push_operand" "=<,<,<")
803 (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
804 "TARGET_M6811 && !TARGET_M6812"
807 cc_status = cc_prev_status;
808 if (D_REG_P (operands[1]))
810 output_asm_insn (\"pshb\", operands);
813 else if (X_REG_P (operands[1]))
817 else if (Y_REG_P (operands[1]))
821 fatal_insn (\"Invalid register in the instruction\", insn);
824 (define_insn "*movhi2_pop"
825 [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
826 (match_operand:HI 1 "pop_operand" ">,>"))]
830 cc_status = cc_prev_status;
831 if (D_REG_P (operands[0]))
833 output_asm_insn (\"pula\", operands);
836 else if (X_REG_P (operands[0]))
840 else if (Y_REG_P (operands[0]))
844 fatal_insn (\"Invalid register in the instruction\", insn);
847 (define_expand "movhi"
848 [(set (match_operand:HI 0 "nonimmediate_operand" "")
849 (match_operand:HI 1 "general_operand" ""))]
853 if (reload_in_progress)
855 if (m68hc11_reload_operands (operands))
860 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
862 if (GET_CODE (operands[0]) == MEM &&
863 (GET_CODE (operands[1]) == MEM
864 || GET_CODE (operands[1]) == CONST_INT))
866 operands[1] = force_reg (HImode, operands[1]);
868 else if (IS_STACK_PUSH (operands[0])
869 && GET_CODE (operands[1]) != REG)
871 operands[1] = force_reg (HImode, operands[1]);
874 /* For push/pop, emit a REG_INC note to make sure the reload
875 inheritance and reload CSE pass notice the change of the stack
877 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
881 insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
882 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
889 (define_insn "*movhi_68hc12"
890 [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
891 (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
895 m68hc11_gen_movhi (insn, operands);
899 (define_insn "movhi_const0"
900 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
906 clr\\t%b0\\n\\tclr\\t%h0")
908 (define_insn "*movhi_m68hc11"
909 [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
910 (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
914 m68hc11_gen_movhi (insn, operands);
918 ;;--------------------------------------------------------------------
919 ;;- 8-bit Move Operations.
920 ;; We don't need a scratch register.
921 ;;--------------------------------------------------------------------
923 ;; The *a alternative also clears the high part of the register.
924 ;; This should be ok since this is not the (strict_low_part) set.
926 (define_insn "movqi_const0"
927 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
938 ;; 8-bit operations on address registers.
940 ;; Switch temporary to the D register and load the value in B.
941 ;; This is possible as long as the address register does not
942 ;; appear in the source operand.
945 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
946 (match_operand:QI 1 "general_operand" ""))]
947 "z_replacement_completed == 2
948 && !reg_mentioned_p (operands[0], operands[1])
949 && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
950 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
951 (set (match_dup 2) (reg:HI D_REGNUM))])
952 (set (reg:QI D_REGNUM) (match_dup 1))
953 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
954 (set (match_dup 2) (reg:HI D_REGNUM))])]
955 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
958 ;; 8-bit operations on address registers.
961 [(set (match_operand:QI 0 "nonimmediate_operand" "")
962 (match_operand:QI 1 "hard_addr_reg_operand" ""))]
963 "z_replacement_completed == 2
964 && !reg_mentioned_p (operands[1], operands[0])
965 && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
966 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
967 (set (match_dup 2) (reg:HI D_REGNUM))])
968 (set (match_dup 0) (reg:QI D_REGNUM))
969 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
970 (set (match_dup 2) (reg:HI D_REGNUM))])]
971 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
973 (define_insn "*movqi2_push"
974 [(set (match_operand:QI 0 "push_operand" "=<,<")
975 (match_operand:QI 1 "general_operand" "d,!*A"))]
979 if (A_REG_P (operands[1]))
982 cc_status = cc_prev_status;
987 (define_expand "movqi"
988 [(set (match_operand:QI 0 "nonimmediate_operand" "")
989 (match_operand:QI 1 "general_operand" ""))]
993 if (reload_in_progress)
995 if (m68hc11_reload_operands (operands))
1000 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
1002 if (GET_CODE (operands[0]) == MEM
1003 && (GET_CODE (operands[1]) == MEM
1004 || GET_CODE (operands[1]) == CONST_INT))
1006 operands[1] = force_reg (QImode, operands[1]);
1008 else if (IS_STACK_PUSH (operands[0])
1009 && GET_CODE (operands[1]) != REG)
1011 operands[1] = force_reg (QImode, operands[1]);
1014 /* For push/pop, emit a REG_INC note to make sure the reload
1015 inheritance and reload CSE pass notice the change of the stack
1017 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
1021 insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
1022 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
1029 (define_insn "*movqi_68hc12"
1030 [(set (match_operand:QI 0 "nonimmediate_operand"
1031 "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
1032 (match_operand:QI 1 "general_operand"
1033 "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
1037 m68hc11_gen_movqi (insn, operands);
1041 (define_insn "*movqi_m68hc11"
1042 [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
1043 (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
1047 m68hc11_gen_movqi (insn, operands);
1051 ;;--------------------------------------------------------------------
1053 ;;--------------------------------------------------------------------
1054 ;; Swapping registers is used for split patterns.
1055 (define_insn "swap_areg"
1056 [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1057 (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1058 (set (match_dup 1) (match_dup 0))]
1062 m68hc11_output_swap (insn, operands);
1066 ;;--------------------------------------------------------------------
1067 ;;- Truncation insns.
1068 ;;--------------------------------------------------------------------
1070 ;; Truncation are not necessary because GCC knows how to truncate,
1071 ;; specially when values lie in consecutive registers.
1074 (define_expand "floatunssisf2"
1075 [(set (match_operand:SF 0 "nonimmediate_operand" "")
1076 (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1078 "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
1079 SFmode, SImode, 2, operands);
1082 (define_expand "floatunssidf2"
1083 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1084 (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1086 "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
1087 DFmode, SImode, 2, operands);
1090 ;;--------------------------------------------------------------------
1091 ;;- Zero extension insns.
1092 ;;--------------------------------------------------------------------
1095 ;; 64-bit extend. The insn will be split into 16-bit instructions just
1096 ;; before the final pass. We need a scratch register for the split.
1097 ;; The final value can be generated on the stack directly. This is more
1098 ;; efficient and useful for conversions made during parameter passing rules.
1100 (define_insn "zero_extendqidi2"
1101 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1103 (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1104 (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1109 [(set (match_operand:DI 0 "push_operand" "")
1110 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1111 (clobber (match_scratch:HI 2 "=&dB"))]
1112 "z_replacement_completed == 2"
1116 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1117 rtx push = m68hc11_gen_lowpart (HImode, low);
1118 rtx src = operands[1];
1120 /* Source operand must be in a hard register. */
1123 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1124 emit_move_insn (src, operands[1]);
1127 /* Source is in D, we can push B then one word of 0 and we do
1128 a correction on the stack pointer. */
1131 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1132 emit_move_insn (operands[2], const0_rtx);
1133 if (D_REG_P (operands[2]))
1135 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1139 emit_move_insn (push, operands[2]);
1140 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1141 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1147 /* Source is in X or Y. It's better to push the 16-bit register
1148 and then to some stack adjustment. */
1149 src = gen_rtx_REG (HImode, REGNO (src));
1150 emit_move_insn (push, src);
1151 emit_move_insn (operands[2], const0_rtx);
1152 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1153 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1155 emit_move_insn (push, operands[2]);
1156 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1157 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1160 emit_move_insn (push, operands[2]);
1161 emit_move_insn (push, operands[2]);
1162 emit_move_insn (push, operands[2]);
1167 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1168 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1169 (clobber (match_scratch:HI 2 "=&dB"))]
1170 "z_replacement_completed == 2"
1174 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1175 rtx low2 = m68hc11_gen_lowpart (HImode, low);
1176 rtx src = operands[1];
1178 /* Source operand must be in a hard register. */
1181 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1182 emit_move_insn (src, operands[1]);
1185 emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1186 emit_move_insn (operands[2], const0_rtx);
1187 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1188 emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1190 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1191 low = m68hc11_gen_highpart (SImode, operands[0]);
1192 emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1193 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1197 (define_insn "zero_extendhidi2"
1198 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1200 (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1201 (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1206 [(set (match_operand:DI 0 "non_push_operand" "")
1208 (match_operand:HI 1 "nonimmediate_operand" "")))
1209 (clobber (match_scratch:HI 2 ""))]
1210 "z_replacement_completed == 2"
1214 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1215 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1216 rtx src = operands[1];
1218 /* Make sure the source is in a hard register. */
1222 emit_move_insn (src, operands[1]);
1225 /* Move the low part first for the push. */
1226 emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1228 /* Now, use the scratch register to fill in the zeros. */
1229 emit_move_insn (operands[2], const0_rtx);
1230 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1231 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1232 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1236 (define_insn "zero_extendsidi2"
1237 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1239 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1240 (clobber (match_scratch:HI 2 "=d,d,d,d"))]
1245 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1247 (match_operand:SI 1 "nonimmediate_operand" "")))
1248 (clobber (match_scratch:HI 2 ""))]
1249 "z_replacement_completed == 2"
1253 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1254 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1256 /* Move the low part first so that this is ok for a push. */
1257 m68hc11_split_move (low, operands[1], operands[2]);
1259 /* Use the scratch register to clear the high part of the destination. */
1260 emit_move_insn (operands[2], const0_rtx);
1261 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1262 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1267 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1268 ;; because it's less efficient.
1270 (define_insn "zero_extendhisi2"
1271 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1273 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1274 (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1279 [(set (match_operand:SI 0 "non_push_operand" "")
1281 (match_operand:HI 1 "nonimmediate_operand" "")))
1282 (clobber (match_scratch:HI 2 ""))]
1287 rtx src = operands[1];
1289 if (!H_REG_P (src) && !H_REG_P (operands[0]))
1292 emit_move_insn (src, operands[1]);
1294 emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1295 emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1299 (define_insn "zero_extendqisi2"
1300 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1302 (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1307 [(set (match_operand:SI 0 "non_push_operand" "")
1308 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1309 "reload_completed && !X_REG_P (operands[0])"
1310 [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1311 (set (match_dup 3) (const_int 0))]
1313 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1314 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1317 [(set (match_operand:SI 0 "hard_reg_operand" "")
1318 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1319 "z_replacement_completed == 2 && X_REG_P (operands[0])"
1320 [(set (match_dup 2) (match_dup 3))
1321 (set (match_dup 4) (const_int 0))
1322 (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1324 if (X_REG_P (operands[1]))
1326 emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
1327 gen_rtx_REG (HImode, HARD_X_REGNUM)));
1328 emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
1329 gen_rtx_REG (QImode, HARD_D_REGNUM)));
1330 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
1335 if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
1337 emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1340 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
1343 operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1344 operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1345 if (A_REG_P (operands[1]))
1347 operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1348 operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
1349 operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
1353 operands[5] = operands[2] =
1354 operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1355 operands[6] = operands[1];
1359 (define_insn "zero_extendqihi2"
1360 [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
1362 (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1366 if (A_REG_P (operands[0]))
1369 if (H_REG_P (operands[0]))
1371 output_asm_insn (\"clra\", operands);
1372 if (operands[0] != operands[1]
1373 && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1375 if (X_REG_P (operands[1])
1376 || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1378 output_asm_insn (\"stx\\t%t1\", operands);
1379 output_asm_insn (\"ldab\\t%T0\", operands);
1381 else if (Y_REG_P (operands[1])
1382 || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1384 output_asm_insn (\"sty\\t%t1\", operands);
1385 output_asm_insn (\"ldab\\t%T0\", operands);
1389 output_asm_insn (\"ldab\\t%b1\", operands);
1391 cc_status.flags |= CC_NOT_NEGATIVE;
1395 /* Status refers to the clra insn. Status is ok for others
1396 * since we have loaded the value in B.
1403 if (A_REG_P (operands[1]))
1405 output_asm_insn (\"st%1\\t%0\", operands);
1406 output_asm_insn (\"clr\\t%h0\", operands);
1411 output_asm_insn (\"clr\\t%h0\", operands);
1412 output_asm_insn (\"stab\\t%b0\", operands);
1413 cc_status.flags |= CC_NOT_NEGATIVE;
1420 ;;--------------------------------------------------------------------
1421 ;;- Sign extension insns.
1422 ;;--------------------------------------------------------------------
1424 (define_insn "extendqisi2"
1425 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1426 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1433 /* The 68HC12 has a sign-extension instruction. Use it when the
1434 destination is the register (X,D). First sign-extend the low
1435 part and fill X with the sign-extension of the high part. */
1436 if (TARGET_M6812 && X_REG_P (operands[0]))
1438 if (!D_REG_P (operands[1]))
1440 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1441 ops[1] = operands[1];
1442 m68hc11_gen_movqi (insn, ops);
1444 return \"sex\\tb,d\\n\\tsex\\ta,x\";
1447 ops[2] = gen_label_rtx ();
1449 if (X_REG_P (operands[1]))
1451 output_asm_insn (\"xgdx\", operands);
1454 else if (X_REG_P (operands[0]))
1456 /* X can be used as an indexed addressing in the source.
1457 Get the value before clearing it. */
1458 if (reg_mentioned_p (ix_reg, operands[1]))
1460 output_asm_insn (\"ldab\\t%b1\", operands);
1463 output_asm_insn (\"ldx\\t#0\", operands);
1466 output_asm_insn (\"clra\", operands);
1467 if (!X_REG_P (operands[0]))
1469 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1470 ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1472 if (IS_STACK_PUSH (operands[0]))
1474 output_asm_insn (\"pshb\", ops);
1475 output_asm_insn (\"tstb\", ops);
1479 output_asm_insn (\"stab\\t%b1\", ops);
1482 else if (D_REG_P (operands[1]) || need_tst)
1484 output_asm_insn (\"tstb\", operands);
1488 output_asm_insn (\"ldab\\t%b1\", operands);
1490 output_asm_insn (\"bpl\\t%l2\", ops);
1491 output_asm_insn (\"deca\", operands);
1492 if (X_REG_P (operands[0]))
1493 output_asm_insn (\"dex\", operands);
1495 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1497 if (!X_REG_P (operands[0]))
1499 if (IS_STACK_PUSH (operands[0]))
1501 output_asm_insn (\"psha\", ops);
1502 output_asm_insn (\"psha\", ops);
1503 output_asm_insn (\"psha\", ops);
1507 output_asm_insn (\"staa\\t%h0\", ops);
1509 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1510 if (dead_register_here (insn, d_reg))
1512 output_asm_insn (\"tab\", ops);
1513 output_asm_insn (\"std\\t%0\", ops);
1517 output_asm_insn (\"staa\\t%b0\", ops);
1518 output_asm_insn (\"staa\\t%h0\", ops);
1528 (define_insn "extendqihi2"
1529 [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1530 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1536 if (A_REG_P (operands[0]))
1539 ops[0] = gen_label_rtx ();
1540 if (D_REG_P (operands[0]))
1544 if (!D_REG_P (operands[1]))
1546 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1547 ops[1] = operands[1];
1548 m68hc11_gen_movqi (insn, ops);
1550 return \"sex\\tb,d\";
1552 output_asm_insn (\"clra\", operands);
1553 if (H_REG_P (operands[1]))
1555 output_asm_insn (\"tstb\", operands);
1559 output_asm_insn (\"ldab\\t%b1\", operands);
1561 output_asm_insn (\"bpl\\t%l0\", ops);
1562 output_asm_insn (\"deca\", operands);
1564 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1565 CODE_LABEL_NUMBER (ops[0]));
1569 output_asm_insn (\"clr\\t%h0\", operands);
1570 if (m68hc11_register_indirect_p (operands[1], HImode))
1572 ops[1] = operands[1];
1573 output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1578 output_asm_insn (\"tst\\t%b1\", operands);
1579 output_asm_insn (\"bpl\\t%l0\", ops);
1581 output_asm_insn (\"dec\\t%h0\", operands);
1582 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1583 CODE_LABEL_NUMBER (ops[0]));
1590 ;; Split the special case where the source of the sign extend is
1591 ;; either Y or Z. In that case, we can't move the source in the D
1592 ;; register directly. The movhi pattern handles this move by using
1593 ;; a temporary scratch memory location.
1596 [(set (match_operand:SI 0 "register_operand" "")
1597 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1598 "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1599 [(set (reg:HI D_REGNUM) (match_dup 1))
1600 (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1603 (define_insn "extendhisi2"
1604 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1605 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1612 if (Y_REG_P (operands[1]))
1615 if (X_REG_P (operands[1]))
1617 output_asm_insn (\"xgdx\", operands);
1622 /* X can be used as an indexed addressing in the source.
1623 Get the value before clearing it. */
1624 x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1627 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1628 ops[1] = operands[1];
1629 m68hc11_gen_movhi (insn, ops);
1634 if (TARGET_M6812 && 0)
1636 /* This sequence of code is larger than the one for 68HC11.
1637 Don't use it; keep it for documentation. */
1638 if (!D_REG_P (operands[1]) && !x_reg_used)
1640 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1641 ops[1] = operands[1];
1642 m68hc11_gen_movhi (insn, ops);
1644 output_asm_insn (\"sex\\ta,x\", operands);
1645 output_asm_insn (\"xgdx\", operands);
1646 output_asm_insn (\"sex\\ta,d\", operands);
1650 output_asm_insn (\"ldx\\t#0\", operands);
1651 if (D_REG_P (operands[1]) || x_reg_used)
1653 output_asm_insn (\"tsta\", operands);
1657 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1658 ops[1] = operands[1];
1659 m68hc11_gen_movhi (insn, ops);
1662 ops[0] = gen_label_rtx ();
1663 output_asm_insn (\"bpl\\t%l0\", ops);
1664 output_asm_insn (\"dex\", operands);
1665 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1671 ;;--------------------------------------------------------------------
1672 ;;- Min and Max instructions (68HC12).
1673 ;;--------------------------------------------------------------------
1674 (define_insn "uminqi3"
1675 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1676 (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1677 (match_operand:QI 2 "general_operand" "m,d")))]
1678 "TARGET_M6812 && TARGET_MIN_MAX"
1681 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1682 The mina/minm use A as the source or destination. This is the
1683 high part of D. There is no way to express that in the pattern
1684 so we must use 'exg a,b' to put the operand in the good register. */
1686 if (D_REG_P (operands[0]))
1688 return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1692 return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1696 (define_insn "umaxqi3"
1697 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1698 (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1699 (match_operand:QI 2 "general_operand" "m,d")))]
1700 "TARGET_M6812 && TARGET_MIN_MAX"
1703 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1704 The maxa/maxm use A as the source or destination. This is the
1705 high part of D. There is no way to express that in the pattern
1706 so we must use 'exg a,b' to put the operand in the good register. */
1708 if (D_REG_P (operands[0]))
1710 return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1714 return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1718 (define_insn "uminhi3"
1719 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1720 (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1721 (match_operand:HI 2 "general_operand" "m,d")))]
1722 "TARGET_M6812 && TARGET_MIN_MAX"
1725 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1727 if (D_REG_P (operands[0]))
1729 return \"emind\\t%2\";
1733 return \"eminm\\t%0\";
1737 (define_insn "umaxhi3"
1738 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1739 (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1740 (match_operand:HI 2 "general_operand" "m,d")))]
1741 "TARGET_M6812 && TARGET_MIN_MAX"
1744 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1746 if (D_REG_P (operands[0]))
1748 return \"emaxd\\t%2\";
1752 return \"emaxm\\t%0\";
1757 ;;--------------------------------------------------------------------
1758 ;;- Add instructions.
1759 ;;--------------------------------------------------------------------
1760 ;; 64-bit: Use a library call because what GCC generates is huge.
1762 (define_expand "adddi3"
1763 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1764 (plus:DI (match_operand:DI 1 "general_operand" "")
1765 (match_operand:DI 2 "general_operand" "")))]
1767 "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1773 (define_expand "addsi3"
1774 [(parallel [(set (match_operand:SI 0 "register_operand" "")
1775 (plus:SI (match_operand:SI 1 "general_operand" "")
1776 (match_operand:SI 2 "general_operand" "")))
1777 (clobber (match_scratch:HI 3 ""))])]
1781 (define_insn "*addsi3_zero_extendhi"
1782 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1783 (plus:SI (zero_extend:SI
1784 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1785 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1786 (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1792 if (X_REG_P (operands[2]))
1794 ops[0] = operands[1];
1798 if (X_REG_P (operands[1]))
1800 output_asm_insn (\"xgdx\", ops);
1802 else if (!D_REG_P (operands[1]))
1804 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1805 ops[1] = operands[1];
1806 m68hc11_gen_movhi (insn, ops);
1808 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1809 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1811 ops[2] = gen_label_rtx ();
1813 /* ldx preserves the carry, propagate it by incrementing X directly. */
1814 output_asm_insn (\"addd\\t%0\", ops);
1815 if (!X_REG_P (operands[2]))
1816 output_asm_insn (\"ldx\\t%1\", ops);
1818 output_asm_insn (\"bcc\\t%l2\", ops);
1819 output_asm_insn (\"inx\", ops);
1822 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1827 (define_split /* "*addsi3_zero_extendqi" */
1828 [(set (match_operand:SI 0 "register_operand" "")
1829 (plus:SI (zero_extend:SI
1830 (match_operand:QI 1 "general_operand" ""))
1831 (match_operand:SI 2 "memory_operand" "")))
1832 (clobber (match_scratch:HI 3 "=X,X"))]
1834 [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1835 (parallel [(set (match_dup 0)
1836 (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1837 (clobber (match_dup 3))])]
1840 (define_insn "*addsi3_zero_extendqi"
1841 [(set (match_operand:SI 0 "register_operand" "=D,D")
1842 (plus:SI (zero_extend:SI
1843 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1844 (match_operand:SI 2 "general_operand" "miD,!muiD")))
1845 (clobber (match_scratch:HI 3 "=X,X"))]
1851 if (GET_CODE (operands[2]) == MEM)
1854 if (X_REG_P (operands[2]))
1856 if (H_REG_P (operands[1]))
1858 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1859 ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1860 m68hc11_gen_movhi (insn, ops);
1864 ops[0] = operands[1];
1866 ops[1] = const0_rtx;
1870 if (X_REG_P (operands[1]))
1872 output_asm_insn (\"xgdx\", ops);
1874 else if (!D_REG_P (operands[1]))
1876 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1877 ops[1] = operands[1];
1878 m68hc11_gen_movqi (insn, ops);
1881 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1883 ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1884 output_asm_insn (\"clra\", ops);
1887 /* ldx preserves the carry, propagate it by incrementing X directly. */
1888 output_asm_insn (\"addb\\t%b0\", ops);
1889 output_asm_insn (\"adca\\t%h1\", ops);
1890 if (!X_REG_P (operands[2]))
1891 output_asm_insn (\"ldx\\t%2\", ops);
1893 /* If the above adca was adding some constant, we don't need to propagate
1894 the carry unless the constant was 0xff. */
1895 if (X_REG_P (operands[2])
1896 || GET_CODE (ops[1]) != CONST_INT
1897 || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1899 ops[3] = gen_label_rtx ();
1901 output_asm_insn (\"bcc\\t%l3\", ops);
1902 output_asm_insn (\"inx\", ops);
1904 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1905 CODE_LABEL_NUMBER (ops[3]));
1911 (define_insn "*addsi3"
1912 [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
1913 (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1914 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
1915 (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1920 const char* add_insn;
1921 const char* inc_insn;
1922 const char* incb_mem;
1923 const char* inch_mem;
1926 if (which_alternative > 2)
1931 val = INTVAL (operands[2]);
1932 if ((val & 0x0ffffL) == 0)
1934 if (!H_REG_P (operands[0]))
1936 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1937 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1938 output_asm_insn (\"ldd\\t%0\", ops);
1939 output_asm_insn (\"addd\\t%1\", ops);
1940 output_asm_insn (\"std\\t%0\", ops);
1952 if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1959 ops[1] = operands[2];
1960 add_insn = \"addd\\t%1\";
1961 inc_insn = \"inx\\t\";
1962 incb_mem = \"inc\\t%b1\";
1963 inch_mem = \"inc\\t%h1\";
1967 ops[1] = GEN_INT (- val);
1968 add_insn = \"subd\\t%1\";
1970 incb_mem = \"dec\\t%b1\";
1971 inch_mem = \"dec\\t%h1\";
1974 ops[2] = gen_label_rtx ();
1975 if (!H_REG_P (operands[0]))
1977 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1978 output_asm_insn (\"ldd\\t%0\", ops);
1980 output_asm_insn (add_insn, ops);
1981 if (!H_REG_P (operands[0]))
1983 output_asm_insn (\"std\\t%0\", ops);
1985 output_asm_insn (\"bcc\\t%l2\", ops);
1986 if (H_REG_P (operands[0]))
1988 output_asm_insn (inc_insn, ops);
1992 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1994 if (INTVAL (operands[2]) < 0)
1996 output_asm_insn (\"ldd\\t%1\", ops);
1997 output_asm_insn (\"addd\\t#-1\", ops);
1998 output_asm_insn (\"std\\t%1\", ops);
2002 output_asm_insn (incb_mem, ops);
2003 output_asm_insn (\"bne\\t%l2\", ops);
2004 output_asm_insn (inch_mem, ops);
2007 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
2014 [(set (match_operand:SI 0 "register_operand" "")
2015 (plus:SI (match_operand:SI 1 "register_operand" "")
2016 (match_operand:SI 2 "const_int_operand" "")))
2017 (clobber (match_scratch:HI 3 ""))]
2018 "reload_completed && z_replacement_completed == 2
2019 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
2020 [(set (match_dup 5) (match_dup 6))
2021 (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
2022 (set (match_dup 6) (match_dup 5))]
2023 "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2024 if (X_REG_P (operands[0]))
2026 operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
2030 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2031 operands[5] = operands[3];
2036 [(set (match_operand:SI 0 "register_operand" "")
2037 (plus:SI (match_operand:SI 1 "register_operand" "")
2038 (match_operand:SI 2 "general_operand" "")))
2039 (clobber (match_scratch:HI 3 "=X"))]
2040 "reload_completed && z_replacement_completed == 2
2041 && (GET_CODE (operands[2]) != CONST_INT ||
2042 (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
2043 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2044 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2045 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2046 (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2047 (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2048 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2049 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
2050 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2051 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2052 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2053 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2056 ;; Instruction generated to propagate the carry of a 16-bit add
2057 ;; to the upper 16-bit part (in register X).
2059 (define_insn "*addsi_carry"
2060 [(set (match_operand:HI 0 "register_operand" "=x")
2061 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2063 (reg:HI CC_REGNUM)))]
2069 ops[0] = gen_label_rtx ();
2070 output_asm_insn (\"bcc\\t%l0\", ops);
2071 output_asm_insn (\"in%0\", operands);
2072 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2080 (define_expand "addhi3"
2081 [(set (match_operand:HI 0 "register_operand" "")
2082 (plus:HI (match_operand:HI 1 "register_operand" "")
2083 (match_operand:HI 2 "general_operand" "")))]
2087 if (TARGET_M6811 && SP_REG_P (operands[0]))
2089 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
2090 gen_rtx_SET (VOIDmode,
2092 gen_rtx_PLUS (HImode,
2093 operand1, operand2)),
2094 gen_rtx_CLOBBER (VOIDmode,
2095 gen_rtx_SCRATCH (HImode)))));
2100 (define_insn "*addhi3_68hc12"
2101 [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
2102 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
2103 (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
2108 const char* insn_code;
2110 if (which_alternative >= 4)
2112 if (A_REG_P (operands[2]))
2115 output_asm_insn (\"xgd%2\", operands);
2116 output_asm_insn (\"lea%0 d,%0\", operands);
2122 if (D_REG_P (operands[0]))
2124 if (X_REG_P (operands[2]))
2126 m68hc11_notice_keep_cc (operands[0]);
2127 output_asm_insn (\"xgdx\", operands);
2128 output_asm_insn (\"leax\\td,%2\", operands);
2131 else if (Y_REG_P (operands[2]))
2133 m68hc11_notice_keep_cc (operands[0]);
2134 output_asm_insn (\"xgdy\", operands);
2135 output_asm_insn (\"leay\\td,%2\", operands);
2138 else if (SP_REG_P (operands[2]))
2140 output_asm_insn (\"sts\\t%t0\", operands);
2141 return \"addd\\t%t0\";
2143 return \"addd\\t%2\";
2146 if (GET_CODE (operands[2]) == CONST_INT)
2147 val = INTVAL (operands[2]);
2151 if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
2153 m68hc11_notice_keep_cc (operands[0]);
2154 switch (REGNO (operands[0]))
2157 return \"leax\\t%i2,%1\";
2160 return \"leay\\t%i2,%1\";
2162 case HARD_SP_REGNUM:
2163 return \"leas\\t%i2,%1\";
2166 fatal_insn (\"Invalid operands in the instruction\", insn);
2171 insn_code = X_REG_P (operands[0]) ? \"inx\"
2172 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2177 insn_code = X_REG_P (operands[0]) ? \"dex\"
2178 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2181 /* For X and Y increment, the flags are not complete. Only the Z flag
2182 is updated. For SP increment, flags are not changed. */
2183 if (SP_REG_P (operands[0]))
2185 cc_status = cc_prev_status;
2186 if (INTVAL (operands[2]) < 0)
2190 output_asm_insn (\"pshx\", operands);
2204 output_asm_insn (insn_code, operands);
2211 ;; Specific pattern to add to the stack pointer.
2212 ;; We also take care of the clobbering of the IY register.
2214 (define_insn "addhi_sp"
2215 [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2216 (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2217 (match_operand:HI 2 "general_operand" "P,im,u,im")))
2218 (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2224 if (optimize && Y_REG_P (operands[3])
2225 && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
2226 operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
2228 if (GET_CODE (operands[2]) == CONST_INT
2229 && (val = INTVAL (operands[2])) != 0
2230 && (CONST_OK_FOR_LETTER_P (val, 'P')
2231 || (val > 0 && val <= 8)))
2233 while (val > 1 || val < -1)
2237 if (!H_REG_P (operands[3]))
2240 output_asm_insn (\"pul%3\", operands);
2245 output_asm_insn (\"pshx\", operands);
2253 output_asm_insn (\"ins\", operands);
2258 output_asm_insn (\"des\", operands);
2262 cc_status = cc_prev_status;
2266 /* Need to transfer to SP to X/Y and then to D register.
2267 Register X/Y is lost, this is specified by the (clobber) statement. */
2268 output_asm_insn (\"ts%3\", operands);
2269 if (GET_CODE (operands[2]) == CONST_INT
2270 && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
2271 && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
2273 output_asm_insn (\"ldab\\t%2\", operands);
2274 output_asm_insn (\"ab%3\", operands);
2279 output_asm_insn (\"xgd%3\", operands);
2280 output_asm_insn (\"addd\\t%2\", operands);
2281 output_asm_insn (\"xgd%3\", operands);
2284 /* The status flags correspond to the addd. xgdy and tys do not
2285 modify the flags. */
2289 (define_insn "*addhi3"
2290 [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
2291 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
2292 (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
2296 const char* insn_code;
2299 if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2301 output_asm_insn (\"sts\\t%t0\", operands);
2302 output_asm_insn (\"addd\\t%t0\", operands);
2303 return \"addd\\t#1\";
2305 if (GET_CODE (operands[2]) != CONST_INT)
2307 /* Adding to an address register or with another/same register
2308 is not possible. This must be replaced. */
2309 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2312 return \"addd\\t%2\";
2314 val = INTVAL (operands[2]);
2315 if (!SP_REG_P (operands[0]))
2317 if (D_REG_P (operands[0]))
2319 if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2322 return \"adda\\t%h2\";
2326 return \"addd\\t%2\";
2329 else if (GET_CODE (operands[2]) != CONST_INT
2330 || INTVAL (operands[2]) < -4
2331 || INTVAL (operands[2]) > 4)
2336 insn_code = X_REG_P (operands[0]) ? \"inx\"
2337 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2342 insn_code = X_REG_P (operands[0]) ? \"dex\"
2343 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2346 /* For X and Y increment, the flags are not complete. Only the Z flag
2347 is updated. For SP increment, flags are not changed. */
2348 if (SP_REG_P (operands[0]))
2350 cc_status = cc_prev_status;
2351 if (INTVAL (operands[2]) < 0)
2355 output_asm_insn (\"pshx\", operands);
2359 else if (optimize && dead_register_here (insn, ix_reg))
2363 output_asm_insn (\"pulx\", operands);
2375 output_asm_insn (insn_code, operands);
2381 (define_insn "*addhi3_zext"
2382 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2383 (plus:HI (zero_extend:HI
2384 (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2385 (match_operand:HI 2 "general_operand" "0,0")))]
2390 if (A_REG_P (operands[0]))
2392 else if (A_REG_P (operands[1]))
2393 return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2395 return \"addb\\t%b1\\n\\tadca\\t#0\";
2399 ;; Translate d = d + d into d = << 1
2400 ;; We have to do this because adding a register to itself is not possible.
2401 ;; ??? It's not clear whether this is really necessary.
2404 [(set (match_operand:QI 0 "hard_reg_operand" "")
2405 (plus:QI (match_dup 0)
2407 "0 && reload_completed"
2408 [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2411 (define_insn "addqi3"
2412 [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2413 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2414 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2418 if (GET_CODE (operands[2]) == CONST_INT)
2420 if (INTVAL (operands[2]) == 1)
2422 if (DA_REG_P (operands[0]))
2426 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2431 else if (A_REG_P (operands[0]))
2433 /* This applies on the 16-bit register. This should be ok since
2434 this is not a strict_low_part increment. */
2439 return \"inc\\t%b0\";
2442 else if (INTVAL (operands[2]) == -1)
2444 if (DA_REG_P (operands[0]))
2448 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2452 else if (A_REG_P (operands[0]))
2454 /* This applies on the 16-bit register. This should be ok since
2455 this is not a strict_low_part decrement. */
2460 return \"dec\\t%b0\";
2464 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2466 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2467 return \"addb\\t%b2\";
2469 return \"adda\\t%b2\";
2473 ;; add with carry is used for 32-bit add.
2475 (define_insn "*adcq"
2476 [(set (match_operand:QI 0 "register_operand" "=q")
2477 (plus:QI (plus:QI (reg:QI CC_REGNUM)
2478 (match_operand:QI 1 "register_operand" "%0"))
2479 (match_operand:QI 2 "general_operand" "ium")))]
2483 ;;--------------------------------------------------------------------
2484 ;;- Subtract instructions.
2485 ;;--------------------------------------------------------------------
2487 (define_expand "subdi3"
2488 [(set (match_operand:DI 0 "nonimmediate_operand" "")
2489 (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2490 (match_operand:DI 2 "general_operand" "")))]
2492 "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2496 ;; 32-bit Subtract (see addsi3)
2497 ;; Subtract with a constant are handled by addsi3.
2502 (define_expand "subsi3"
2503 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2504 (minus:SI (match_operand:SI 1 "register_operand" "")
2505 (match_operand:SI 2 "general_operand" "")))
2506 (clobber (match_scratch:HI 3 ""))])]
2510 (define_insn "*subsi3"
2511 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
2512 (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2513 (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
2514 (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
2518 (define_insn "*subsi3_zero_extendhi"
2519 [(set (match_operand:SI 0 "register_operand" "=D")
2520 (minus:SI (match_operand:SI 1 "register_operand" "0")
2521 (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
2522 (clobber (match_scratch:HI 3 "=X"))]
2528 if (A_REG_P (operands[2]))
2531 ops[0] = gen_rtx_MEM (HImode,
2532 gen_rtx_PRE_DEC (HImode,
2533 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2535 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2537 ops[1] = operands[2];
2538 m68hc11_gen_movhi (insn, ops);
2540 operands[2] = gen_rtx_MEM (HImode,
2541 gen_rtx_POST_INC (HImode,
2542 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2544 operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2546 ops[0] = gen_label_rtx ();
2547 output_asm_insn (\"subd\\t%2\", operands);
2548 output_asm_insn (\"bcc\\t%l0\", ops);
2549 output_asm_insn (\"dex\", ops);
2550 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2555 (define_insn "*subsi3_zero_extendqi"
2556 [(set (match_operand:SI 0 "register_operand" "=D")
2557 (minus:SI (match_operand:SI 1 "register_operand" "0")
2558 (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
2559 (clobber (match_scratch:HI 3 "=X"))]
2565 if (A_REG_P (operands[2]))
2567 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2568 ops[1] = operands[2];
2569 m68hc11_gen_movhi (insn, ops);
2570 operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2572 ops[0] = gen_label_rtx ();
2573 output_asm_insn (\"subb\\t%b2\", operands);
2574 output_asm_insn (\"sbca\\t#0\", operands);
2575 output_asm_insn (\"bcc\\t%l0\", ops);
2576 output_asm_insn (\"dex\", ops);
2577 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2583 ;; reg:HI 1 -> d reg:QI 6 -> B
2584 ;; reg:QI 7 -> ccr reg:QI 5 -> A
2586 (define_split /* "*subsi3" */
2587 [(set (match_operand:SI 0 "register_operand" "")
2588 (minus:SI (match_operand:SI 1 "register_operand" "")
2589 (match_operand:SI 2 "general_operand" "")))
2590 (clobber (match_scratch:HI 3 "=X"))]
2591 "reload_completed && z_replacement_completed == 2
2592 && X_REG_P (operands[1])"
2593 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2594 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2595 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2596 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2597 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2598 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2599 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2600 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2601 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2602 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2603 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2605 (define_split /* "*subsi3" */
2606 [(set (match_operand:SI 0 "register_operand" "")
2607 (minus:SI (match_operand:SI 1 "general_operand" "")
2608 (match_operand:SI 2 "register_operand" "")))
2609 (clobber (match_scratch:HI 3 "=X"))]
2610 "reload_completed && z_replacement_completed == 2
2611 && X_REG_P (operands[2])"
2612 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2613 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2614 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2615 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2616 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2617 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2618 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2619 (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2620 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2621 operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2622 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2623 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2625 (define_split /* "*subsi3" */
2626 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2627 (minus:SI (match_operand:SI 1 "general_operand" "")
2628 (match_operand:SI 2 "general_operand" "")))
2629 (clobber (match_scratch:HI 3 "=d"))]
2630 "reload_completed && z_replacement_completed == 2
2631 && !X_REG_P (operands[0])"
2632 [(set (match_dup 3) (match_dup 4))
2633 (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2634 (set (match_dup 4) (match_dup 3))
2635 (set (match_dup 3) (match_dup 6))
2636 (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2637 (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2638 (set (match_dup 6) (match_dup 3))]
2639 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2640 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2641 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2642 operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2643 operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2644 operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2647 ;; - 16-bit Subtract.
2649 (define_expand "subhi3"
2650 [(set (match_operand:HI 0 "register_operand" "=r")
2651 (minus:HI (match_operand:HI 1 "register_operand" "0")
2652 (match_operand:HI 2 "general_operand" "g")))]
2657 ;; Subtract from stack. This is better if we provide a pattern.
2659 (define_insn "*subhi3_sp"
2660 [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2661 (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2662 (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2663 (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2667 if (X_REG_P (operands[2]))
2669 operands[2] = m68hc11_soft_tmp_reg;
2670 output_asm_insn (\"stx\\t%2\", operands);
2672 else if (Y_REG_P (operands[2]))
2674 operands[2] = m68hc11_soft_tmp_reg;
2675 output_asm_insn (\"sty\\t%2\", operands);
2677 else if (D_REG_P (operands[2]))
2679 operands[2] = m68hc11_soft_tmp_reg;
2680 output_asm_insn (\"std\\t%2\", operands);
2683 if (D_REG_P (operands[3]))
2687 save_x = !dead_register_here (insn, ix_reg);
2689 output_asm_insn (\"xgdx\", operands);
2690 output_asm_insn (\"tsx\", operands);
2691 output_asm_insn (\"xgdx\", operands);
2692 output_asm_insn (\"subd\\t%2\", operands);
2693 output_asm_insn (\"xgdx\", operands);
2695 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2696 modify the flags. */
2697 output_asm_insn (\"txs\", operands);
2704 /* Need to transfer to SP to X,Y and then to D register.
2705 Register X,Y is lost, this is specified by the (clobber) statement. */
2706 output_asm_insn (\"ts%3\", operands);
2707 output_asm_insn (\"xgd%3\", operands);
2708 output_asm_insn (\"subd\\t%2\", operands);
2709 output_asm_insn (\"xgd%3\", operands);
2711 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2712 modify the flags. */
2717 (define_insn "*subhi3"
2718 [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
2719 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
2720 (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
2724 /* Adding to an address register or with another/same register
2725 is not possible. This must be replaced. */
2726 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2729 return \"subd\\t%2\";
2732 (define_insn "*subhi3_zext"
2733 [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2734 (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2735 (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2740 if (A_REG_P (operands[2]))
2744 ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2745 ops[1] = operands[2];
2746 m68hc11_gen_movqi (insn, ops);
2747 return \"subb\\t%T0\\n\\tsbca\\t#0\";
2749 return \"subb\\t%b2\\n\\tsbca\\t#0\";
2752 (define_insn "subqi3"
2753 [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2754 (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2755 (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2759 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2761 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2762 return \"subb\\t%b2\";
2764 return \"suba\\t%b2\";
2768 ;; subtract with carry is used for 32-bit subtract.
2770 (define_insn "*subcq"
2771 [(set (match_operand:QI 0 "register_operand" "=q")
2772 (minus:QI (minus:QI (reg:QI CC_REGNUM)
2773 (match_operand:QI 1 "register_operand" "0"))
2774 (match_operand:QI 2 "general_operand" "ium")))]
2778 ;;--------------------------------------------------------------------
2779 ;;- Multiply instructions.
2780 ;;--------------------------------------------------------------------
2782 ;; 32 and 64-bit multiply are handled by the library
2785 (define_expand "mulsi3"
2786 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2787 (mult:SI (match_operand:SI 1 "general_operand" "")
2788 (match_operand:SI 2 "general_operand" "")))]
2790 "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2793 (define_expand "mulhi3"
2794 [(parallel [(set (match_operand:HI 0 "register_operand" "")
2795 (mult:HI (match_operand:HI 1 "register_operand" "")
2796 (match_operand:HI 2 "register_operand" "")))
2797 (clobber (match_scratch:HI 3 ""))])]
2801 (define_insn "mulhi3_m68hc11"
2802 [(set (match_operand:HI 0 "register_operand" "=d")
2803 (mult:HI (match_operand:HI 1 "register_operand" "%0")
2804 (match_operand:HI 2 "register_operand" "x")))
2805 (clobber (match_scratch:HI 3 "=X"))]
2810 /* D * X -> D (X and Y are preserved by this function call). */
2811 return \"jsr\\t___mulhi3\";
2814 (define_insn "mulhi3_m68hc12"
2815 [(set (match_operand:HI 0 "register_operand" "=d,d")
2816 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2817 (match_operand:HI 2 "register_operand" "y,x")))
2818 (clobber (match_scratch:HI 3 "=2,2"))]
2823 if (X_REG_P (operands[2]))
2824 return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2829 (define_insn "umulhisi3"
2830 [(set (match_operand:SI 0 "register_operand" "=D,D")
2831 (mult:SI (zero_extend:SI
2832 (match_operand:HI 1 "register_operand" "%d,d"))
2834 (match_operand:HI 2 "register_operand" "y,x"))))
2835 (clobber (match_scratch:HI 3 "=2,X"))]
2839 if (X_REG_P (operands [2]))
2840 output_asm_insn (\"exg\\tx,y\", operands);
2842 /* Can't use the carry after that; other flags are ok when testing
2843 the 32-bit result. */
2844 cc_status.flags |= CC_NO_OVERFLOW;
2845 return \"emul\\n\\texg\\tx,y\";
2848 (define_insn "mulhisi3"
2849 [(set (match_operand:SI 0 "register_operand" "=D,D")
2850 (mult:SI (sign_extend:SI
2851 (match_operand:HI 1 "register_operand" "%d,d"))
2853 (match_operand:HI 2 "register_operand" "y,x"))))
2854 (clobber (match_scratch:HI 3 "=2,X"))]
2858 if (X_REG_P (operands [2]))
2859 output_asm_insn (\"exg\\tx,y\", operands);
2861 /* Can't use the carry after that; other flags are ok when testing
2862 the 32-bit result. */
2863 cc_status.flags |= CC_NO_OVERFLOW;
2864 return \"emuls\\n\\texg\\tx,y\";
2867 (define_insn "umulqihi3"
2868 [(set (match_operand:HI 0 "register_operand" "=d")
2869 (mult:HI (zero_extend:HI
2870 (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2872 (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2876 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2878 output_asm_insn (\"tba\", operands);
2884 if (D_REG_P (operands[2]))
2886 rtx temp = operands[2];
2887 operands[2] = operands[1];
2891 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2892 ops[1] = operands[2];
2893 m68hc11_gen_movqi (insn, ops);
2895 if (!D_REG_P (operands[1]))
2897 output_asm_insn (\"ldab\\t%b1\", operands);
2905 (define_insn "mulqi3"
2906 [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
2907 (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
2908 (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
2912 if (A_REG_P (operands[0]))
2915 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2917 output_asm_insn (\"tba\", operands);
2921 if (D_REG_P (operands[2]))
2923 rtx temp = operands[2];
2924 operands[2] = operands[1];
2928 output_asm_insn (\"ldaa\\t%b2\", operands);
2930 if (!D_REG_P (operands[1]))
2932 output_asm_insn (\"ldab\\t%b1\", operands);
2941 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
2942 (mult:QI (match_operand:QI 1 "general_operand" "")
2943 (match_operand:QI 2 "general_operand" "")))]
2944 "z_replacement_completed == 2"
2945 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2946 (set (match_dup 3) (reg:HI D_REGNUM))])
2947 (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
2948 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2949 (set (match_dup 3) (reg:HI D_REGNUM))])]
2951 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
2952 if (A_REG_P (operands[1]))
2953 operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2955 operands[5] = operands[1];
2956 if (A_REG_P (operands[2]))
2957 operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2959 operands[6] = operands[2];
2962 (define_insn "mulqihi3"
2963 [(set (match_operand:HI 0 "register_operand" "=d,d,d")
2964 (mult:HI (sign_extend:HI
2965 (match_operand:QI 1 "register_operand" "%0,0,0"))
2967 (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
2973 /* Special case when multiplying the register with itself. */
2974 if (D_REG_P (operands[2]))
2976 output_asm_insn (\"tba\", operands);
2980 if (!H_REG_P (operands[2]))
2982 output_asm_insn (\"ldaa\\t%b2\", operands);
2988 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2989 ops[1] = operands[2];
2990 m68hc11_gen_movqi (insn, ops);
2992 return \"jsr\\t___mulqi3\";
2995 ;;--------------------------------------------------------------------
2996 ;;- Divide instructions.
2997 ;;--------------------------------------------------------------------
2999 (define_insn "divmodhi4"
3000 [(set (match_operand:HI 0 "register_operand" "=d,d")
3001 (div:HI (match_operand:HI 1 "register_operand" "0,0")
3002 (match_operand:HI 2 "general_operand" "A,ium")))
3003 (set (match_operand:HI 3 "register_operand" "=&x,&x")
3004 (mod:HI (match_dup 1) (match_dup 2)))]
3008 if (!X_REG_P (operands[2]))
3010 if (Y_REG_P (operands[2]))
3012 output_asm_insn (\"sty\\t%t1\", operands);
3013 output_asm_insn (\"ldx\\t%t1\", operands);
3017 output_asm_insn (\"ldx\\t%2\", operands);
3022 /* Flags are ok after that. */
3023 return \"idivs\\n\\txgdx\";
3028 return \"bsr\\t__divmodhi4\";
3032 (define_insn "udivmodhi4"
3033 [(set (match_operand:HI 0 "register_operand" "=d,d")
3034 (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
3035 (match_operand:HI 2 "general_operand" "A,ium")))
3036 (set (match_operand:HI 3 "register_operand" "=x,x")
3037 (umod:HI (match_dup 1) (match_dup 2)))]
3041 if (!X_REG_P (operands[2]))
3043 if (Y_REG_P (operands[2]))
3045 output_asm_insn (\"sty\\t%t1\", operands);
3046 output_asm_insn (\"ldx\\t%t1\", operands);
3050 output_asm_insn (\"ldx\\t%2\", operands);
3054 /* Z V and C flags are set but N is unchanged.
3055 Since this is an unsigned divide, we can probably keep the flags
3056 and indicate this. */
3057 cc_status.flags |= CC_NOT_NEGATIVE;
3058 return \"idiv\\n\\txgdx\";
3061 ;;--------------------------------------------------------------------
3062 ;;- and instructions.
3063 ;;--------------------------------------------------------------------
3065 (define_insn_and_split "anddi3"
3066 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3067 (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3068 (match_operand:DI 2 "general_operand" "imu,imu")))
3069 (clobber (match_scratch:HI 3 "=d,d"))]
3074 "m68hc11_split_logical (SImode, AND, operands);
3077 (define_insn_and_split "andsi3"
3078 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3079 (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3080 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3081 (clobber (match_scratch:HI 3 "=X,d"))]
3086 "m68hc11_split_logical (HImode, AND, operands);
3089 (define_expand "andhi3"
3090 [(set (match_operand:HI 0 "register_operand" "")
3091 (and:HI (match_operand:HI 1 "register_operand" "")
3092 (match_operand:HI 2 "general_operand" "")))]
3096 (define_insn "*andhi3_mem"
3097 [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3098 (and:HI (match_dup 0)
3099 (match_operand:HI 1 "immediate_operand" "i,i")))
3100 (clobber (match_scratch:HI 2 "=X,xy"))]
3101 "TARGET_RELAX && !TARGET_M6812"
3104 int val = INTVAL (operands[1]) & 0x0FFFF;
3108 cc_status = cc_prev_status;
3114 /* The bclr instruction uses an inverted mask. */
3115 operands[1] = GEN_INT ((~val) & 0x0FFFF);
3117 /* When destination is a global variable, generate a .relax instruction
3118 and load the address in the clobber register. That load can be
3119 eliminated by the linker if the address is in page0. */
3120 if (which_alternative == 1)
3124 ops[0] = operands[2];
3125 ops[1] = XEXP (operands[0], 0);
3126 ops[2] = gen_label_rtx ();
3127 output_asm_insn (\".relax\\t%l2\", ops);
3128 m68hc11_gen_movhi (insn, ops);
3129 if ((val & 0x0FF) != 0x0FF)
3130 output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
3132 if ((val & 0x0FF00) != 0x0FF00)
3133 output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
3135 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3136 CODE_LABEL_NUMBER (ops[2]));
3140 if ((val & 0x0FF) != 0x0FF)
3141 output_asm_insn (\"bclr\\t%b0, %b1\", operands);
3143 if ((val & 0x0FF00) != 0x0FF00)
3144 output_asm_insn (\"bclr\\t%h0, %h1\", operands);
3149 (define_insn "*andhi3_const"
3150 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3151 (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3152 (match_operand:HI 2 "const_int_operand" "")))]
3156 int val = INTVAL (operands[2]) & 0x0FFFF;
3157 int lowpart_zero = 0;
3158 int highpart_zero = 0;
3159 int lowpart_unknown = 0;
3160 int highpart_unknown = 0;
3162 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3167 cc_status = cc_prev_status;
3171 /* First, try to clear the low and high part.
3172 If that's possible, the second 'and' will give
3173 the good status flags and we can avoid a tsthi. */
3174 if ((val & 0x0FF) == 0)
3176 if (D_REG_P (operands[0]))
3177 output_asm_insn (\"clrb\", operands);
3179 output_asm_insn (\"clr\\t%b0\", operands);
3182 if ((val & 0x0FF00) == 0)
3184 if (D_REG_P (operands[0]))
3185 output_asm_insn (\"clra\", operands);
3187 output_asm_insn (\"clr\\t%h0\", operands);
3191 if ((val & 0x0FF) == 0x0FF)
3193 lowpart_unknown = 1;
3195 else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3199 ops[0] = operands[0];
3200 ops[1] = GEN_INT ((~val) & 0x0FF);
3201 output_asm_insn (\"bclr\\t%b0, %1\", ops);
3203 else if ((val & 0x0FF) != 0)
3205 output_asm_insn (\"andb\\t%b2\", operands);
3208 if ((val & 0x0FF00) == 0x0FF00)
3210 highpart_unknown = 1;
3212 else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3216 ops[0] = operands[0];
3217 ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
3218 output_asm_insn (\"bclr\\t%h0, %1\", ops);
3220 else if ((val & 0x0FF00) != 0)
3222 output_asm_insn (\"anda\\t%h2\", operands);
3225 if (highpart_unknown || lowpart_unknown)
3227 else if (highpart_zero == 0 && lowpart_zero == 0)
3233 (define_insn "*andhi3_gen"
3234 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3235 (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3236 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3240 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3244 return \"anda\\t%h2\\n\\tandb\\t%b2\";
3247 (define_expand "andqi3"
3248 [(set (match_operand:QI 0 "register_operand" "")
3249 (and:QI (match_operand:QI 1 "register_operand" "")
3250 (match_operand:QI 2 "general_operand" "")))]
3254 (define_insn "*andqi3_mem"
3255 [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3256 (and:QI (match_dup 0)
3257 (match_operand:QI 1 "const_int_operand" "i,i")))
3258 (clobber (match_scratch:HI 2 "=X,xy"))]
3259 "TARGET_RELAX && !TARGET_M6812"
3262 int val = INTVAL (operands[1]) & 0x0FF;
3266 cc_status = cc_prev_status;
3270 /* The bclr instruction uses an inverted mask. */
3271 operands[1] = GEN_INT ((~val) & 0x0FF);
3273 /* When destination is a global variable, generate a .relax instruction
3274 and load the address in the clobber register. That load can be
3275 eliminated by the linker if the address is in page0. */
3276 if (which_alternative == 1)
3280 ops[0] = operands[2];
3281 ops[1] = XEXP (operands[0], 0);
3282 ops[2] = gen_label_rtx ();
3283 output_asm_insn (\".relax\\t%l2\", ops);
3284 m68hc11_gen_movhi (insn, ops);
3285 output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3286 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3287 CODE_LABEL_NUMBER (ops[2]));
3290 return \"bclr\\t%b0, %1\";
3293 (define_insn "*andqi3_const"
3294 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3295 (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3296 (match_operand:QI 2 "const_int_operand" "")))]
3300 int val = INTVAL (operands[2]) & 0x0FF;
3302 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3307 cc_status = cc_prev_status;
3310 if (!H_REG_P (operands[0]))
3314 ops[0] = operands[0];
3315 ops[1] = GEN_INT ((~val) & 0x0FF);
3316 output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3319 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3320 return \"andb\\t%b2\";
3321 else if (DA_REG_P (operands[0]))
3322 return \"anda\\t%b2\";
3324 fatal_insn (\"Invalid operand in the instruction\", insn);
3327 (define_insn "*andqi3_gen"
3328 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3329 (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3330 (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
3334 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3337 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3338 return \"andb\\t%b2\";
3339 else if (DA_REG_P (operands[0]))
3340 return \"anda\\t%b2\";
3342 fatal_insn (\"Invalid operand in the instruction\", insn);
3345 ;;--------------------------------------------------------------------
3346 ;;- Bit set or instructions.
3347 ;;--------------------------------------------------------------------
3349 (define_insn_and_split "iordi3"
3350 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3351 (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3352 (match_operand:DI 2 "general_operand" "imu,imu")))
3353 (clobber (match_scratch:HI 3 "=d,d"))]
3358 "m68hc11_split_logical (SImode, IOR, operands);
3361 (define_insn_and_split "iorsi3"
3362 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3363 (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3364 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3365 (clobber (match_scratch:HI 3 "=X,d"))]
3370 "m68hc11_split_logical (HImode, IOR, operands);
3373 (define_expand "iorhi3"
3374 [(set (match_operand:HI 0 "register_operand" "")
3375 (ior:HI (match_operand:HI 1 "register_operand" "")
3376 (match_operand:HI 2 "splitable_operand" "")))]
3380 (define_insn "*iorhi3_mem"
3381 [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3382 (ior:HI (match_dup 0)
3383 (match_operand:HI 1 "const_int_operand" "")))
3384 (clobber (match_scratch:HI 2 "=X,xy"))]
3385 "TARGET_RELAX && !TARGET_M6812"
3388 int val = INTVAL (operands[1]) & 0x0FFFF;
3392 cc_status = cc_prev_status;
3396 if (which_alternative == 1)
3400 ops[0] = operands[2];
3401 ops[1] = XEXP (operands[0], 0);
3402 ops[2] = gen_label_rtx ();
3403 output_asm_insn (\".relax\\t%l2\", ops);
3404 m68hc11_gen_movhi (insn, ops);
3405 if ((val & 0x0FF) != 0)
3406 output_asm_insn (\"bset\\t1,%2, %b1\", operands);
3408 if ((val & 0x0FF00) != 0)
3409 output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3410 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3411 CODE_LABEL_NUMBER (ops[2]));
3415 if ((val & 0x0FF) != 0)
3416 output_asm_insn (\"bset\\t%b0, %b1\", operands);
3418 if ((val & 0x0FF00) != 0)
3419 output_asm_insn (\"bset\\t%h0, %h1\", operands);
3424 (define_insn "*iorhi3_const"
3425 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3426 (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3427 (match_operand:HI 2 "const_int_operand" "")))]
3431 int val = INTVAL (operands[2]) & 0x0FFFF;
3433 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3438 cc_status = cc_prev_status;
3442 if ((val & 0x0FF) != 0)
3444 if (!H_REG_P (operands[0]))
3445 output_asm_insn (\"bset\\t%b0, %b2\", operands);
3447 output_asm_insn (\"orab\\t%b2\", operands);
3450 if ((val & 0x0FF00) != 0)
3452 if (!H_REG_P (operands[0]))
3453 output_asm_insn (\"bset\\t%h0, %h2\", operands);
3455 output_asm_insn (\"oraa\\t%h2\", operands);
3462 (define_insn "*iorhi3_gen"
3463 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3464 (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3465 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3469 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3473 return \"oraa\\t%h2\\n\\torab\\t%b2\";
3476 (define_expand "iorqi3"
3477 [(set (match_operand:QI 0 "register_operand" "")
3478 (ior:QI (match_operand:QI 1 "register_operand" "")
3479 (match_operand:QI 2 "general_operand" "")))]
3483 (define_insn "*iorqi3_mem"
3484 [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3485 (ior:QI (match_dup 0)
3486 (match_operand:QI 1 "const_int_operand" "")))
3487 (clobber (match_scratch:HI 2 "=X,xy"))]
3488 "TARGET_RELAX && !TARGET_M6812"
3491 int val = INTVAL (operands[1]) & 0x0FF;
3495 cc_status = cc_prev_status;
3498 if (which_alternative == 1)
3502 ops[0] = operands[2];
3503 ops[1] = XEXP (operands[0], 0);
3504 ops[2] = gen_label_rtx ();
3505 output_asm_insn (\".relax\\t%l2\", ops);
3506 m68hc11_gen_movhi (insn, ops);
3507 output_asm_insn (\"bset\\t0,%2, %1\", operands);
3508 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3509 CODE_LABEL_NUMBER (ops[2]));
3512 return \"bset\\t%b0, %1\";
3515 (define_insn "*iorqi3_const"
3516 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3517 (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3518 (match_operand:QI 2 "const_int_operand" "")))]
3522 int val = INTVAL (operands[2]) & 0x0FF;
3524 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3529 cc_status = cc_prev_status;
3532 if (!H_REG_P (operands[0]))
3534 return \"bset\\t%b0, %2\";
3537 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3538 return \"orab\\t%b2\";
3539 else if (DA_REG_P (operands[0]))
3540 return \"oraa\\t%b2\";
3542 fatal_insn (\"Invalid operand in the instruction\", insn);
3545 (define_insn "*iorqi3_gen"
3546 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3547 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3548 (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
3552 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3555 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3556 return \"orab\\t%b2\";
3557 else if (DA_REG_P (operands[0]))
3558 return \"oraa\\t%b2\";
3560 fatal_insn (\"Invalid operand in the instruction\", insn);
3564 ;;--------------------------------------------------------------------
3565 ;;- xor instructions.
3566 ;;--------------------------------------------------------------------
3568 (define_insn_and_split "xordi3"
3569 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3570 (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3571 (match_operand:DI 2 "general_operand" "imu,imu")))
3572 (clobber (match_scratch:HI 3 "=d,d"))]
3577 "m68hc11_split_logical (SImode, XOR, operands);
3580 (define_insn_and_split "xorsi3"
3581 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3582 (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3583 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3584 (clobber (match_scratch:HI 3 "=X,d"))]
3589 "m68hc11_split_logical (HImode, XOR, operands);
3592 (define_insn "xorhi3"
3593 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3594 (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3595 (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
3599 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3602 if (GET_CODE (operands[2]) == CONST_INT)
3604 int val = INTVAL (operands[2]) & 0x0FFFF;
3608 cc_status = cc_prev_status;
3611 if ((val & 0x0FF) != 0)
3613 output_asm_insn (\"eorb\\t%b2\", operands);
3615 else if ((val & 0x0FF) == 0x0FF)
3617 output_asm_insn (\"comb\", operands);
3620 if ((val & 0x0FF00) != 0)
3622 output_asm_insn (\"eora\\t%h2\", operands);
3624 else if ((val & 0x0FF00) == 0x0FF00)
3626 output_asm_insn (\"coma\", operands);
3634 return \"eora\\t%h2\\n\\teorb\\t%b2\";
3637 (define_insn "xorqi3"
3638 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3639 (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3640 (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
3644 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3647 if (GET_CODE (operands[2]) == CONST_INT)
3649 int val = INTVAL (operands[2]) & 0x0FF;
3653 cc_status = cc_prev_status;
3658 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3664 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3665 return \"eorb\\t%b2\";
3666 else if (DA_REG_P (operands[0]))
3667 return \"eora\\t%b2\";
3669 fatal_insn (\"Invalid operand in the instruction\", insn);
3672 ;;--------------------------------------------------------------------
3673 ;;- Bit set or instructions.
3674 ;;--------------------------------------------------------------------
3676 (define_insn_and_split "*logicalsi3_zexthi"
3677 [(set (match_operand:SI 0 "register_operand" "=D")
3678 (match_operator:SI 3 "m68hc11_logical_operator"
3680 (match_operand:HI 1 "general_operand" "imudA"))
3681 (match_operand:SI 2 "general_operand" "Dimu")]))]
3685 [(set (reg:HI D_REGNUM) (match_dup 4))
3686 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3687 (set (reg:HI X_REGNUM) (match_dup 6))]
3688 "PUT_MODE (operands[3], HImode);
3689 if (X_REG_P (operands[2]))
3691 operands[5] = operands[1];
3692 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3693 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3694 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3698 operands[4] = operands[1];
3699 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3700 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3702 /* For an AND, make sure the high 16-bit part is cleared. */
3703 if (GET_CODE (operands[3]) == AND)
3705 operands[6] = const0_rtx;
3709 (define_insn_and_split "*logicalsi3_zextqi"
3710 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3711 (match_operator:SI 3 "m68hc11_logical_operator"
3713 (match_operand:QI 1 "general_operand" "d,*A,imu"))
3714 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3717 "z_replacement_completed == 2"
3718 [(set (reg:QI A_REGNUM) (match_dup 4))
3719 (set (reg:QI D_REGNUM) (match_dup 7))
3720 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3721 (set (reg:HI X_REGNUM) (match_dup 6))]
3722 "PUT_MODE (operands[3], QImode);
3723 if (X_REG_P (operands[2]))
3725 operands[5] = operands[1];
3726 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3727 operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3728 operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
3729 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3733 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3734 operands[7] = operands[1];
3735 operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3736 operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3737 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3739 /* For an AND, make sure the high 24-bit part is cleared. */
3740 if (GET_CODE (operands[3]) == AND)
3742 operands[4] = const0_rtx;
3743 operands[6] = const0_rtx;
3747 (define_insn_and_split "*logicalhi3_zexthi_ashift8"
3748 [(set (match_operand:HI 0 "register_operand" "=d")
3749 (match_operator:HI 3 "m68hc11_logical_operator"
3751 (match_operand:QI 1 "general_operand" "imud*A"))
3753 (match_operand:HI 2 "general_operand" "imud*A")
3757 "z_replacement_completed == 2"
3758 [(set (reg:QI A_REGNUM) (match_dup 4))
3759 (set (reg:QI B_REGNUM) (match_dup 5))]
3761 if (GET_CODE (operands[3]) == AND)
3763 emit_insn (gen_movhi (operands[0], const0_rtx));
3768 operands[5] = operands[1];
3769 if (D_REG_P (operands[2]))
3771 operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3775 operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3780 (define_insn_and_split "*logicalhi3_zexthi"
3781 [(set (match_operand:HI 0 "register_operand" "=d,d")
3782 (match_operator:HI 3 "m68hc11_logical_operator"
3784 (match_operand:QI 1 "general_operand" "imd*A,?u"))
3785 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3788 "z_replacement_completed == 2"
3789 [(set (reg:QI B_REGNUM) (match_dup 6))
3790 (set (reg:QI A_REGNUM) (match_dup 4))
3791 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3793 PUT_MODE (operands[3], QImode);
3794 if (D_REG_P (operands[2]))
3796 operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3797 operands[5] = operands[1];
3798 operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3802 operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3803 operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3804 if (D_REG_P (operands[1]))
3805 operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3807 operands[6] = operands[1];
3809 /* For an AND, make sure the high 8-bit part is cleared. */
3810 if (GET_CODE (operands[3]) == AND)
3812 operands[4] = const0_rtx;
3817 (define_insn_and_split "*logicalsi3_silshr16"
3818 [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
3819 (match_operator:SI 3 "m68hc11_logical_operator"
3821 (match_operand:SI 1 "general_operand" "uim,uim,0,0")
3823 (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
3827 [(set (reg:HI D_REGNUM) (match_dup 4))
3828 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3829 (set (reg:HI X_REGNUM) (match_dup 6))]
3830 "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3831 if (X_REG_P (operands[2]))
3833 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3834 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3838 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3839 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3841 PUT_MODE (operands[3], HImode);
3843 /* For an AND, make sure the high 16-bit part is cleared. */
3844 if (GET_CODE (operands[3]) == AND)
3846 operands[6] = const0_rtx;
3850 (define_insn_and_split "*logicalsi3_silshl16"
3851 [(set (match_operand:SI 0 "register_operand" "=D,D")
3852 (match_operator:SI 3 "m68hc11_logical_operator"
3854 (match_operand:SI 1 "general_operand" "uim,?D")
3856 (match_operand:SI 2 "general_operand" "0,0")]))]
3859 "z_replacement_completed == 2"
3860 [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3861 (set (reg:HI D_REGNUM) (match_dup 5))]
3862 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3863 PUT_MODE (operands[3], HImode);
3865 if (GET_CODE (operands[3]) == AND)
3866 operands[5] = const0_rtx;
3868 operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3871 (define_insn_and_split "*logicalsi3_silshl16_zext"
3872 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3873 (match_operator:SI 3 "m68hc11_logical_operator"
3876 (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
3878 (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
3881 ;; Must split before z register replacement
3883 [(set (match_dup 4) (match_dup 5))
3884 (set (match_dup 6) (match_dup 7))]
3886 /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
3887 if (GET_CODE (operands[1]) == HARD_D_REGNUM
3888 && GET_CODE (operands[3]) != AND)
3890 /* This particular case is too early to be split before
3891 Z register replacement because the cse-reg pass we do
3892 does not recognize the 'swap_areg'. It is ok to handle
3894 if (z_replacement_completed != 2)
3898 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
3899 emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
3900 gen_rtx_REG (HImode, HARD_X_REGNUM)));
3902 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3903 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3904 operands[5] = operands[2];
3905 operands[7] = operands[1];
3907 if (GET_CODE (operands[3]) == AND)
3908 operands[5] = operands[7] = const0_rtx;
3911 ;;--------------------------------------------------------------------
3912 ;; 16-bit Arithmetic and logical operations on X and Y:
3914 ;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3916 ;; Operations on X or Y registers are split here. Instructions are
3918 ;; - xgdx/xgdy instruction pattern,
3919 ;; - The same operation on register D,
3920 ;; - xgdx/xgdy instruction pattern.
3921 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3922 ;; We also handle the case were the address register is used in both source
3923 ;; operands, such as:
3925 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3927 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3931 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3932 (match_operator:HI 3 "m68hc11_arith_operator"
3933 [(match_operand:HI 1 "hard_addr_reg_operand" "")
3934 (match_operand:HI 2 "general_operand" "")]))]
3935 "z_replacement_completed == 2
3936 /* If we are adding a small constant to X or Y, it's
3937 better to use one or several inx/iny instructions. */
3938 && !(GET_CODE (operands[3]) == PLUS
3940 && (immediate_operand (operands[2], HImode)
3941 || hard_reg_operand (operands[2], HImode)))
3942 || (GET_CODE (operands[2]) == CONST_INT
3943 && INTVAL (operands[2]) >= -4
3944 && INTVAL (operands[2]) <= 4)))"
3945 [(set (match_dup 9) (match_dup 0))
3946 (set (match_dup 4) (match_dup 5))
3947 (set (match_dup 8) (match_dup 7))
3948 (set (match_dup 0) (match_dup 1))
3949 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3950 (set (match_dup 0) (reg:HI D_REGNUM))])
3951 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3952 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3953 (set (match_dup 0) (reg:HI D_REGNUM))])]
3955 operands[9] = operands[0];
3956 /* For 68HC12, push the value on the stack and do the operation
3959 && m68hc11_non_shift_operator (operands[3], HImode)
3960 && (H_REG_P (operands[2])
3961 || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3962 && reg_mentioned_p (operands[0], operands[2]))))
3964 operands[4] = gen_rtx_MEM (HImode,
3965 gen_rtx_PRE_DEC (HImode,
3966 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3967 operands[6] = gen_rtx_MEM (HImode,
3968 gen_rtx_POST_INC (HImode,
3969 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3970 operands[5] = operands[2];
3971 operands[8] = operands[7] = operands[0];
3973 /* Save the operand2 in a temporary location and use it. */
3974 else if ((H_REG_P (operands[2])
3975 || reg_mentioned_p (operands[0], operands[2]))
3976 && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3978 if (GET_CODE (operands[3]) == MINUS
3979 && reg_mentioned_p (operands[0], operands[2]))
3981 operands[9] = gen_rtx_MEM (HImode,
3982 gen_rtx_PRE_DEC (HImode,
3983 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3984 operands[1] = gen_rtx_MEM (HImode,
3985 gen_rtx_POST_INC (HImode,
3986 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3987 operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3988 operands[4] = operands[7] = operands[0];
3989 operands[6] = operands[8];
3990 operands[5] = operands[2];
3994 operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3995 operands[6] = operands[4];
3996 if (!H_REG_P (operands[2]))
3998 operands[5] = operands[0];
3999 operands[7] = operands[2];
4000 operands[8] = operands[0];
4004 operands[5] = operands[2];
4005 operands[8] = operands[7] = operands[0];
4011 operands[4] = operands[5] = operands[0];
4012 operands[6] = operands[2];
4013 operands[8] = operands[7] = operands[0];
4018 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4019 (match_operator:HI 3 "m68hc11_arith_operator"
4020 [(match_operand:HI 1 "general_operand" "")
4021 (match_operand:HI 2 "general_operand" "")]))]
4022 "z_replacement_completed == 2
4023 /* If we are adding a small constant to X or Y, it's
4024 better to use one or several inx/iny instructions. */
4025 && !(GET_CODE (operands[3]) == PLUS
4027 && (immediate_operand (operands[2], HImode)
4028 || hard_reg_operand (operands[2], HImode)))
4029 || (GET_CODE (operands[2]) == CONST_INT
4030 && INTVAL (operands[2]) >= -4
4031 && INTVAL (operands[2]) <= 4)))"
4032 [(set (match_dup 0) (match_dup 1))
4033 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4034 (set (match_dup 0) (reg:HI D_REGNUM))])
4035 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
4036 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4037 (set (match_dup 0) (reg:HI D_REGNUM))])]
4042 ;; Next split handles the logical operations on D register with
4043 ;; another hard register for the second operand. For this, we
4044 ;; have to save the second operand in a scratch location and use
4045 ;; it instead. This must be supported because in some (rare) cases
4046 ;; the second operand can come in a hard register and the reload
4047 ;; pass doesn't know how to reload it in a memory location.
4049 ;; PLUS MINUS AND IOR XOR
4051 ;; The shift operators are special and must not appear here.
4054 [(set (match_operand:HI 0 "d_register_operand" "")
4055 (match_operator:HI 3 "m68hc11_non_shift_operator"
4056 [(match_operand:HI 1 "d_register_operand" "")
4057 (match_operand:HI 2 "hard_reg_operand" "")]))]
4059 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4060 [(set (match_dup 4) (match_dup 2))
4061 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4062 "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
4065 ;; For 68HC12, push the operand[2] value on the stack and do the
4066 ;; logical/arithmetic operation with a pop.
4069 [(set (match_operand:HI 0 "d_register_operand" "")
4070 (match_operator:HI 3 "m68hc11_non_shift_operator"
4071 [(match_operand:HI 1 "d_register_operand" "")
4072 (match_operand:HI 2 "hard_reg_operand" "")]))]
4074 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4075 [(set (match_dup 4) (match_dup 2))
4076 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4077 "operands[4] = gen_rtx_MEM (HImode,
4078 gen_rtx_PRE_DEC (HImode,
4079 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4080 operands[5] = gen_rtx_MEM (HImode,
4081 gen_rtx_POST_INC (HImode,
4082 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4085 ;;--------------------------------------------------------------------
4086 ;; 16-bit Unary operations on X and Y:
4090 ;; Operations on X or Y registers are split here. Instructions are
4092 ;; - xgdx/xgdy instruction pattern,
4093 ;; - The same operation on register D,
4094 ;; - xgdx/xgdy instruction pattern.
4095 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4096 ;; We also handle the case were the address register is used in both source
4097 ;; operands, such as:
4099 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4101 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4104 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4105 (match_operator:HI 2 "m68hc11_unary_operator"
4106 [(match_operand 1 "general_operand" "")]))]
4107 "z_replacement_completed == 2"
4108 [(set (match_dup 4) (match_dup 5))
4109 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4110 (set (match_dup 0) (reg:HI D_REGNUM))])
4111 (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4112 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4113 (set (match_dup 0) (reg:HI D_REGNUM))])]
4116 if ((H_REG_P (operands[1])
4117 && !rtx_equal_p (operands[0], operands[1]))
4118 || reg_mentioned_p (operands[0], operands[1]))
4120 /* Move to the destination register, before the xgdx. */
4121 operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
4122 REGNO (operands[0]));
4123 operands[5] = operands[1];
4125 /* Apply the operation on D. */
4126 operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
4130 /* Generate a copy to same register (nop). */
4131 operands[4] = operands[5] = operands[0];
4132 operands[3] = operands[1];
4137 ;; 8-bit operations on address registers.
4139 ;; We have to take care that the address register is not used for the
4140 ;; source of operand2. If operand2 is the D register, we have to save
4141 ;; that register in a temporary location.
4143 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4146 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4147 (match_operator:QI 3 "m68hc11_arith_operator"
4148 [(match_operand:QI 1 "hard_addr_reg_operand" "")
4149 (match_operand:QI 2 "general_operand" "")]))]
4150 "z_replacement_completed == 2
4151 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
4152 incqi pattern generates a better code. */
4153 && !(GET_CODE (operands[3]) == PLUS
4154 && GET_CODE (operands[2]) == CONST_INT
4155 && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4156 [(set (match_dup 5) (match_dup 6))
4157 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4158 (set (match_dup 4) (reg:HI D_REGNUM))])
4159 (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4160 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4161 (set (match_dup 4) (reg:HI D_REGNUM))])]
4162 "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
4164 /* For the second operand is a hard register or if the address
4165 register appears in the source, we have to save the operand[2]
4166 value in a temporary location and then use that temp.
4167 Otherwise, it's ok and we generate a (set (D) (D)) that
4168 will result in a nop. */
4169 if (H_REG_P (operands[2]))
4171 operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4172 operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
4173 operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4175 else if (reg_mentioned_p (operands[0], operands[2]))
4177 operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4178 operands[6] = operands[2];
4179 operands[7] = operands[5];
4183 operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4184 operands[7] = operands[2];
4189 ;; Next split handles the logical operations on D register with
4190 ;; another hard register for the second operand. For this, we
4191 ;; have to save the second operand in a scratch location and use
4192 ;; it instead. This must be supported because in some (rare) cases
4193 ;; the second operand can come in a hard register and the reload
4194 ;; pass doesn't know how to reload it in a memory location.
4196 ;; PLUS MINUS AND IOR XOR
4198 ;; The shift operators are special and must not appear here.
4201 [(set (match_operand:QI 0 "d_register_operand" "")
4202 (match_operator:QI 3 "m68hc11_non_shift_operator"
4203 [(match_operand:QI 1 "d_register_operand" "")
4204 (match_operand:QI 2 "hard_reg_operand" "")]))]
4206 [(set (match_dup 5) (match_dup 6))
4207 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4208 "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4209 operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4210 operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
4212 ;;--------------------------------------------------------------------
4213 ;; 8-bit Unary operations on X and Y:
4217 ;; Operations on X or Y registers are split here. Instructions are
4219 ;; - xgdx/xgdy instruction pattern,
4220 ;; - The same operation on register D,
4221 ;; - xgdx/xgdy instruction pattern.
4222 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4223 ;; We also handle the case were the address register is used in both source
4224 ;; operands, such as:
4226 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4228 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4231 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4232 (match_operator:QI 2 "m68hc11_unary_operator"
4233 [(match_operand:QI 1 "general_operand" "")]))]
4234 "z_replacement_completed == 2"
4235 [(set (match_dup 4) (match_dup 5))
4236 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4237 (set (match_dup 3) (reg:HI D_REGNUM))])
4238 (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4239 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4240 (set (match_dup 3) (reg:HI D_REGNUM))])]
4243 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4244 if ((H_REG_P (operands[1])
4245 && !rtx_equal_p (operands[0], operands[1]))
4246 || reg_mentioned_p (operands[0], operands[1]))
4248 /* Move to the destination register, before the xgdx. */
4249 operands[4] = operands[0];
4250 operands[5] = operands[1];
4252 /* Apply the operation on D. */
4253 operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4257 operands[4] = operands[5] = operands[0];
4258 operands[6] = operands[1];
4263 ;;--------------------------------------------------------------------
4265 ;;--------------------------------------------------------------------
4267 (define_expand "negdi2"
4268 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4269 (neg:DI (match_operand:DI 1 "general_operand" "")))]
4271 "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4275 (define_insn "negsi2"
4276 [(set (match_operand:SI 0 "register_operand" "=D")
4277 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
4285 /* With -Os or without -O, use a special library call. */
4286 if (optimize_size || optimize == 0)
4287 return \"bsr\\t___negsi2\";
4289 ops[0] = gen_label_rtx ();
4291 /* 32-bit complement and add 1. */
4292 output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4293 output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4294 output_asm_insn (\"bne\\t%l0\", ops);
4295 output_asm_insn (\"inx\", operands);
4296 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4300 (define_insn "neghi2"
4301 [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
4302 (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4305 coma\\n\\tcomb\\n\\taddd\\t#1
4306 clra\\n\\tclrb\\n\\tsubd\\t%1
4307 xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4309 (define_insn "negqi2"
4310 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4311 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
4320 ;; - 32-bit complement. GCC knows how to translate them but providing a
4321 ;; pattern generates better/smaller code.
4323 (define_expand "one_cmpldi2"
4324 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4325 (not:DI (match_operand:DI 1 "general_operand" "")))]
4327 "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4330 (define_insn "one_cmplsi2"
4331 [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4332 (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4333 (clobber (match_scratch:HI 2 "=X,d,X"))]
4336 bsr\\t___one_cmplsi2
4340 (define_insn "one_cmplhi2"
4341 [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
4342 (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
4346 com\\t%b0\\n\\tcom\\t%h0
4348 com\\t%b0\\n\\tcom\\t%h0")
4350 (define_insn "one_cmplqi2"
4351 [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
4352 (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
4360 (define_split /* "*one_cmplsi2" */
4361 [(set (match_operand:SI 0 "non_push_operand" "")
4362 (not:SI (match_dup 0)))
4363 (clobber (match_scratch:HI 1 ""))]
4364 "z_replacement_completed == 2
4365 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4366 [(set (match_dup 2) (not:HI (match_dup 2)))
4367 (set (match_dup 3) (not:HI (match_dup 3)))]
4368 "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4369 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
4371 (define_split /* "*one_cmplsi2" */
4372 [(set (match_operand:SI 0 "non_push_operand" "")
4373 (not:SI (match_operand:SI 1 "non_push_operand" "")))
4374 (clobber (match_operand:HI 2 "d_register_operand" ""))]
4375 "z_replacement_completed == 2
4376 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4377 [(set (match_dup 2) (match_dup 3))
4378 (set (match_dup 2) (not:HI (match_dup 2)))
4379 (set (match_dup 4) (match_dup 2))
4380 (set (match_dup 2) (match_dup 5))
4381 (set (match_dup 2) (not:HI (match_dup 2)))
4382 (set (match_dup 6) (match_dup 2))]
4383 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4384 operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4385 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4386 operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
4388 ;;--------------------------------------------------------------------
4389 ;;- arithmetic shifts
4390 ;;--------------------------------------------------------------------
4392 ;; Provide some 64-bit shift patterns.
4393 (define_expand "ashldi3"
4394 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4395 (ashift:DI (match_operand:DI 1 "general_operand" "")
4396 (match_operand:HI 2 "general_operand" "")))
4397 (clobber (match_scratch:HI 3 ""))])]
4401 if (GET_CODE (operands[2]) != CONST_INT
4402 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4408 (define_insn_and_split "*ashldi3_const32"
4409 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4410 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4412 (clobber (match_scratch:HI 2 "=&A,d,d"))]
4417 "/* Move the lowpart in the highpart first in case the shift
4418 is applied on the source. */
4419 if (IS_STACK_PUSH (operands[0]))
4421 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4422 const0_rtx, operands[2]);
4424 /* Adjust first operand if it uses SP so that we take into
4425 account the above push. Can occur only for 68HC12. */
4426 if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
4428 operands[1] = adjust_address (operands[1],
4429 GET_MODE (operands[0]), 4);
4431 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4432 m68hc11_gen_lowpart (SImode, operands[1]),
4434 if (!IS_STACK_PUSH (operands[0]))
4436 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4437 const0_rtx, operands[2]);
4441 (define_insn_and_split "*ashldi3_const1"
4442 [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4443 (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4445 (clobber (match_scratch:HI 2 "=d,d,d"))]
4448 "z_replacement_completed == 2"
4449 [(set (match_dup 2) (match_dup 3))
4450 (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4451 (set (match_dup 4) (match_dup 2))
4453 (set (match_dup 2) (match_dup 5))
4454 (parallel [(set (match_dup 2)
4455 (rotate:HI (match_dup 2) (const_int 1)))
4456 (clobber (reg:HI CC_REGNUM))])
4457 (set (match_dup 6) (match_dup 2))
4459 (set (match_dup 2) (match_dup 7))
4460 (parallel [(set (match_dup 2)
4461 (rotate:HI (match_dup 2) (const_int 1)))
4462 (clobber (reg:HI CC_REGNUM))])
4463 (set (match_dup 8) (match_dup 2))
4465 (set (match_dup 2) (match_dup 9))
4466 (parallel [(set (match_dup 2)
4467 (rotate:HI (match_dup 2) (const_int 1)))
4468 (clobber (reg:HI CC_REGNUM))])
4469 (set (match_dup 10) (match_dup 2))]
4470 "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4471 operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4472 operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4474 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4475 operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4476 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4478 operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4479 operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4480 operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4482 operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4483 operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4484 operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4486 (define_insn "addsi_silshr16"
4487 [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
4488 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
4490 (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
4495 [(set (match_operand:SI 0 "register_operand" "")
4496 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4498 (match_operand:SI 2 "general_operand" "")))]
4499 "z_replacement_completed == 2 && !X_REG_P (operands[1])"
4500 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4501 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4503 (reg:HI CC_REGNUM)))]
4504 "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4507 [(set (match_operand:SI 0 "register_operand" "")
4508 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4510 (match_operand:SI 2 "general_operand" "")))]
4511 "z_replacement_completed == 2 && X_REG_P (operands[1])"
4512 [(set (reg:HI D_REGNUM) (match_dup 5))
4513 (set (reg:HI X_REGNUM) (match_dup 3))
4514 (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4515 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4517 (reg:HI CC_REGNUM)))]
4518 "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4519 if (X_REG_P (operands[2]))
4521 operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4522 operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4526 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4527 operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4531 (define_insn "addsi_ashift16"
4532 [(set (match_operand:SI 0 "register_operand" "=D")
4534 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4536 (match_operand:SI 1 "general_operand" "0")))
4537 (clobber (match_scratch:HI 3 "=X"))]
4542 [(set (match_operand:SI 0 "register_operand" "")
4544 (mult:SI (match_operand:SI 2 "general_operand" "")
4546 (match_operand:SI 1 "general_operand" "")))
4547 (clobber (match_scratch:HI 3 "=X"))]
4548 "0 && reload_completed && z_replacement_completed == 2"
4549 [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4552 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4555 (define_insn_and_split "addsi_andshr16"
4556 [(set (match_operand:SI 0 "register_operand" "=D")
4557 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4559 (match_operand:SI 2 "general_operand" "0")))]
4562 "z_replacement_completed == 2"
4563 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4564 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4565 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4568 ;; 32-bit shifts are made by a small library routine that uses
4569 ;; a specific passing convention for parameters (for efficiency reasons).
4571 ;; [D + X] -> Value to be shifted
4574 ;; The shift count is clobbered by the routine.
4576 (define_expand "ashlsi3"
4578 [(set (match_operand:SI 0 "register_operand" "")
4579 (match_operand:SI 1 "general_operand" ""))
4580 (clobber (scratch:HI))])
4582 [(set (match_dup 0) (ashift:SI (match_dup 0)
4583 (match_operand:HI 2 "nonmemory_operand" "")))
4584 (clobber (scratch:HI))])]
4589 [(set (match_operand:SI 0 "nonimmediate_operand" "")
4590 (ashift:SI (match_operand:SI 1 "general_operand" "")
4592 (clobber (match_scratch:HI 3 ""))]
4594 [(set (match_dup 2) (match_dup 3))
4595 (set (match_dup 4) (const_int 0))]
4596 "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4597 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4598 operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4600 (define_insn "*ashlsi3_const16"
4601 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4602 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4604 (clobber (match_scratch:HI 2 "=X,X,X"))]
4608 (define_insn_and_split "*ashlsi3_const16_zexthi"
4609 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4610 (ashift:SI (zero_extend:HI
4611 (match_operand:HI 1 "general_operand" "duim*A"))
4613 (clobber (match_scratch:HI 2 "=X"))]
4617 [(set (reg:HI X_REGNUM) (match_dup 1))
4618 (set (reg:HI D_REGNUM) (const_int 0))]
4621 (define_insn "*ashlsi3_const1"
4622 [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
4623 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
4625 (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
4630 if (X_REG_P (operands[1]))
4632 return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4638 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4639 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4640 m68hc11_gen_movhi (insn, ops);
4641 output_asm_insn (\"lsld\", ops);
4642 if (!X_REG_P (operands[0]))
4645 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4646 m68hc11_gen_movhi (insn, ops);
4648 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4649 m68hc11_gen_movhi (insn, ops);
4653 /* Load the high part in X in case the source operand
4654 uses X as a memory pointer. */
4655 ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4656 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4657 m68hc11_gen_movhi (insn, ops);
4658 output_asm_insn (\"xgdx\", ops);
4660 output_asm_insn (\"rolb\", ops);
4661 output_asm_insn (\"rola\", ops);
4662 if (!X_REG_P (operands[0]))
4665 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4666 m68hc11_gen_movhi (insn, ops);
4670 output_asm_insn (\"xgdx\", ops);
4676 (define_insn "*ashlsi3_const"
4677 [(set (match_operand:SI 0 "register_operand" "+D")
4678 (ashift:SI (match_dup 0)
4679 (match_operand:HI 1 "const_int_operand" "")))
4680 (clobber (match_scratch:HI 2 "=y"))]
4681 "TARGET_M6811 /* See *ashlsi3 note. */"
4685 return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4688 (define_insn "*ashlsi3"
4689 [(set (match_operand:SI 0 "register_operand" "+D,D")
4690 (ashift:SI (match_dup 0)
4691 (match_operand:HI 1 "general_operand" "y,mi")))
4692 (clobber (match_scratch:HI 2 "=1,X"))]
4698 /* There is a reload problem if we don't accept 'm' for the shift value.
4699 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4700 and this conflicts with all reloads. Since X, Y, Z are used there
4701 is not enough register in class A_REGS.
4703 Assuming that 'operands[1]' does not refer to the stack (which
4704 is true for 68hc11 only, we save temporary the value of Y.
4706 For 68HC12 we must also accept a constant because Z register is
4707 disabled when compiling with -fomit-frame-pointer. We can come up
4708 with a reload problem and the *lshrsi3_const pattern was disabled
4710 if (!Y_REG_P (operands[2]))
4713 int y_dead = dead_register_here (insn, iy_reg);
4715 ops[0] = operands[1];
4718 output_asm_insn (\"pshy\", operands);
4719 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4720 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4722 output_asm_insn (\"ldy\\t%0\", ops);
4723 output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4724 return y_dead == 0 ? \"puly\" : \"\";
4726 return \"bsr\\t___ashlsi3\";
4729 (define_expand "ashlhi3"
4730 [(set (match_operand:HI 0 "register_operand" "")
4731 (ashift:HI (match_operand:HI 1 "register_operand" "")
4732 (match_operand:HI 2 "general_operand" "")))]
4736 if (GET_CODE (operands[2]) != CONST_INT)
4738 rtx scratch = gen_reg_rtx (HImode);
4739 emit_move_insn (scratch, operands[2]);
4740 emit_insn (gen_rtx_PARALLEL (VOIDmode,
4741 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4743 gen_rtx_ASHIFT (HImode,
4744 operand1, scratch)),
4745 gen_rtx_CLOBBER (VOIDmode, scratch))));
4750 (define_insn "*ashlhi3_const1"
4751 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4752 (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4757 if (A_REG_P (operands[0]))
4760 if (D_REG_P (operands[0]))
4765 output_asm_insn (\"asl\\t%b0\", operands);
4766 output_asm_insn (\"rol\\t%h0\", operands);
4772 (define_insn "*ashlhi3_2"
4773 [(set (match_operand:HI 0 "register_operand" "=d,*x")
4774 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4775 (match_operand:HI 2 "register_operand" "+x,+d")))
4776 (clobber (match_dup 2))]
4780 if (A_REG_P (operands[0]))
4784 return \"bsr\\t___lshlhi3\";
4787 (define_insn "*ashlhi3"
4788 [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4789 (ashift:HI (match_dup 0)
4790 (match_operand:HI 1 "register_operand" "+x")))
4791 (clobber (match_dup 1))]
4796 return \"bsr\\t___lshlhi3\";
4799 (define_insn "*ashlhi3"
4800 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4801 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4802 (match_operand:HI 2 "const_int_operand" "")))]
4808 if (A_REG_P (operands[0]))
4811 i = INTVAL (operands[2]);
4815 output_asm_insn (\"tba\", operands);
4818 output_asm_insn (\"rora\", operands);
4819 output_asm_insn (\"anda\\t#0\", operands);
4820 output_asm_insn (\"rora\", operands);
4825 output_asm_insn (\"asla\", operands);
4830 for (i = 0; i < INTVAL (operands[2]) - 1; i++)
4832 output_asm_insn (\"asld\", operands);
4837 (define_expand "ashlqi3"
4838 [(set (match_operand:QI 0 "register_operand" "")
4839 (ashift:QI (match_operand:QI 1 "register_operand" "")
4840 (match_operand:QI 2 "general_operand" "")))]
4844 (define_insn "*ashlqi3_const1"
4845 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4846 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4856 (define_insn "*ashlqi3_const"
4857 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4858 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4859 (match_operand:QI 2 "const_int_operand" "")))]
4864 const char* insn_code;
4866 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4867 insn_code = \"aslb\";
4868 else if (DA_REG_P (operands[0]))
4869 insn_code = \"asla\";
4873 i = INTVAL (operands[2]);
4876 if (DA_REG_P (operands[0]))
4883 if (DA_REG_P (operands[0]))
4885 output_asm_insn (\"rora\", operands);
4886 output_asm_insn (\"ldaa\\t#0\", operands);
4891 output_asm_insn (\"rorb\", operands);
4892 output_asm_insn (\"ldab\\t#0\", operands);
4898 if (DA_REG_P (operands[0]))
4900 output_asm_insn (\"rora\", operands);
4901 output_asm_insn (\"rora\", operands);
4902 output_asm_insn (\"rora\", operands);
4903 return \"anda\\t#0xC0\";
4907 output_asm_insn (\"rorb\", operands);
4908 output_asm_insn (\"rorb\", operands);
4909 output_asm_insn (\"rorb\", operands);
4910 return \"andb\\t#0xC0\";
4915 output_asm_insn (insn_code, operands);
4920 (define_insn "*ashlqi3"
4921 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4922 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4923 (match_operand:QI 2 "nonimmediate_operand"
4924 "m*u*d*A,m*u*d*A,m*u")))]
4930 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4933 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
4934 ops[1] = operands[2];
4935 m68hc11_gen_movqi (insn, ops);
4938 return \"bsr\\t___lshlqi3\";
4941 (define_expand "ashrhi3"
4942 [(set (match_operand:HI 0 "register_operand" "")
4943 (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4944 (match_operand:HI 2 "general_operand" "")))]
4948 if (GET_CODE (operands[2]) != CONST_INT)
4950 rtx scratch = gen_reg_rtx (HImode);
4952 emit_move_insn (scratch, operands[2]);
4953 emit_insn (gen_rtx_PARALLEL (VOIDmode,
4954 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4956 gen_rtx_ASHIFTRT (HImode,
4957 operand1, scratch)),
4958 gen_rtx_CLOBBER (VOIDmode, scratch))));
4963 (define_insn "*ashrhi3_const1"
4964 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4965 (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4970 if (A_REG_P (operands[0]))
4974 if (D_REG_P (operands[0]))
4976 return \"asra\\n\\trorb\";
4979 output_asm_insn (\"asr\\t%h0\", operands);
4980 output_asm_insn (\"ror\\t%b0\", operands);
4985 (define_insn "*ashrhi3_const"
4986 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4987 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4988 (match_operand:HI 2 "const_int_operand" "")))]
4993 int val = INTVAL (operands[2]);
4995 if (A_REG_P (operands[0]))
5000 ops[0] = gen_label_rtx ();
5002 output_asm_insn (\"clrb\", operands);
5003 output_asm_insn (\"rola\", operands);
5005 /* Clear A without clearing the carry flag. */
5006 output_asm_insn (\"tba\", operands);
5007 output_asm_insn (\"bcc\\t%l0\", ops);
5008 output_asm_insn (\"coma\", operands);
5009 output_asm_insn (\"comb\", operands);
5012 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5013 CODE_LABEL_NUMBER (ops[0]));
5018 ops[0] = gen_label_rtx ();
5020 output_asm_insn (\"tab\", operands);
5021 output_asm_insn (\"clra\", operands);
5022 output_asm_insn (\"tstb\", operands);
5023 output_asm_insn (\"bge\\t%l0\", ops);
5024 output_asm_insn (\"deca\", operands);
5026 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5027 CODE_LABEL_NUMBER (ops[0]));
5033 output_asm_insn (\"asrb\", operands);
5041 ops[0] = gen_label_rtx ();
5042 output_asm_insn (\"rolb\", operands);
5043 output_asm_insn (\"rola\", operands);
5044 output_asm_insn (\"tab\", operands);
5045 output_asm_insn (\"anda\\t#0\", operands);
5046 output_asm_insn (\"bcc\\t%l0\", ops);
5047 output_asm_insn (\"coma\", ops);
5049 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5050 CODE_LABEL_NUMBER (ops[0]));
5055 output_asm_insn (\"asra\", operands);
5056 output_asm_insn (\"rorb\", operands);
5064 (define_insn "*ashrhi3"
5065 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5066 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5067 (match_operand:HI 2 "register_operand" "+x,+d")))
5068 (clobber (match_dup 2))]
5072 if (A_REG_P (operands[0]))
5075 output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5079 (define_expand "ashrsi3"
5081 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5082 (clobber (scratch:HI))])
5084 [(set (match_operand:SI 0 "register_operand" "")
5085 (ashiftrt:SI (match_dup 0)
5086 (match_operand:HI 2 "general_operand" "")))
5087 (clobber (scratch:HI))])]
5091 (define_insn "*ashrsi3_const"
5092 [(set (match_operand:SI 0 "register_operand" "+D")
5093 (ashiftrt:SI (match_dup 0)
5094 (match_operand:HI 1 "const_int_operand" "")))
5095 (clobber (match_scratch:HI 2 "=y"))]
5096 "TARGET_M6811 /* See *ashrsi3 note. */"
5100 return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
5103 (define_insn "*ashrsi3"
5104 [(set (match_operand:SI 0 "register_operand" "+D,D")
5105 (ashiftrt:SI (match_dup 0)
5106 (match_operand:HI 1 "general_operand" "y,mi")))
5107 (clobber (match_scratch:HI 2 "=1,X"))]
5112 /* There is a reload problem if we don't accept 'm' for the shift value.
5113 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5114 and this conflicts with all reloads. Since X, Y, Z are used there
5115 is not enough register in class A_REGS.
5117 Assuming that 'operands[1]' does not refer to the stack (which
5118 is true for 68hc11 only, we save temporary the value of Y.
5120 For 68HC12 we must also accept a constant because Z register is
5121 disabled when compiling with -fomit-frame-pointer. We can come up
5122 with a reload problem and the *lshrsi3_const pattern was disabled
5124 if (!Y_REG_P (operands[2]))
5127 int y_dead = dead_register_here (insn, iy_reg);
5129 ops[0] = operands[1];
5132 output_asm_insn (\"pshy\", operands);
5133 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5134 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5136 output_asm_insn (\"ldy\\t%0\", ops);
5137 output_asm_insn (\"bsr\\t___ashrsi3\", operands);
5138 return y_dead == 0 ? \"puly\" : \"\";
5140 return \"bsr\\t___ashrsi3\";
5143 (define_expand "ashrqi3"
5144 [(set (match_operand:QI 0 "register_operand" "")
5145 (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5146 (match_operand:QI 2 "general_operand" "")))]
5150 (define_insn "*ashrqi3_const1"
5151 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5152 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5162 (define_insn "*ashrqi3_const"
5163 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5164 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5165 (match_operand:QI 2 "const_int_operand" "")))]
5170 const char* insn_code;
5172 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5173 insn_code = \"asrb\";
5174 else if (DA_REG_P (operands[0]))
5175 insn_code = \"asra\";
5179 i = INTVAL (operands[2]);
5184 output_asm_insn (insn_code, operands);
5189 (define_insn "*ashrqi3"
5190 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5191 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5192 (match_operand:QI 2 "nonimmediate_operand"
5193 "m*u*d*A,m*u*d*A,m*u")))]
5199 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5202 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5203 ops[1] = operands[2];
5204 m68hc11_gen_movqi (insn, ops);
5207 return \"bsr\\t___ashrqi3\";
5210 ;;--------------------------------------------------------------------
5211 ;; logical shift instructions
5212 ;;--------------------------------------------------------------------
5213 (define_expand "lshrdi3"
5214 [(parallel [(set (match_operand:DI 0 "general_operand" "")
5215 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5216 (match_operand:HI 2 "general_operand" "")))
5217 (clobber (match_scratch:HI 3 ""))])]
5221 if (GET_CODE (operands[2]) != CONST_INT
5222 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5223 && INTVAL (operands[2]) != 1))
5229 (define_insn_and_split "*lshrdi3_const32"
5230 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5231 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
5233 (clobber (match_scratch:HI 2 "=&A,d,d"))]
5238 "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5239 m68hc11_gen_highpart (SImode, operands[1]),
5241 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5242 const0_rtx, operands[2]);
5245 (define_insn "*lshrdi3_const63"
5246 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5247 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5248 (match_operand:DI 2 "const_int_operand" "")))
5249 (clobber (match_scratch:HI 3 "=d,d"))]
5250 "INTVAL (operands[2]) >= 48"
5254 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5255 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5256 (match_operand:DI 2 "const_int_operand" "")))
5257 (clobber (match_scratch:HI 3 "=d"))]
5258 "z_replacement_completed && INTVAL (operands[2]) >= 56"
5259 [(set (reg:QI D_REGNUM) (match_dup 9))
5260 (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5261 (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5262 (set (match_dup 4) (reg:HI D_REGNUM))
5263 (set (reg:QI D_REGNUM) (const_int 0))
5264 (set (match_dup 5) (reg:HI D_REGNUM))
5265 (set (match_dup 6) (reg:HI D_REGNUM))
5266 (set (match_dup 7) (reg:HI D_REGNUM))]
5267 "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
5268 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5269 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5270 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5272 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5273 operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5274 operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5276 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5277 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5278 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5281 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5282 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5283 (match_operand:DI 2 "const_int_operand" "")))
5284 (clobber (match_scratch:HI 3 "=d"))]
5285 "z_replacement_completed && INTVAL (operands[2]) >= 48
5286 && INTVAL (operands[2]) < 56"
5287 [(set (reg:HI D_REGNUM) (match_dup 9))
5288 (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5289 (set (match_dup 4) (reg:HI D_REGNUM))
5290 (set (reg:HI D_REGNUM) (const_int 0))
5291 (set (match_dup 5) (reg:HI D_REGNUM))
5292 (set (match_dup 6) (reg:HI D_REGNUM))
5293 (set (match_dup 7) (reg:HI D_REGNUM))]
5294 "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
5295 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5296 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5297 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5299 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5300 operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5301 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5302 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5303 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5305 (define_insn_and_split "*lshrdi_const1"
5306 [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5307 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5309 (clobber (match_scratch:HI 2 "=d,d"))]
5312 "z_replacement_completed == 2"
5313 [(set (match_dup 2) (match_dup 3))
5314 (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5315 (set (match_dup 4) (match_dup 2))
5317 (set (match_dup 2) (match_dup 5))
5318 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5319 (clobber (reg:HI CC_REGNUM))])
5320 (set (match_dup 6) (match_dup 2))
5322 (set (match_dup 2) (match_dup 7))
5323 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5324 (clobber (reg:HI CC_REGNUM))])
5325 (set (match_dup 8) (match_dup 2))
5327 (set (match_dup 2) (match_dup 9))
5328 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5329 (clobber (reg:HI CC_REGNUM))])
5330 (set (match_dup 10) (match_dup 2))]
5331 "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5332 operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5333 operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5335 operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5336 operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5337 operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5339 operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5340 operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5341 operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5343 operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5344 operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5345 operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5347 (define_expand "lshrsi3"
5349 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5350 (clobber (scratch:HI))])
5352 [(set (match_operand:SI 0 "register_operand" "")
5353 (lshiftrt:SI (match_dup 0)
5354 (match_operand:HI 2 "general_operand" "")))
5355 (clobber (scratch:HI))])]
5360 [(set (match_operand:SI 0 "non_push_operand" "")
5361 (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
5363 (clobber (match_scratch:HI 3 ""))]
5364 "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5365 [(set (match_dup 2) (match_dup 3))
5366 (set (match_dup 4) (const_int 0))]
5367 "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5368 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5369 operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5371 (define_insn "*lshrsi3_const16"
5372 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5373 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
5375 (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5383 (define_insn "*lshrsi3_const1"
5384 [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
5385 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
5387 (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
5392 if (X_REG_P (operands[1]))
5394 return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5400 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5401 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
5402 m68hc11_gen_movhi (insn, ops);
5403 output_asm_insn (\"lsrd\", ops);
5404 if (!X_REG_P (operands[0]))
5407 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5408 m68hc11_gen_movhi (insn, ops);
5410 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5411 m68hc11_gen_movhi (insn, ops);
5415 /* Load the lowpart in X in case the operands is some N,x. */
5416 ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
5417 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5418 m68hc11_gen_movhi (insn, ops);
5419 output_asm_insn (\"xgdx\", ops);
5421 output_asm_insn (\"rora\", ops);
5422 output_asm_insn (\"rorb\", ops);
5423 if (!X_REG_P (operands[0]))
5426 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5427 m68hc11_gen_movhi (insn, ops);
5433 (define_insn "*lshrsi3_const"
5434 [(set (match_operand:SI 0 "register_operand" "+D")
5435 (lshiftrt:SI (match_dup 0)
5436 (match_operand:HI 1 "const_int_operand" "")))
5437 (clobber (match_scratch:HI 2 "=y"))]
5438 "TARGET_M6811 /* See *lshrsi3 note. */"
5442 return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5445 (define_insn "*lshrsi3"
5446 [(set (match_operand:SI 0 "register_operand" "+D,D")
5447 (lshiftrt:SI (match_dup 0)
5448 (match_operand:HI 1 "general_operand" "y,mi")))
5449 (clobber (match_scratch:HI 2 "=1,X"))]
5454 /* There is a reload problem if we don't accept 'm' for the shift value.
5455 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5456 and this conflicts with all reloads. Since X, Y, Z are used there
5457 is not enough register in class A_REGS.
5459 Assuming that 'operands[1]' does not refer to the stack (which
5460 is true for 68hc11 only, we save temporary the value of Y.
5462 For 68HC12 we must also accept a constant because Z register is
5463 disabled when compiling with -fomit-frame-pointer. We can come up
5464 with a reload problem and the *lshrsi3_const pattern was disabled
5466 if (!Y_REG_P (operands[2]))
5469 int y_dead = dead_register_here (insn, iy_reg);
5471 ops[0] = operands[1];
5474 output_asm_insn (\"pshy\", operands);
5475 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5476 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5478 output_asm_insn (\"ldy\\t%0\", ops);
5479 output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5480 return y_dead == 0 ? \"puly\" : \"\";
5482 return \"bsr\\t___lshrsi3\";
5485 (define_expand "lshrhi3"
5486 [(set (match_operand:HI 0 "register_operand" "")
5487 (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5488 (match_operand:HI 2 "general_operand" "")))]
5492 if (GET_CODE (operands[2]) != CONST_INT)
5494 rtx scratch = gen_reg_rtx (HImode);
5495 operand1 = force_reg (HImode, operand1);
5497 emit_move_insn (scratch, operands[2]);
5498 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5499 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5501 gen_rtx_LSHIFTRT (HImode,
5502 operand1, scratch)),
5503 gen_rtx_CLOBBER (VOIDmode, scratch))));
5508 (define_insn "lshrhi3_const1"
5509 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5510 (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5515 if (A_REG_P (operands[0]))
5518 if (D_REG_P (operands[0]))
5522 return \"lsr\\t%h0\\n\\tror\\t%b0\";
5525 (define_insn "lshrhi3_const"
5526 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5527 (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5528 (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5532 int val = INTVAL (operands[2]);
5534 if (A_REG_P (operands[0]))
5542 if (!H_REG_P (operands[1]))
5544 output_asm_insn (\"clra\", operands);
5545 output_asm_insn (\"ldab\\t%h1\", operands);
5547 else if (A_REG_P (operands[1]))
5549 output_asm_insn (\"st%1\\t%t0\", operands);
5550 output_asm_insn (\"ldab\\t%t0\", operands);
5551 output_asm_insn (\"clra\", operands);
5555 output_asm_insn (\"tab\", operands);
5556 output_asm_insn (\"clra\", operands);
5562 output_asm_insn (\"rolb\", operands);
5563 output_asm_insn (\"tab\", operands);
5564 output_asm_insn (\"rolb\", operands);
5568 output_asm_insn (\"rolb\", operands);
5569 output_asm_insn (\"rolb\", operands);
5570 output_asm_insn (\"rolb\", operands);
5571 output_asm_insn (\"andb\\t#3\", operands);
5578 output_asm_insn (\"lsrb\", operands);
5585 if (!D_REG_P (operands[1]))
5586 m68hc11_gen_movhi (insn, operands);
5590 output_asm_insn (\"rolb\", operands);
5591 output_asm_insn (\"tab\", operands);
5592 output_asm_insn (\"rolb\", operands);
5593 output_asm_insn (\"rola\", operands);
5594 output_asm_insn (\"rola\", operands);
5595 output_asm_insn (\"anda\\t#1\", operands);
5603 output_asm_insn (\"lsrd\", operands);
5609 (define_insn "*lshrhi3"
5610 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5611 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5612 (match_operand:HI 2 "register_operand" "+x,+d")))
5613 (clobber (match_dup 2))]
5617 if (A_REG_P (operands[0]))
5620 return \"bsr\\t___lshrhi3\";
5623 (define_expand "lshrqi3"
5624 [(set (match_operand:QI 0 "register_operand" "")
5625 (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5626 (match_operand:QI 2 "general_operand" "")))]
5630 (define_insn "*lshrqi3_const1"
5631 [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5632 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5642 (define_insn "*lshrqi3_const"
5643 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5644 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5645 (match_operand:QI 2 "const_int_operand" "")))]
5650 const char* insn_code;
5652 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5653 insn_code = \"lsrb\";
5654 else if (DA_REG_P (operands[0]))
5655 insn_code = \"lsra\";
5659 i = INTVAL (operands[2]);
5662 if (DA_REG_P (operands[0]))
5669 if (DA_REG_P (operands[0]))
5671 output_asm_insn (\"rola\", operands);
5672 output_asm_insn (\"ldaa\\t#0\", operands);
5677 output_asm_insn (\"rolb\", operands);
5678 output_asm_insn (\"ldab\\t#0\", operands);
5684 if (DA_REG_P (operands[0]))
5686 output_asm_insn (\"rola\", operands);
5687 output_asm_insn (\"rola\", operands);
5688 output_asm_insn (\"rola\", operands);
5689 return \"anda\\t#3\";
5693 output_asm_insn (\"rolb\", operands);
5694 output_asm_insn (\"rolb\", operands);
5695 output_asm_insn (\"rolb\", operands);
5696 return \"andb\\t#3\";
5701 output_asm_insn (insn_code, operands);
5706 (define_insn "*lshrqi3"
5707 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5708 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5709 (match_operand:QI 2 "nonimmediate_operand"
5710 "m*u*d*A,m*u*d*A,m*u")))]
5716 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5720 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5721 ops[1] = operands[2];
5722 m68hc11_gen_movqi (insn, ops);
5724 if (!optimize || optimize_size)
5726 return \"bsr\\t___lshrqi3\";
5729 ops[0] = gen_label_rtx ();
5730 ops[1] = gen_label_rtx ();
5731 output_asm_insn (\"ble\\t%l1\", ops);
5733 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5734 CODE_LABEL_NUMBER (ops[0]));
5736 output_asm_insn (\"lsrb\", operands);
5737 output_asm_insn (\"deca\", operands);
5738 output_asm_insn (\"bne\\t%l0\", ops);
5740 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5741 CODE_LABEL_NUMBER (ops[1]));
5745 (define_insn "*rotlqi3_with_carry"
5746 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5747 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5748 (reg:QI CC_REGNUM)))]
5752 if (DA_REG_P (operands[0]))
5758 (define_insn "*rotlhi3_with_carry"
5759 [(set (match_operand:HI 0 "register_operand" "=d")
5760 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5762 (clobber (reg:HI CC_REGNUM))]
5767 return \"rolb\\n\\trola\";
5770 (define_insn "*rotrhi3_with_carry"
5771 [(set (match_operand:HI 0 "register_operand" "=d")
5772 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5774 (clobber (reg:HI CC_REGNUM))]
5779 return \"rora\\n\\trorb\";
5782 (define_insn "rotlqi3"
5783 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5784 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5785 (match_operand:QI 2 "const_int_operand" "i,i")))]
5789 m68hc11_gen_rotate (ROTATE, insn, operands);
5793 (define_insn "rotrqi3"
5794 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5795 (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5796 (match_operand:QI 2 "const_int_operand" "i,i")))]
5800 m68hc11_gen_rotate (ROTATERT, insn, operands);
5804 (define_expand "rotlhi3"
5805 [(set (match_operand:HI 0 "register_operand" "")
5806 (rotate:HI (match_operand:HI 1 "register_operand" "")
5807 (match_operand:HI 2 "general_operand" "")))]
5811 if (GET_CODE (operands[2]) != CONST_INT)
5813 rtx scratch = gen_reg_rtx (HImode);
5814 operand1 = force_reg (HImode, operand1);
5816 emit_move_insn (scratch, operands[2]);
5817 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5818 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5820 gen_rtx_ROTATE (HImode,
5821 operand1, scratch)),
5822 gen_rtx_CLOBBER (VOIDmode, scratch))));
5827 (define_insn "rotlhi3_const"
5828 [(set (match_operand:HI 0 "register_operand" "=d")
5829 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5830 (match_operand:HI 2 "const_int_operand" "i")))]
5834 m68hc11_gen_rotate (ROTATE, insn, operands);
5838 (define_insn "*rotlhi3"
5839 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5840 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
5841 (match_operand:HI 2 "general_operand" "+x,+d")))
5842 (clobber (match_dup 2))]
5846 if (A_REG_P (operands[0]))
5849 return \"bsr\\t___rotlhi3\";
5852 (define_expand "rotrhi3"
5853 [(set (match_operand:HI 0 "register_operand" "")
5854 (rotatert:HI (match_operand:HI 1 "general_operand" "")
5855 (match_operand:HI 2 "general_operand" "")))]
5859 if (GET_CODE (operands[2]) != CONST_INT)
5861 rtx scratch = gen_reg_rtx (HImode);
5862 operand1 = force_reg (HImode, operand1);
5864 emit_move_insn (scratch, operands[2]);
5865 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5866 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5868 gen_rtx_ROTATERT (HImode,
5869 operand1, scratch)),
5870 gen_rtx_CLOBBER (VOIDmode, scratch))));
5875 (define_insn "rotrhi3_const"
5876 [(set (match_operand:HI 0 "register_operand" "=d")
5877 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5878 (match_operand:HI 2 "const_int_operand" "i")))]
5882 m68hc11_gen_rotate (ROTATERT, insn, operands);
5886 (define_insn "*rotrhi3"
5887 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5888 (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
5889 (match_operand:HI 2 "general_operand" "+x,+d")))
5890 (clobber (match_dup 2))]
5894 if (A_REG_P (operands[0]))
5897 return \"bsr\\t___rotrhi3\";
5900 ;; Split a shift operation on an address register in a shift
5902 (define_split /* "*rotrhi3_addr" */
5903 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
5904 (match_operator:HI 3 "m68hc11_shift_operator"
5905 [(match_operand:HI 1 "register_operand" "")
5906 (match_operand:HI 2 "register_operand" "")]))
5907 (clobber (match_dup 2))]
5908 "z_replacement_completed == 2"
5909 [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5910 (set (match_dup 0) (reg:HI D_REGNUM))])
5911 (parallel [(set (reg:HI D_REGNUM)
5912 (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
5913 (clobber (match_dup 0))])
5914 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5915 (set (match_dup 0) (reg:HI D_REGNUM))])]
5918 ;;--------------------------------------------------------------------
5919 ;;- 68HC12 Decrement/Increment and branch
5920 ;;--------------------------------------------------------------------
5921 ;; These patterns are used by loop optimization as well as peephole2
5922 ;; They must handle reloading themselves and the scratch register
5923 ;; is used for that. Even if we accept memory operand, we must not
5924 ;; accept them on the predicate because it might create too many reloads.
5925 ;; (specially on HC12 due to its auto-incdec addressing modes).
5927 (define_expand "decrement_and_branch_until_zero"
5928 [(parallel [(set (pc)
5930 (ne (plus:HI (match_operand:HI 0 "register_operand" "")
5933 (label_ref (match_operand 1 "" ""))
5936 (plus:HI (match_dup 0)
5938 (clobber (match_scratch:HI 2 ""))])]
5942 (define_expand "doloop_end"
5943 [(use (match_operand 0 "" "")) ; loop pseudo
5944 (use (match_operand 1 "" "")) ; iterations; zero if unknown
5945 (use (match_operand 2 "" "")) ; max iterations
5946 (use (match_operand 3 "" "")) ; loop level
5947 (use (match_operand 4 "" ""))] ; label
5951 /* Reject non-constant loops as it generates bigger code due to
5952 the handling of the loop register. We can do better by using
5953 the peephole2 dbcc/ibcc patterns. */
5954 if (INTVAL (operands[1]) == 0)
5959 /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
5960 the operator and its operands are not relevant. */
5961 if (GET_MODE (operands[0]) == HImode)
5963 emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
5970 if (GET_MODE (operands[0]) == QImode)
5972 emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
5983 ;; Decrement-and-branch insns.
5984 (define_insn "m68hc12_dbcc_dec_hi"
5987 (match_operator 1 "m68hc11_eq_compare_operator"
5988 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5990 (label_ref (match_operand 2 "" ""))
5993 (plus:HI (match_dup 0) (const_int -1)))
5994 (clobber (match_scratch:HI 3 "=X,dxy"))]
5998 if (!H_REG_P (operands[0]))
6002 if (GET_CODE (operands[1]) == EQ)
6003 return \"dbeq\\t%0,%l2\";
6005 return \"dbne\\t%0,%l2\";
6008 ;; Decrement-and-branch insns.
6009 (define_insn "m68hc12_dbcc_inc_hi"
6012 (match_operator 1 "m68hc11_eq_compare_operator"
6013 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
6015 (label_ref (match_operand 2 "" ""))
6018 (plus:HI (match_dup 0) (const_int 1)))
6019 (clobber (match_scratch:HI 3 "=X,dxy"))]
6023 if (!H_REG_P (operands[0]))
6027 if (GET_CODE (operands[1]) == EQ)
6028 return \"ibeq\\t%0,%l2\";
6030 return \"ibeq\\t%0,%l2\";
6033 ;; Decrement-and-branch (QImode).
6034 (define_insn "m68hc12_dbcc_dec_qi"
6037 (match_operator 1 "m68hc11_eq_compare_operator"
6038 [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6040 (label_ref (match_operand 2 "" ""))
6043 (plus:QI (match_dup 0) (const_int -1)))
6044 (clobber (match_scratch:QI 3 "=X,d"))]
6048 if (!D_REG_P (operands[0]))
6052 if (GET_CODE (operands[1]) == EQ)
6053 return \"dbeq\\tb,%l2\";
6055 return \"dbne\\tb,%l2\";
6058 ;; Increment-and-branch (QImode).
6059 (define_insn "m68hc12_dbcc_inc_qi"
6062 (match_operator 1 "m68hc11_eq_compare_operator"
6063 [(match_operand:QI 0 "register_operand" "+d,m*u*A")
6065 (label_ref (match_operand 2 "" ""))
6068 (plus:QI (match_dup 0) (const_int 1)))
6069 (clobber (match_scratch:QI 3 "=X,d"))]
6073 if (!D_REG_P (operands[0]))
6077 if (GET_CODE (operands[1]) == EQ)
6078 return \"ibeq\\tb,%l2\";
6080 return \"ibeq\\tb,%l2\";
6083 ;; Split the above to handle the case where operand 0 is in memory
6084 ;; (a register that couldn't get a hard register)
6088 (match_operator 3 "m68hc11_eq_compare_operator"
6089 [(match_operand:HI 0 "general_operand" "")
6090 (match_operand:HI 1 "const_int_operand" "")])
6091 (label_ref (match_operand 4 "" ""))
6094 (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6095 (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
6096 "TARGET_M6812 && reload_completed"
6097 [(set (match_dup 5) (match_dup 0))
6098 (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
6099 (set (match_dup 0) (match_dup 5))
6101 (if_then_else (match_op_dup 3
6102 [(match_dup 5) (const_int 0)])
6103 (label_ref (match_dup 4)) (pc)))]
6106 ;; Split the above to handle the case where operand 0 is in memory
6107 ;; (a register that couldn't get a hard register)
6111 (match_operator 3 "m68hc11_eq_compare_operator"
6112 [(match_operand:QI 0 "general_operand" "")
6113 (match_operand:QI 1 "const_int_operand" "")])
6114 (label_ref (match_operand 4 "" ""))
6117 (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6118 (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
6119 "TARGET_M6812 && reload_completed"
6120 [(set (match_dup 5) (match_dup 0))
6121 (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
6122 (set (match_dup 0) (match_dup 5))
6124 (if_then_else (match_op_dup 3
6125 [(match_dup 5) (const_int 0)])
6126 (label_ref (match_dup 4)) (pc)))]
6129 ;;--------------------------------------------------------------------
6130 ;;- Jumps and transfers
6131 ;;--------------------------------------------------------------------
6134 (label_ref (match_operand 0 "" "")))]
6138 (define_expand "beq"
6140 (if_then_else (eq (cc0)
6142 (label_ref (match_operand 0 "" ""))
6147 m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
6148 m68hc11_compare_op1,
6153 (define_expand "bne"
6155 (if_then_else (ne (cc0)
6157 (label_ref (match_operand 0 "" ""))
6162 m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
6163 m68hc11_compare_op1,
6168 (define_expand "bgt"
6170 (if_then_else (gt (cc0)
6172 (label_ref (match_operand 0 "" ""))
6177 m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
6178 m68hc11_compare_op1,
6183 (define_expand "bgtu"
6185 (if_then_else (gtu (cc0)
6187 (label_ref (match_operand 0 "" ""))
6192 m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
6193 m68hc11_compare_op1,
6198 (define_expand "blt"
6200 (if_then_else (lt (cc0)
6202 (label_ref (match_operand 0 "" ""))
6207 m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
6208 m68hc11_compare_op1,
6213 (define_expand "bltu"
6215 (if_then_else (ltu (cc0)
6217 (label_ref (match_operand 0 "" ""))
6222 m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
6223 m68hc11_compare_op1,
6228 (define_expand "bge"
6230 (if_then_else (ge (cc0)
6232 (label_ref (match_operand 0 "" ""))
6237 m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
6238 m68hc11_compare_op1,
6243 (define_expand "bgeu"
6245 (if_then_else (geu (cc0)
6247 (label_ref (match_operand 0 "" ""))
6252 m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
6253 m68hc11_compare_op1,
6258 (define_expand "ble"
6260 (if_then_else (le (cc0)
6262 (label_ref (match_operand 0 "" ""))
6267 m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
6268 m68hc11_compare_op1,
6273 (define_expand "bleu"
6275 (if_then_else (leu (cc0)
6277 (label_ref (match_operand 0 "" ""))
6282 m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
6283 m68hc11_compare_op1,
6289 ;; Test and branch instructions for 68HC12 for EQ and NE.
6290 ;; 'z' must not appear in the constraints because the z replacement
6291 ;; pass does not know how to restore the replacement register.
6293 (define_insn "*tbeq"
6295 (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
6297 (label_ref (match_operand 1 "" ""))
6302 /* If the flags are already set correctly, use 'bne/beq' which are
6303 smaller and a little bit faster. This happens quite often due
6304 to reloading of operands[0]. In that case, flags are set correctly
6305 due to the load instruction. */
6306 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6307 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6308 return \"beq\\t%l1\";
6310 return \"tbeq\\t%0,%l1\";
6313 (define_insn "*tbne"
6315 (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6317 (label_ref (match_operand 1 "" ""))
6322 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6323 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6324 return \"bne\\t%l1\";
6326 return \"tbne\\t%0,%l1\";
6330 ;; Test and branch with 8-bit register. Register must be B (or A).
6332 (define_insn "*tbeq8"
6334 (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6336 (label_ref (match_operand 1 "" ""))
6341 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6342 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6343 return \"beq\\t%l1\";
6345 return \"tbeq\\tb,%l1\";
6348 (define_insn "*tbne8"
6350 (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6352 (label_ref (match_operand 1 "" ""))
6357 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6358 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6359 return \"bne\\t%l1\";
6361 return \"tbne\\tb,%l1\";
6366 (if_then_else (eq (cc0)
6368 (label_ref (match_operand 0 "" ""))
6375 (if_then_else (ne (cc0)
6377 (label_ref (match_operand 0 "" ""))
6384 (if_then_else (gt (cc0)
6386 (label_ref (match_operand 0 "" ""))
6391 (define_insn "*bgtu"
6393 (if_then_else (gtu (cc0)
6395 (label_ref (match_operand 0 "" ""))
6402 (if_then_else (lt (cc0)
6404 (label_ref (match_operand 0 "" ""))
6409 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6410 return \"bmi\\t%l0\";
6412 return \"blt\\t%l0\";
6415 (define_insn "*bltu"
6417 (if_then_else (ltu (cc0)
6419 (label_ref (match_operand 0 "" ""))
6426 (if_then_else (ge (cc0)
6428 (label_ref (match_operand 0 "" ""))
6433 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6434 return \"bpl\\t%l0\";
6436 return \"bge\\t%l0\";
6439 (define_insn "*bgeu"
6441 (if_then_else (geu (cc0)
6443 (label_ref (match_operand 0 "" ""))
6450 (if_then_else (le (cc0)
6452 (label_ref (match_operand 0 "" ""))
6457 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6458 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6460 return \"ble\\t%l0\";
6463 (define_insn "*bleu"
6465 (if_then_else (leu (cc0)
6467 (label_ref (match_operand 0 "" ""))
6472 ;;--------------------------------------------------------------------
6473 ;;- Negative test and branch
6474 ;;--------------------------------------------------------------------
6477 (if_then_else (eq (cc0)
6480 (label_ref (match_operand 0 "" ""))))]
6486 (if_then_else (ne (cc0)
6489 (label_ref (match_operand 0 "" ""))))]
6495 (if_then_else (gt (cc0)
6498 (label_ref (match_operand 0 "" ""))))]
6502 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6503 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6505 return \"ble\\t%l0\";
6510 (if_then_else (gtu (cc0)
6513 (label_ref (match_operand 0 "" ""))))]
6519 (if_then_else (lt (cc0)
6522 (label_ref (match_operand 0 "" ""))))]
6526 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6527 return \"bpl\\t%l0\";
6529 return \"bge\\t%l0\";
6534 (if_then_else (ltu (cc0)
6537 (label_ref (match_operand 0 "" ""))))]
6543 (if_then_else (ge (cc0)
6546 (label_ref (match_operand 0 "" ""))))]
6550 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6551 return \"bmi\\t%l0\";
6553 return \"blt\\t%l0\";
6558 (if_then_else (geu (cc0)
6561 (label_ref (match_operand 0 "" ""))))]
6567 (if_then_else (le (cc0)
6570 (label_ref (match_operand 0 "" ""))))]
6576 (if_then_else (leu (cc0)
6579 (label_ref (match_operand 0 "" ""))))]
6583 ;;--------------------------------------------------------------------
6585 ;;--------------------------------------------------------------------
6587 ;;- Call a function that returns no value.
6589 [(call (match_operand:QI 0 "memory_operand" "m")
6590 (match_operand:SI 1 "general_operand" "g"))]
6591 ;; Operand 1 not really used on the m68hc11.
6595 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6597 if (m68hc11_is_far_symbol (operands[0]))
6601 output_asm_insn (\"call\\t%0\", operands);
6606 output_asm_insn (\"pshb\", operands);
6607 output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
6608 output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
6609 return \"jsr\\t__call_a32\";
6612 if (m68hc11_is_trap_symbol (operands[0]))
6615 return \"bsr\\t%0\";
6619 return \"jsr\\t%0\";
6623 (define_insn "call_value"
6624 [(set (match_operand 0 "" "=g")
6625 (call (match_operand:QI 1 "memory_operand" "m")
6626 (match_operand:SI 2 "general_operand" "g")))]
6630 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6632 if (m68hc11_is_far_symbol (operands[1]))
6636 output_asm_insn (\"call\\t%1\", operands);
6641 output_asm_insn (\"pshb\", operands);
6642 output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
6643 output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
6644 return \"jsr\\t__call_a32\";
6647 if (m68hc11_is_trap_symbol (operands[1]))
6650 return \"bsr\\t%1\";
6654 return \"jsr\\t%1\";
6658 ;; Call subroutine returning any type.
6660 (define_expand "untyped_call"
6661 [(parallel [(call (match_operand 0 "" "")
6663 (match_operand 1 "" "")
6664 (match_operand 2 "" "")])]
6670 emit_call_insn (gen_call (operands[0], const0_rtx));
6672 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6674 rtx set = XVECEXP (operands[2], 0, i);
6675 emit_move_insn (SET_DEST (set), SET_SRC (set));
6678 /* The optimizer does not know that the call sets the function value
6679 registers we stored in the result block. We avoid problems by
6680 claiming that all hard registers are used and clobbered at this
6682 emit_insn (gen_blockage ());
6687 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6688 ;; all of memory. This blocks insns from being moved across this point.
6690 (define_insn "blockage"
6691 [(unspec_volatile [(const_int 0)] 0)]
6700 (define_expand "prologue"
6709 (define_expand "epilogue"
6718 ;; Used for frameless functions which save no regs and allocate no locals.
6719 (define_expand "return"
6721 "reload_completed && m68hc11_total_frame_size () == 0"
6726 if (current_function_return_rtx)
6727 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6729 /* Emit use notes only when HAVE_return is true. */
6730 if (m68hc11_total_frame_size () != 0)
6733 if (ret_size && ret_size <= 2)
6735 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6736 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6737 gen_rtx_USE (VOIDmode,
6738 gen_rtx_REG (HImode, 1)))));
6743 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6744 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6745 gen_rtx_USE (VOIDmode,
6746 gen_rtx_REG (SImode, 0)))));
6751 (define_insn "*return_void"
6756 rtx next = next_active_insn (insn);
6759 && GET_CODE (next) == JUMP_INSN
6760 && GET_CODE (PATTERN (next)) == RETURN)
6762 if (current_function_interrupt || current_function_trap)
6764 else if (!current_function_far)
6766 else if (TARGET_M6812)
6772 if (current_function_return_rtx)
6773 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6776 return \"jmp\\t__return_void\";
6778 return \"jmp\\t__return_16\";
6780 return \"jmp\\t__return_32\";
6781 return \"jmp\\t__return_16\";
6785 (define_insn "*return_16bit"
6787 (use (reg:HI D_REGNUM))]
6788 "reload_completed && m68hc11_total_frame_size () == 0"
6791 rtx next = next_active_insn (insn);
6794 && GET_CODE (next) == JUMP_INSN
6795 && GET_CODE (PATTERN (next)) == RETURN)
6797 if (current_function_interrupt || current_function_trap)
6799 else if (!current_function_far)
6801 else if (TARGET_M6812)
6804 return \"jmp\\t__return_16\";
6807 (define_insn "*return_32bit"
6810 "reload_completed && m68hc11_total_frame_size () == 0"
6813 rtx next = next_active_insn (insn);
6816 && GET_CODE (next) == JUMP_INSN
6817 && GET_CODE (PATTERN (next)) == RETURN)
6819 if (current_function_interrupt || current_function_trap)
6821 else if (!current_function_far)
6823 else if (TARGET_M6812)
6826 return \"jmp\\t__return_32\";
6829 (define_insn "indirect_jump"
6830 [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6834 ;;--------------------------------------------------------------------
6836 ;;--------------------------------------------------------------------
6838 ;; Operand 0 is the address of the table element to use
6839 ;; operand 1 is the CODE_LABEL for the table
6840 ;;--------------------------------------------------------------------
6841 (define_expand "tablejump"
6842 [(parallel [(set (pc) (match_operand 0 "" ""))
6843 (use (label_ref (match_operand 1 "" "")))])]
6847 (define_insn "*jump_indirect"
6849 (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6850 (use (label_ref (match_operand 1 "" "")))])]
6854 ;;--------------------------------------------------------------------
6856 ;;--------------------------------------------------------------------
6858 ;;--------------------------------------------------------------------
6859 ;;- 68HC12 dbcc/ibcc peepholes
6860 ;;--------------------------------------------------------------------
6862 ;; Replace: "addd #-1; bne L1" into "dbne d,L1"
6863 ;; "addd #-1; beq L1" into "dbeq d,L1"
6864 ;; "addd #1; bne L1" into "ibne d,L1"
6865 ;; "addd #1; beq L1" into "ibeq d,L1"
6868 [(set (match_operand:HI 0 "hard_reg_operand" "")
6869 (plus:HI (match_dup 0)
6870 (match_operand:HI 1 "const_int_operand" "")))
6872 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6875 (label_ref (match_operand 3 "" "")) (pc)))]
6876 "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6878 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6879 (label_ref (match_dup 3)) (pc)))
6880 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
6881 (clobber (match_dup 4))])]
6882 "operands[4] = gen_rtx_SCRATCH(HImode);
6883 operands[5] = GEN_INT (-INTVAL (operands[1]));")
6887 ;; Replace: "addb #-1; bne L1" into "dbne b,L1"
6888 ;; "addb #-1; beq L1" into "dbeq b,L1"
6891 [(set (match_operand:QI 0 "hard_reg_operand" "")
6892 (plus:QI (match_dup 0)
6893 (match_operand:QI 1 "const_int_operand" "")))
6895 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6898 (label_ref (match_operand 3 "" "")) (pc)))]
6899 "TARGET_M6812 && D_REG_P (operands[0])
6900 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6902 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6903 (label_ref (match_dup 3)) (pc)))
6904 (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
6905 (clobber (match_dup 4))])]
6906 "operands[4] = gen_rtx_SCRATCH(QImode);
6907 operands[5] = GEN_INT (-INTVAL (operands[1]));")
6910 ;;--------------------------------------------------------------------
6912 ;;--------------------------------------------------------------------
6915 ;; Replace "leas 2,sp" with a "pulx" or a "puly".
6916 ;; On 68HC12, this is one cycle slower but one byte smaller.
6917 ;; pr target/6899: This peephole was not valid because a register CSE
6918 ;; pass removes the pulx/puly. The 'use' clause ensure that the pulx is
6922 [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6923 (match_scratch:HI 0 "xy")]
6924 "TARGET_M6812 && optimize_size"
6925 [(set (match_dup 0) (match_dup 1))
6926 (use (match_dup 0))]
6927 "operands[1] = gen_rtx_MEM (HImode,
6928 gen_rtx_POST_INC (HImode,
6929 gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
6931 ;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
6933 ;; PR 14542: emit a use to pretend we need the value of initial register.
6934 ;; Otherwise verify_local_live_at_start will die due to a live change
6935 ;; of that register.
6938 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6939 (match_operand:HI 0 "hard_reg_operand" ""))
6941 (match_operand:HI 1 "hard_reg_operand" ""))
6942 (set (mem:HI (reg:HI SP_REGNUM))
6945 [(use (match_dup 0))
6946 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6948 (set (match_dup 0) (match_dup 1))]
6952 ;; Change: "ldd 0,sp; pulx" into "puld"
6953 ;; This sequence usually appears at end a functions.
6955 [(set (match_operand:HI 0 "hard_reg_operand" "")
6956 (mem:HI (reg:HI SP_REGNUM)))
6958 (set (match_operand:HI 1 "hard_reg_operand" "")
6959 (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
6960 "peep2_reg_dead_p (2, operands[1])"
6961 [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
6962 (use (match_dup 0))]
6965 ;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
6966 ;; Appears to allocate local variables.
6968 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6969 (match_operand:HI 0 "hard_reg_operand" ""))
6970 (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
6972 (set (mem:QI (reg:HI SP_REGNUM))
6975 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6979 ;; Likewise for HI mode
6981 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6982 (match_operand:HI 0 "hard_reg_operand" ""))
6983 (set (mem:HI (reg:HI SP_REGNUM))
6986 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6989 ;;--------------------------------------------------------------------
6991 ;;--------------------------------------------------------------------
6993 ;; Optimize memory<->memory moves when the value is also loaded in
6997 [(set (match_operand:QI 0 "memory_operand" "")
6998 (match_operand:QI 1 "memory_operand" ""))
6999 (set (reg:QI D_REGNUM)
7000 (match_operand:QI 2 "memory_operand" ""))]
7001 "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
7002 || (GET_CODE (XEXP (operands[0], 0)) == REG
7003 && GET_CODE (XEXP (operands[2], 0)) == POST_INC
7004 && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
7005 [(set (reg:QI D_REGNUM) (match_dup 1))
7006 (set (match_dup 2) (reg:QI D_REGNUM))]
7010 ;; Remove a possible move before a compare instruction when that
7011 ;; move will go in a dead register. Compare with the source then.
7014 [(set (match_operand:HI 0 "hard_reg_operand" "")
7015 (match_operand:HI 1 "hard_reg_operand" ""))
7017 (compare (match_dup 0)
7018 (match_operand:HI 2 "cmp_operand" "")))]
7019 "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
7020 && peep2_reg_dead_p (2, operands[0])
7021 && !reg_mentioned_p (operands[0], operands[2])"
7022 [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
7026 ;; Optimize loading a constant to memory when that same constant
7027 ;; is loaded to a hard register. Switch the two to use the register
7028 ;; for memory initialization. In most cases, the constant is 0.
7031 [(set (match_operand:HI 0 "memory_operand" "")
7032 (match_operand:HI 1 "immediate_operand" ""))
7033 (set (match_operand:HI 2 "hard_reg_operand" "")
7035 "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
7036 && !reg_mentioned_p (operands[2], operands[0])"
7037 [(set (match_dup 2) (match_dup 1))
7038 (set (match_dup 0) (match_dup 2))]
7042 ;; Reorganize to optimize address computations.
7045 [(set (match_operand:HI 0 "hard_reg_operand" "")
7046 (match_operand:HI 1 "const_int_operand" ""))
7048 (plus:HI (match_dup 0)
7049 (match_operand:HI 2 "general_operand" "")))]
7050 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7051 [(set (match_dup 0) (match_dup 2))
7052 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7056 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7059 [(set (match_operand:HI 0 "hard_reg_operand" "")
7060 (match_operand:HI 1 "const_int_operand" ""))
7062 (plus:HI (match_dup 0)
7063 (match_operand:HI 2 "general_operand" "")))
7064 (match_scratch:QI 3 "d")]
7065 "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
7066 [(set (match_dup 3) (match_dup 4))
7067 (set (match_dup 0) (match_dup 2))
7068 (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
7069 "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
7072 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
7075 [(set (match_operand:HI 0 "hard_reg_operand" "")
7076 (match_operand:HI 1 "const_int_operand" ""))
7078 (plus:HI (match_dup 0)
7079 (match_operand:HI 2 "general_operand" "")))]
7081 [(set (match_dup 0) (match_dup 2))
7082 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7086 ;; Optimize an address register increment and a compare to use
7087 ;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
7088 ;; before reload, but can be enabled after).
7091 [(set (match_operand:HI 0 "hard_reg_operand" "")
7092 (plus:HI (match_dup 0)
7093 (match_operand:HI 1 "const_int_operand" "")))
7095 (match_operand:QI 2 "memory_operand" ""))]
7096 "TARGET_AUTO_INC_DEC
7097 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7098 && reg_mentioned_p (operands[0], operands[2])"
7099 [(set (cc0) (match_dup 3))]
7100 "if (INTVAL (operands[1]) == 1)
7101 operands[3] = gen_rtx_MEM (QImode,
7102 gen_rtx_PRE_INC (HImode, operands[0]));
7104 operands[3] = gen_rtx_MEM (QImode,
7105 gen_rtx_PRE_DEC (HImode, operands[0]));
7109 ;; Likewise for compare.
7112 [(set (match_operand:HI 0 "hard_reg_operand" "")
7113 (plus:HI (match_dup 0)
7114 (match_operand:HI 1 "const_int_operand" "")))
7116 (compare (match_operand:QI 2 "hard_reg_operand" "")
7117 (match_operand:QI 3 "memory_operand" "")))]
7118 "TARGET_AUTO_INC_DEC
7119 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7120 && reg_mentioned_p (operands[0], operands[3])"
7121 [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
7122 "if (INTVAL (operands[1]) == 1)
7123 operands[4] = gen_rtx_MEM (QImode,
7124 gen_rtx_PRE_INC (HImode, operands[0]));
7126 operands[4] = gen_rtx_MEM (QImode,
7127 gen_rtx_PRE_DEC (HImode, operands[0]));
7131 [(set (match_operand:HI 0 "hard_reg_operand" "")
7132 (plus:HI (match_dup 0)
7133 (match_operand:HI 1 "const_int_operand" "")))
7135 (compare (match_operand:QI 2 "memory_operand" "")
7136 (match_operand:QI 3 "hard_reg_operand" "")))]
7137 "TARGET_AUTO_INC_DEC
7138 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
7139 && reg_mentioned_p (operands[0], operands[2])"
7140 [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
7141 "if (INTVAL (operands[1]) == 1)
7142 operands[4] = gen_rtx_MEM (QImode,
7143 gen_rtx_PRE_INC (HImode, operands[0]));
7145 operands[4] = gen_rtx_MEM (QImode,
7146 gen_rtx_PRE_DEC (HImode, operands[0]));
7150 ;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
7151 ;; (avoids many temporary moves because we can't add sp to another reg easily)
7154 [(set (match_operand:HI 0 "hard_reg_operand" "")
7155 (match_operand:HI 1 "const_int_operand" ""))
7156 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7158 [(set (match_dup 0) (reg:HI SP_REGNUM))
7159 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7163 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7166 [(set (match_operand:HI 0 "hard_reg_operand" "")
7167 (match_operand:HI 1 "const_int_operand" ""))
7169 (plus:HI (match_dup 0)
7170 (match_operand:HI 2 "general_operand" "")))]
7171 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7172 [(set (match_dup 0) (match_dup 2))
7173 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7181 [(set (match_operand:SI 0 "hard_reg_operand" "")
7182 (ashift:SI (match_operand:SI 1 "general_operand" "")
7184 (clobber (match_scratch:HI 2 ""))])
7185 (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
7186 (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
7187 "!X_REG_P (operands[1])
7188 && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
7189 && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
7190 [(set (reg:HI D_REGNUM) (match_dup 5))
7191 (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
7192 (set (match_dup 3) (reg:HI D_REGNUM))
7193 (set (reg:HI D_REGNUM) (match_dup 6))
7194 (parallel [(set (reg:HI D_REGNUM)
7195 (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
7196 (clobber (reg:HI CC_REGNUM))])
7197 (set (match_dup 4) (reg:HI D_REGNUM))]
7198 "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
7199 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
7202 ;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
7205 [(set (match_operand:HI 0 "hard_reg_operand" "")
7206 (match_operand:HI 1 "memory_operand" ""))
7207 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
7209 (match_scratch:HI 2 "x")]
7210 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
7211 [(set (match_dup 2) (match_dup 1))
7212 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
7216 ;; Remove one load when copying a value to/from memory and also
7217 ;; to a register. Take care not clobbering a possible register used
7219 ;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
7222 [(set (match_operand:HI 0 "hard_reg_operand" "")
7223 (match_operand:HI 1 "general_operand" ""))
7224 (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
7225 (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
7226 "peep2_reg_dead_p (2, operands[0])
7227 && !side_effects_p (operands[1])
7228 && !side_effects_p (operands[2])
7229 && !reg_mentioned_p (operands[3], operands[2])"
7230 [(set (match_dup 3) (match_dup 1))
7231 (set (match_dup 2) (match_dup 3))]
7235 ;; Replace a "ldd <mem>; addd #N; std <mem>" into a
7236 ;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
7237 ;; and the constant is small.
7240 [(set (match_operand:HI 0 "hard_reg_operand" "")
7241 (match_operand:HI 1 "general_operand" ""))
7242 (set (match_dup 0) (plus:HI (match_dup 0)
7243 (match_operand:HI 2 "const_int_operand" "")))
7244 (set (match_operand:HI 3 "nonimmediate_operand" "")
7246 (match_scratch:HI 4 "xy")]
7247 "D_REG_P (operands[0])
7249 || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
7250 && peep2_reg_dead_p (3, operands[0])"
7251 [(set (match_dup 4) (match_dup 1))
7252 (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
7253 (set (match_dup 3) (match_dup 4))]
7254 "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
7255 if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
7257 ;;--------------------------------------------------------------------
7259 ;;--------------------------------------------------------------------
7260 ;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
7262 ;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
7263 ;; Register D must be dead and there must be no register side effects for mem.
7264 ;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
7265 ;; The good side effect is that it makes the sequence atomic.
7268 [(set (match_operand:QI 0 "hard_reg_operand" "")
7269 (match_operand:QI 1 "nonimmediate_operand" ""))
7270 (set (match_dup 0) (ior:QI (match_dup 0)
7271 (match_operand:QI 2 "const_int_operand" "")))
7272 (set (match_dup 1) (match_dup 0))]
7273 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7274 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7275 && peep2_reg_dead_p (3, operands[0])"
7276 [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
7280 [(set (match_operand:HI 0 "hard_reg_operand" "")
7281 (match_operand:HI 1 "nonimmediate_operand" ""))
7282 (set (match_dup 0) (ior:HI (match_dup 0)
7283 (match_operand:HI 2 "const_int_operand" "")))
7284 (set (match_dup 1) (match_dup 0))]
7285 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7286 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7287 && peep2_reg_dead_p (3, operands[0])"
7288 [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
7291 ;;--------------------------------------------------------------------
7293 ;;--------------------------------------------------------------------
7294 ;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
7295 ;; See Bset peephole2.
7298 [(set (match_operand:QI 0 "hard_reg_operand" "")
7299 (match_operand:QI 1 "nonimmediate_operand" ""))
7300 (set (match_dup 0) (and:QI (match_dup 0)
7301 (match_operand:QI 2 "const_int_operand" "")))
7302 (set (match_dup 1) (match_dup 0))]
7303 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7304 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7305 && peep2_reg_dead_p (3, operands[0])"
7306 [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
7310 [(set (match_operand:HI 0 "hard_reg_operand" "")
7311 (match_operand:HI 1 "nonimmediate_operand" ""))
7312 (set (match_dup 0) (and:HI (match_dup 0)
7313 (match_operand:HI 2 "const_int_operand" "")))
7314 (set (match_dup 1) (match_dup 0))]
7315 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7316 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7317 && peep2_reg_dead_p (3, operands[0])"
7318 [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
7322 ;;--------------------------------------------------------------------
7323 ;;- Compare peephole2
7324 ;;--------------------------------------------------------------------
7326 [(set (match_operand:HI 0 "hard_reg_operand" "")
7327 (match_operand:HI 1 "hard_reg_operand" ""))
7328 (set (match_dup 1) (plus:HI (match_dup 1)
7329 (match_operand:HI 2 "const_int_operand" "")))
7330 (set (cc0) (match_dup 0))]
7331 "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
7332 [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
7333 (set (cc0) (compare (match_dup 1) (match_dup 2)))]
7337 [(set (match_operand:HI 0 "hard_reg_operand" "")
7338 (match_operand:HI 1 "hard_reg_operand" ""))
7339 (set (match_operand:HI 2 "hard_reg_operand" "")
7340 (plus:HI (match_dup 2)
7341 (match_operand:HI 3 "const_int_operand" "")))
7342 (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
7343 (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
7344 "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
7345 && !reg_mentioned_p (operands[2], operands[4])
7347 && ((rtx_equal_p (operands[5], operands[0])
7348 && rtx_equal_p (operands[2], operands[1]))
7350 || (rtx_equal_p (operands[5], operands[1])
7351 && rtx_equal_p (operands[2], operands[0])))"
7352 [(set (match_dup 2) (match_dup 1))
7353 (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
7354 (set (match_dup 4) (match_dup 2))
7355 (set (cc0) (compare (match_dup 2) (match_dup 3)))]
7359 ;;--------------------------------------------------------------------
7361 ;;--------------------------------------------------------------------
7363 ;; Optimize initialization of 2 hard regs from the same memory location
7364 ;; Since we can't copy easily X, Y and D to each other, load the 2 registers
7365 ;; from the same memory location.
7368 [(set (match_operand:HI 0 "hard_reg_operand" "")
7369 (match_operand:HI 1 "memory_operand" ""))
7370 (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7372 && !side_effects_p (operands[1])
7373 && !reg_mentioned_p (operands[0], operands[1])"
7374 [(set (match_dup 0) (match_dup 1))
7375 (set (match_dup 2) (match_dup 1))]
7378 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7381 [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7382 (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7383 (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7384 (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
7385 (match_scratch:HI 4 "d")]
7387 [(set (match_dup 4) (const_int 0))
7388 (set (match_dup 0) (match_dup 4))
7389 (set (match_dup 1) (match_dup 4))
7390 (set (match_dup 2) (match_dup 4))
7391 (set (match_dup 3) (match_dup 4))]
7395 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7398 [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7399 (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7400 (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7401 (match_scratch:HI 3 "d")]
7403 [(set (match_dup 3) (const_int 0))
7404 (set (match_dup 0) (match_dup 3))
7405 (set (match_dup 1) (match_dup 3))
7406 (set (match_dup 2) (match_dup 3))]
7410 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7413 [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
7414 (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
7415 (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
7416 (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
7417 (match_scratch:HI 4 "x")]
7418 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
7419 [(set (match_dup 4) (const_int 0))
7420 (set (match_dup 1) (match_dup 4))
7421 (set (match_dup 2) (match_dup 4))
7422 (set (match_dup 3) (match_dup 4))]
7426 ;; This peephole catches the address computations generated by the reload
7429 [(set (match_operand:HI 0 "hard_reg_operand" "xy")
7430 (match_operand:HI 1 "const_int_operand" ""))
7431 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7432 (set (match_dup 0) (reg:HI D_REGNUM))])
7433 (set (reg:HI D_REGNUM)
7434 (plus (reg:HI D_REGNUM)
7435 (match_operand:HI 2 "general_operand" "")))
7436 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7437 (set (match_dup 0) (reg:HI D_REGNUM))])]
7438 "(INTVAL (operands[1]) & 0x0FF) == 0"
7441 int value_loaded = 1;
7443 if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
7447 ops[0] = operands[0];
7448 ops[1] = operands[2];
7449 m68hc11_gen_movhi (insn, ops);
7450 output_asm_insn (\"xgd%0\", operands);
7452 else if (Y_REG_P (operands[0]))
7454 if (reg_mentioned_p (iy_reg, operands[2]))
7455 output_asm_insn (\"ldy\\t%2\", operands);
7458 output_asm_insn (\"xgdy\", operands);
7462 output_asm_insn (\"ldd\\t%2\", operands);
7465 if (value_loaded == 0)
7466 output_asm_insn (\"ldd\\t%2\", operands);
7467 if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
7468 output_asm_insn (\"inca\", operands);
7469 else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
7470 output_asm_insn (\"deca\", operands);
7471 else if (INTVAL (operands[1]) != 0)
7472 output_asm_insn (\"adda\\t%h1\", operands);
7474 if (X_REG_P (operands[0]))
7476 else if (Y_REG_P (operands[0]))
7484 [(set (match_operand:HI 0 "hard_reg_operand" "h")
7485 (match_operand:HI 1 "non_push_operand" "g"))
7486 (set (match_operand:HI 2 "hard_reg_operand" "h")
7488 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7489 && !S_REG_P (operands[2])"
7494 ops[0] = operands[2];
7495 ops[1] = operands[1];
7496 m68hc11_gen_movhi (insn, ops);
7502 [(set (match_operand:HI 0 "hard_reg_operand" "h")
7503 (match_operand:HI 1 "hard_reg_operand" "h"))
7504 (set (match_operand:HI 2 "non_push_operand" "g")
7506 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7507 && !S_REG_P (operands[2])"
7512 ops[0] = operands[2];
7513 ops[1] = operands[1];
7514 m68hc11_gen_movhi (insn, ops);
7520 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
7521 ;; the set, so we don't need to emit anything. 'ins1' refers to the
7525 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7526 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7527 (set (match_dup 0) (reg:HI D_REGNUM))])]
7528 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7531 cc_status = cc_prev_status;
7536 ;; Same as above but due to some split, there may be a noop set
7539 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7540 (set (match_dup 0) (match_dup 0))
7541 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7542 (set (match_dup 0) (reg:HI D_REGNUM))])]
7543 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7546 cc_status = cc_prev_status;
7552 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
7553 ;; and we must, at least, setup X/Y with value of D.
7556 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7557 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7558 (set (match_dup 0) (reg:HI D_REGNUM))])]
7564 ops[0] = operands[0];
7565 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7566 m68hc11_gen_movhi (insn, ops);
7572 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7573 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7576 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7577 (set (match_dup 0) (reg:HI D_REGNUM))])
7578 (set (reg:HI D_REGNUM) (match_dup 0))]
7579 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7582 cc_status = cc_prev_status;
7588 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7589 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7592 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7593 (set (match_dup 0) (reg:HI D_REGNUM))])
7594 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7595 "REGNO (operands[0]) == REGNO (operands[1])
7596 && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7599 cc_status = cc_prev_status;
7605 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7606 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7609 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7610 (set (match_dup 0) (reg:HI D_REGNUM))])
7611 (set (reg:HI D_REGNUM) (match_dup 0))]
7617 ops[0] = operands[0];
7618 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7619 m68hc11_gen_movhi (insn, ops);
7625 ;;; Same peephole with a QI set. The copy is made as 16-bit to comply
7629 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7630 (set (match_dup 0) (reg:HI D_REGNUM))])
7631 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7632 "REGNO (operands[0]) == REGNO (operands[1])"
7637 ops[0] = operands[0];
7638 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7639 m68hc11_gen_movhi (insn, ops);
7645 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
7648 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7649 (set (match_dup 0) (reg:HI D_REGNUM))])
7650 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7651 (set (match_dup 0) (reg:HI D_REGNUM))])]
7655 cc_status = cc_prev_status;
7661 [(set (match_operand:HI 0 "hard_reg_operand" "")
7662 (match_operand:HI 1 "stack_register_operand" ""))
7663 (set (match_operand:HI 2 "hard_reg_operand" "")
7664 (match_operand:HI 3 "memory_operand" "m"))
7666 (match_operand:HI 4 "memory_operand" "m"))]
7667 "IS_STACK_POP (operands[4])
7668 && (GET_CODE (operands[3]) == MEM &&
7669 rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
7674 ops[0] = operands[2];
7675 ops[1] = gen_rtx_MEM (HImode,
7676 gen_rtx_POST_INC (HImode, stack_pointer_rtx));
7677 m68hc11_gen_movhi (insn, ops);
7683 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
7686 [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
7687 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7691 return \"sts\\t%t0\\n\\tld%0\\t%t0\";
7696 [(set (match_operand:HI 0 "hard_reg_operand" "")
7697 (match_operand:HI 1 "memory_operand" ""))
7698 (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7700 && !side_effects_p (operands[1])
7701 && !reg_mentioned_p (operands[0], operands[1])"
7706 ops[0] = operands[0];
7707 ops[1] = operands[1];
7708 m68hc11_gen_movhi (insn, ops);
7709 ops[0] = operands[2];
7710 m68hc11_gen_movhi (insn, ops);
7714 ;; Peephole for Z register replacement.
7715 ;; Avoid to use _.tmp register when comparing D and X if we can compare
7716 ;; with soft register
7718 [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
7719 (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
7720 (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
7721 (reg:HI SOFT_TMP_REGNUM)))]
7722 "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
7727 ops[0] = operands[0];
7728 ops[1] = operands[1];
7729 m68hc11_gen_movhi (insn, ops);
7730 return \"cp%2\\t%1\";