1 ;;- Machine description file for Motorola 68HC11 and 68HC12.
2 ;;- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 ;;- Contributed by Stephane Carrez (stcarrez@worldnet.fr)
5 ;; This file is part of GNU CC.
7 ;; GNU CC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; GNU CC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU CC; see the file COPYING. If not, write to
19 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
23 ;; A first 68HC11 port was made by Otto Lind (otto@coactive.com)
24 ;; on gcc 2.6.3. I have used it as a starting point for this port.
25 ;; However, this new port is a complete re-write. Its internal
26 ;; design is completely different. The generated code is not
27 ;; compatible with the gcc 2.6.3 port.
29 ;; The gcc 2.6.3 port is available at:
31 ;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
34 ;;- Instruction patterns. When multiple patterns apply,
35 ;;- the first one in the file is chosen.
37 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
39 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
40 ;;- updates for most instructions.
43 ;; The following constraints are used:
45 ;; Single pair registers:
46 ;; a register 'a' 8-bit
47 ;; b register 'b' 8-bit
48 ;; d register 'd' 16-bit
49 ;; t pseudo soft register 'TMP' 16-bit
50 ;; v register 'd' for 68hc11, 16-bit
52 ;; (used for scratch register)
53 ;; w register 'sp' 16-bit
54 ;; x register 'x' 16-bit
55 ;; y register 'y' 16-bit
56 ;; z register 'z' 16-bit (fake r for 68HC11 and 68HC12)
57 ;; D register 'd+x' 32-bit
59 ;; Group of registers:
60 ;; q register 'a' or 'b' or 'd' 8-bit
61 ;; u pseudo soft register 16-bit
62 ;; A register 'x', 'y', 'z' 16-bit
63 ;; B register 'x', 'y' 16-bit
64 ;; h register 'd', 'x', 'y', 'z' 16-bit
68 ;; T an operand that can be accessed with 68HC1X direct addressing
69 ;; mode. For 68HC11 this includes the pseudo soft registers and
70 ;; any memory operand that is a direct addressing (.page0).
73 ;; Immediate integer operand constraints:
74 ;; `L' is for range -65536 to 65536
75 ;; `M' is for values whose 16-bit low part is 0
76 ;; 'N' is for +1 or -1.
77 ;; 'O' is for 16 (for rotate using swap).
78 ;; 'P' is for range -8 to 2 (used by addhi_sp)
80 ;; In many cases, it's not possible to use the 'g' or 'r' constraints.
82 ;; Operands modifiers:
84 ;; %b Get the low part of the operand (to obtain a QImode)
85 ;; This modified must always be used for QImode operations
86 ;; because a correction must be applied when the operand
87 ;; is a soft register (ex: *ZD1). Otherwise, we generate
88 ;; *ZD1 and this is the high part of the register. For other
89 ;; kinds of operands, if the operand is already QImode, no
90 ;; additional correction is made.
91 ;; %h Get the high part of the operand (to obtain a QImode)
92 ;; %t Represents the temporary/scratch register *_.tmp
93 ;; The scratch register is used in some cases when GCC puts
94 ;; some values in bad registers.
96 ;; 32/64-bit Patterns:
97 ;; The 68HC11 does not support 32/64-bit operations. Most of the
98 ;; 32/64-bit patterns are defined to split the instruction in
99 ;; 16-bits patterns. Providing split patterns generates better code
100 ;; than letting GCC implement the 32/64-bit operation itself.
105 ;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
106 ;; otherwise some insn are not satisfied.
108 ;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
109 ;; be valid only when z_replacement_completed == 2 because once these
110 ;; swap instructions are generated, a flow/cse pass fails to handle
111 ;; them correctly (it would treat the X, Y or D register as dead sometimes).
113 ;; o Some split pattern generate instructions that operate on 'a' or 'b'
114 ;; register directory (high part and low part of D respectively).
115 ;; Such split pattern must also be valid when z_replacement_completed == 2
116 ;; because flow/cse is not aware that D is composed of {a, b}.
118 ;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
119 ;; the high part of a soft register must be expanded after z_replacement
122 ;;---------------------------------------------------------------------------
127 (X_REGNUM 0) ; Index X register
128 (D_REGNUM 1) ; Data register
129 (Y_REGNUM 2) ; Index Y register
130 (SP_REGNUM 3) ; Stack pointer
131 (PC_REGNUM 4) ; Program counter
132 (A_REGNUM 5) ; A (high part of D)
133 (B_REGNUM 6) ; B (low part of D)
134 (CC_REGNUM 7) ; Condition code register
137 ;;--------------------------------------------------------------------
139 ;;--------------------------------------------------------------------
141 ;; The test and compare insn must not accept a memory operand with
142 ;; an auto-inc mode. If we do this, the reload can emit move insns
143 ;; after the test or compare. Such move will set the flags and therefore
144 ;; break the comparison. This can happen if the auto-inc register
145 ;; does not happen to be a hard register (ie, reloading occurs).
146 ;; An offsetable memory operand should be ok. The 'tst_operand' and
147 ;; 'cmp_operand' predicates take care of this rule.
149 (define_expand "tstsi"
151 (match_operand:SI 0 "tst_operand" ""))]
155 m68hc11_compare_op0 = operands[0];
156 m68hc11_compare_op1 = const0_rtx;
160 (define_expand "tsthi"
162 (match_operand:HI 0 "tst_operand" ""))]
166 m68hc11_compare_op0 = operands[0];
167 m68hc11_compare_op1 = const0_rtx;
171 (define_insn "tsthi_1"
173 (match_operand:HI 0 "tst_operand" "dx,y"))]
177 if (D_REG_P (operands[0]) && !TARGET_M6812)
178 return \"std\\t%t0\";
180 return \"cp%0\\t#0\";
183 (define_expand "tstqi"
185 (match_operand:QI 0 "tst_operand" ""))]
189 m68hc11_compare_op0 = operands[0];
190 m68hc11_compare_op1 = const0_rtx;
195 ;; Split pattern for (tst:QI) on an address register.
196 ;; The value is saved in memory and we test the low part only.
200 (match_operand:QI 0 "hard_addr_reg_operand" "xy"))]
201 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
202 [(set (match_dup 3) (match_dup 2))
203 (set (cc0) (match_dup 4))]
204 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));
205 operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
206 operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);")
208 (define_insn "tstqi_1"
210 (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
219 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
220 ;; during the Z register replacement. They are used when an operand
221 ;; uses the Z register as an index register (ie, (MEM:QI (REG:HI Z))).
222 ;; In that case, we have to preserve the values of the replacement
223 ;; register (as well as the CC0 since the insns are compare insns).
224 ;; To do this, the replacement register is pushed on the stack and
225 ;; restored after the real compare. A pattern+split is defined to
226 ;; avoid problems with the flow+cse register pass which are made
227 ;; after Z register replacement.
229 (define_insn "tstqi_z_used"
231 (match_operand:QI 0 "tst_operand" "m"))
232 (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
237 (define_split /* "tstqi_z_used" */
239 (match_operand:QI 0 "tst_operand" "m"))
240 (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
242 "z_replacement_completed == 2"
243 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
244 (set (match_dup 1) (match_dup 2))
245 (set (cc0) (match_dup 0))
246 (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
247 "operands[2] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
250 ;;--------------------------------------------------------------------
252 ;;--------------------------------------------------------------------
254 (define_expand "cmpsi"
256 (compare (match_operand:SI 0 "tst_operand" "")
257 (match_operand:SI 1 "cmp_operand" "")))]
261 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
262 operands[0] = force_reg (SImode, operands[0]);
264 m68hc11_compare_op0 = operands[0];
265 m68hc11_compare_op1 = operands[1];
270 ;; Comparison of a hard register with another one is provided because
271 ;; it helps GCC to avoid to spill a pseudo hard register.
272 ;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
273 ;; (except that we loose the information that the value is saved in it).
275 ;; The split pattern transforms the comparison into a save of one hard
276 ;; register and a comparison with the temporary.
280 (compare (match_operand:HI 0 "hard_reg_operand" "dxy")
281 (match_operand:HI 1 "hard_reg_operand" "Aw")))]
283 [(set (match_dup 2) (match_dup 1))
285 (compare (match_dup 0) (match_dup 2)))]
286 "operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);")
288 (define_expand "cmphi"
290 (compare (match_operand:HI 0 "tst_operand" "")
291 (match_operand:HI 1 "cmp_operand" "")))]
295 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
296 operands[0] = force_reg (HImode, operands[0]);
298 m68hc11_compare_op0 = operands[0];
299 m68hc11_compare_op1 = operands[1];
303 (define_insn "cmphi_1"
305 (compare (match_operand:HI 0 "tst_operand"
306 "xy,d,?xy,d,dxy,dxy,dxy")
307 (match_operand:HI 1 "cmp_operand"
308 "i,i,m,m,?*d*A,?u,!*w")))]
312 if (H_REG_P (operands[1]))
315 return \"cp%0\\t%1\";
318 (define_insn "cmphi_z_used"
320 (compare (match_operand:HI 0 "hard_reg_operand" "dxy")
321 (match_operand:HI 1 "cmp_operand" "m")))
322 (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
327 (define_split /* "cmphi_z_used" */
329 (compare (match_operand:HI 0 "hard_reg_operand" "dxy")
330 (match_operand:HI 1 "cmp_operand" "m")))
331 (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
333 "z_replacement_completed == 2"
334 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
335 (set (match_dup 2) (match_dup 3))
336 (set (cc0) (compare (match_dup 0) (match_dup 1)))
337 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
338 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
341 ;; 8-bit comparison with address register.
342 ;; There is no such comparison instruction, we have to temporarily switch
343 ;; the address register and the D register and do the comparison with D.
344 ;; The xgdx and xgdy instructions preserve the flags.
348 (compare (match_operand:QI 0 "hard_addr_reg_operand" "xy")
349 (match_operand:QI 1 "cmp_operand" "uimA")))]
350 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
351 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
352 (set (match_dup 3) (reg:HI D_REGNUM))])
354 (compare (reg:QI D_REGNUM) (match_dup 1)))
355 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
356 (set (match_dup 3) (reg:HI D_REGNUM))])]
357 "operands[3] = gen_rtx (REG, HImode, REGNO (operands[0]));")
361 (compare (match_operand:QI 0 "hard_reg_operand" "dxy")
362 (match_operand:QI 1 "hard_reg_operand" "dxy")))]
364 [(set (match_dup 3) (match_dup 4))
366 (compare (match_dup 0) (match_dup 2)))]
367 "operands[2] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
368 operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
369 operands[4] = gen_rtx (REG, HImode, REGNO (operands[1]));")
371 (define_expand "cmpqi"
373 (compare (match_operand:QI 0 "tst_operand" "")
374 (match_operand:QI 1 "cmp_operand" "")))]
378 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
379 operands[0] = force_reg (QImode, operands[0]);
381 m68hc11_compare_op0 = operands[0];
382 m68hc11_compare_op1 = operands[1];
386 (define_insn "bitcmpqi"
388 (and:QI (match_operand:QI 0 "tst_operand" "d,d,d")
389 (match_operand:QI 1 "cmp_operand" "im,*A,u")))]
396 (define_insn "bitcmpqi_z_used"
398 (and:QI (match_operand:QI 0 "tst_operand" "d")
399 (match_operand:QI 1 "cmp_operand" "m")))
400 (use (match_operand:HI 2 "hard_reg_operand" "xy"))
405 (define_split /* "bitcmpqi_z_used" */
407 (and:QI (match_operand:QI 0 "tst_operand" "d")
408 (match_operand:QI 1 "cmp_operand" "m")))
409 (use (match_operand:HI 2 "hard_reg_operand" "xy"))
411 "z_replacement_completed == 2"
412 [(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 2))
413 (set (match_dup 2) (match_dup 3))
414 (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
415 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI 3))))]
416 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
418 (define_insn "bitcmphi"
420 (and:HI (match_operand:HI 0 "tst_operand" "d")
421 (match_operand:HI 1 "const_int_operand" "i")))]
422 "(INTVAL (operands[1]) & 0x0ff) == 0
423 || (INTVAL (operands[1]) & 0x0ff00) == 0"
426 if ((INTVAL (operands[1]) & 0x0ff) == 0)
427 return \"bita\\t%h1\";
429 return \"bitb\\t%1\";
432 (define_insn "bitcmpqi_12"
434 (zero_extract (match_operand:HI 0 "tst_operand" "d")
435 (match_operand:HI 1 "const_int_operand" "i")
436 (match_operand:HI 2 "const_int_operand" "i")))]
437 "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
438 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
439 && (unsigned) INTVAL (operands[2]) >= 8)"
444 int startpos = INTVAL (operands[2]);
445 int bitsize = INTVAL (operands[1]);
450 mask = (1 << (startpos + bitsize)) - 1;
451 mask &= ~((1 << startpos) - 1);
453 ops[0] = GEN_INT (mask);
454 output_asm_insn (\"bita\\t%0\", ops);
458 mask = (1 << (startpos + bitsize)) - 1;
459 mask &= ~((1 << startpos) - 1);
461 ops[0] = GEN_INT (mask);
462 output_asm_insn (\"bitb\\t%0\", ops);
467 (define_insn "cmpqi_1"
469 (compare (match_operand:QI 0 "tst_operand" "d,d,*x*y,*x*y")
470 (match_operand:QI 1 "cmp_operand" "im,!u,!u,?dim*x*y")))]
478 (define_insn "cmpqi_z_used"
480 (compare (match_operand:QI 0 "hard_reg_operand" "dxy")
481 (match_operand:QI 1 "cmp_operand" "m")))
482 (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
487 (define_split /* cmpqi_z_used */
489 (compare (match_operand:QI 0 "hard_reg_operand" "dxy")
490 (match_operand:QI 1 "cmp_operand" "m")))
491 (use (match_operand:HI 2 "hard_reg_operand" "dxy"))
493 "z_replacement_completed == 2"
494 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
495 (set (match_dup 2) (match_dup 3))
496 (set (cc0) (compare (match_dup 0) (match_dup 1)))
497 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
498 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
500 (define_expand "cmpdf"
502 (compare (match_operand:DF 0 "general_operand" "")
503 (match_operand:DF 1 "general_operand" "")))]
507 m68hc11_compare_op0 = operands[0];
508 m68hc11_compare_op1 = operands[1];
512 (define_expand "cmpsf"
514 (compare (match_operand:SF 0 "general_operand" "")
515 (match_operand:SF 1 "general_operand" "")))]
519 m68hc11_compare_op0 = operands[0];
520 m68hc11_compare_op1 = operands[1];
524 ;;--------------------------------------------------------------------
525 ;;- Move strict_low_part
526 ;;--------------------------------------------------------------------
528 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
529 ;; The replacement must be made at the very end because we loose the
530 ;; (strict_low_part ...) information. This is correct for our machine
531 ;; description but not for GCC optimization passes.
533 (define_insn "movstrictsi"
534 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
535 (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
540 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
541 (match_operand:SI 1 "general_operand" "D,Dim,u"))]
542 "z_replacement_completed == 2"
543 [(set (match_dup 0) (match_dup 1))]
546 (define_insn "movstricthi"
547 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
548 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
553 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
554 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
555 "z_replacement_completed == 2"
556 [(set (match_dup 0) (match_dup 1))]
559 (define_insn "movstrictqi"
560 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
561 (match_operand:QI 1 "general_operand" "d,imudA"))]
566 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,dA"))
567 (match_operand:QI 1 "general_operand" "d,imudA"))]
568 "z_replacement_completed == 2"
569 [(set (match_dup 0) (match_dup 1))]
572 ;;--------------------------------------------------------------------
573 ;;- 64-bit Move Operations.
574 ;; The movdi and movdf patterns are identical except for the mode.
575 ;; They are also very similar to those for movsi and movsf.
577 ;; For 68HC11, we need a scratch register (either D, X, Y)
578 ;; because there is no memory->memory moves. It must be defined with
579 ;; earlyclobber (&) so that it does not appear in the source or destination
580 ;; address. Providing patterns for movdi/movdf allows GCC to generate
581 ;; better code. [Until now, the scratch register is limited to D becuse
582 ;; otherwise we can run out of registers in the A_REGS class for reload].
584 ;; For 68HC12, the scratch register is not necessary. To use the same
585 ;; pattern and same split, we use the 'v' constraint. This tells the
586 ;; reload to use the _.tmp register (which is not used at all).
587 ;; The insn will be split in one or several memory moves (movw).
588 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
589 ;;--------------------------------------------------------------------
590 (define_expand "movdi"
591 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
592 (match_operand:DI 1 "general_operand" ""))
593 (clobber (match_scratch:HI 2 ""))])]
596 /* For push/pop, emit a REG_INC note to make sure the reload
597 inheritance and reload CSE pass notice the change of the stack
599 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
603 insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
604 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
611 (define_insn "movdi_internal"
612 [(set (match_operand:DI 0 "nonimmediate_operand" "=U,!u,U,m,m,!u")
613 (match_operand:DI 1 "general_operand" "iU,iU,!u,mi,!u,!mu"))
614 (clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))]
619 [(set (match_operand:DI 0 "nonimmediate_operand" "=uUm")
620 (match_operand:DI 1 "general_operand" "iuUm"))
621 (clobber (match_scratch:HI 2 "=&d"))]
624 "m68hc11_split_move (operands[0], operands[1], operands[2]);
627 (define_expand "movdf"
628 [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
629 (match_operand:DF 1 "general_operand" ""))
630 (clobber (match_scratch:HI 2 ""))])]
632 "/* For push/pop, emit a REG_INC note to make sure the reload
633 inheritance and reload CSE pass notice the change of the stack
635 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
639 insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
640 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
647 (define_insn "movdf_internal"
648 [(set (match_operand:DF 0 "nonimmediate_operand" "=U,!u,U,m,m,!u")
649 (match_operand:DF 1 "general_operand" "iU,iU,!u,mi,!u,!mu"))
650 (clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))]
655 [(set (match_operand:DF 0 "nonimmediate_operand" "=uUm")
656 (match_operand:DF 1 "general_operand" "iuUm"))
657 (clobber (match_scratch:HI 2 "=&d"))]
660 "m68hc11_split_move (operands[0], operands[1], operands[2]);
663 ;;--------------------------------------------------------------------
664 ;;- 32-bit Move Operations.
665 ;; The movsi and movsf patterns are identical except for the mode.
666 ;; When we move to/from a hard register (d+x), we don't need a scratch.
667 ;; Otherwise, a scratch register is used as intermediate register for
668 ;; the move. The '&' constraint is necessary to make sure the reload
669 ;; pass does not give us a register that dies in the insn and is used
670 ;; for input/output operands.
671 ;;--------------------------------------------------------------------
672 (define_expand "movsi"
673 [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
674 (match_operand:SI 1 "general_operand" ""))
675 (clobber (match_scratch:HI 2 ""))])]
677 "/* For push/pop, emit a REG_INC note to make sure the reload
678 inheritance and reload CSE pass notice the change of the stack
680 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
684 insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
685 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
692 (define_insn "movsi_internal"
693 [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,?D,m,?D,?u,?u,!u,D")
694 (match_operand:SI 1 "general_operand" "imu,im,?D,!u,?D,mi,!u,!D"))
695 (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
700 [(set (match_operand:SI 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
701 (match_operand:SI 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
702 (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
705 "m68hc11_split_move (operands[0], operands[1], operands[2]);
708 (define_expand "movsf"
709 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
710 (match_operand:SF 1 "general_operand" ""))
711 (clobber (match_scratch:HI 2 ""))])]
713 "/* For push/pop, emit a REG_INC note to make sure the reload
714 inheritance and reload CSE pass notice the change of the stack
716 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
720 insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
721 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
728 (define_insn "movsf_internal"
729 [(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
730 (match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
731 (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
736 [(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
737 (match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
738 (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
741 "m68hc11_split_move (operands[0], operands[1], operands[2]);
745 ;;--------------------------------------------------------------------
746 ;;- 16-bit Move Operations.
747 ;; We don't need a scratch register.
748 ;;--------------------------------------------------------------------
750 (define_insn "*movhi2_push"
751 [(set (match_operand:HI 0 "push_operand" "=<,<")
752 (match_operand:HI 1 "general_operand" "xy,?d"))]
753 "TARGET_M6811 && !TARGET_M6812"
756 cc_status = cc_prev_status;
757 if (D_REG_P (operands[1]))
759 output_asm_insn (\"pshb\", operands);
762 else if (X_REG_P (operands[1]))
766 else if (Y_REG_P (operands[1]))
770 fatal_insn (\"Invalid register in the instruction\", insn);
773 (define_insn "*movhi2_pop"
774 [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
775 (match_operand:HI 1 "pop_operand" ">,>"))]
779 cc_status = cc_prev_status;
780 if (D_REG_P (operands[0]))
782 output_asm_insn (\"pula\", operands);
785 else if (X_REG_P (operands[0]))
789 else if (Y_REG_P (operands[0]))
793 fatal_insn (\"Invalid register in the instruction\", insn);
796 (define_expand "movhi"
797 [(set (match_operand:HI 0 "nonimmediate_operand" "")
798 (match_operand:HI 1 "general_operand" ""))]
802 if (reload_in_progress)
804 if (m68hc11_reload_operands (operands))
809 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
811 if (GET_CODE (operands[0]) == MEM &&
812 (GET_CODE (operands[1]) == MEM
813 || GET_CODE (operands[1]) == CONST_INT))
815 operands[1] = force_reg (HImode, operands[1]);
817 else if (IS_STACK_PUSH (operands[0])
818 && GET_CODE (operands[1]) != REG)
820 operands[1] = force_reg (HImode, operands[1]);
823 /* For push/pop, emit a REG_INC note to make sure the reload
824 inheritance and reload CSE pass notice the change of the stack
826 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
830 insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
831 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
838 (define_insn "movhi_const0"
839 [(set (match_operand:HI 0 "non_push_operand" "=d,A,um")
845 clr\\t%b0\\n\\tclr\\t%h0")
847 (define_insn "*movhi_68hc12"
848 [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,U,U,m,!u")
849 (match_operand:HI 1 "general_operand" "U,rim,dAwi,!u,dAw,riU"))]
853 m68hc11_gen_movhi (insn, operands);
857 (define_insn "*movhi_m68hc11"
858 [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
859 (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
863 m68hc11_gen_movhi (insn, operands);
867 ;;--------------------------------------------------------------------
868 ;;- 8-bit Move Operations.
869 ;; We don't need a scratch register.
870 ;;--------------------------------------------------------------------
872 ;; The *a alternative also clears the high part of the register.
873 ;; This should be ok since this is not the (strict_low_part) set.
875 (define_insn "movqi_const0"
876 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
887 ;; 8-bit operations on address registers.
889 ;; Switch temporary to the D register and load the value in B.
890 ;; This is possible as long as the address register does not
891 ;; appear in the source operand.
894 [(set (match_operand:QI 0 "hard_addr_reg_operand" "=A")
895 (match_operand:QI 1 "general_operand" ""))]
896 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode
897 && !reg_mentioned_p (operands[0], operands[1])
898 && !D_REG_P (operands[1])"
899 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
900 (set (match_dup 2) (reg:HI D_REGNUM))])
901 (set (reg:QI D_REGNUM) (match_dup 1))
902 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
903 (set (match_dup 2) (reg:HI D_REGNUM))])]
904 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));")
907 ;; 8-bit operations on address registers.
910 [(set (match_operand:QI 0 "nonimmediate_operand" "")
911 (match_operand:QI 1 "hard_addr_reg_operand" "=A"))]
912 "z_replacement_completed == 2 && GET_MODE (operands[1]) == QImode
913 && !reg_mentioned_p (operands[1], operands[0])
914 && !D_REG_P (operands[0])"
915 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
916 (set (match_dup 2) (reg:HI D_REGNUM))])
917 (set (match_dup 0) (reg:QI D_REGNUM))
918 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
919 (set (match_dup 2) (reg:HI D_REGNUM))])]
920 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1]));")
922 (define_insn "*movqi2_push"
923 [(set (match_operand:QI 0 "push_operand" "=<,<")
924 (match_operand:QI 1 "general_operand" "d,!*A"))]
928 if (A_REG_P (operands[1]))
931 cc_status = cc_prev_status;
936 (define_expand "movqi"
937 [(set (match_operand:QI 0 "nonimmediate_operand" "")
938 (match_operand:QI 1 "general_operand" ""))]
942 if (reload_in_progress)
944 if (m68hc11_reload_operands (operands))
949 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
951 if (GET_CODE (operands[0]) == MEM
952 && (GET_CODE (operands[1]) == MEM
953 || GET_CODE (operands[1]) == CONST_INT))
955 operands[1] = force_reg (QImode, operands[1]);
957 else if (IS_STACK_PUSH (operands[0])
958 && GET_CODE (operands[1]) != REG)
960 operands[1] = force_reg (QImode, operands[1]);
963 /* For push/pop, emit a REG_INC note to make sure the reload
964 inheritance and reload CSE pass notice the change of the stack
966 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
970 insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
971 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
978 (define_insn "*movqi_68hc12"
979 [(set (match_operand:QI 0 "nonimmediate_operand" "=d*AuU*q,d*A*qu,d*A*q,m,m")
980 (match_operand:QI 1 "general_operand" "rui*q,U,m,d*q,!A"))]
984 m68hc11_gen_movqi (insn, operands);
988 (define_insn "*movqi_m68hc11"
989 [(set (match_operand:QI 0 "nonimmediate_operand" "=dA*q,m,m,dA*q,*u")
990 (match_operand:QI 1 "general_operand" "dAim*q,d*q,!A,*u,dA*q"))]
994 m68hc11_gen_movqi (insn, operands);
998 ;;--------------------------------------------------------------------
1000 ;;--------------------------------------------------------------------
1001 ;; Swapping registers is used for split patterns.
1002 (define_insn "swap_areg"
1003 [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1004 (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1005 (set (match_dup 1) (match_dup 0))]
1009 m68hc11_output_swap (insn, operands);
1013 ;;--------------------------------------------------------------------
1014 ;;- Truncation insns.
1015 ;;--------------------------------------------------------------------
1017 ;; Truncation are not necessary because GCC knows how to truncate,
1018 ;; specially when values lie in consecutive registers.
1021 (define_expand "floatunssisf2"
1022 [(set (match_operand:SF 0 "nonimmediate_operand" "")
1023 (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1025 "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
1026 SFmode, SImode, 2, operands);
1029 (define_expand "floatunssidf2"
1030 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1031 (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1033 "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
1034 DFmode, SImode, 2, operands);
1037 ;;--------------------------------------------------------------------
1038 ;;- Zero extension insns.
1039 ;;--------------------------------------------------------------------
1042 ;; 64-bit extend. The insn will be split into 16-bit instructions just
1043 ;; before the final pass. We need a scratch register for the split.
1044 ;; The final value can be generated on the stack directly. This is more
1045 ;; efficient and useful for conversions made during parameter passing rules.
1047 (define_insn "zero_extendqidi2"
1048 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1050 (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1051 (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1056 [(set (match_operand:DI 0 "push_operand" "=<")
1057 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "dmu*B")))
1058 (clobber (match_scratch:HI 2 "=&dB"))]
1059 "z_replacement_completed == 2"
1063 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1064 rtx push = m68hc11_gen_lowpart (HImode, low);
1065 rtx src = operands[1];
1067 /* Source operand must be in a hard register. */
1070 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1071 emit_move_insn (src, operands[1]);
1074 /* Source is in D, we can push B then one word of 0 and we do
1075 a correction on the stack pointer. */
1078 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1079 emit_move_insn (operands[2], const0_rtx);
1080 if (D_REG_P (operands[2]))
1082 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1086 emit_move_insn (push, operands[2]);
1087 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1088 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1094 /* Source is in X or Y. It's better to push the 16-bit register
1095 and then to some stack adjustment. */
1096 src = gen_rtx (REG, HImode, REGNO (src));
1097 emit_move_insn (push, src);
1098 emit_move_insn (operands[2], const0_rtx);
1099 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1100 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1102 emit_move_insn (push, operands[2]);
1103 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1104 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1107 emit_move_insn (push, operands[2]);
1108 emit_move_insn (push, operands[2]);
1109 emit_move_insn (push, operands[2]);
1114 [(set (match_operand:DI 0 "nonimmediate_operand" "=mu")
1115 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "dmu*B")))
1116 (clobber (match_scratch:HI 2 "=&dB"))]
1117 "z_replacement_completed == 2"
1121 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1122 rtx low2 = m68hc11_gen_lowpart (HImode, low);
1123 rtx src = operands[1];
1125 /* Source operand must be in a hard register. */
1128 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1129 emit_move_insn (src, operands[1]);
1132 emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1133 emit_move_insn (operands[2], const0_rtx);
1134 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1135 emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1137 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1138 low = m68hc11_gen_highpart (SImode, operands[0]);
1139 emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1140 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1144 (define_insn "zero_extendhidi2"
1145 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1147 (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1148 (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1153 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,!u,!u")
1155 (match_operand:HI 1 "nonimmediate_operand" "m,dA,!u,dmA,!u")))
1156 (clobber (match_scratch:HI 2 "=&d,&dB,&dB,&dB,&dB"))]
1157 "z_replacement_completed == 2"
1161 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1162 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1163 rtx src = operands[1];
1165 /* Make sure the source is in a hard register. */
1169 emit_move_insn (src, operands[1]);
1172 /* Move the low part first for the push. */
1173 emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1175 /* Now, use the scratch register to fill in the zeros. */
1176 emit_move_insn (operands[2], const0_rtx);
1177 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1178 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1179 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1183 (define_insn "zero_extendsidi2"
1184 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1186 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1187 (clobber (match_scratch:HI 2 "=d,d,&dB,d"))]
1192 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1194 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1195 (clobber (match_scratch:HI 2 "=d,d,&dB,d"))]
1196 "z_replacement_completed == 2"
1200 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1201 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1203 /* Move the low part first so that this is ok for a push. */
1204 m68hc11_split_move (low, operands[1], operands[2]);
1206 /* Use the scratch register to clear the high part of the destination. */
1207 emit_move_insn (operands[2], const0_rtx);
1208 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1209 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1214 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1215 ;; because it's less efficient.
1217 (define_insn "zero_extendhisi2"
1218 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1220 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1221 (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1226 [(set (match_operand:SI 0 "non_push_operand" "=D,mu,m,m,!u,!u")
1228 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,m,!u,m,!u")))
1229 (clobber (match_scratch:HI 2 "=X,X,&d,&dB,&dB,&dB"))]
1234 rtx src = operands[1];
1236 if (!H_REG_P (src) && !H_REG_P (operands[0]))
1239 emit_move_insn (src, operands[1]);
1241 emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1242 emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1246 (define_insn "zero_extendqisi2"
1247 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u")
1249 (match_operand:QI 1 "nonimmediate_operand" "dxymu,dxy,dxy")))]
1254 [(set (match_operand:SI 0 "non_push_operand" "=mu")
1255 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxy")))]
1256 "reload_completed && !X_REG_P (operands[0])"
1257 [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1258 (set (match_dup 3) (const_int 0))]
1260 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1261 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1264 [(set (match_operand:SI 0 "hard_reg_operand" "=D")
1265 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxymu")))]
1266 "z_replacement_completed == 2 && X_REG_P (operands[0])"
1267 [(set (match_dup 2) (match_dup 3))
1268 (set (match_dup 4) (const_int 0))
1269 (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1271 if (X_REG_P (operands[1]))
1273 emit_insn (gen_swap_areg (gen_rtx (REG, HImode, HARD_D_REGNUM),
1274 gen_rtx (REG, HImode, HARD_X_REGNUM)));
1275 emit_insn (gen_zero_extendqihi2 (gen_rtx (REG, HImode, HARD_D_REGNUM),
1276 gen_rtx (REG, QImode, HARD_D_REGNUM)));
1277 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM),
1282 if (reg_mentioned_p (gen_rtx (REG, HImode, HARD_X_REGNUM), operands[1]))
1284 emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1287 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), const0_rtx);
1290 operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1291 operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1292 if (A_REG_P (operands[1]))
1294 operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
1295 operands[3] = gen_rtx (REG, HImode, REGNO (operands[1]));
1296 operands[6] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
1300 operands[5] = operands[2] =
1301 operands[3] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1302 operands[6] = operands[1];
1306 (define_insn "zero_extendqihi2"
1307 [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!u,d,m,!u")
1309 (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1315 if (A_REG_P (operands[0]))
1318 if (H_REG_P (operands[0]))
1320 output_asm_insn (\"clra\", operands);
1321 if (operands[0] != operands[1]
1322 && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1324 if (X_REG_P (operands[1])
1325 || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1327 output_asm_insn (\"stx\\t%t1\", operands);
1328 output_asm_insn (\"ldab\\t%T0\", operands);
1330 else if (Y_REG_P (operands[1])
1331 || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1333 output_asm_insn (\"sty\\t%t1\", operands);
1334 output_asm_insn (\"ldab\\t%T0\", operands);
1338 output_asm_insn (\"ldab\\t%b1\", operands);
1340 cc_status.flags |= CC_NOT_NEGATIVE;
1344 /* Status refers to the clra insn. Status is ok for others
1345 * since we have loaded the value in B.
1352 if (A_REG_P (operands[1]))
1354 output_asm_insn (\"st%1\\t%0\", operands);
1355 output_asm_insn (\"clr\\t%h0\", operands);
1360 output_asm_insn (\"clr\\t%h0\", operands);
1361 output_asm_insn (\"stab\\t%b0\", operands);
1362 cc_status.flags |= CC_NOT_NEGATIVE;
1369 ;;--------------------------------------------------------------------
1370 ;;- Sign extension insns.
1371 ;;--------------------------------------------------------------------
1373 (define_insn "extendqisi2"
1374 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1375 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1383 /* The 68HC12 has a sign-extension instruction. Use it when the
1384 destination is the register (X,D). First sign-extend the low
1385 part and fill X with the sign-extension of the high part. */
1386 if (TARGET_M6812 && X_REG_P (operands[0]))
1388 if (!D_REG_P (operands[1]))
1390 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1391 ops[1] = operands[1];
1392 m68hc11_gen_movqi (insn, ops);
1394 return \"sex\\tb,d\\n\\tsex\\ta,x\";
1397 ops[2] = gen_label_rtx ();
1399 if (X_REG_P (operands[1]))
1401 output_asm_insn (\"xgdx\", operands);
1404 else if (X_REG_P (operands[0]))
1406 /* X can be used as an indexed addressing in the source.
1407 Get the value before clearing it. */
1408 if (reg_mentioned_p (ix_reg, operands[1]))
1410 output_asm_insn (\"ldab\\t%b1\", operands);
1413 output_asm_insn (\"ldx\\t#0\", operands);
1416 output_asm_insn (\"clra\", operands);
1417 if (!X_REG_P (operands[0]))
1419 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1420 ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1422 if (IS_STACK_PUSH (operands[0]))
1424 output_asm_insn (\"pshb\", ops);
1425 output_asm_insn (\"tstb\", ops);
1429 output_asm_insn (\"stab\\t%b1\", ops);
1432 else if (D_REG_P (operands[1]) || need_tst)
1434 output_asm_insn (\"tstb\", operands);
1438 output_asm_insn (\"ldab\\t%b1\", operands);
1440 output_asm_insn (\"bpl\\t%l2\", ops);
1441 output_asm_insn (\"deca\", operands);
1442 if (X_REG_P (operands[0]))
1443 output_asm_insn (\"dex\", operands);
1445 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1447 if (!X_REG_P (operands[0]))
1449 if (IS_STACK_PUSH (operands[0]))
1451 output_asm_insn (\"psha\", ops);
1452 output_asm_insn (\"psha\", ops);
1453 output_asm_insn (\"psha\", ops);
1457 output_asm_insn (\"staa\\t%h0\", ops);
1459 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1460 if (dead_register_here (insn, d_reg))
1462 output_asm_insn (\"tab\", ops);
1463 output_asm_insn (\"std\\t%0\", ops);
1467 output_asm_insn (\"staa\\t%b0\", ops);
1468 output_asm_insn (\"staa\\t%h0\", ops);
1478 (define_insn "extendqihi2"
1479 [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1480 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1486 if (A_REG_P (operands[0]))
1489 ops[0] = gen_label_rtx ();
1490 if (D_REG_P (operands[0]))
1494 if (!D_REG_P (operands[1]))
1496 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1497 ops[1] = operands[1];
1498 m68hc11_gen_movqi (insn, ops);
1500 return \"sex\\tb,d\";
1502 output_asm_insn (\"clra\", operands);
1503 if (H_REG_P (operands[1]))
1505 output_asm_insn (\"tstb\", operands);
1509 output_asm_insn (\"ldab\\t%b1\", operands);
1511 output_asm_insn (\"bpl\\t%l0\", ops);
1512 output_asm_insn (\"deca\", operands);
1514 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1515 CODE_LABEL_NUMBER (ops[0]));
1519 output_asm_insn (\"clr\\t%h0\", operands);
1520 if (m68hc11_register_indirect_p (operands[1], HImode))
1522 ops[1] = operands[1];
1523 output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1528 output_asm_insn (\"tst\\t%b1\", operands);
1529 output_asm_insn (\"bpl\\t%l0\", ops);
1531 output_asm_insn (\"dec\\t%h0\", operands);
1532 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1533 CODE_LABEL_NUMBER (ops[0]));
1540 ;; Split the special case where the source of the sign extend is
1541 ;; either Y or Z. In that case, we can't move the source in the D
1542 ;; register directly. The movhi pattern handles this move by using
1543 ;; a temporary scratch memory location.
1546 [(set (match_operand:SI 0 "register_operand" "=D")
1547 (sign_extend:SI (match_operand:HI 1 "register_operand" "A")))]
1548 "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1549 [(set (reg:HI D_REGNUM) (match_dup 1))
1550 (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1553 (define_insn "extendhisi2"
1554 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1555 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1563 if (Y_REG_P (operands[1]))
1566 if (X_REG_P (operands[1]))
1568 output_asm_insn (\"xgdx\", operands);
1573 /* X can be used as a indexed addressing in the source.
1574 Get the value before clearing it. */
1575 x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1578 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1579 ops[1] = operands[1];
1580 m68hc11_gen_movhi (insn, ops);
1585 if (TARGET_M6812 && 0)
1587 /* This sequence of code is larger than the one for 68HC11.
1588 Don't use it; keep it for documentation. */
1589 if (!D_REG_P (operands[1]) && !x_reg_used)
1591 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1592 ops[1] = operands[1];
1593 m68hc11_gen_movhi (insn, ops);
1595 output_asm_insn (\"sex\\ta,x\", operands);
1596 output_asm_insn (\"xgdx\", operands);
1597 output_asm_insn (\"sex\\ta,d\", operands);
1601 output_asm_insn (\"ldx\\t#0\", operands);
1602 if (D_REG_P (operands[1]) || x_reg_used)
1604 output_asm_insn (\"tsta\", operands);
1608 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1609 ops[1] = operands[1];
1610 m68hc11_gen_movhi (insn, ops);
1613 ops[0] = gen_label_rtx ();
1614 output_asm_insn (\"bpl\\t%l0\", ops);
1615 output_asm_insn (\"dex\", operands);
1616 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1622 ;;--------------------------------------------------------------------
1623 ;;- Min and Max instructions (68HC12).
1624 ;;--------------------------------------------------------------------
1625 (define_insn "uminqi3"
1626 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1627 (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1628 (match_operand:QI 2 "general_operand" "m,d")))]
1632 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1633 The mina/minm use A as the source or destination. This is the
1634 high part of D. There is no way to express that in the pattern
1635 so we must use 'exg a,b' to put the operand in the good register. */
1637 if (D_REG_P (operands[0]))
1639 return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1643 return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1647 (define_insn "umaxqi3"
1648 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1649 (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1650 (match_operand:QI 2 "general_operand" "m,d")))]
1654 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1655 The maxa/maxm use A as the source or destination. This is the
1656 high part of D. There is no way to express that in the pattern
1657 so we must use 'exg a,b' to put the operand in the good register. */
1659 if (D_REG_P (operands[0]))
1661 return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1665 return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1669 (define_insn "uminhi3"
1670 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1671 (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1672 (match_operand:HI 2 "general_operand" "m,d")))]
1676 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1678 if (D_REG_P (operands[0]))
1680 return \"emind\\t%2\";
1684 return \"eminm\\t%0\";
1688 (define_insn "umaxhi3"
1689 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1690 (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1691 (match_operand:HI 2 "general_operand" "m,d")))]
1695 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1697 if (D_REG_P (operands[0]))
1699 return \"emaxd\\t%2\";
1703 return \"emaxm\\t%0\";
1708 ;;--------------------------------------------------------------------
1709 ;;- Add instructions.
1710 ;;--------------------------------------------------------------------
1711 ;; 64-bit: Use a library call because what GCC generates is huge.
1713 (define_expand "adddi3"
1714 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1715 (plus:DI (match_operand:DI 1 "general_operand" "")
1716 (match_operand:DI 2 "general_operand" "")))]
1718 "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1724 (define_expand "addsi3"
1725 [(parallel [(set (match_operand:SI 0 "register_operand" "")
1726 (plus:SI (match_operand:SI 1 "register_operand" "")
1727 (match_operand:SI 2 "general_operand" "")))
1728 (clobber (match_scratch:HI 3 ""))])]
1733 ;; Translate D = D + D into D = D << 1
1734 ;; We have to do this because adding a register to itself is not possible.
1736 ;; Manipulation of A and B registers directly confuses the cse-regs pass
1737 ;; so the split must be made after z-replacement register.
1740 [(set (match_operand:SI 0 "register_operand" "=D")
1741 (plus:SI (match_dup 0)
1743 (clobber (match_scratch:HI 1 "=X"))]
1744 "reload_completed && z_replacement_completed == 2"
1745 [(set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
1746 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
1747 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
1748 (set (reg:QI B_REGNUM) (rotate:QI (reg:QI B_REGNUM) (reg:QI CC_REGNUM)))
1749 (set (reg:QI A_REGNUM) (rotate:QI (reg:QI A_REGNUM) (reg:QI CC_REGNUM)))
1750 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
1751 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
1755 (define_insn "*addsi3_zero_extendhi"
1756 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1757 (plus:SI (zero_extend:SI
1758 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1759 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1760 (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1766 if (X_REG_P (operands[2]))
1768 ops[0] = operands[1];
1772 if (X_REG_P (operands[1]))
1774 output_asm_insn (\"xgdx\", ops);
1776 else if (!D_REG_P (operands[1]))
1778 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1779 ops[1] = operands[1];
1780 m68hc11_gen_movhi (insn, ops);
1782 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1783 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1785 ops[2] = gen_label_rtx ();
1787 /* ldx preserves the carry, propagate it by incrementing X directly. */
1788 output_asm_insn (\"addd\\t%0\", ops);
1789 if (!X_REG_P (operands[2]))
1790 output_asm_insn (\"ldx\\t%1\", ops);
1792 output_asm_insn (\"bcc\\t%l2\", ops);
1793 output_asm_insn (\"inx\", ops);
1796 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1801 (define_split /* "*addsi3_zero_extendqi" */
1802 [(set (match_operand:SI 0 "register_operand" "=D,D")
1803 (plus:SI (zero_extend:SI
1804 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1805 (match_operand:SI 2 "memory_operand" "m,m")))
1806 (clobber (match_scratch:HI 3 "=X,X"))]
1808 [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1809 (parallel [(set (match_dup 0)
1810 (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1811 (clobber (match_dup 3))])]
1814 (define_insn "*addsi3_zero_extendqi"
1815 [(set (match_operand:SI 0 "register_operand" "=D,D")
1816 (plus:SI (zero_extend:SI
1817 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1818 (match_operand:SI 2 "general_operand" "miD,!muiD")))
1819 (clobber (match_scratch:HI 3 "=X,X"))]
1825 if (GET_CODE (operands[2]) == MEM)
1828 if (X_REG_P (operands[2]))
1830 if (H_REG_P (operands[1]))
1832 ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
1833 ops[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
1834 m68hc11_gen_movhi (insn, ops);
1838 ops[0] = operands[1];
1840 ops[1] = gen_rtx (CONST_INT, VOIDmode, 0);
1844 if (X_REG_P (operands[1]))
1846 output_asm_insn (\"xgdx\", ops);
1848 else if (!D_REG_P (operands[1]))
1850 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1851 ops[1] = operands[1];
1852 m68hc11_gen_movqi (insn, ops);
1855 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1857 ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1858 output_asm_insn (\"clra\", ops);
1861 /* ldx preserves the carry, propagate it by incrementing X directly. */
1862 output_asm_insn (\"addb\\t%b0\", ops);
1863 output_asm_insn (\"adca\\t%h1\", ops);
1864 if (!X_REG_P (operands[2]))
1865 output_asm_insn (\"ldx\\t%2\", ops);
1867 /* If the above adca was adding some constant, we don't need to propagate
1868 the carry unless the constant was 0xff. */
1869 if (X_REG_P (operands[2])
1870 || GET_CODE (ops[1]) != CONST_INT
1871 || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1873 ops[3] = gen_label_rtx ();
1875 output_asm_insn (\"bcc\\t%l3\", ops);
1876 output_asm_insn (\"inx\", ops);
1878 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1879 CODE_LABEL_NUMBER (ops[3]));
1885 (define_insn "*addsi3"
1886 [(set (match_operand:SI 0 "non_push_operand" "=m,D,!u,?D,D")
1887 (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1888 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?miu")))
1889 (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1900 if (which_alternative > 2)
1905 val = INTVAL (operands[2]);
1906 if ((val & 0x0ffffL) == 0)
1908 if (!H_REG_P (operands[0]))
1910 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1911 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1912 output_asm_insn (\"ldd\\t%0\", ops);
1913 output_asm_insn (\"addd\\t%1\", ops);
1914 output_asm_insn (\"std\\t%0\", ops);
1926 if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1933 ops[1] = operands[2];
1934 add_insn = \"addd\\t%1\";
1935 inc_insn = \"inx\\t\";
1936 incb_mem = \"inc\\t%b1\";
1937 inch_mem = \"inc\\t%h1\";
1941 ops[1] = gen_rtx (CONST_INT, VOIDmode, - val);
1942 add_insn = \"subd\\t%1\";
1944 incb_mem = \"dec\\t%b1\";
1945 inch_mem = \"dec\\t%h1\";
1948 ops[2] = gen_label_rtx ();
1949 if (!H_REG_P (operands[0]))
1951 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1952 output_asm_insn (\"ldd\\t%0\", ops);
1954 output_asm_insn (add_insn, ops);
1955 if (!H_REG_P (operands[0]))
1957 output_asm_insn (\"std\\t%0\", ops);
1959 output_asm_insn (\"bcc\\t%l2\", ops);
1960 if (H_REG_P (operands[0]))
1962 output_asm_insn (inc_insn, ops);
1966 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1968 if (INTVAL (operands[2]) < 0)
1970 output_asm_insn (\"ldd\\t%1\", ops);
1971 output_asm_insn (\"addd\\t#-1\", ops);
1972 output_asm_insn (\"std\\t%1\", ops);
1976 output_asm_insn (incb_mem, ops);
1977 output_asm_insn (\"bne\\t%l2\", ops);
1978 output_asm_insn (inch_mem, ops);
1981 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1988 [(set (match_operand:SI 0 "register_operand" "=D,u")
1989 (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
1990 (match_operand:SI 2 "const_int_operand" "")))
1991 (clobber (match_scratch:HI 3 "=X,d"))]
1992 "reload_completed && z_replacement_completed == 2
1993 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
1994 [(set (match_dup 5) (match_dup 6))
1995 (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
1996 (set (match_dup 6) (match_dup 5))]
1997 "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
1998 if (X_REG_P (operands[0]))
2000 operands[5] = operands[6] = gen_rtx (REG, HImode, HARD_D_REGNUM);
2004 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2005 operands[5] = operands[3];
2010 [(set (match_operand:SI 0 "register_operand" "=D")
2011 (plus:SI (match_operand:SI 1 "register_operand" "%0")
2012 (match_operand:SI 2 "general_operand" "mui")))
2013 (clobber (match_scratch:HI 3 "=X"))]
2014 "reload_completed && z_replacement_completed == 2
2015 && (GET_CODE (operands[2]) != CONST_INT ||
2016 (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
2017 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2018 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2019 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2020 (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2021 (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2022 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2023 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
2024 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2025 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2026 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2027 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2030 ;; Instruction generated to propagate the carry of a 16-bit add
2031 ;; to the upper 16-bit part (in register X).
2033 (define_insn "*addsi_carry"
2034 [(set (match_operand:HI 0 "register_operand" "=x")
2035 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2037 (reg:HI CC_REGNUM)))]
2043 ops[0] = gen_label_rtx ();
2044 output_asm_insn (\"bcc\\t%l0\", ops);
2045 output_asm_insn (\"in%0\", operands);
2046 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2054 (define_expand "addhi3"
2055 [(set (match_operand:HI 0 "register_operand" "")
2056 (plus:HI (match_operand:HI 1 "register_operand" "")
2057 (match_operand:HI 2 "general_operand" "")))]
2061 if (TARGET_M6811 && SP_REG_P (operands[0]))
2063 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2064 gen_rtx (SET, VOIDmode,
2066 gen_rtx (PLUS, HImode,
2067 operand1, operand2)),
2068 gen_rtx (CLOBBER, VOIDmode,
2069 gen_rtx (SCRATCH, HImode)))));
2074 (define_split /* "*addhi3_strict_low_part" */
2075 [(set (strict_low_part (match_operand:QI 0 "register_operand" "+dxy"))
2076 (plus:QI (match_operand:QI 1 "register_operand" "")
2077 (match_operand:QI 2 "general_operand" "")))]
2078 "0 && z_replacement_completed == 2"
2080 (plus:QI (match_dup 1) (match_dup 2)))]
2083 (define_split /* "*addhi3_strict_low_part" */
2084 [(set (match_operand:HI 0 "register_operand" "=dA")
2085 (plus:HI (match_operand:HI 1 "register_operand" "%0")
2086 (match_operand:HI 2 "general_operand" "")))
2087 (clobber (match_scratch:HI 3 ""))]
2088 "0 && z_replacement_completed == 2 && !SP_REG_P (operands[0])"
2090 (plus:HI (match_dup 1) (match_dup 2)))]
2093 (define_insn "*addhi3_68hc12"
2094 [(set (match_operand:HI 0 "register_operand" "=*d,A*w,A*w,A")
2095 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw,0")
2096 (match_operand:HI 2 "general_operand" "imA*wu,id,id,!muA")))]
2101 const char* insn_code;
2103 if (which_alternative >= 3)
2105 if (A_REG_P (operands[2]))
2108 output_asm_insn (\"xgd%2\", operands);
2109 output_asm_insn (\"lea%0 d,%0\", operands);
2115 if (D_REG_P (operands[0]))
2117 if (X_REG_P (operands[2]))
2119 m68hc11_notice_keep_cc (operands[0]);
2120 output_asm_insn (\"xgdx\", operands);
2121 output_asm_insn (\"leax\\td,%2\", operands);
2124 else if (Y_REG_P (operands[2]))
2126 m68hc11_notice_keep_cc (operands[0]);
2127 output_asm_insn (\"xgdy\", operands);
2128 output_asm_insn (\"leay\\td,%2\", operands);
2131 else if (SP_REG_P (operands[2]))
2133 output_asm_insn (\"sts\\t%t0\", operands);
2134 return \"addd\\t%t0\";
2136 return \"addd\\t%2\";
2139 if (GET_CODE (operands[2]) == CONST_INT)
2140 val = INTVAL (operands[2]);
2144 if (val != -1 || val != 1 || !rtx_equal_p (operands[0], operands[1]))
2146 m68hc11_notice_keep_cc (operands[0]);
2147 switch (REGNO (operands[0]))
2150 return \"leax\\t%i2,%1\";
2153 return \"leay\\t%i2,%1\";
2155 case HARD_SP_REGNUM:
2156 return \"leas\\t%i2,%1\";
2159 fatal_insn (\"Invalid operands in the instruction\", insn);
2164 insn_code = X_REG_P (operands[0]) ? \"inx\"
2165 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2170 insn_code = X_REG_P (operands[0]) ? \"dex\"
2171 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2174 /* For X and Y increment, the flags are not complete. Only the Z flag
2175 is updated. For SP increment, flags are not changed. */
2176 if (SP_REG_P (operands[0]))
2178 cc_status = cc_prev_status;
2179 if (INTVAL (operands[2]) < 0)
2183 output_asm_insn (\"pshx\", operands);
2197 output_asm_insn (insn_code, operands);
2204 ;; Specific pattern to add to the stack pointer.
2205 ;; We also take care of the clobbering of the IY register.
2207 (define_insn "addhi_sp"
2208 [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2209 (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2210 (match_operand:HI 2 "general_operand" "P,im,u,im")))
2211 (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2217 if (GET_CODE (operands[2]) == CONST_INT
2218 && (val = INTVAL (operands[2])) != 0
2219 && (CONST_OK_FOR_LETTER_P (val, 'P')
2220 || (val > 0 && val <= 8)))
2222 if (optimize && Y_REG_P (operands[3])
2223 && dead_register_here (insn, gen_rtx (REG, HImode, HARD_X_REGNUM)))
2224 operands[3] = gen_rtx (REG, HImode, HARD_X_REGNUM);
2225 while (val > 1 || val < -1)
2229 if (!H_REG_P (operands[3]))
2232 output_asm_insn (\"pul%3\", operands);
2237 output_asm_insn (\"pshx\", operands);
2245 output_asm_insn (\"ins\", operands);
2250 output_asm_insn (\"des\", operands);
2254 cc_status = cc_prev_status;
2258 /* Need to transfer to SP to IY and then to D register.
2259 Register IY is lost, this is specified by the (clobber) statement. */
2260 output_asm_insn (\"ts%3\", operands);
2261 output_asm_insn (\"xgd%3\", operands);
2262 output_asm_insn (\"addd\\t%2\", operands);
2263 output_asm_insn (\"xgd%3\", operands);
2265 /* The status flags correspond to the addd. xgdy and tys do not
2266 modify the flags. */
2271 ;; Translate d = d + d into d = d << 1
2272 ;; We have to do this because adding a register to itself is not possible.
2273 ;; ??? It's not clear whether this is really necessary.
2276 [(set (match_operand:HI 0 "hard_reg_operand" "=dA")
2277 (plus:HI (match_dup 0)
2280 [(set (match_dup 0) (ashift:HI (match_dup 0) (const_int 1)))]
2283 (define_insn "*addhi3"
2284 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d")
2285 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0")
2286 (match_operand:HI 2 "general_operand" "N,i,I,mi*A*d,!u*d*w")))]
2290 const char* insn_code;
2294 if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2296 output_asm_insn (\"sts\\t%t0\", operands);
2297 output_asm_insn (\"addd\\t%t0\", operands);
2298 return \"addd\\t#1\";
2300 if (GET_CODE (operands[2]) != CONST_INT)
2302 /* Adding to an address register or with another/same register
2303 is not possible. This must be replaced. */
2304 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2307 return \"addd\\t%2\";
2309 val = INTVAL (operands[2]);
2310 if (!SP_REG_P (operands[0]))
2312 if (D_REG_P (operands[0]))
2314 if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2317 return \"adda\\t%h2\";
2321 return \"addd\\t%2\";
2324 else if (GET_CODE (operands[2]) != CONST_INT
2325 || INTVAL (operands[2]) < -4
2326 || INTVAL (operands[2]) > 4)
2331 insn_code = X_REG_P (operands[0]) ? \"inx\"
2332 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2337 insn_code = X_REG_P (operands[0]) ? \"dex\"
2338 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2341 /* For X and Y increment, the flags are not complete. Only the Z flag
2342 is updated. For SP increment, flags are not changed. */
2343 if (SP_REG_P (operands[0]))
2345 cc_status = cc_prev_status;
2346 if (INTVAL (operands[2]) < 0)
2350 output_asm_insn (\"pshx\", operands);
2354 else if (optimize && dead_register_here (insn, ix_reg))
2358 output_asm_insn (\"pulx\", operands);
2370 output_asm_insn (insn_code, operands);
2376 (define_insn "*addhi3_zext"
2377 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2378 (plus:HI (zero_extend:HI
2379 (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2380 (match_operand:HI 2 "hard_reg_operand" "0,0")))]
2385 if (A_REG_P (operands[0]))
2387 else if (A_REG_P (operands[1]))
2388 return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2390 return \"addb\\t%b1\\n\\tadca\\t#0\";
2394 ;; Translate d = d + d into d = << 1
2395 ;; We have to do this because adding a register to itself is not possible.
2396 ;; ??? It's not clear whether this is really necessary.
2399 [(set (match_operand:QI 0 "hard_reg_operand" "=dA")
2400 (plus:QI (match_dup 0)
2402 "0 && reload_completed"
2403 [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2406 (define_insn "addqi3"
2407 [(set (match_operand:QI 0 "nonimmediate_operand" "=!*rm,dq*A")
2408 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
2409 (match_operand:QI 2 "general_operand" "N,ium*A*d")))]
2413 if (GET_CODE (operands[2]) == CONST_INT)
2415 if (INTVAL (operands[2]) == 1)
2417 if (DA_REG_P (operands[0]))
2421 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2426 else if (A_REG_P (operands[0]))
2428 /* This applies on the 16-bit register. This should be ok since
2429 this is not a strict_low_part increment. */
2434 return \"inc\\t%b0\";
2437 else if (INTVAL (operands[2]) == -1)
2439 if (DA_REG_P (operands[0]))
2443 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2447 else if (A_REG_P (operands[0]))
2449 /* This applies on the 16-bit register. This should be ok since
2450 this is not a strict_low_part decrement. */
2455 return \"dec\\t%b0\";
2459 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2461 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2462 return \"addb\\t%b2\";
2464 return \"adda\\t%b2\";
2468 ;; add with carry is used for 32-bit add.
2470 (define_insn "*adcq"
2471 [(set (match_operand:QI 0 "register_operand" "=q")
2472 (plus:QI (plus:QI (reg:QI CC_REGNUM)
2473 (match_operand:QI 1 "register_operand" "%0"))
2474 (match_operand:QI 2 "general_operand" "ium")))]
2478 ;;--------------------------------------------------------------------
2479 ;;- Subtract instructions.
2480 ;;--------------------------------------------------------------------
2482 (define_expand "subdi3"
2483 [(set (match_operand:DI 0 "nonimmediate_operand" "")
2484 (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2485 (match_operand:DI 2 "general_operand" "")))]
2487 "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2491 ;; 32-bit Subtract (see addsi3)
2492 ;; Subtract with a constant are handled by addsi3.
2497 (define_expand "subsi3"
2498 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2499 (minus:SI (match_operand:SI 1 "register_operand" "")
2500 (match_operand:SI 2 "general_operand" "")))
2501 (clobber (match_scratch:HI 3 ""))])]
2505 (define_insn "*subsi3"
2506 [(set (match_operand:SI 0 "register_operand" "=D,D")
2507 (minus:SI (match_operand:SI 1 "general_operand" "0,!mui")
2508 (match_operand:SI 2 "general_operand" "!mui,!D")))
2509 (clobber (match_scratch:HI 3 "=X,X"))]
2513 (define_insn "*subsi3_zero_extendhi"
2514 [(set (match_operand:SI 0 "register_operand" "=D")
2515 (minus:SI (match_operand:SI 1 "register_operand" "0")
2516 (zero_extend:SI (match_operand:HI 2 "general_operand" "d!mui"))))
2517 (clobber (match_scratch:HI 3 "=X"))]
2523 ops[0] = gen_label_rtx ();
2524 output_asm_insn (\"subd\\t%2\", operands);
2525 output_asm_insn (\"bcc\\t%l0\", ops);
2526 output_asm_insn (\"dex\", ops);
2527 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2532 (define_insn "*subsi3_zero_extendqi"
2533 [(set (match_operand:SI 0 "register_operand" "=D")
2534 (minus:SI (match_operand:SI 1 "register_operand" "0")
2535 (zero_extend:SI (match_operand:QI 2 "general_operand" "!dmui"))))
2536 (clobber (match_scratch:HI 3 "=X"))]
2542 ops[0] = gen_label_rtx ();
2543 output_asm_insn (\"subb\\t%b2\", operands);
2544 output_asm_insn (\"sbca\\t#0\", operands);
2545 output_asm_insn (\"bcc\\t%l0\", ops);
2546 output_asm_insn (\"dex\", ops);
2547 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2553 ;; reg:HI 1 -> d reg:QI 6 -> B
2554 ;; reg:QI 7 -> ccr reg:QI 5 -> A
2556 (define_split /* "*subsi3" */
2557 [(set (match_operand:SI 0 "register_operand" "=D")
2558 (minus:SI (match_operand:SI 1 "register_operand" "0")
2559 (match_operand:SI 2 "general_operand" "mui")))
2560 (clobber (match_scratch:HI 3 "=X"))]
2561 "reload_completed && z_replacement_completed == 2
2562 && X_REG_P (operands[1])"
2563 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2564 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2565 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2566 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2567 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2568 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2569 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2570 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2571 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2572 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2573 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2575 (define_split /* "*subsi3" */
2576 [(set (match_operand:SI 0 "register_operand" "=D")
2577 (minus:SI (match_operand:SI 1 "general_operand" "mui")
2578 (match_operand:SI 2 "register_operand" "D")))
2579 (clobber (match_scratch:HI 3 "=X"))]
2580 "reload_completed && z_replacement_completed == 2
2581 && X_REG_P (operands[2])"
2582 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2583 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2584 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2585 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2586 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2587 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2588 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2589 (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2590 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2591 operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2592 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2593 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2596 ;; - 16-bit Subtract.
2598 (define_expand "subhi3"
2599 [(set (match_operand:HI 0 "register_operand" "=r")
2600 (minus:HI (match_operand:HI 1 "register_operand" "0")
2601 (match_operand:HI 2 "general_operand" "g")))]
2605 if (TARGET_M6811 && SP_REG_P (operands[0]))
2607 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2608 gen_rtx (SET, VOIDmode,
2610 gen_rtx (MINUS, HImode,
2611 operand1, operand2)),
2612 gen_rtx (CLOBBER, VOIDmode,
2613 gen_rtx (SCRATCH, HImode, 0)))));
2619 ;; Subtract from stack. This is better if we provide a pattern.
2621 (define_insn "*subhi3_sp"
2622 [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2623 (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2624 (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2625 (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2629 if (X_REG_P (operands[2]))
2631 operands[2] = m68hc11_soft_tmp_reg;
2632 output_asm_insn (\"stx\\t%2\", operands);
2634 else if (Y_REG_P (operands[2]))
2636 operands[2] = m68hc11_soft_tmp_reg;
2637 output_asm_insn (\"sty\\t%2\", operands);
2639 else if (D_REG_P (operands[2]))
2641 operands[2] = m68hc11_soft_tmp_reg;
2642 output_asm_insn (\"std\\t%2\", operands);
2645 if (D_REG_P (operands[3]))
2647 output_asm_insn (\"xgdx\", operands);
2648 output_asm_insn (\"tsx\", operands);
2649 output_asm_insn (\"xgdx\", operands);
2650 output_asm_insn (\"subd\\t%2\", operands);
2651 output_asm_insn (\"xgdx\", operands);
2653 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2654 modify the flags. */
2655 output_asm_insn (\"txs\", operands);
2659 /* Need to transfer to SP to X,Y and then to D register.
2660 Register X,Y is lost, this is specified by the (clobber) statement. */
2661 output_asm_insn (\"ts%3\", operands);
2662 output_asm_insn (\"xgd%3\", operands);
2663 output_asm_insn (\"subd\\t%2\", operands);
2664 output_asm_insn (\"xgd%3\", operands);
2666 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2667 modify the flags. */
2672 (define_insn "*subhi3"
2673 [(set (match_operand:HI 0 "register_operand" "=d,*A,d*A")
2674 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
2675 (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,!u")))]
2679 /* Adding to an address register or with another/same register
2680 is not possible. This must be replaced. */
2681 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2684 return \"subd\\t%2\";
2687 (define_insn "*subhi3_zext"
2688 [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2689 (minus:HI (match_operand:HI 1 "hard_reg_operand" "0,0")
2690 (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2695 if (A_REG_P (operands[2]))
2699 ops[0] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
2700 ops[1] = operands[2];
2701 m68hc11_gen_movqi (insn, ops);
2702 return \"subb\\t%T0\\n\\tsbca\\t#0\";
2704 return \"subb\\t%b2\\n\\tsbca\\t#0\";
2707 (define_insn "subqi3"
2708 [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2709 (minus:QI (match_operand:QI 1 "hard_reg_operand" "0,0")
2710 (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2714 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2716 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2717 return \"subb\\t%b2\";
2719 return \"suba\\t%b2\";
2723 ;; subtract with carry is used for 32-bit subtract.
2725 (define_insn "*subcq"
2726 [(set (match_operand:QI 0 "register_operand" "=q")
2727 (minus:QI (minus:QI (reg:QI CC_REGNUM)
2728 (match_operand:QI 1 "register_operand" "0"))
2729 (match_operand:QI 2 "general_operand" "ium")))]
2733 ;;--------------------------------------------------------------------
2734 ;;- Multiply instructions.
2735 ;;--------------------------------------------------------------------
2737 ;; 32 and 64-bit multiply are handled by the library
2740 (define_expand "mulsi3"
2741 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2742 (mult:SI (match_operand:SI 1 "general_operand" "")
2743 (match_operand:SI 2 "general_operand" "")))]
2745 "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2748 (define_expand "mulhi3"
2749 [(parallel [(set (match_operand:HI 0 "register_operand" "")
2750 (mult:HI (match_operand:HI 1 "register_operand" "")
2751 (match_operand:HI 2 "register_operand" "")))
2752 (clobber (match_scratch:HI 3 ""))])]
2756 (define_insn "mulhi3_m68hc11"
2757 [(set (match_operand:HI 0 "register_operand" "=d")
2758 (mult:HI (match_operand:HI 1 "register_operand" "%0")
2759 (match_operand:HI 2 "register_operand" "x")))
2760 (clobber (match_scratch:HI 3 "=X"))]
2765 /* D * X -> D (X and Y are preserved by this function call). */
2766 return \"jsr\\t___mulhi3\";
2769 (define_insn "mulhi3_m68hc12"
2770 [(set (match_operand:HI 0 "register_operand" "=d,d")
2771 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2772 (match_operand:HI 2 "register_operand" "y,x")))
2773 (clobber (match_scratch:HI 3 "=2,2"))]
2778 if (X_REG_P (operands[2]))
2779 return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2784 (define_insn "umulhisi3"
2785 [(set (match_operand:SI 0 "register_operand" "=D,D")
2786 (mult:SI (zero_extend:SI
2787 (match_operand:HI 1 "register_operand" "%d,d"))
2789 (match_operand:HI 2 "register_operand" "y,x"))))
2790 (clobber (match_scratch:HI 3 "=2,X"))]
2794 if (X_REG_P (operands [2]))
2795 output_asm_insn (\"exg\\tx,y\", operands);
2797 /* Can't use the carry after that; other flags are ok when testing
2798 the 32-bit result. */
2799 cc_status.flags |= CC_NO_OVERFLOW;
2800 return \"emul\\n\\texg\\tx,y\";
2803 (define_insn "mulhisi3"
2804 [(set (match_operand:SI 0 "register_operand" "=D,D")
2805 (mult:SI (sign_extend:SI
2806 (match_operand:HI 1 "register_operand" "%d,d"))
2808 (match_operand:HI 2 "register_operand" "y,x"))))
2809 (clobber (match_scratch:HI 3 "=2,X"))]
2813 if (X_REG_P (operands [2]))
2814 output_asm_insn (\"exg\\tx,y\", operands);
2816 /* Can't use the carry after that; other flags are ok when testing
2817 the 32-bit result. */
2818 cc_status.flags |= CC_NO_OVERFLOW;
2819 return \"emuls\\n\\texg\\tx,y\";
2822 (define_insn "umulqihi3"
2823 [(set (match_operand:HI 0 "register_operand" "=d")
2824 (mult:HI (zero_extend:HI
2825 (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2827 (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2831 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2833 output_asm_insn (\"tba\", operands);
2839 if (D_REG_P (operands[2]))
2841 rtx temp = operands[2];
2842 operands[2] = operands[1];
2846 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
2847 ops[1] = operands[2];
2848 m68hc11_gen_movqi (insn, ops);
2850 if (!D_REG_P (operands[1]))
2852 output_asm_insn (\"ldab\\t%b1\", operands);
2860 (define_insn "mulqi3"
2861 [(set (match_operand:QI 0 "register_operand" "=d")
2862 (mult:QI (match_operand:QI 1 "nonimmediate_operand" "dum")
2863 (match_operand:QI 2 "nonimmediate_operand" "dum")))]
2867 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2869 output_asm_insn (\"tba\", operands);
2873 if (D_REG_P (operands[2]))
2875 rtx temp = operands[2];
2876 operands[2] = operands[1];
2880 output_asm_insn (\"ldaa\\t%b2\", operands);
2882 if (!D_REG_P (operands[1]))
2884 output_asm_insn (\"ldab\\t%b1\", operands);
2892 (define_insn "mulqihi3"
2893 [(set (match_operand:HI 0 "register_operand" "=d,d")
2894 (mult:HI (sign_extend:HI
2895 (match_operand:QI 1 "register_operand" "%0,0"))
2897 (match_operand:QI 2 "nonimmediate_operand" "dm,*A"))))]
2903 /* Special case when multiplying the register with itself. */
2904 if (D_REG_P (operands[2]))
2906 output_asm_insn (\"tba\", operands);
2910 if (!H_REG_P (operands[2]))
2912 output_asm_insn (\"ldaa\\t%b2\", operands);
2918 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
2919 ops[1] = operands[2];
2920 m68hc11_gen_movqi (insn, ops);
2922 return \"jsr\\t___mulqi3\";
2925 ;;--------------------------------------------------------------------
2926 ;;- Divide instructions.
2927 ;;--------------------------------------------------------------------
2929 (define_insn "divmodhi4"
2930 [(set (match_operand:HI 0 "register_operand" "=d,d")
2931 (div:HI (match_operand:HI 1 "register_operand" "0,0")
2932 (match_operand:HI 2 "general_operand" "A,ium")))
2933 (set (match_operand:HI 3 "register_operand" "=&x,&x")
2934 (mod:HI (match_dup 1) (match_dup 2)))]
2938 if (!X_REG_P (operands[2]))
2940 if (Y_REG_P (operands[2]))
2942 output_asm_insn (\"sty\\t%t1\", operands);
2943 output_asm_insn (\"ldx\\t%t1\", operands);
2947 output_asm_insn (\"ldx\\t%2\", operands);
2952 /* Flags are ok after that. */
2953 return \"idivs\\n\\txgdx\";
2958 return \"bsr\\t__divmodhi4\";
2962 (define_insn "udivmodhi4"
2963 [(set (match_operand:HI 0 "register_operand" "=d,d")
2964 (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
2965 (match_operand:HI 2 "general_operand" "A,ium")))
2966 (set (match_operand:HI 3 "register_operand" "=x,x")
2967 (umod:HI (match_dup 1) (match_dup 2)))]
2971 if (!X_REG_P (operands[2]))
2973 if (Y_REG_P (operands[2]))
2975 output_asm_insn (\"sty\\t%t1\", operands);
2976 output_asm_insn (\"ldx\\t%t1\", operands);
2980 output_asm_insn (\"ldx\\t%2\", operands);
2984 /* Z V and C flags are set but N is unchanged.
2985 Since this is an unsigned divide, we can probably keep the flags
2986 and indicate this. */
2987 cc_status.flags |= CC_NOT_NEGATIVE;
2988 return \"idiv\\n\\txgdx\";
2991 ;;--------------------------------------------------------------------
2992 ;;- and instructions.
2993 ;;--------------------------------------------------------------------
2995 (define_insn "anddi3"
2996 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
2997 (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
2998 (match_operand:DI 2 "general_operand" "imu,imu")))
2999 (clobber (match_scratch:HI 3 "=d,d"))]
3003 (define_insn "andsi3"
3004 [(set (match_operand:SI 0 "register_operand" "=D")
3005 (and:SI (match_operand:SI 1 "register_operand" "%0")
3006 (match_operand:SI 2 "general_operand" "Dimu")))]
3010 (define_insn "andhi3"
3011 [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A")
3012 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
3013 (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))]
3017 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3020 if (GET_CODE (operands[2]) == CONST_INT)
3022 int val = INTVAL (operands[2]) & 0x0FFFF;
3023 char lowpart_zero = 0;
3024 char lowpart_unknown = 0;
3025 char highpart_zero = 0;
3026 char highpart_unknown = 0;
3030 cc_status = cc_prev_status;
3034 /* First, try to clear the low and high part.
3035 If that's possible, the second 'and' will give
3036 the good status flags and we can avoid a tsthi. */
3037 if ((val & 0x0FF) == 0)
3039 if (D_REG_P (operands[0]))
3040 output_asm_insn (\"clrb\", operands);
3042 output_asm_insn (\"clr\\t%b0\", operands);
3045 if ((val & 0x0FF00) == 0)
3047 if (D_REG_P (operands[0]))
3048 output_asm_insn (\"clra\", operands);
3050 output_asm_insn (\"clr\\t%h0\", operands);
3054 if ((val & 0x0FF) == 0x0FF)
3056 lowpart_unknown = 1;
3058 else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3062 ops[0] = operands[0];
3063 ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
3064 output_asm_insn (\"bclr\\t%b0, %1\", ops);
3066 else if ((val & 0x0FF) != 0)
3068 output_asm_insn (\"andb\\t%b2\", operands);
3071 if ((val & 0x0FF00) == 0x0FF00)
3073 highpart_unknown = 1;
3075 else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3079 ops[0] = operands[0];
3080 ops[1] = gen_rtx (CONST_INT, VOIDmode, ((~val) & 0x0FF00) >> 8);
3081 output_asm_insn (\"bclr\\t%h0, %1\", ops);
3083 else if ((val & 0x0FF00) != 0)
3085 output_asm_insn (\"anda\\t%h2\", operands);
3088 if (highpart_unknown || lowpart_unknown)
3090 else if (highpart_zero == 0 && lowpart_zero == 0)
3097 return \"andb\\t%b2\\n\\tanda\\t%h2\";
3100 (define_insn "andqi3"
3101 [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q")
3102 (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0")
3103 (match_operand:QI 2 "general_operand" "i,i,!um,?*A,!ium,?*A*d,!ium*A")))]
3107 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3110 if (GET_CODE (operands[2]) == CONST_INT)
3112 int val = INTVAL (operands[2]) & 0x0FF;
3116 cc_status = cc_prev_status;
3121 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3123 else if (DA_REG_P (operands[0]))
3126 return \"clr\\t%b0\";
3128 if (!H_REG_P (operands[0]))
3131 ops[0] = operands[0];
3132 ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
3133 output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3137 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3138 return \"andb\\t%b2\";
3139 else if (DA_REG_P (operands[0]))
3140 return \"anda\\t%b2\";
3142 fatal_insn (\"Invalid operand in the instruction\", insn);
3145 ;;--------------------------------------------------------------------
3146 ;;- Bit set or instructions.
3147 ;;--------------------------------------------------------------------
3149 (define_insn "iordi3"
3150 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3151 (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3152 (match_operand:DI 2 "general_operand" "imu,imu")))
3153 (clobber (match_scratch:HI 3 "=d,d"))]
3157 (define_insn "iorsi3"
3158 [(set (match_operand:SI 0 "register_operand" "=D")
3159 (ior:SI (match_operand:SI 1 "register_operand" "%0")
3160 (match_operand:SI 2 "general_operand" "Dimu")))]
3164 (define_insn "iorhi3"
3165 [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A")
3166 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
3167 (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))]
3171 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3174 if (GET_CODE (operands[2]) == CONST_INT)
3176 int val = INTVAL (operands[2]) & 0x0FFFF;
3180 cc_status = cc_prev_status;
3183 if ((val & 0x0FF) != 0)
3185 if (!H_REG_P (operands[0]))
3186 output_asm_insn (\"bset\\t%b0, %b2\", operands);
3188 output_asm_insn (\"orab\\t%b2\", operands);
3191 if ((val & 0x0FF00) != 0)
3193 if (!H_REG_P (operands[0]))
3194 output_asm_insn (\"bset\\t%h0, %h2\", operands);
3196 output_asm_insn (\"oraa\\t%h2\", operands);
3204 return \"orab\\t%b2\\n\\toraa\\t%h2\";
3207 (define_insn "iorqi3"
3208 [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q")
3209 (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0")
3210 (match_operand:QI 2 "general_operand" "i,i,!um,!*A,!ium,?*A*d,!ium*A")))]
3214 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3217 if (GET_CODE (operands[2]) == CONST_INT)
3219 int val = INTVAL (operands[2]) & 0x0FF;
3223 cc_status = cc_prev_status;
3226 if (!H_REG_P (operands[0]))
3228 return \"bset\\t%b0, %2\";
3231 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3232 return \"orab\\t%b2\";
3233 else if (DA_REG_P (operands[0]))
3234 return \"oraa\\t%b2\";
3236 fatal_insn (\"Invalid operand in the instruction\", insn);
3239 ;;--------------------------------------------------------------------
3240 ;;- xor instructions.
3241 ;;--------------------------------------------------------------------
3243 (define_insn "xordi3"
3244 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3245 (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3246 (match_operand:DI 2 "general_operand" "imu,imu")))
3247 (clobber (match_scratch:HI 3 "=d,d"))]
3251 (define_insn "xorsi3"
3252 [(set (match_operand:SI 0 "register_operand" "=D")
3253 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3254 (match_operand:SI 2 "general_operand" "Dimu")))]
3258 (define_insn "xorhi3"
3259 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3260 (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
3261 (match_operand:HI 2 "general_operand" "im,!u*A,!ium*A")))]
3265 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3268 if (GET_CODE (operands[2]) == CONST_INT)
3270 int val = INTVAL (operands[2]) & 0x0FFFF;
3274 cc_status = cc_prev_status;
3277 if ((val & 0x0FF) != 0)
3279 output_asm_insn (\"eorb\\t%b2\", operands);
3281 else if ((val & 0x0FF) == 0x0FF)
3283 output_asm_insn (\"comb\", operands);
3286 if ((val & 0x0FF00) != 0)
3288 output_asm_insn (\"eora\\t%h2\", operands);
3290 else if ((val & 0x0FF00) == 0x0FF00)
3292 output_asm_insn (\"coma\", operands);
3300 return \"eorb\\t%b2\\n\\teora\\t%h2\";
3303 (define_insn "xorqi3"
3304 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3305 (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
3306 (match_operand:QI 2 "general_operand" "i,!um,!*A,!ium,?*A*d,!ium*A")))]
3310 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3313 if (GET_CODE (operands[2]) == CONST_INT)
3315 int val = INTVAL (operands[2]) & 0x0FF;
3319 cc_status = cc_prev_status;
3324 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3330 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3331 return \"eorb\\t%b2\";
3332 else if (DA_REG_P (operands[0]))
3333 return \"eora\\t%b2\";
3335 fatal_insn (\"Invalid operand in the instruction\", insn);
3338 ;;--------------------------------------------------------------------
3339 ;;- Bit set or instructions.
3340 ;;--------------------------------------------------------------------
3342 (define_insn "*logicalsi3_zexthi"
3343 [(set (match_operand:SI 0 "register_operand" "=D,D")
3344 (match_operator:SI 3 "m68hc11_logical_operator"
3346 (match_operand:HI 1 "general_operand" "imdA,!udimA"))
3347 (match_operand:SI 2 "general_operand" "Dimu,!Dimu")]))]
3351 (define_insn "*logicalsi3_zextqi"
3352 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3353 (match_operator:SI 3 "m68hc11_logical_operator"
3355 (match_operand:QI 1 "general_operand" "d,*A,imu"))
3356 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3361 [(set (match_operand:SI 0 "register_operand" "=D,D")
3362 (match_operator:SI 3 "m68hc11_logical_operator"
3364 (match_operand:QI 1 "general_operand" "dxy,imu"))
3365 (match_operand:SI 2 "general_operand" "imuD,imuD")]))]
3366 "z_replacement_completed == 2"
3367 [(set (reg:QI A_REGNUM) (match_dup 4))
3368 (set (reg:QI D_REGNUM) (match_dup 7))
3369 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3370 (set (reg:HI X_REGNUM) (match_dup 6))]
3371 "PUT_MODE (operands[3], QImode);
3372 if (X_REG_P (operands[2]))
3374 operands[5] = operands[1];
3375 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3376 operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM);
3377 operands[7] = gen_rtx (REG, QImode, HARD_D_REGNUM);
3378 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3382 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3383 operands[7] = operands[1];
3384 operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3385 operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3386 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3391 [(set (match_operand:SI 0 "register_operand" "=D,D")
3392 (match_operator:SI 3 "m68hc11_logical_operator"
3394 (match_operand:HI 1 "general_operand" "dA,imu"))
3395 (match_operand:SI 2 "general_operand" "imuD,imuD")]))]
3397 [(set (reg:HI D_REGNUM) (match_dup 4))
3398 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3399 (set (reg:HI X_REGNUM) (match_dup 6))]
3400 "PUT_MODE (operands[3], HImode);
3401 if (X_REG_P (operands[2]))
3403 operands[5] = operands[1];
3404 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3405 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3406 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3410 operands[4] = operands[1];
3411 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3412 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3416 (define_insn "*logicallhi3_zexthi_ashift8"
3417 [(set (match_operand:HI 0 "register_operand" "=d")
3418 (match_operator:HI 3 "m68hc11_logical_operator"
3420 (match_operand:QI 1 "general_operand" "imud"))
3422 (match_operand:HI 2 "general_operand" "dimu")
3427 (define_insn "*logicalhi3_zexthi"
3428 [(set (match_operand:HI 0 "register_operand" "=d")
3429 (match_operator:HI 3 "m68hc11_logical_operator"
3431 (match_operand:QI 1 "general_operand" "imud"))
3432 (match_operand:HI 2 "general_operand" "dimu")]))]
3437 [(set (match_operand:HI 0 "register_operand" "=d")
3438 (match_operator:HI 3 "m68hc11_logical_operator"
3440 (match_operand:QI 1 "general_operand" "imud"))
3441 (match_operand:HI 2 "general_operand" "dimu")]))]
3442 "z_replacement_completed == 2"
3443 [(set (reg:QI B_REGNUM) (match_dup 6))
3444 (set (reg:QI A_REGNUM) (match_dup 4))
3445 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3447 PUT_MODE (operands[3], QImode);
3448 if (D_REG_P (operands[2]))
3450 operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM);
3451 operands[5] = operands[1];
3452 operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3456 operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3457 operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3458 if (D_REG_P (operands[1]))
3459 operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3461 operands[6] = operands[1];
3466 [(set (match_operand:HI 0 "register_operand" "=d")
3467 (match_operator:HI 3 "m68hc11_logical_operator"
3469 (match_operand:QI 1 "general_operand" "imud"))
3471 (match_operand:HI 2 "general_operand" "dimu")
3473 "z_replacement_completed == 2"
3474 [(set (reg:QI A_REGNUM) (match_dup 4))
3475 (set (reg:QI B_REGNUM) (match_dup 5))]
3477 if (GET_CODE (operands[3]) == AND)
3479 emit_insn (gen_movhi (operands[0], const0_rtx));
3484 operands[5] = operands[1];
3485 if (D_REG_P (operands[2]))
3487 operands[4] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3491 operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3496 (define_insn "*logicalsi3_silshr16"
3497 [(set (match_operand:SI 0 "register_operand" "=D,D")
3498 (match_operator:SI 3 "m68hc11_logical_operator"
3500 (match_operand:SI 1 "general_operand" "uim,?D")
3502 (match_operand:SI 2 "general_operand" "uim,0")]))]
3507 [(set (match_operand:SI 0 "register_operand" "=D,D")
3508 (match_operator:SI 3 "m68hc11_logical_operator"
3510 (match_operand:SI 1 "general_operand" "uim,?D")
3512 (match_operand:SI 2 "general_operand" "uim,0")]))]
3514 [(set (reg:HI D_REGNUM) (match_dup 4))
3515 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3516 (set (reg:HI X_REGNUM) (match_dup 6))]
3517 "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3518 if (X_REG_P (operands[2]))
3520 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3521 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3525 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3526 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3528 PUT_MODE (operands[3], HImode);
3532 (define_insn "*logicalsi3_silshl16"
3533 [(set (match_operand:SI 0 "register_operand" "=D,D")
3534 (match_operator:SI 3 "m68hc11_logical_operator"
3536 (match_operand:SI 1 "general_operand" "uim,?D")
3538 (match_operand:SI 2 "general_operand" "0,0")]))]
3543 [(set (match_operand:SI 0 "register_operand" "=D,D")
3544 (match_operator:SI 3 "m68hc11_logical_operator"
3546 (match_operand:SI 1 "general_operand" "uim,?D")
3548 (match_operand:SI 2 "general_operand" "0,0")]))]
3549 "z_replacement_completed == 2"
3550 [(parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
3551 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
3552 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 4)]))
3553 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
3554 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
3555 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3556 PUT_MODE (operands[3], HImode);")
3559 ;;--------------------------------------------------------------------
3560 ;;- 64/32-bit Logical Operations. Patterns are defined so that GCC
3561 ;; can optimize correctly. These insns are split by the `final'
3562 ;; pass (# pattern). They are split to fall in the corresponding
3563 ;; 16-bit logical patterns.
3564 ;;--------------------------------------------------------------------
3566 ;; Split 64-bit logical operations (AND, OR, XOR).
3568 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=mu")
3569 (match_operator:DI 4 "m68hc11_logical_operator"
3570 [(match_operand:DI 1 "reg_or_some_mem_operand" "%imu")
3571 (match_operand:DI 2 "general_operand" "imu")]))
3572 (clobber (match_scratch:HI 3 "=d"))]
3575 "m68hc11_split_logical (SImode, GET_CODE (operands[4]), operands);
3578 ;; Split 32-bit logical operations (AND, OR, XOR).
3580 [(set (match_operand:SI 0 "register_operand" "=D")
3581 (match_operator:SI 3 "m68hc11_logical_operator"
3582 [(match_operand:SI 1 "register_operand" "%0")
3583 (match_operand:SI 2 "general_operand" "Dimu")]))]
3586 "m68hc11_split_logical (HImode, GET_CODE (operands[3]), operands);
3589 ;;--------------------------------------------------------------------
3590 ;; 16-bit Arithmetic and logical operations on X and Y:
3592 ;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3594 ;; Operations on X or Y registers are split here. Instructions are
3596 ;; - xgdx/xgdy instruction pattern,
3597 ;; - The same operation on register D,
3598 ;; - xgdx/xgdy instruction pattern.
3599 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3600 ;; We also handle the case were the address register is used in both source
3601 ;; operands, such as:
3603 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3605 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3609 [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
3610 (match_operator:HI 3 "m68hc11_arith_operator"
3611 [(match_operand:HI 1 "hard_addr_reg_operand" "0")
3612 (match_operand:HI 2 "general_operand" "dAuim")]))]
3613 "z_replacement_completed == 2
3614 /* If we are adding a small constant to X or Y, it's
3615 better to use one or several inx/iny instructions. */
3616 && !(GET_CODE (operands[3]) == PLUS
3618 && (immediate_operand (operands[2], HImode)
3619 || hard_reg_operand (operands[2], HImode)))
3620 || (GET_CODE (operands[2]) == CONST_INT
3621 && INTVAL (operands[2]) >= -4
3622 && INTVAL (operands[2]) <= 4)))"
3623 [(set (match_dup 4) (match_dup 5))
3624 (set (match_dup 8) (match_dup 7))
3625 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3626 (set (match_dup 0) (reg:HI D_REGNUM))])
3627 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3628 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3629 (set (match_dup 0) (reg:HI D_REGNUM))])]
3631 /* Save the operand2 in a temporary location and use it. */
3632 if (H_REG_P (operands[2])
3633 || reg_mentioned_p (operands[0], operands[2]))
3635 operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
3636 operands[6] = operands[4];
3637 if (!H_REG_P (operands[2]))
3639 operands[5] = operands[0];
3640 operands[7] = operands[2];
3641 operands[8] = operands[0];
3645 operands[5] = operands[2];
3646 operands[8] = operands[7] = operands[0];
3651 operands[4] = operands[5] = operands[0];
3652 operands[6] = operands[2];
3653 operands[8] = operands[7] = operands[0];
3658 [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
3659 (match_operator:HI 3 "m68hc11_arith_operator"
3660 [(match_operand:HI 1 "general_operand" "mu")
3661 (match_operand:HI 2 "general_operand" "dAuim")]))]
3662 "z_replacement_completed == 2
3663 /* If we are adding a small constant to X or Y, it's
3664 better to use one or several inx/iny instructions. */
3665 && !(GET_CODE (operands[3]) == PLUS
3667 && (immediate_operand (operands[2], HImode)
3668 || hard_reg_operand (operands[2], HImode)))
3669 || (GET_CODE (operands[2]) == CONST_INT
3670 && INTVAL (operands[2]) >= -4
3671 && INTVAL (operands[2]) <= 4)))"
3672 [(set (match_dup 0) (match_dup 1))
3673 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3674 (set (match_dup 0) (reg:HI D_REGNUM))])
3675 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
3676 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3677 (set (match_dup 0) (reg:HI D_REGNUM))])]
3682 ;; Next split handles the logical operations on D register with
3683 ;; another hard register for the second operand. For this, we
3684 ;; have to save the second operand in a scratch location and use
3685 ;; it instead. This must be supported because in some (rare) cases
3686 ;; the second operand can come in a hard register and the reload
3687 ;; pass doesn't know how to reload it in a memory location.
3689 ;; PLUS MINUS AND IOR XOR
3691 ;; The shift operators are special and must not appear here.
3694 [(set (match_operand:HI 0 "d_register_operand" "=d")
3695 (match_operator:HI 3 "m68hc11_non_shift_operator"
3696 [(match_operand:HI 1 "d_register_operand" "%0")
3697 (match_operand:HI 2 "hard_reg_operand" "*d*A")]))]
3698 "z_replacement_completed == 2 && !SP_REG_P (operands[2])"
3699 [(set (match_dup 4) (match_dup 2))
3700 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
3701 "operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);")
3703 ;;--------------------------------------------------------------------
3704 ;; 16-bit Unary operations on X and Y:
3708 ;; Operations on X or Y registers are split here. Instructions are
3710 ;; - xgdx/xgdy instruction pattern,
3711 ;; - The same operation on register D,
3712 ;; - xgdx/xgdy instruction pattern.
3713 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3714 ;; We also handle the case were the address register is used in both source
3715 ;; operands, such as:
3717 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3719 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3722 [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
3723 (match_operator:HI 2 "m68hc11_unary_operator"
3724 [(match_operand 1 "general_operand" "uim*d*A")]))]
3725 "z_replacement_completed == 2"
3726 [(set (match_dup 4) (match_dup 5))
3727 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3728 (set (match_dup 0) (reg:HI D_REGNUM))])
3729 (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
3730 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3731 (set (match_dup 0) (reg:HI D_REGNUM))])]
3734 if ((H_REG_P (operands[1])
3735 && !rtx_equal_p (operands[0], operands[1]))
3736 || reg_mentioned_p (operands[0], operands[1]))
3738 /* Move to the destination register, before the xgdx. */
3739 operands[4] = gen_rtx (REG, GET_MODE (operands[1]),
3740 REGNO (operands[0]));
3741 operands[5] = operands[1];
3743 /* Apply the operation on D. */
3744 operands[3] = gen_rtx (REG, GET_MODE (operands[1]), HARD_D_REGNUM);
3748 /* Generate a copy to same register (nop). */
3749 operands[4] = operands[5] = operands[0];
3750 operands[3] = operands[1];
3755 ;; 8-bit operations on address registers.
3757 ;; We have to take care that the address register is not used for the
3758 ;; source of operand2. If operand2 is the D register, we have to save
3759 ;; that register in a temporary location.
3761 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3764 [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy")
3765 (match_operator:QI 3 "m68hc11_arith_operator"
3766 [(match_operand:QI 1 "hard_addr_reg_operand" "%0")
3767 (match_operand:QI 2 "general_operand" "dxyuim")]))]
3768 "z_replacement_completed == 2
3769 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
3770 incqi pattern generates a better code. */
3771 && !(GET_CODE (operands[3]) == PLUS
3772 && GET_CODE (operands[2]) == CONST_INT
3773 && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
3774 [(set (match_dup 5) (match_dup 6))
3775 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
3776 (set (match_dup 4) (reg:HI D_REGNUM))])
3777 (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
3778 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
3779 (set (match_dup 4) (reg:HI D_REGNUM))])]
3780 "operands[4] = gen_rtx (REG, HImode, REGNO (operands[0]));
3782 /* For the second operand is a hard register or if the address
3783 register appears in the source, we have to save the operand[2]
3784 value in a temporary location and then use that temp.
3785 Otherwise, it's ok and we generate a (set (D) (D)) that
3786 will result in a nop. */
3787 if (H_REG_P (operands[2]))
3789 operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
3790 operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));
3791 operands[7] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
3793 else if (reg_mentioned_p (operands[0], operands[2]))
3795 operands[5] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
3796 operands[6] = operands[2];
3797 operands[7] = operands[5];
3801 operands[5] = operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM);
3802 operands[7] = operands[2];
3807 ;; Next split handles the logical operations on D register with
3808 ;; another hard register for the second operand. For this, we
3809 ;; have to save the second operand in a scratch location and use
3810 ;; it instead. This must be supported because in some (rare) cases
3811 ;; the second operand can come in a hard register and the reload
3812 ;; pass doesn't know how to reload it in a memory location.
3814 ;; PLUS MINUS AND IOR XOR
3816 ;; The shift operators are special and must not appear here.
3819 [(set (match_operand:QI 0 "d_register_operand" "=d")
3820 (match_operator:QI 3 "m68hc11_non_shift_operator"
3821 [(match_operand:QI 1 "d_register_operand" "%0")
3822 (match_operand:QI 2 "hard_reg_operand" "*d*x*y")]))]
3824 [(set (match_dup 5) (match_dup 6))
3825 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
3826 "operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
3827 operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
3828 operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));")
3830 ;;--------------------------------------------------------------------
3831 ;; 8-bit Unary operations on X and Y:
3835 ;; Operations on X or Y registers are split here. Instructions are
3837 ;; - xgdx/xgdy instruction pattern,
3838 ;; - The same operation on register D,
3839 ;; - xgdx/xgdy instruction pattern.
3840 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3841 ;; We also handle the case were the address register is used in both source
3842 ;; operands, such as:
3844 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3846 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3849 [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy")
3850 (match_operator:QI 2 "m68hc11_unary_operator"
3851 [(match_operand:QI 1 "general_operand" "uim*d*x*y")]))]
3852 "z_replacement_completed == 2"
3853 [(set (match_dup 4) (match_dup 5))
3854 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
3855 (set (match_dup 3) (reg:HI D_REGNUM))])
3856 (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
3857 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
3858 (set (match_dup 3) (reg:HI D_REGNUM))])]
3861 operands[3] = gen_rtx (REG, HImode, REGNO (operands[0]));
3862 if ((H_REG_P (operands[1])
3863 && !rtx_equal_p (operands[0], operands[1]))
3864 || reg_mentioned_p (operands[0], operands[1]))
3866 /* Move to the destination register, before the xgdx. */
3867 operands[4] = operands[0];
3868 operands[5] = operands[1];
3870 /* Apply the operation on D. */
3871 operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM);
3875 operands[4] = operands[5] = operands[0];
3876 operands[6] = operands[1];
3881 ;;--------------------------------------------------------------------
3883 ;;--------------------------------------------------------------------
3885 (define_expand "negdi2"
3886 [(set (match_operand:DI 0 "nonimmediate_operand" "")
3887 (neg:DI (match_operand:DI 1 "general_operand" "")))]
3889 "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
3893 (define_insn "negsi2"
3894 [(set (match_operand:SI 0 "register_operand" "=D")
3895 (neg:SI (match_operand:SI 1 "register_operand" "0")))]
3901 /* With -Os or without -O, use a special library call. */
3902 if (optimize_size || optimize == 0)
3903 return \"bsr\\t___negsi2\";
3905 /* 32-bit complement and add 1. The comb/coma set the carry and they
3906 are smaller (use it for low-part). The eorb/eora leave the carry
3907 unchanged but are bigger (use it for high-part). */
3908 output_asm_insn (\"comb\\n\\tcoma\\n\\taddd\\t#1\\n\\txgdx\", operands);
3909 output_asm_insn (\"eorb\\t#0xFF\\n\\teora\\t#0xFF\", operands);
3910 return \"adcb\\t#0\\n\\tadca\\t#0\\n\\txgdx\";
3913 (define_insn "neghi2"
3914 [(set (match_operand:HI 0 "register_operand" "=d,d,*A")
3915 (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
3918 coma\\n\\tcomb\\n\\taddd\\t#1
3919 clra\\n\\tclrb\\n\\tsubd\\t%1
3920 xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
3922 (define_insn "negqi2"
3923 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
3924 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
3933 ;; - 32-bit complement. GCC knows how to translate them but providing a
3934 ;; pattern generates better/smaller code.
3936 (define_expand "one_cmpldi2"
3937 [(set (match_operand:DI 0 "nonimmediate_operand" "")
3938 (not:DI (match_operand:DI 1 "general_operand" "")))]
3940 "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
3943 (define_insn "one_cmplsi2"
3944 [(set (match_operand:SI 0 "non_push_operand" "=D")
3945 (not:SI (match_operand:SI 1 "general_operand" "0")))]
3947 "bsr\\t___one_cmplsi2")
3949 (define_insn "one_cmplhi2"
3950 [(set (match_operand:HI 0 "non_push_operand" "=d,m,!u,*A")
3951 (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
3955 com\\t%b0\\n\\tcom\\t%h0
3956 com\\t%b0\\n\\tcom\\t%h0
3959 (define_insn "one_cmplqi2"
3960 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,!*A")
3961 (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
3969 (define_split /* "*one_cmplsi2" */
3970 [(set (match_operand:SI 0 "non_push_operand" "=Dum")
3971 (not:SI (match_operand:SI 1 "non_push_operand" "0")))]
3972 "z_replacement_completed == 2
3973 && (!D_REG_P (operands[0]) || (optimize && optimize_size == 0))"
3974 [(set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM)))
3975 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
3976 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
3977 (set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM)))
3978 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
3979 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
3982 /* The result pattern only works for D register.
3983 Generate 2 one_cmplhi2 instructions. */
3984 if (!D_REG_P (operands[0]))
3988 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
3989 ops[1] = m68hc11_gen_highpart (HImode, operands[0]);
3990 emit_insn (gen_one_cmplhi2 (ops[0], ops[0]));
3991 emit_insn (gen_one_cmplhi2 (ops[1], ops[1]));
3996 ;;--------------------------------------------------------------------
3997 ;;- arithmetic shifts
3998 ;;--------------------------------------------------------------------
4000 ;; Provide some 64-bit shift patterns.
4001 (define_expand "ashldi3"
4002 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4003 (ashift:DI (match_operand:DI 1 "general_operand" "")
4004 (match_operand:HI 2 "general_operand" "")))
4005 (clobber (match_scratch:HI 3 ""))])]
4009 if (GET_CODE (operands[2]) != CONST_INT
4010 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4016 (define_insn "*ashldi3_const32"
4017 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4018 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4020 (clobber (match_scratch:HI 2 "=&A,d,d"))]
4025 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,um")
4026 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi")
4028 (clobber (match_scratch:HI 2 "=&A,d"))]
4031 "/* Move the lowpart in the highpart first in case the shift
4032 is applied on the source. */
4033 if (IS_STACK_PUSH (operands[0]))
4035 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4036 const0_rtx, operands[2]);
4038 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4039 m68hc11_gen_lowpart (SImode, operands[1]),
4041 if (!IS_STACK_PUSH (operands[0]))
4043 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4044 const0_rtx, operands[2]);
4048 (define_insn "*ashldi3_const1"
4049 [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4050 (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4052 (clobber (match_scratch:HI 2 "=d,d,d"))]
4057 [(set (match_operand:DI 0 "non_push_operand" "=um")
4058 (ashift:DI (match_operand:DI 1 "general_operand" "umi")
4060 (clobber (match_scratch:HI 2 "=d"))]
4061 "z_replacement_completed == 2"
4062 [(set (match_dup 2) (match_dup 3))
4063 (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4064 (set (match_dup 4) (match_dup 2))
4066 (set (match_dup 2) (match_dup 5))
4067 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
4068 (set (match_dup 6) (match_dup 2))
4070 (set (match_dup 2) (match_dup 7))
4071 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
4072 (set (match_dup 8) (match_dup 2))
4074 (set (match_dup 2) (match_dup 9))
4075 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
4076 (set (match_dup 10) (match_dup 2))]
4077 "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4078 operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4079 operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4081 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4082 operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4083 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4085 operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4086 operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4087 operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4089 operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4090 operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4091 operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4093 (define_insn "addsi_silshr16"
4094 [(set (match_operand:SI 0 "register_operand" "=D")
4095 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim")
4097 (match_operand:SI 2 "general_operand" "0")))]
4102 [(set (match_operand:SI 0 "register_operand" "=D")
4103 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim")
4105 (match_operand:SI 2 "general_operand" "0")))]
4106 "z_replacement_completed == 2"
4107 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4108 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4109 "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4111 (define_insn "addsi_ashift16"
4112 [(set (match_operand:SI 0 "register_operand" "=D")
4114 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4116 (match_operand:SI 1 "general_operand" "0")))
4117 (clobber (match_scratch:HI 3 "=X"))]
4122 [(set (match_operand:SI 0 "register_operand" "=D")
4124 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4126 (match_operand:SI 1 "general_operand" "0")))
4127 (clobber (match_scratch:HI 3 "=X"))]
4128 "0 && reload_completed && z_replacement_completed == 2"
4129 [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4132 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4135 (define_insn "addsi_andshr16"
4136 [(set (match_operand:SI 0 "register_operand" "=D")
4137 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4139 (match_operand:SI 2 "general_operand" "0")))]
4144 [(set (match_operand:SI 0 "register_operand" "=D")
4145 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4147 (match_operand:SI 2 "general_operand" "0")))]
4148 "z_replacement_completed == 2"
4149 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4150 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4151 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4154 ;; 32-bit shifts are made by a small library routine that uses
4155 ;; a specific passing convention for parameters (for efficiency reasons).
4157 ;; [D + X] -> Value to be shifted
4160 ;; The shift count is clobbered by the routine.
4162 (define_expand "ashlsi3"
4164 [(set (match_operand:SI 0 "register_operand" "")
4165 (match_operand:SI 1 "general_operand" ""))
4166 (clobber (scratch:HI))])
4168 [(set (match_dup 0) (ashift:SI (match_dup 0)
4169 (match_operand:HI 2 "nonmemory_operand" "")))
4170 (clobber (scratch:HI))])]
4175 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,um")
4176 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D")
4178 (clobber (match_scratch:HI 3 "=X,X"))]
4180 [(set (match_dup 2) (match_dup 3))
4181 (set (match_dup 4) (const_int 0))]
4182 "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4183 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4184 operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4186 (define_insn "*ashlsi3_const16"
4187 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4188 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4190 (clobber (match_scratch:HI 2 "=X,X,X"))]
4194 (define_insn "*ashlsi3_const16_zexthi"
4195 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4196 (ashift:SI (zero_extend:HI
4197 (match_operand:HI 1 "general_operand" "duim*A"))
4199 (clobber (match_scratch:HI 2 "=X"))]
4203 (define_split /* "*ashlsi3_const16_zexthi"*/
4204 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4205 (ashift:SI (zero_extend:HI
4206 (match_operand:HI 1 "general_operand" "duim*a"))
4208 (clobber (match_scratch:HI 2 "=X"))]
4210 [(set (reg:HI X_REGNUM) (match_dup 1))
4211 (set (reg:HI D_REGNUM) (const_int 0))]
4214 (define_insn "*ashlsi3_const1"
4215 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,!*u,?*um")
4216 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,*um,0,0,*um")
4218 (clobber (match_scratch:HI 2 "=X,X,&d,&d,&d"))]
4223 if (X_REG_P (operands[1]))
4225 return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4231 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4232 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
4233 m68hc11_gen_movhi (insn, ops);
4234 output_asm_insn (\"lsld\", ops);
4235 if (!X_REG_P (operands[0]))
4238 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4239 m68hc11_gen_movhi (insn, ops);
4241 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4242 m68hc11_gen_movhi (insn, ops);
4246 /* Load the high part in X in case the source operand
4247 uses X as a memory pointer. */
4248 ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM);
4249 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4250 m68hc11_gen_movhi (insn, ops);
4251 output_asm_insn (\"xgdx\", ops);
4253 output_asm_insn (\"rolb\", ops);
4254 output_asm_insn (\"rola\", ops);
4255 if (!X_REG_P (operands[0]))
4258 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4259 m68hc11_gen_movhi (insn, ops);
4263 output_asm_insn (\"xgdx\", ops);
4269 (define_insn "*ashlsi3_const"
4270 [(set (match_operand:SI 0 "register_operand" "+D")
4271 (ashift:SI (match_dup 0)
4272 (match_operand:HI 1 "const_int_operand" "")))
4273 (clobber (match_scratch:HI 2 "=y"))]
4278 return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4281 (define_insn "*ashlsi3"
4282 [(set (match_operand:SI 0 "register_operand" "+D,D")
4283 (ashift:SI (match_dup 0)
4284 (match_operand:HI 1 "general_operand" "y,m")))
4285 (clobber (match_scratch:HI 2 "=1,X"))]
4291 /* There is a reload problem if we don't accept 'm' for the shift value.
4292 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4293 and this conflicts with all reloads. Since X, Y, Z are used there
4294 is not enough register in class A_REGS.
4296 Assuming that 'operands[1]' does not refer to the stack (which
4297 is true for 68hc11 only, we save temporary the value of Y. */
4298 if (!Y_REG_P (operands[2]))
4302 ops[0] = operands[1];
4303 output_asm_insn (\"pshy\", operands);
4304 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4306 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4308 output_asm_insn (\"ldy\\t%0\", ops);
4309 output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4312 return \"bsr\\t___ashlsi3\";
4315 (define_expand "ashlhi3"
4316 [(set (match_operand:HI 0 "register_operand" "")
4317 (ashift:HI (match_operand:HI 1 "register_operand" "")
4318 (match_operand:HI 2 "general_operand" "")))]
4322 if (GET_CODE (operands[2]) != CONST_INT)
4324 rtx scratch = gen_reg_rtx (HImode);
4325 emit_move_insn (scratch, operands[2]);
4326 emit_insn (gen_rtx (PARALLEL, VOIDmode,
4327 gen_rtvec (2, gen_rtx (SET, VOIDmode,
4329 gen_rtx_ASHIFT (HImode,
4330 operand1, scratch)),
4331 gen_rtx (CLOBBER, VOIDmode, scratch))));
4336 (define_insn "*ashlhi3_const1"
4337 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4338 (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4343 if (A_REG_P (operands[0]))
4346 if (D_REG_P (operands[0]))
4351 output_asm_insn (\"asl\\t%b0\", operands);
4352 output_asm_insn (\"rol\\t%h0\", operands);
4358 (define_insn "*ashlhi3_2"
4359 [(set (match_operand:HI 0 "register_operand" "=d")
4360 (ashift:HI (match_operand:HI 1 "register_operand" "0")
4361 (match_operand:HI 2 "register_operand" "+x")))
4362 (clobber (match_dup 2))]
4367 return \"bsr\\t___lshlhi3\";
4370 (define_insn "*ashlhi3"
4371 [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4372 (ashift:HI (match_dup 0)
4373 (match_operand:HI 1 "register_operand" "+x")))
4374 (clobber (match_dup 1))]
4379 return \"bsr\\t___lshlhi3\";
4382 (define_insn "*ashlhi3"
4383 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4384 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4385 (match_operand:HI 2 "const_int_operand" "")))]
4391 if (A_REG_P (operands[0]))
4394 i = INTVAL (operands[2]);
4398 output_asm_insn (\"tba\", operands);
4401 output_asm_insn (\"rora\", operands);
4402 output_asm_insn (\"anda\\t#0\", operands);
4403 output_asm_insn (\"rora\", operands);
4408 output_asm_insn (\"asla\", operands);
4413 for (i = 0; i < INTVAL (operands[2]) - 1; i++)
4415 output_asm_insn (\"asld\", operands);
4420 (define_expand "ashlqi3"
4421 [(set (match_operand:QI 0 "register_operand" "")
4422 (ashift:QI (match_operand:QI 1 "register_operand" "")
4423 (match_operand:QI 2 "general_operand" "")))]
4427 (define_insn "*ashlqi3_const1"
4428 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4429 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4439 (define_insn "*ashlqi3_const"
4440 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4441 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4442 (match_operand:QI 2 "const_int_operand" "")))]
4447 const char* insn_code;
4449 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4450 insn_code = \"aslb\";
4451 else if (DA_REG_P (operands[0]))
4452 insn_code = \"asla\";
4456 i = INTVAL (operands[2]);
4459 if (DA_REG_P (operands[0]))
4466 if (DA_REG_P (operands[0]))
4468 output_asm_insn (\"rora\", operands);
4469 output_asm_insn (\"ldaa\\t#0\", operands);
4474 output_asm_insn (\"rorb\", operands);
4475 output_asm_insn (\"ldab\\t#0\", operands);
4481 if (DA_REG_P (operands[0]))
4483 output_asm_insn (\"rora\", operands);
4484 output_asm_insn (\"rora\", operands);
4485 output_asm_insn (\"rora\", operands);
4486 return \"anda\\t#0xC0\";
4490 output_asm_insn (\"rorb\", operands);
4491 output_asm_insn (\"rorb\", operands);
4492 output_asm_insn (\"rorb\", operands);
4493 return \"andb\\t#0xC0\";
4498 output_asm_insn (insn_code, operands);
4503 (define_insn "*ashlqi3"
4504 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4505 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4506 (match_operand:QI 2 "nonimmediate_operand"
4507 "m*u*d*A,m*u*d*A,m*u")))]
4513 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4516 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
4517 ops[1] = operands[2];
4518 m68hc11_gen_movqi (insn, ops);
4521 return \"bsr\\t___lshlqi3\";
4524 (define_expand "ashrhi3"
4525 [(set (match_operand:HI 0 "register_operand" "")
4526 (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4527 (match_operand:HI 2 "general_operand" "")))]
4531 if (GET_CODE (operands[2]) != CONST_INT)
4533 rtx scratch = gen_reg_rtx (HImode);
4535 emit_move_insn (scratch, operands[2]);
4536 emit_insn (gen_rtx (PARALLEL, VOIDmode,
4537 gen_rtvec (2, gen_rtx (SET, VOIDmode,
4539 gen_rtx_ASHIFTRT (HImode,
4540 operand1, scratch)),
4541 gen_rtx (CLOBBER, VOIDmode, scratch))));
4546 (define_insn "*ashrhi3_const1"
4547 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4548 (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4553 if (A_REG_P (operands[0]))
4557 if (D_REG_P (operands[0]))
4559 return \"asra\\n\\trorb\";
4562 output_asm_insn (\"asr\\t%h0\", operands);
4563 output_asm_insn (\"ror\\t%b0\", operands);
4568 (define_insn "*ashrhi3_const"
4569 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4570 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4571 (match_operand:HI 2 "const_int_operand" "")))]
4576 int val = INTVAL (operands[2]);
4578 if (A_REG_P (operands[0]))
4583 ops[0] = gen_label_rtx ();
4585 output_asm_insn (\"clrb\", operands);
4586 output_asm_insn (\"rola\", operands);
4588 /* Clear A without clearing the carry flag. */
4589 output_asm_insn (\"tba\", operands);
4590 output_asm_insn (\"bcc\\t%l0\", ops);
4591 output_asm_insn (\"coma\", operands);
4592 output_asm_insn (\"comb\", operands);
4595 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4596 CODE_LABEL_NUMBER (ops[0]));
4601 ops[0] = gen_label_rtx ();
4603 output_asm_insn (\"tab\", operands);
4604 output_asm_insn (\"clra\", operands);
4605 output_asm_insn (\"tstb\", operands);
4606 output_asm_insn (\"bge\\t%l0\", ops);
4607 output_asm_insn (\"deca\", operands);
4609 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4610 CODE_LABEL_NUMBER (ops[0]));
4616 output_asm_insn (\"asrb\", operands);
4624 ops[0] = gen_label_rtx ();
4625 output_asm_insn (\"rolb\", operands);
4626 output_asm_insn (\"rola\", operands);
4627 output_asm_insn (\"tab\", operands);
4628 output_asm_insn (\"anda\\t#0\", operands);
4629 output_asm_insn (\"bcc\\t%l0\", ops);
4630 output_asm_insn (\"coma\", ops);
4632 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4633 CODE_LABEL_NUMBER (ops[0]));
4638 output_asm_insn (\"asra\", operands);
4639 output_asm_insn (\"rorb\", operands);
4647 (define_insn "*ashrhi3"
4648 [(set (match_operand:HI 0 "register_operand" "=d,x")
4649 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4650 (match_operand:HI 2 "register_operand" "+x,+d")))
4651 (clobber (match_dup 2))]
4656 if (D_REG_P (operands[2]))
4657 output_asm_insn (\"xgd%0\", operands);
4659 output_asm_insn (\"bsr\\t___ashrhi3\", operands);
4660 if (D_REG_P (operands[2]))
4661 output_asm_insn (\"xgd%0\", operands);
4666 (define_expand "ashrsi3"
4668 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
4669 (clobber (scratch:HI))])
4671 [(set (match_operand:SI 0 "register_operand" "")
4672 (ashiftrt:SI (match_dup 0)
4673 (match_operand:HI 2 "general_operand" "")))
4674 (clobber (scratch:HI))])]
4678 (define_insn "*ashrsi3_const"
4679 [(set (match_operand:SI 0 "register_operand" "+D")
4680 (ashiftrt:SI (match_dup 0)
4681 (match_operand:HI 1 "const_int_operand" "")))
4682 (clobber (match_scratch:HI 2 "=y"))]
4687 return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
4690 (define_insn "*ashrsi3"
4691 [(set (match_operand:SI 0 "register_operand" "+D,D")
4692 (ashiftrt:SI (match_dup 0)
4693 (match_operand:HI 1 "general_operand" "y,m")))
4694 (clobber (match_scratch:HI 2 "=1,X"))]
4699 /* There is a reload problem if we don't accept 'm' for the shift value.
4700 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4701 and this conflicts with all reloads. Since X, Y, Z are used there
4702 is not enough register in class A_REGS.
4704 Assuming that 'operands[1]' does not refer to the stack (which
4705 is true for 68hc11 only, we save temporary the value of Y. */
4706 if (!Y_REG_P (operands[2]))
4710 ops[0] = operands[1];
4711 output_asm_insn (\"pshy\", operands);
4712 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4714 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4716 output_asm_insn (\"ldy\\t%0\", ops);
4717 output_asm_insn (\"bsr\\t___ashrsi3\", operands);
4720 return \"bsr\\t___ashrsi3\";
4723 (define_expand "ashrqi3"
4724 [(set (match_operand:QI 0 "register_operand" "")
4725 (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
4726 (match_operand:QI 2 "general_operand" "")))]
4730 (define_insn "*ashrqi3_const1"
4731 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4732 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4742 (define_insn "*ashrqi3_const"
4743 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4744 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
4745 (match_operand:QI 2 "const_int_operand" "")))]
4750 const char* insn_code;
4752 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4753 insn_code = \"asrb\";
4754 else if (DA_REG_P (operands[0]))
4755 insn_code = \"asra\";
4759 i = INTVAL (operands[2]);
4764 output_asm_insn (insn_code, operands);
4769 (define_insn "*ashrqi3"
4770 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4771 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
4772 (match_operand:QI 2 "nonimmediate_operand"
4773 "m*u*d*A,m*u*d*A,m*u")))]
4779 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4782 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
4783 ops[1] = operands[2];
4784 m68hc11_gen_movqi (insn, ops);
4787 return \"bsr\\t___ashrqi3\";
4790 ;;--------------------------------------------------------------------
4791 ;; logical shift instructions
4792 ;;--------------------------------------------------------------------
4793 (define_expand "lshrdi3"
4794 [(parallel [(set (match_operand:DI 0 "general_operand" "")
4795 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
4796 (match_operand:HI 2 "general_operand" "")))
4797 (clobber (match_scratch:HI 3 ""))])]
4801 if (GET_CODE (operands[2]) != CONST_INT
4802 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
4803 && INTVAL (operands[2]) != 1))
4809 (define_insn "*lshrdi3_const32"
4810 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4811 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4813 (clobber (match_scratch:HI 2 "=&A,d,d"))]
4818 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,um")
4819 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
4821 (clobber (match_scratch:HI 2 "=&A,d"))]
4824 "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4825 m68hc11_gen_highpart (SImode, operands[1]),
4827 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4828 const0_rtx, operands[2]);
4831 (define_insn "*lshrdi3_const63"
4832 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
4833 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
4834 (match_operand:DI 2 "const_int_operand" "")))
4835 (clobber (match_scratch:HI 3 "=d,d"))]
4836 "INTVAL (operands[2]) >= 48"
4840 [(set (match_operand:DI 0 "nonimmediate_operand" "=um")
4841 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
4842 (match_operand:DI 2 "const_int_operand" "")))
4843 (clobber (match_scratch:HI 3 "=d"))]
4844 "z_replacement_completed && INTVAL (operands[2]) >= 56"
4845 [(set (reg:QI D_REGNUM) (match_dup 9))
4846 (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
4847 (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
4848 (set (match_dup 4) (reg:HI D_REGNUM))
4849 (set (reg:QI D_REGNUM) (const_int 0))
4850 (set (match_dup 5) (reg:HI D_REGNUM))
4851 (set (match_dup 6) (reg:HI D_REGNUM))
4852 (set (match_dup 7) (reg:HI D_REGNUM))]
4853 "operands[8] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 56);
4854 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4855 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
4856 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4858 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
4859 operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
4860 operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
4862 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
4863 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
4864 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
4867 [(set (match_operand:DI 0 "nonimmediate_operand" "=um")
4868 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
4869 (match_operand:DI 2 "const_int_operand" "")))
4870 (clobber (match_scratch:HI 3 "=d"))]
4871 "z_replacement_completed && INTVAL (operands[2]) >= 48
4872 && INTVAL (operands[2]) < 56"
4873 [(set (reg:HI D_REGNUM) (match_dup 9))
4874 (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
4875 (set (match_dup 4) (reg:HI D_REGNUM))
4876 (set (reg:HI D_REGNUM) (const_int 0))
4877 (set (match_dup 5) (reg:HI D_REGNUM))
4878 (set (match_dup 6) (reg:HI D_REGNUM))
4879 (set (match_dup 7) (reg:HI D_REGNUM))]
4880 "operands[8] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 48);
4881 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4882 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
4883 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4885 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
4886 operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
4887 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
4888 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
4889 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
4891 (define_insn "*lshrdi_const1"
4892 [(set (match_operand:DI 0 "non_push_operand" "=m,u")
4893 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
4895 (clobber (match_scratch:HI 2 "=d,d"))]
4900 [(set (match_operand:DI 0 "non_push_operand" "=um")
4901 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
4903 (clobber (match_scratch:HI 2 "=d"))]
4904 "z_replacement_completed == 2"
4905 [(set (match_dup 2) (match_dup 3))
4906 (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
4907 (set (match_dup 4) (match_dup 2))
4909 (set (match_dup 2) (match_dup 5))
4910 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
4911 (set (match_dup 6) (match_dup 2))
4913 (set (match_dup 2) (match_dup 7))
4914 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
4915 (set (match_dup 8) (match_dup 2))
4917 (set (match_dup 2) (match_dup 9))
4918 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
4919 (set (match_dup 10) (match_dup 2))]
4920 "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
4921 operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
4922 operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
4924 operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
4925 operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
4926 operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
4928 operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
4929 operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
4930 operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
4932 operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
4933 operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
4934 operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
4936 (define_expand "lshrsi3"
4938 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
4939 (clobber (scratch:HI))])
4941 [(set (match_operand:SI 0 "register_operand" "")
4942 (lshiftrt:SI (match_dup 0)
4943 (match_operand:HI 2 "general_operand" "")))
4944 (clobber (scratch:HI))])]
4949 [(set (match_operand:SI 0 "non_push_operand" "=D,um")
4950 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,D")
4952 (clobber (match_scratch:HI 3 "=X,X"))]
4953 "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
4954 [(set (match_dup 2) (match_dup 3))
4955 (set (match_dup 4) (const_int 0))]
4956 "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
4957 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4958 operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4960 (define_insn "*lshrsi3_const16"
4961 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
4962 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
4964 (clobber (match_scratch:HI 2 "=X,X,X,X"))]
4972 (define_insn "*lshrsi3_const1"
4973 [(set (match_operand:SI 0 "non_push_operand" "=D,m,*u")
4974 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "D*um,*um,*um")
4976 (clobber (match_scratch:HI 2 "=X,&d,&d"))]
4981 if (X_REG_P (operands[1]))
4983 return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
4989 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4990 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
4991 m68hc11_gen_movhi (insn, ops);
4992 output_asm_insn (\"lsrd\", ops);
4993 if (!X_REG_P (operands[0]))
4996 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4997 m68hc11_gen_movhi (insn, ops);
4999 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5000 m68hc11_gen_movhi (insn, ops);
5004 /* Load the lowpart in X in case the operands is some N,x. */
5005 ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM);
5006 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5007 m68hc11_gen_movhi (insn, ops);
5008 output_asm_insn (\"xgdx\", ops);
5010 output_asm_insn (\"rora\", ops);
5011 output_asm_insn (\"rorb\", ops);
5012 if (!X_REG_P (operands[0]))
5015 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5016 m68hc11_gen_movhi (insn, ops);
5022 (define_insn "*lshrsi3_const"
5023 [(set (match_operand:SI 0 "register_operand" "+D")
5024 (lshiftrt:SI (match_dup 0)
5025 (match_operand:HI 1 "const_int_operand" "")))
5026 (clobber (match_scratch:HI 2 "=y"))]
5031 return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5034 (define_insn "*lshrsi3"
5035 [(set (match_operand:SI 0 "register_operand" "+D,D")
5036 (lshiftrt:SI (match_dup 0)
5037 (match_operand:HI 1 "general_operand" "y,m")))
5038 (clobber (match_scratch:HI 2 "=1,X"))]
5043 /* There is a reload problem if we don't accept 'm' for the shift value.
5044 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5045 and this conflicts with all reloads. Since X, Y, Z are used there
5046 is not enough register in class A_REGS.
5048 Assuming that 'operands[1]' does not refer to the stack (which
5049 is true for 68hc11 only, we save temporary the value of Y. */
5050 if (!Y_REG_P (operands[2]))
5054 ops[0] = operands[1];
5055 output_asm_insn (\"pshy\", operands);
5056 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5058 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5060 output_asm_insn (\"ldy\\t%0\", ops);
5061 output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5064 return \"bsr\\t___lshrsi3\";
5067 (define_expand "lshrhi3"
5068 [(set (match_operand:HI 0 "register_operand" "")
5069 (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5070 (match_operand:HI 2 "general_operand" "")))]
5074 if (GET_CODE (operands[2]) != CONST_INT)
5076 rtx scratch = gen_reg_rtx (HImode);
5077 operand1 = force_reg (HImode, operand1);
5079 emit_move_insn (scratch, operands[2]);
5080 emit_insn (gen_rtx (PARALLEL, VOIDmode,
5081 gen_rtvec (2, gen_rtx (SET, VOIDmode,
5083 gen_rtx_LSHIFTRT (HImode,
5084 operand1, scratch)),
5085 gen_rtx (CLOBBER, VOIDmode, scratch))));
5090 (define_insn "lshrhi3_const1"
5091 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5092 (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5097 if (A_REG_P (operands[0]))
5100 if (D_REG_P (operands[0]))
5104 return \"lsr\\t%h0\\n\\tror\\t%b0\";
5107 (define_insn "lshrhi3_const"
5108 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5109 (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5110 (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5114 int val = INTVAL (operands[2]);
5116 if (A_REG_P (operands[0]))
5124 if (!H_REG_P (operands[1]))
5126 output_asm_insn (\"clra\", operands);
5127 output_asm_insn (\"ldab\\t%h1\", operands);
5129 else if (A_REG_P (operands[1]))
5131 output_asm_insn (\"st%1\\t%t0\", operands);
5132 output_asm_insn (\"ldab\\t%t0\", operands);
5133 output_asm_insn (\"clra\", operands);
5137 output_asm_insn (\"tab\", operands);
5138 output_asm_insn (\"clra\", operands);
5144 output_asm_insn (\"rolb\", operands);
5145 output_asm_insn (\"tab\", operands);
5146 output_asm_insn (\"rolb\", operands);
5150 output_asm_insn (\"rolb\", operands);
5151 output_asm_insn (\"rolb\", operands);
5152 output_asm_insn (\"rolb\", operands);
5153 output_asm_insn (\"andb\\t#3\", operands);
5160 output_asm_insn (\"lsrb\", operands);
5167 if (!D_REG_P (operands[1]))
5168 m68hc11_gen_movhi (insn, operands);
5172 output_asm_insn (\"rolb\", operands);
5173 output_asm_insn (\"tab\", operands);
5174 output_asm_insn (\"rolb\", operands);
5175 output_asm_insn (\"rola\", operands);
5176 output_asm_insn (\"rola\", operands);
5177 output_asm_insn (\"anda\\t#1\", operands);
5185 output_asm_insn (\"lsrd\", operands);
5191 (define_insn "*lshrhi3"
5192 [(set (match_operand:HI 0 "register_operand" "=d,x")
5193 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5194 (match_operand:HI 2 "register_operand" "+x,+d")))
5195 (clobber (match_dup 2))]
5200 if (D_REG_P (operands[2]))
5201 output_asm_insn (\"xgd%0\", operands);
5203 output_asm_insn (\"bsr\\t___lshrhi3\", operands);
5204 if (D_REG_P (operands[2]))
5205 output_asm_insn (\"xgd%0\", operands);
5210 (define_expand "lshrqi3"
5211 [(set (match_operand:QI 0 "register_operand" "")
5212 (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5213 (match_operand:QI 2 "general_operand" "")))]
5217 (define_insn "*lshrqi3_const1"
5218 [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5219 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5229 (define_insn "*lshrqi3_const"
5230 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5231 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5232 (match_operand:QI 2 "const_int_operand" "")))]
5237 const char* insn_code;
5239 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5240 insn_code = \"lsrb\";
5241 else if (DA_REG_P (operands[0]))
5242 insn_code = \"lsra\";
5246 i = INTVAL (operands[2]);
5249 if (DA_REG_P (operands[0]))
5256 if (DA_REG_P (operands[0]))
5258 output_asm_insn (\"rola\", operands);
5259 output_asm_insn (\"ldaa\\t#0\", operands);
5264 output_asm_insn (\"rolb\", operands);
5265 output_asm_insn (\"ldab\\t#0\", operands);
5271 if (DA_REG_P (operands[0]))
5273 output_asm_insn (\"rola\", operands);
5274 output_asm_insn (\"rola\", operands);
5275 output_asm_insn (\"rola\", operands);
5276 return \"anda\\t#3\";
5280 output_asm_insn (\"rolb\", operands);
5281 output_asm_insn (\"rolb\", operands);
5282 output_asm_insn (\"rolb\", operands);
5283 return \"andb\\t#3\";
5288 output_asm_insn (insn_code, operands);
5293 (define_insn "*lshrqi3"
5294 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5295 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5296 (match_operand:QI 2 "nonimmediate_operand"
5297 "m*u*d*A,m*u*d*A,m*u")))]
5303 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5307 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
5308 ops[1] = operands[2];
5309 m68hc11_gen_movqi (insn, ops);
5311 if (!optimize || optimize_size)
5313 return \"bsr\\t___lshrqi3\";
5316 ops[0] = gen_label_rtx ();
5317 ops[1] = gen_label_rtx ();
5318 output_asm_insn (\"ble\\t%l1\", ops);
5320 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
5321 CODE_LABEL_NUMBER (ops[0]));
5323 output_asm_insn (\"lsrb\", operands);
5324 output_asm_insn (\"deca\", operands);
5325 output_asm_insn (\"bne\\t%l0\", ops);
5327 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
5328 CODE_LABEL_NUMBER (ops[1]));
5332 (define_insn "*rotlqi3_with_carry"
5333 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5334 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5335 (reg:QI CC_REGNUM)))]
5339 if (DA_REG_P (operands[0]))
5345 (define_insn "*rotlhi3_with_carry"
5346 [(set (match_operand:HI 0 "register_operand" "=d")
5347 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5348 (reg:HI CC_REGNUM)))]
5353 return \"rolb\\n\\trola\";
5356 (define_insn "*rotrhi3_with_carry"
5357 [(set (match_operand:HI 0 "register_operand" "=d")
5358 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5359 (reg:HI CC_REGNUM)))]
5364 return \"rora\\n\\trorb\";
5367 (define_insn "rotlqi3"
5368 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5369 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5370 (match_operand:QI 2 "const_int_operand" "i,i")))]
5374 m68hc11_gen_rotate (ROTATE, insn, operands);
5378 (define_insn "rotlhi3"
5379 [(set (match_operand:HI 0 "register_operand" "=d")
5380 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5381 (match_operand:HI 2 "const_int_operand" "i")))]
5385 m68hc11_gen_rotate (ROTATE, insn, operands);
5389 (define_insn "rotrqi3"
5390 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5391 (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5392 (match_operand:QI 2 "const_int_operand" "i,i")))]
5396 m68hc11_gen_rotate (ROTATERT, insn, operands);
5400 (define_insn "rotrhi3"
5401 [(set (match_operand:HI 0 "register_operand" "=d")
5402 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5403 (match_operand:HI 2 "const_int_operand" "i")))]
5407 m68hc11_gen_rotate (ROTATERT, insn, operands);
5411 ;;--------------------------------------------------------------------
5412 ;;- Jumps and transfers
5413 ;;--------------------------------------------------------------------
5416 (label_ref (match_operand 0 "" "")))]
5420 (define_expand "beq"
5422 (if_then_else (eq (cc0)
5424 (label_ref (match_operand 0 "" ""))
5429 m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
5430 m68hc11_compare_op1,
5435 (define_expand "bne"
5437 (if_then_else (ne (cc0)
5439 (label_ref (match_operand 0 "" ""))
5444 m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
5445 m68hc11_compare_op1,
5450 (define_expand "bgt"
5452 (if_then_else (gt (cc0)
5454 (label_ref (match_operand 0 "" ""))
5459 m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
5460 m68hc11_compare_op1,
5465 (define_expand "bgtu"
5467 (if_then_else (gtu (cc0)
5469 (label_ref (match_operand 0 "" ""))
5474 m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
5475 m68hc11_compare_op1,
5480 (define_expand "blt"
5482 (if_then_else (lt (cc0)
5484 (label_ref (match_operand 0 "" ""))
5489 m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
5490 m68hc11_compare_op1,
5495 (define_expand "bltu"
5497 (if_then_else (ltu (cc0)
5499 (label_ref (match_operand 0 "" ""))
5504 m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
5505 m68hc11_compare_op1,
5510 (define_expand "bge"
5512 (if_then_else (ge (cc0)
5514 (label_ref (match_operand 0 "" ""))
5519 m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
5520 m68hc11_compare_op1,
5525 (define_expand "bgeu"
5527 (if_then_else (geu (cc0)
5529 (label_ref (match_operand 0 "" ""))
5534 m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
5535 m68hc11_compare_op1,
5540 (define_expand "ble"
5542 (if_then_else (le (cc0)
5544 (label_ref (match_operand 0 "" ""))
5549 m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
5550 m68hc11_compare_op1,
5555 (define_expand "bleu"
5557 (if_then_else (leu (cc0)
5559 (label_ref (match_operand 0 "" ""))
5564 m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
5565 m68hc11_compare_op1,
5571 ;; Test and branch instructions for 68HC12 for EQ and NE.
5572 ;; 'z' must not appear in the constraints because the z replacement
5573 ;; pass does not know how to restore the replacement register.
5575 (define_insn "*tbeq"
5577 (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
5579 (label_ref (match_operand 1 "" ""))
5584 /* If the flags are already set correctly, use 'bne/beq' which are
5585 smaller and a little bit faster. This happens quite often due
5586 to reloading of operands[0]. In that case, flags are set correctly
5587 due to the load instruction. */
5588 if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5589 return \"beq\\t%l1\";
5591 return \"tbeq\\t%0,%l1\";
5594 (define_insn "*tbne"
5596 (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
5598 (label_ref (match_operand 1 "" ""))
5603 if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5604 return \"bne\\t%l1\";
5606 return \"tbne\\t%0,%l1\";
5610 ;; Test and branch with 8-bit register. Register must be B (or A).
5612 (define_insn "*tbeq8"
5614 (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
5616 (label_ref (match_operand 1 "" ""))
5621 if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5622 return \"beq\\t%l1\";
5624 return \"tbeq\\tb,%l1\";
5627 (define_insn "*tbne8"
5629 (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
5631 (label_ref (match_operand 1 "" ""))
5636 if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5637 return \"bne\\t%l1\";
5639 return \"tbne\\tb,%l1\";
5644 (if_then_else (eq (cc0)
5646 (label_ref (match_operand 0 "" ""))
5653 (if_then_else (ne (cc0)
5655 (label_ref (match_operand 0 "" ""))
5662 (if_then_else (gt (cc0)
5664 (label_ref (match_operand 0 "" ""))
5669 (define_insn "*bgtu"
5671 (if_then_else (gtu (cc0)
5673 (label_ref (match_operand 0 "" ""))
5680 (if_then_else (lt (cc0)
5682 (label_ref (match_operand 0 "" ""))
5687 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5688 return \"bmi\\t%l0\";
5690 return \"blt\\t%l0\";
5693 (define_insn "*bltu"
5695 (if_then_else (ltu (cc0)
5697 (label_ref (match_operand 0 "" ""))
5704 (if_then_else (ge (cc0)
5706 (label_ref (match_operand 0 "" ""))
5711 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5712 return \"bpl\\t%l0\";
5714 return \"bge\\t%l0\";
5717 (define_insn "*bgeu"
5719 (if_then_else (geu (cc0)
5721 (label_ref (match_operand 0 "" ""))
5728 (if_then_else (le (cc0)
5730 (label_ref (match_operand 0 "" ""))
5735 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5736 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
5738 return \"ble\\t%l0\";
5741 (define_insn "*bleu"
5743 (if_then_else (leu (cc0)
5745 (label_ref (match_operand 0 "" ""))
5750 ;;--------------------------------------------------------------------
5751 ;;- Negative test and branch
5752 ;;--------------------------------------------------------------------
5755 (if_then_else (eq (cc0)
5758 (label_ref (match_operand 0 "" ""))))]
5764 (if_then_else (ne (cc0)
5767 (label_ref (match_operand 0 "" ""))))]
5773 (if_then_else (gt (cc0)
5776 (label_ref (match_operand 0 "" ""))))]
5780 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5781 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
5783 return \"ble\\t%l0\";
5788 (if_then_else (gtu (cc0)
5791 (label_ref (match_operand 0 "" ""))))]
5797 (if_then_else (lt (cc0)
5800 (label_ref (match_operand 0 "" ""))))]
5804 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5805 return \"bpl\\t%l0\";
5807 return \"bge\\t%l0\";
5812 (if_then_else (ltu (cc0)
5815 (label_ref (match_operand 0 "" ""))))]
5821 (if_then_else (ge (cc0)
5824 (label_ref (match_operand 0 "" ""))))]
5828 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5829 return \"bmi\\t%l0\";
5831 return \"blt\\t%l0\";
5836 (if_then_else (geu (cc0)
5839 (label_ref (match_operand 0 "" ""))))]
5845 (if_then_else (le (cc0)
5848 (label_ref (match_operand 0 "" ""))))]
5854 (if_then_else (leu (cc0)
5857 (label_ref (match_operand 0 "" ""))))]
5861 ;;--------------------------------------------------------------------
5863 ;;--------------------------------------------------------------------
5865 ;;- Call a function that returns no value.
5867 [(call (match_operand:QI 0 "memory_operand" "m")
5868 (match_operand:SI 1 "general_operand" "g"))]
5869 ;; Operand 1 not really used on the m68hc11.
5873 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
5875 if (SYMBOL_REF_FLAG (XEXP (operands[0], 0)) == 1)
5878 return \"bsr\\t%0\";
5882 return \"jsr\\t%0\";
5886 (define_insn "call_value"
5887 [(set (match_operand 0 "" "=g")
5888 (call (match_operand:QI 1 "memory_operand" "m")
5889 (match_operand:SI 2 "general_operand" "g")))]
5893 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
5895 if (SYMBOL_REF_FLAG (XEXP (operands[1], 0)) == 1)
5898 return \"bsr\\t%1\";
5902 return \"jsr\\t%1\";
5906 ;; Call subroutine returning any type.
5908 (define_expand "untyped_call"
5909 [(parallel [(call (match_operand 0 "" "")
5911 (match_operand 1 "" "")
5912 (match_operand 2 "" "")])]
5918 emit_call_insn (gen_call (operands[0], const0_rtx));
5920 for (i = 0; i < XVECLEN (operands[2], 0); i++)
5922 rtx set = XVECEXP (operands[2], 0, i);
5923 emit_move_insn (SET_DEST (set), SET_SRC (set));
5926 /* The optimizer does not know that the call sets the function value
5927 registers we stored in the result block. We avoid problems by
5928 claiming that all hard registers are used and clobbered at this
5930 emit_insn (gen_blockage ());
5935 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5936 ;; all of memory. This blocks insns from being moved across this point.
5938 (define_insn "blockage"
5939 [(unspec_volatile [(const_int 0)] 0)]
5948 (define_expand "prologue"
5957 (define_expand "epilogue"
5966 ;; Used for frameless functions which save no regs and allocate no locals.
5967 (define_expand "return"
5969 "reload_completed && m68hc11_total_frame_size () == 0"
5974 if (current_function_return_rtx)
5975 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
5977 /* Emit use notes only when HAVE_return is true. */
5978 if (m68hc11_total_frame_size () != 0)
5981 if (ret_size && ret_size <= 2)
5983 emit_insn (gen_rtx (PARALLEL, VOIDmode,
5984 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
5985 gen_rtx_USE (VOIDmode,
5986 gen_rtx_REG (HImode, 1)))));
5991 emit_insn (gen_rtx (PARALLEL, VOIDmode,
5992 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
5993 gen_rtx_USE (VOIDmode,
5994 gen_rtx_REG (SImode, 0)))));
5999 (define_insn "*return_void"
6004 rtx next = next_active_insn (insn);
6007 && GET_CODE (next) == JUMP_INSN
6008 && GET_CODE (PATTERN (next)) == RETURN)
6010 if (current_function_interrupt || current_function_trap)
6015 (define_insn "*return_16bit"
6017 (use (reg:HI D_REGNUM))]
6018 "reload_completed && m68hc11_total_frame_size () == 0"
6021 rtx next = next_active_insn (insn);
6024 && GET_CODE (next) == JUMP_INSN
6025 && GET_CODE (PATTERN (next)) == RETURN)
6027 if (current_function_interrupt || current_function_trap)
6032 (define_insn "*return_32bit"
6035 "reload_completed && m68hc11_total_frame_size () == 0"
6038 rtx next = next_active_insn (insn);
6041 && GET_CODE (next) == JUMP_INSN
6042 && GET_CODE (PATTERN (next)) == RETURN)
6044 if (current_function_interrupt || current_function_trap)
6049 (define_insn "indirect_jump"
6050 [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6054 ;;--------------------------------------------------------------------
6056 ;;--------------------------------------------------------------------
6058 ;; Operand 0 is the address of the table element to use
6059 ;; operand 1 is the CODE_LABEL for the table
6060 ;;--------------------------------------------------------------------
6061 (define_expand "tablejump"
6062 [(parallel [(set (pc) (match_operand 0 "" ""))
6063 (use (label_ref (match_operand 1 "" "")))])]
6067 (define_insn "*jump_indirect"
6069 (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6070 (use (label_ref (match_operand 1 "" "")))])]
6074 ;;--------------------------------------------------------------------
6076 ;;--------------------------------------------------------------------
6079 ;; This peephole catches the address computations generated by the reload
6082 [(set (match_operand:HI 0 "hard_reg_operand" "xy")
6083 (match_operand:HI 1 "const_int_operand" ""))
6084 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6085 (set (match_dup 0) (reg:HI D_REGNUM))])
6086 (set (reg:HI D_REGNUM)
6087 (plus (reg:HI D_REGNUM)
6088 (match_operand:HI 2 "general_operand" "")))
6089 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6090 (set (match_dup 0) (reg:HI D_REGNUM))])]
6091 "(INTVAL (operands[1]) & 0x0FF) == 0"
6094 int value_loaded = 1;
6096 if (X_REG_P (operands[0]))
6098 output_asm_insn (\"ldx\\t%2\\n\\txgdx\", operands);
6100 else if (Y_REG_P (operands[0]))
6102 if (reg_mentioned_p (iy_reg, operands[2]))
6103 output_asm_insn (\"ldy\\t%2\", operands);
6106 output_asm_insn (\"xgdy\", operands);
6110 output_asm_insn (\"ldd\\t%2\", operands);
6113 if (value_loaded == 0)
6114 output_asm_insn (\"ldd\\t%2\", operands);
6115 if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
6116 output_asm_insn (\"inca\", operands);
6117 else if (INTVAL (operands[1]) & 0x0ff00 == 0xff00)
6118 output_asm_insn (\"deca\", operands);
6119 else if (INTVAL (operands[1]) != 0)
6120 output_asm_insn (\"adda\\t%h1\", operands);
6122 if (X_REG_P (operands[0]))
6124 else if (Y_REG_P (operands[0]))
6132 [(set (match_operand:HI 0 "hard_reg_operand" "h")
6133 (match_operand:HI 1 "non_push_operand" "g"))
6134 (set (match_operand:HI 2 "hard_reg_operand" "h")
6136 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
6137 && !S_REG_P (operands[2])"
6142 ops[0] = operands[2];
6143 ops[1] = operands[1];
6144 m68hc11_gen_movhi (insn, ops);
6150 [(set (match_operand:HI 0 "hard_reg_operand" "h")
6151 (match_operand:HI 1 "hard_reg_operand" "h"))
6152 (set (match_operand:HI 2 "non_push_operand" "g")
6154 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
6155 && !S_REG_P (operands[2])"
6160 ops[0] = operands[2];
6161 ops[1] = operands[1];
6162 m68hc11_gen_movhi (insn, ops);
6168 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
6169 ;; the set, so we don't need to emit anything. 'ins1' refers to the
6173 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
6174 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6175 (set (match_dup 0) (reg:HI D_REGNUM))])]
6176 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
6179 cc_status = cc_prev_status;
6184 ;; Same as above but due to some split, there may be a noop set
6187 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
6188 (set (match_dup 0) (match_dup 0))
6189 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6190 (set (match_dup 0) (reg:HI D_REGNUM))])]
6191 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
6194 cc_status = cc_prev_status;
6200 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
6201 ;; and we must, at least, setup X/Y with value of D.
6204 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
6205 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6206 (set (match_dup 0) (reg:HI D_REGNUM))])]
6212 ops[0] = operands[0];
6213 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6214 m68hc11_gen_movhi (insn, ops);
6220 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6221 ;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
6224 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6225 (set (match_dup 0) (reg:HI D_REGNUM))])
6226 (set (reg:HI D_REGNUM) (match_dup 0))]
6227 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
6230 cc_status = cc_prev_status;
6236 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6237 ;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
6240 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6241 (set (match_dup 0) (reg:HI D_REGNUM))])
6242 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
6243 "REGNO (operands[0]) == REGNO (operands[1])
6244 && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
6247 cc_status = cc_prev_status;
6253 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6254 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
6257 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6258 (set (match_dup 0) (reg:HI D_REGNUM))])
6259 (set (reg:HI D_REGNUM) (match_dup 0))]
6265 ops[0] = operands[0];
6266 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6267 m68hc11_gen_movhi (insn, ops);
6273 ;;; Same peephole with a QI set. The copy is made as 16-bit to comply
6277 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6278 (set (match_dup 0) (reg:HI D_REGNUM))])
6279 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
6280 "REGNO (operands[0]) == REGNO (operands[1])"
6285 ops[0] = operands[0];
6286 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6287 m68hc11_gen_movhi (insn, ops);
6293 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
6296 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6297 (set (match_dup 0) (reg:HI D_REGNUM))])
6298 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6299 (set (match_dup 0) (reg:HI D_REGNUM))])]
6303 cc_status = cc_prev_status;
6309 [(set (match_operand:HI 0 "hard_reg_operand" "")
6310 (match_operand:HI 1 "stack_register_operand" ""))
6311 (set (match_operand:HI 2 "hard_reg_operand" "")
6312 (match_operand:HI 3 "memory_operand" "m"))
6314 (match_operand:HI 4 "memory_operand" "m"))]
6315 "IS_STACK_POP (operands[4])
6316 && (GET_CODE (operands[3]) == MEM &&
6317 rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
6322 ops[0] = operands[2];
6323 ops[1] = gen_rtx (MEM, HImode,
6324 gen_rtx (POST_INC, HImode, stack_pointer_rtx));
6325 m68hc11_gen_movhi (insn, ops);
6331 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
6334 [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
6335 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
6339 return \"sts\\t%t0\\n\\tld%0\\t%t0\";