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 "x,dy,xyd,?xy,d,m,!u,dxy,dxy")
307 (match_operand:HI 1 "cmp_operand"
308 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
312 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
314 cc_status.flags |= CC_REVERSED;
315 return \"cp%1\\t%0\";
317 else if (H_REG_P (operands[1]))
320 return \"cp%0\\t%1\";
323 (define_insn "cmphi_z_used"
325 (compare (match_operand:HI 0 "tst_operand" "dxy,m")
326 (match_operand:HI 1 "cmp_operand" "m,dxy")))
327 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
332 (define_split /* "cmphi_z_used" */
334 (compare (match_operand:HI 0 "tst_operand" "dxy,m")
335 (match_operand:HI 1 "cmp_operand" "m,dxy")))
336 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
338 "z_replacement_completed == 2"
339 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
340 (set (match_dup 2) (match_dup 3))
341 (set (cc0) (compare (match_dup 0) (match_dup 1)))
342 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
343 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
346 ;; 8-bit comparison with address register.
347 ;; There is no such comparison instruction, we have to temporarily switch
348 ;; the address register and the D register and do the comparison with D.
349 ;; The xgdx and xgdy instructions preserve the flags.
353 (compare (match_operand:QI 0 "hard_addr_reg_operand" "xy")
354 (match_operand:QI 1 "cmp_operand" "uimA")))]
355 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
356 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
357 (set (match_dup 3) (reg:HI D_REGNUM))])
359 (compare (reg:QI D_REGNUM) (match_dup 1)))
360 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
361 (set (match_dup 3) (reg:HI D_REGNUM))])]
362 "operands[3] = gen_rtx (REG, HImode, REGNO (operands[0]));")
366 (compare (match_operand:QI 0 "hard_reg_operand" "dxy")
367 (match_operand:QI 1 "hard_reg_operand" "dxy")))]
369 [(set (match_dup 3) (match_dup 4))
371 (compare (match_dup 0) (match_dup 2)))]
372 "operands[2] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
373 operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
374 operands[4] = gen_rtx (REG, HImode, REGNO (operands[1]));")
376 (define_expand "cmpqi"
378 (compare (match_operand:QI 0 "tst_operand" "")
379 (match_operand:QI 1 "cmp_operand" "")))]
383 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
384 operands[0] = force_reg (QImode, operands[0]);
386 m68hc11_compare_op0 = operands[0];
387 m68hc11_compare_op1 = operands[1];
391 (define_insn "bitcmpqi"
393 (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
394 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
403 (define_split /* "bitcmpqi" */
405 (and:QI (match_operand:QI 0 "tst_operand" "d")
406 (match_operand:QI 1 "hard_addr_reg_operand" "xy")))]
407 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
408 [(set (match_dup 3) (match_dup 2))
409 (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
410 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1]));
411 operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
412 operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);")
414 (define_insn "bitcmpqi_z_used"
416 (and:QI (match_operand:QI 0 "tst_operand" "d,m")
417 (match_operand:QI 1 "cmp_operand" "m,d")))
418 (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
423 (define_split /* "bitcmpqi_z_used" */
425 (and:QI (match_operand:QI 0 "tst_operand" "d,m")
426 (match_operand:QI 1 "cmp_operand" "m,d")))
427 (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
429 "z_replacement_completed == 2"
430 [(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 2))
431 (set (match_dup 2) (match_dup 3))
432 (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
433 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI 3))))]
434 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
436 (define_insn "bitcmphi"
438 (and:HI (match_operand:HI 0 "tst_operand" "d")
439 (match_operand:HI 1 "const_int_operand" "i")))]
440 "(INTVAL (operands[1]) & 0x0ff) == 0
441 || (INTVAL (operands[1]) & 0x0ff00) == 0"
444 if ((INTVAL (operands[1]) & 0x0ff) == 0)
445 return \"bita\\t%h1\";
447 return \"bitb\\t%1\";
450 (define_insn "bitcmpqi_12"
452 (zero_extract (match_operand:HI 0 "tst_operand" "d")
453 (match_operand:HI 1 "const_int_operand" "i")
454 (match_operand:HI 2 "const_int_operand" "i")))]
455 "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
456 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
457 && (unsigned) INTVAL (operands[2]) >= 8)"
462 int startpos = INTVAL (operands[2]);
463 int bitsize = INTVAL (operands[1]);
468 mask = (1 << (startpos + bitsize)) - 1;
469 mask &= ~((1 << startpos) - 1);
471 ops[0] = GEN_INT (mask);
472 output_asm_insn (\"bita\\t%0\", ops);
476 mask = (1 << (startpos + bitsize)) - 1;
477 mask &= ~((1 << startpos) - 1);
479 ops[0] = GEN_INT (mask);
480 output_asm_insn (\"bitb\\t%0\", ops);
485 (define_insn "cmpqi_1"
487 (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
488 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
492 if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
496 else if (D_REG_P (operands[0]))
498 return \"cmpb\\t%b1\";
500 cc_status.flags |= CC_REVERSED;
501 return \"cmpb\\t%b0\";
504 (define_insn "cmpqi_z_used"
506 (compare (match_operand:QI 0 "tst_operand" "dxy,m")
507 (match_operand:QI 1 "cmp_operand" "m,dxy")))
508 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
513 (define_split /* cmpqi_z_used */
515 (compare (match_operand:QI 0 "tst_operand" "dxy,m")
516 (match_operand:QI 1 "cmp_operand" "m,dxy")))
517 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
519 "z_replacement_completed == 2"
520 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
521 (set (match_dup 2) (match_dup 3))
522 (set (cc0) (compare (match_dup 0) (match_dup 1)))
523 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
524 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
526 (define_expand "cmpdf"
528 (compare (match_operand:DF 0 "general_operand" "")
529 (match_operand:DF 1 "general_operand" "")))]
533 m68hc11_compare_op0 = operands[0];
534 m68hc11_compare_op1 = operands[1];
538 (define_expand "cmpsf"
540 (compare (match_operand:SF 0 "general_operand" "")
541 (match_operand:SF 1 "general_operand" "")))]
545 m68hc11_compare_op0 = operands[0];
546 m68hc11_compare_op1 = operands[1];
550 ;;--------------------------------------------------------------------
551 ;;- Move strict_low_part
552 ;;--------------------------------------------------------------------
554 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
555 ;; The replacement must be made at the very end because we loose the
556 ;; (strict_low_part ...) information. This is correct for our machine
557 ;; description but not for GCC optimization passes.
559 (define_insn "movstrictsi"
560 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
561 (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
566 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
567 (match_operand:SI 1 "general_operand" "D,Dim,u"))]
568 "z_replacement_completed == 2"
569 [(set (match_dup 0) (match_dup 1))]
572 (define_insn "movstricthi"
573 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
574 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
579 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
580 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
581 "z_replacement_completed == 2"
582 [(set (match_dup 0) (match_dup 1))]
585 (define_insn "movstrictqi"
586 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
587 (match_operand:QI 1 "general_operand" "d,imudA"))]
592 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,dA"))
593 (match_operand:QI 1 "general_operand" "d,imudA"))]
594 "z_replacement_completed == 2"
595 [(set (match_dup 0) (match_dup 1))]
598 ;;--------------------------------------------------------------------
599 ;;- 64-bit Move Operations.
600 ;; The movdi and movdf patterns are identical except for the mode.
601 ;; They are also very similar to those for movsi and movsf.
603 ;; For 68HC11, we need a scratch register (either D, X, Y)
604 ;; because there is no memory->memory moves. It must be defined with
605 ;; earlyclobber (&) so that it does not appear in the source or destination
606 ;; address. Providing patterns for movdi/movdf allows GCC to generate
607 ;; better code. [Until now, the scratch register is limited to D becuse
608 ;; otherwise we can run out of registers in the A_REGS class for reload].
610 ;; For 68HC12, the scratch register is not necessary. To use the same
611 ;; pattern and same split, we use the 'v' constraint. This tells the
612 ;; reload to use the _.tmp register (which is not used at all).
613 ;; The insn will be split in one or several memory moves (movw).
614 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
615 ;;--------------------------------------------------------------------
616 (define_expand "movdi"
617 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
618 (match_operand:DI 1 "general_operand" ""))
619 (clobber (match_scratch:HI 2 ""))])]
622 /* For push/pop, emit a REG_INC note to make sure the reload
623 inheritance and reload CSE pass notice the change of the stack
625 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
629 insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
630 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
637 (define_insn "movdi_internal"
638 [(set (match_operand:DI 0 "nonimmediate_operand" "=U,!u,U,m,m,!u")
639 (match_operand:DI 1 "general_operand" "iU,iU,!u,mi,!u,!mu"))
640 (clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))]
645 [(set (match_operand:DI 0 "nonimmediate_operand" "=uUm")
646 (match_operand:DI 1 "general_operand" "iuUm"))
647 (clobber (match_scratch:HI 2 "=&d"))]
650 "m68hc11_split_move (operands[0], operands[1], operands[2]);
653 (define_expand "movdf"
654 [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
655 (match_operand:DF 1 "general_operand" ""))
656 (clobber (match_scratch:HI 2 ""))])]
658 "/* For push/pop, emit a REG_INC note to make sure the reload
659 inheritance and reload CSE pass notice the change of the stack
661 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
665 insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
666 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
673 (define_insn "movdf_internal"
674 [(set (match_operand:DF 0 "nonimmediate_operand" "=U,!u,U,m,m,!u")
675 (match_operand:DF 1 "general_operand" "iU,iU,!u,mi,!u,!mu"))
676 (clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))]
681 [(set (match_operand:DF 0 "nonimmediate_operand" "=uUm")
682 (match_operand:DF 1 "general_operand" "iuUm"))
683 (clobber (match_scratch:HI 2 "=&d"))]
686 "m68hc11_split_move (operands[0], operands[1], operands[2]);
689 ;;--------------------------------------------------------------------
690 ;;- 32-bit Move Operations.
691 ;; The movsi and movsf patterns are identical except for the mode.
692 ;; When we move to/from a hard register (d+x), we don't need a scratch.
693 ;; Otherwise, a scratch register is used as intermediate register for
694 ;; the move. The '&' constraint is necessary to make sure the reload
695 ;; pass does not give us a register that dies in the insn and is used
696 ;; for input/output operands.
697 ;;--------------------------------------------------------------------
698 (define_expand "movsi"
699 [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
700 (match_operand:SI 1 "general_operand" ""))
701 (clobber (match_scratch:HI 2 ""))])]
703 "/* For push/pop, emit a REG_INC note to make sure the reload
704 inheritance and reload CSE pass notice the change of the stack
706 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
710 insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
711 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
718 (define_insn "movsi_internal"
719 [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,?D,m,?D,?u,?u,!u,D")
720 (match_operand:SI 1 "general_operand" "imu,im,?D,!u,?D,mi,!u,!D"))
721 (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
726 [(set (match_operand:SI 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
727 (match_operand:SI 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
728 (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
731 "m68hc11_split_move (operands[0], operands[1], operands[2]);
734 (define_expand "movsf"
735 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
736 (match_operand:SF 1 "general_operand" ""))
737 (clobber (match_scratch:HI 2 ""))])]
739 "/* For push/pop, emit a REG_INC note to make sure the reload
740 inheritance and reload CSE pass notice the change of the stack
742 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
746 insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
747 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
754 (define_insn "movsf_internal"
755 [(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
756 (match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
757 (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
762 [(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D")
763 (match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D"))
764 (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))]
767 "m68hc11_split_move (operands[0], operands[1], operands[2]);
771 ;;--------------------------------------------------------------------
772 ;;- 16-bit Move Operations.
773 ;; We don't need a scratch register.
774 ;;--------------------------------------------------------------------
776 (define_insn "*movhi2_push"
777 [(set (match_operand:HI 0 "push_operand" "=<,<")
778 (match_operand:HI 1 "general_operand" "xy,?d"))]
779 "TARGET_M6811 && !TARGET_M6812"
782 cc_status = cc_prev_status;
783 if (D_REG_P (operands[1]))
785 output_asm_insn (\"pshb\", operands);
788 else if (X_REG_P (operands[1]))
792 else if (Y_REG_P (operands[1]))
796 fatal_insn (\"Invalid register in the instruction\", insn);
799 (define_insn "*movhi2_pop"
800 [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
801 (match_operand:HI 1 "pop_operand" ">,>"))]
805 cc_status = cc_prev_status;
806 if (D_REG_P (operands[0]))
808 output_asm_insn (\"pula\", operands);
811 else if (X_REG_P (operands[0]))
815 else if (Y_REG_P (operands[0]))
819 fatal_insn (\"Invalid register in the instruction\", insn);
822 (define_expand "movhi"
823 [(set (match_operand:HI 0 "nonimmediate_operand" "")
824 (match_operand:HI 1 "general_operand" ""))]
828 if (reload_in_progress)
830 if (m68hc11_reload_operands (operands))
835 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
837 if (GET_CODE (operands[0]) == MEM &&
838 (GET_CODE (operands[1]) == MEM
839 || GET_CODE (operands[1]) == CONST_INT))
841 operands[1] = force_reg (HImode, operands[1]);
843 else if (IS_STACK_PUSH (operands[0])
844 && GET_CODE (operands[1]) != REG)
846 operands[1] = force_reg (HImode, operands[1]);
849 /* For push/pop, emit a REG_INC note to make sure the reload
850 inheritance and reload CSE pass notice the change of the stack
852 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
856 insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
857 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
864 (define_insn "movhi_const0"
865 [(set (match_operand:HI 0 "non_push_operand" "=d,A,um")
871 clr\\t%b0\\n\\tclr\\t%h0")
873 (define_insn "*movhi_68hc12"
874 [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,U,U,m,!u")
875 (match_operand:HI 1 "general_operand" "U,rim,dAwi,!u,dAw,riU"))]
879 m68hc11_gen_movhi (insn, operands);
883 (define_insn "*movhi_m68hc11"
884 [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
885 (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
889 m68hc11_gen_movhi (insn, operands);
893 ;;--------------------------------------------------------------------
894 ;;- 8-bit Move Operations.
895 ;; We don't need a scratch register.
896 ;;--------------------------------------------------------------------
898 ;; The *a alternative also clears the high part of the register.
899 ;; This should be ok since this is not the (strict_low_part) set.
901 (define_insn "movqi_const0"
902 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
913 ;; 8-bit operations on address registers.
915 ;; Switch temporary to the D register and load the value in B.
916 ;; This is possible as long as the address register does not
917 ;; appear in the source operand.
920 [(set (match_operand:QI 0 "hard_addr_reg_operand" "=A")
921 (match_operand:QI 1 "general_operand" ""))]
922 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode
923 && !reg_mentioned_p (operands[0], operands[1])
924 && !D_REG_P (operands[1])"
925 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
926 (set (match_dup 2) (reg:HI D_REGNUM))])
927 (set (reg:QI D_REGNUM) (match_dup 1))
928 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
929 (set (match_dup 2) (reg:HI D_REGNUM))])]
930 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));")
933 ;; 8-bit operations on address registers.
936 [(set (match_operand:QI 0 "nonimmediate_operand" "")
937 (match_operand:QI 1 "hard_addr_reg_operand" "=A"))]
938 "z_replacement_completed == 2 && GET_MODE (operands[1]) == QImode
939 && !reg_mentioned_p (operands[1], operands[0])
940 && !D_REG_P (operands[0])"
941 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
942 (set (match_dup 2) (reg:HI D_REGNUM))])
943 (set (match_dup 0) (reg:QI D_REGNUM))
944 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
945 (set (match_dup 2) (reg:HI D_REGNUM))])]
946 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1]));")
948 (define_insn "*movqi2_push"
949 [(set (match_operand:QI 0 "push_operand" "=<,<")
950 (match_operand:QI 1 "general_operand" "d,!*A"))]
954 if (A_REG_P (operands[1]))
957 cc_status = cc_prev_status;
962 (define_expand "movqi"
963 [(set (match_operand:QI 0 "nonimmediate_operand" "")
964 (match_operand:QI 1 "general_operand" ""))]
968 if (reload_in_progress)
970 if (m68hc11_reload_operands (operands))
975 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
977 if (GET_CODE (operands[0]) == MEM
978 && (GET_CODE (operands[1]) == MEM
979 || GET_CODE (operands[1]) == CONST_INT))
981 operands[1] = force_reg (QImode, operands[1]);
983 else if (IS_STACK_PUSH (operands[0])
984 && GET_CODE (operands[1]) != REG)
986 operands[1] = force_reg (QImode, operands[1]);
989 /* For push/pop, emit a REG_INC note to make sure the reload
990 inheritance and reload CSE pass notice the change of the stack
992 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
996 insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
997 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
1004 (define_insn "*movqi_68hc12"
1005 [(set (match_operand:QI 0 "nonimmediate_operand"
1006 "=d*AU*q,d*A*q,*u,d*A*q,m,m")
1007 (match_operand:QI 1 "general_operand"
1008 "*ri*q,U,*ri*qU,m,d*q,!A"))]
1012 m68hc11_gen_movqi (insn, operands);
1016 (define_insn "*movqi_m68hc11"
1017 [(set (match_operand:QI 0 "nonimmediate_operand" "=dA*q,m,m,dA*q,*u")
1018 (match_operand:QI 1 "general_operand" "dAim*q,d*q,!A,*u,dA*q"))]
1022 m68hc11_gen_movqi (insn, operands);
1026 ;;--------------------------------------------------------------------
1028 ;;--------------------------------------------------------------------
1029 ;; Swapping registers is used for split patterns.
1030 (define_insn "swap_areg"
1031 [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1032 (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1033 (set (match_dup 1) (match_dup 0))]
1037 m68hc11_output_swap (insn, operands);
1041 ;;--------------------------------------------------------------------
1042 ;;- Truncation insns.
1043 ;;--------------------------------------------------------------------
1045 ;; Truncation are not necessary because GCC knows how to truncate,
1046 ;; specially when values lie in consecutive registers.
1049 (define_expand "floatunssisf2"
1050 [(set (match_operand:SF 0 "nonimmediate_operand" "")
1051 (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1053 "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
1054 SFmode, SImode, 2, operands);
1057 (define_expand "floatunssidf2"
1058 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1059 (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1061 "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
1062 DFmode, SImode, 2, operands);
1065 ;;--------------------------------------------------------------------
1066 ;;- Zero extension insns.
1067 ;;--------------------------------------------------------------------
1070 ;; 64-bit extend. The insn will be split into 16-bit instructions just
1071 ;; before the final pass. We need a scratch register for the split.
1072 ;; The final value can be generated on the stack directly. This is more
1073 ;; efficient and useful for conversions made during parameter passing rules.
1075 (define_insn "zero_extendqidi2"
1076 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1078 (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1079 (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1084 [(set (match_operand:DI 0 "push_operand" "=<")
1085 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "dmu*B")))
1086 (clobber (match_scratch:HI 2 "=&dB"))]
1087 "z_replacement_completed == 2"
1091 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1092 rtx push = m68hc11_gen_lowpart (HImode, low);
1093 rtx src = operands[1];
1095 /* Source operand must be in a hard register. */
1098 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1099 emit_move_insn (src, operands[1]);
1102 /* Source is in D, we can push B then one word of 0 and we do
1103 a correction on the stack pointer. */
1106 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1107 emit_move_insn (operands[2], const0_rtx);
1108 if (D_REG_P (operands[2]))
1110 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1114 emit_move_insn (push, operands[2]);
1115 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1116 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1122 /* Source is in X or Y. It's better to push the 16-bit register
1123 and then to some stack adjustment. */
1124 src = gen_rtx (REG, HImode, REGNO (src));
1125 emit_move_insn (push, src);
1126 emit_move_insn (operands[2], const0_rtx);
1127 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1128 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1130 emit_move_insn (push, operands[2]);
1131 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1132 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1135 emit_move_insn (push, operands[2]);
1136 emit_move_insn (push, operands[2]);
1137 emit_move_insn (push, operands[2]);
1142 [(set (match_operand:DI 0 "nonimmediate_operand" "=mu")
1143 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "dmu*B")))
1144 (clobber (match_scratch:HI 2 "=&dB"))]
1145 "z_replacement_completed == 2"
1149 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1150 rtx low2 = m68hc11_gen_lowpart (HImode, low);
1151 rtx src = operands[1];
1153 /* Source operand must be in a hard register. */
1156 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1157 emit_move_insn (src, operands[1]);
1160 emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1161 emit_move_insn (operands[2], const0_rtx);
1162 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1163 emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1165 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1166 low = m68hc11_gen_highpart (SImode, operands[0]);
1167 emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1168 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1172 (define_insn "zero_extendhidi2"
1173 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1175 (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1176 (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1181 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,!u,!u")
1183 (match_operand:HI 1 "nonimmediate_operand" "m,dA,!u,dmA,!u")))
1184 (clobber (match_scratch:HI 2 "=&d,&dB,&dB,&dB,&dB"))]
1185 "z_replacement_completed == 2"
1189 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1190 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1191 rtx src = operands[1];
1193 /* Make sure the source is in a hard register. */
1197 emit_move_insn (src, operands[1]);
1200 /* Move the low part first for the push. */
1201 emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1203 /* Now, use the scratch register to fill in the zeros. */
1204 emit_move_insn (operands[2], const0_rtx);
1205 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1206 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1207 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1211 (define_insn "zero_extendsidi2"
1212 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1214 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1215 (clobber (match_scratch:HI 2 "=d,d,&dB,d"))]
1220 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1222 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1223 (clobber (match_scratch:HI 2 "=d,d,&dB,d"))]
1224 "z_replacement_completed == 2"
1228 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1229 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1231 /* Move the low part first so that this is ok for a push. */
1232 m68hc11_split_move (low, operands[1], operands[2]);
1234 /* Use the scratch register to clear the high part of the destination. */
1235 emit_move_insn (operands[2], const0_rtx);
1236 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1237 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1242 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1243 ;; because it's less efficient.
1245 (define_insn "zero_extendhisi2"
1246 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1248 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1249 (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1254 [(set (match_operand:SI 0 "non_push_operand" "=D,mu,m,m,!u,!u")
1256 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,m,!u,m,!u")))
1257 (clobber (match_scratch:HI 2 "=X,X,&d,&dB,&dB,&dB"))]
1262 rtx src = operands[1];
1264 if (!H_REG_P (src) && !H_REG_P (operands[0]))
1267 emit_move_insn (src, operands[1]);
1269 emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1270 emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1274 (define_insn "zero_extendqisi2"
1275 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1277 (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1282 [(set (match_operand:SI 0 "non_push_operand" "=mu")
1283 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxy")))]
1284 "reload_completed && !X_REG_P (operands[0])"
1285 [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1286 (set (match_dup 3) (const_int 0))]
1288 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1289 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1292 [(set (match_operand:SI 0 "hard_reg_operand" "=D")
1293 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxymu")))]
1294 "z_replacement_completed == 2 && X_REG_P (operands[0])"
1295 [(set (match_dup 2) (match_dup 3))
1296 (set (match_dup 4) (const_int 0))
1297 (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1299 if (X_REG_P (operands[1]))
1301 emit_insn (gen_swap_areg (gen_rtx (REG, HImode, HARD_D_REGNUM),
1302 gen_rtx (REG, HImode, HARD_X_REGNUM)));
1303 emit_insn (gen_zero_extendqihi2 (gen_rtx (REG, HImode, HARD_D_REGNUM),
1304 gen_rtx (REG, QImode, HARD_D_REGNUM)));
1305 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM),
1310 if (reg_mentioned_p (gen_rtx (REG, HImode, HARD_X_REGNUM), operands[1]))
1312 emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1315 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), const0_rtx);
1318 operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1319 operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1320 if (A_REG_P (operands[1]))
1322 operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
1323 operands[3] = gen_rtx (REG, HImode, REGNO (operands[1]));
1324 operands[6] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
1328 operands[5] = operands[2] =
1329 operands[3] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1330 operands[6] = operands[1];
1334 (define_insn "zero_extendqihi2"
1335 [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!u,d,m,!u")
1337 (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1343 if (A_REG_P (operands[0]))
1346 if (H_REG_P (operands[0]))
1348 output_asm_insn (\"clra\", operands);
1349 if (operands[0] != operands[1]
1350 && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1352 if (X_REG_P (operands[1])
1353 || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1355 output_asm_insn (\"stx\\t%t1\", operands);
1356 output_asm_insn (\"ldab\\t%T0\", operands);
1358 else if (Y_REG_P (operands[1])
1359 || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1361 output_asm_insn (\"sty\\t%t1\", operands);
1362 output_asm_insn (\"ldab\\t%T0\", operands);
1366 output_asm_insn (\"ldab\\t%b1\", operands);
1368 cc_status.flags |= CC_NOT_NEGATIVE;
1372 /* Status refers to the clra insn. Status is ok for others
1373 * since we have loaded the value in B.
1380 if (A_REG_P (operands[1]))
1382 output_asm_insn (\"st%1\\t%0\", operands);
1383 output_asm_insn (\"clr\\t%h0\", operands);
1388 output_asm_insn (\"clr\\t%h0\", operands);
1389 output_asm_insn (\"stab\\t%b0\", operands);
1390 cc_status.flags |= CC_NOT_NEGATIVE;
1397 ;;--------------------------------------------------------------------
1398 ;;- Sign extension insns.
1399 ;;--------------------------------------------------------------------
1401 (define_insn "extendqisi2"
1402 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1403 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1411 /* The 68HC12 has a sign-extension instruction. Use it when the
1412 destination is the register (X,D). First sign-extend the low
1413 part and fill X with the sign-extension of the high part. */
1414 if (TARGET_M6812 && X_REG_P (operands[0]))
1416 if (!D_REG_P (operands[1]))
1418 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1419 ops[1] = operands[1];
1420 m68hc11_gen_movqi (insn, ops);
1422 return \"sex\\tb,d\\n\\tsex\\ta,x\";
1425 ops[2] = gen_label_rtx ();
1427 if (X_REG_P (operands[1]))
1429 output_asm_insn (\"xgdx\", operands);
1432 else if (X_REG_P (operands[0]))
1434 /* X can be used as an indexed addressing in the source.
1435 Get the value before clearing it. */
1436 if (reg_mentioned_p (ix_reg, operands[1]))
1438 output_asm_insn (\"ldab\\t%b1\", operands);
1441 output_asm_insn (\"ldx\\t#0\", operands);
1444 output_asm_insn (\"clra\", operands);
1445 if (!X_REG_P (operands[0]))
1447 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1448 ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1450 if (IS_STACK_PUSH (operands[0]))
1452 output_asm_insn (\"pshb\", ops);
1453 output_asm_insn (\"tstb\", ops);
1457 output_asm_insn (\"stab\\t%b1\", ops);
1460 else if (D_REG_P (operands[1]) || need_tst)
1462 output_asm_insn (\"tstb\", operands);
1466 output_asm_insn (\"ldab\\t%b1\", operands);
1468 output_asm_insn (\"bpl\\t%l2\", ops);
1469 output_asm_insn (\"deca\", operands);
1470 if (X_REG_P (operands[0]))
1471 output_asm_insn (\"dex\", operands);
1473 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1475 if (!X_REG_P (operands[0]))
1477 if (IS_STACK_PUSH (operands[0]))
1479 output_asm_insn (\"psha\", ops);
1480 output_asm_insn (\"psha\", ops);
1481 output_asm_insn (\"psha\", ops);
1485 output_asm_insn (\"staa\\t%h0\", ops);
1487 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1488 if (dead_register_here (insn, d_reg))
1490 output_asm_insn (\"tab\", ops);
1491 output_asm_insn (\"std\\t%0\", ops);
1495 output_asm_insn (\"staa\\t%b0\", ops);
1496 output_asm_insn (\"staa\\t%h0\", ops);
1506 (define_insn "extendqihi2"
1507 [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1508 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1514 if (A_REG_P (operands[0]))
1517 ops[0] = gen_label_rtx ();
1518 if (D_REG_P (operands[0]))
1522 if (!D_REG_P (operands[1]))
1524 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1525 ops[1] = operands[1];
1526 m68hc11_gen_movqi (insn, ops);
1528 return \"sex\\tb,d\";
1530 output_asm_insn (\"clra\", operands);
1531 if (H_REG_P (operands[1]))
1533 output_asm_insn (\"tstb\", operands);
1537 output_asm_insn (\"ldab\\t%b1\", operands);
1539 output_asm_insn (\"bpl\\t%l0\", ops);
1540 output_asm_insn (\"deca\", operands);
1542 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1543 CODE_LABEL_NUMBER (ops[0]));
1547 output_asm_insn (\"clr\\t%h0\", operands);
1548 if (m68hc11_register_indirect_p (operands[1], HImode))
1550 ops[1] = operands[1];
1551 output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1556 output_asm_insn (\"tst\\t%b1\", operands);
1557 output_asm_insn (\"bpl\\t%l0\", ops);
1559 output_asm_insn (\"dec\\t%h0\", operands);
1560 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1561 CODE_LABEL_NUMBER (ops[0]));
1568 ;; Split the special case where the source of the sign extend is
1569 ;; either Y or Z. In that case, we can't move the source in the D
1570 ;; register directly. The movhi pattern handles this move by using
1571 ;; a temporary scratch memory location.
1574 [(set (match_operand:SI 0 "register_operand" "=D")
1575 (sign_extend:SI (match_operand:HI 1 "register_operand" "A")))]
1576 "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1577 [(set (reg:HI D_REGNUM) (match_dup 1))
1578 (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1581 (define_insn "extendhisi2"
1582 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1583 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1591 if (Y_REG_P (operands[1]))
1594 if (X_REG_P (operands[1]))
1596 output_asm_insn (\"xgdx\", operands);
1601 /* X can be used as a indexed addressing in the source.
1602 Get the value before clearing it. */
1603 x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1606 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1607 ops[1] = operands[1];
1608 m68hc11_gen_movhi (insn, ops);
1613 if (TARGET_M6812 && 0)
1615 /* This sequence of code is larger than the one for 68HC11.
1616 Don't use it; keep it for documentation. */
1617 if (!D_REG_P (operands[1]) && !x_reg_used)
1619 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1620 ops[1] = operands[1];
1621 m68hc11_gen_movhi (insn, ops);
1623 output_asm_insn (\"sex\\ta,x\", operands);
1624 output_asm_insn (\"xgdx\", operands);
1625 output_asm_insn (\"sex\\ta,d\", operands);
1629 output_asm_insn (\"ldx\\t#0\", operands);
1630 if (D_REG_P (operands[1]) || x_reg_used)
1632 output_asm_insn (\"tsta\", operands);
1636 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1637 ops[1] = operands[1];
1638 m68hc11_gen_movhi (insn, ops);
1641 ops[0] = gen_label_rtx ();
1642 output_asm_insn (\"bpl\\t%l0\", ops);
1643 output_asm_insn (\"dex\", operands);
1644 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1650 ;;--------------------------------------------------------------------
1651 ;;- Min and Max instructions (68HC12).
1652 ;;--------------------------------------------------------------------
1653 (define_insn "uminqi3"
1654 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1655 (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1656 (match_operand:QI 2 "general_operand" "m,d")))]
1660 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1661 The mina/minm use A as the source or destination. This is the
1662 high part of D. There is no way to express that in the pattern
1663 so we must use 'exg a,b' to put the operand in the good register. */
1665 if (D_REG_P (operands[0]))
1667 return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1671 return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1675 (define_insn "umaxqi3"
1676 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1677 (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1678 (match_operand:QI 2 "general_operand" "m,d")))]
1682 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1683 The maxa/maxm use A as the source or destination. This is the
1684 high part of D. There is no way to express that in the pattern
1685 so we must use 'exg a,b' to put the operand in the good register. */
1687 if (D_REG_P (operands[0]))
1689 return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1693 return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1697 (define_insn "uminhi3"
1698 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1699 (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1700 (match_operand:HI 2 "general_operand" "m,d")))]
1704 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1706 if (D_REG_P (operands[0]))
1708 return \"emind\\t%2\";
1712 return \"eminm\\t%0\";
1716 (define_insn "umaxhi3"
1717 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1718 (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1719 (match_operand:HI 2 "general_operand" "m,d")))]
1723 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1725 if (D_REG_P (operands[0]))
1727 return \"emaxd\\t%2\";
1731 return \"emaxm\\t%0\";
1736 ;;--------------------------------------------------------------------
1737 ;;- Add instructions.
1738 ;;--------------------------------------------------------------------
1739 ;; 64-bit: Use a library call because what GCC generates is huge.
1741 (define_expand "adddi3"
1742 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1743 (plus:DI (match_operand:DI 1 "general_operand" "")
1744 (match_operand:DI 2 "general_operand" "")))]
1746 "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1752 (define_expand "addsi3"
1753 [(parallel [(set (match_operand:SI 0 "register_operand" "")
1754 (plus:SI (match_operand:SI 1 "register_operand" "")
1755 (match_operand:SI 2 "general_operand" "")))
1756 (clobber (match_scratch:HI 3 ""))])]
1761 ;; Translate D = D + D into D = D << 1
1762 ;; We have to do this because adding a register to itself is not possible.
1764 ;; Manipulation of A and B registers directly confuses the cse-regs pass
1765 ;; so the split must be made after z-replacement register.
1768 [(set (match_operand:SI 0 "register_operand" "=D")
1769 (plus:SI (match_dup 0)
1771 (clobber (match_scratch:HI 1 "=X"))]
1772 "reload_completed && z_replacement_completed == 2"
1773 [(set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
1774 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
1775 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
1776 (set (reg:QI B_REGNUM) (rotate:QI (reg:QI B_REGNUM) (reg:QI CC_REGNUM)))
1777 (set (reg:QI A_REGNUM) (rotate:QI (reg:QI A_REGNUM) (reg:QI CC_REGNUM)))
1778 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
1779 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
1783 (define_insn "*addsi3_zero_extendhi"
1784 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1785 (plus:SI (zero_extend:SI
1786 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1787 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1788 (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1794 if (X_REG_P (operands[2]))
1796 ops[0] = operands[1];
1800 if (X_REG_P (operands[1]))
1802 output_asm_insn (\"xgdx\", ops);
1804 else if (!D_REG_P (operands[1]))
1806 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1807 ops[1] = operands[1];
1808 m68hc11_gen_movhi (insn, ops);
1810 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1811 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1813 ops[2] = gen_label_rtx ();
1815 /* ldx preserves the carry, propagate it by incrementing X directly. */
1816 output_asm_insn (\"addd\\t%0\", ops);
1817 if (!X_REG_P (operands[2]))
1818 output_asm_insn (\"ldx\\t%1\", ops);
1820 output_asm_insn (\"bcc\\t%l2\", ops);
1821 output_asm_insn (\"inx\", ops);
1824 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1829 (define_split /* "*addsi3_zero_extendqi" */
1830 [(set (match_operand:SI 0 "register_operand" "=D,D")
1831 (plus:SI (zero_extend:SI
1832 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1833 (match_operand:SI 2 "memory_operand" "m,m")))
1834 (clobber (match_scratch:HI 3 "=X,X"))]
1836 [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1837 (parallel [(set (match_dup 0)
1838 (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1839 (clobber (match_dup 3))])]
1842 (define_insn "*addsi3_zero_extendqi"
1843 [(set (match_operand:SI 0 "register_operand" "=D,D")
1844 (plus:SI (zero_extend:SI
1845 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1846 (match_operand:SI 2 "general_operand" "miD,!muiD")))
1847 (clobber (match_scratch:HI 3 "=X,X"))]
1853 if (GET_CODE (operands[2]) == MEM)
1856 if (X_REG_P (operands[2]))
1858 if (H_REG_P (operands[1]))
1860 ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
1861 ops[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
1862 m68hc11_gen_movhi (insn, ops);
1866 ops[0] = operands[1];
1868 ops[1] = gen_rtx (CONST_INT, VOIDmode, 0);
1872 if (X_REG_P (operands[1]))
1874 output_asm_insn (\"xgdx\", ops);
1876 else if (!D_REG_P (operands[1]))
1878 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1879 ops[1] = operands[1];
1880 m68hc11_gen_movqi (insn, ops);
1883 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1885 ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1886 output_asm_insn (\"clra\", ops);
1889 /* ldx preserves the carry, propagate it by incrementing X directly. */
1890 output_asm_insn (\"addb\\t%b0\", ops);
1891 output_asm_insn (\"adca\\t%h1\", ops);
1892 if (!X_REG_P (operands[2]))
1893 output_asm_insn (\"ldx\\t%2\", ops);
1895 /* If the above adca was adding some constant, we don't need to propagate
1896 the carry unless the constant was 0xff. */
1897 if (X_REG_P (operands[2])
1898 || GET_CODE (ops[1]) != CONST_INT
1899 || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1901 ops[3] = gen_label_rtx ();
1903 output_asm_insn (\"bcc\\t%l3\", ops);
1904 output_asm_insn (\"inx\", ops);
1906 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1907 CODE_LABEL_NUMBER (ops[3]));
1913 (define_insn "*addsi3"
1914 [(set (match_operand:SI 0 "non_push_operand" "=m,D,!u,?D,D")
1915 (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1916 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?miu")))
1917 (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1928 if (which_alternative > 2)
1933 val = INTVAL (operands[2]);
1934 if ((val & 0x0ffffL) == 0)
1936 if (!H_REG_P (operands[0]))
1938 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1939 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1940 output_asm_insn (\"ldd\\t%0\", ops);
1941 output_asm_insn (\"addd\\t%1\", ops);
1942 output_asm_insn (\"std\\t%0\", ops);
1954 if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1961 ops[1] = operands[2];
1962 add_insn = \"addd\\t%1\";
1963 inc_insn = \"inx\\t\";
1964 incb_mem = \"inc\\t%b1\";
1965 inch_mem = \"inc\\t%h1\";
1969 ops[1] = gen_rtx (CONST_INT, VOIDmode, - val);
1970 add_insn = \"subd\\t%1\";
1972 incb_mem = \"dec\\t%b1\";
1973 inch_mem = \"dec\\t%h1\";
1976 ops[2] = gen_label_rtx ();
1977 if (!H_REG_P (operands[0]))
1979 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1980 output_asm_insn (\"ldd\\t%0\", ops);
1982 output_asm_insn (add_insn, ops);
1983 if (!H_REG_P (operands[0]))
1985 output_asm_insn (\"std\\t%0\", ops);
1987 output_asm_insn (\"bcc\\t%l2\", ops);
1988 if (H_REG_P (operands[0]))
1990 output_asm_insn (inc_insn, ops);
1994 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1996 if (INTVAL (operands[2]) < 0)
1998 output_asm_insn (\"ldd\\t%1\", ops);
1999 output_asm_insn (\"addd\\t#-1\", ops);
2000 output_asm_insn (\"std\\t%1\", ops);
2004 output_asm_insn (incb_mem, ops);
2005 output_asm_insn (\"bne\\t%l2\", ops);
2006 output_asm_insn (inch_mem, ops);
2009 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
2016 [(set (match_operand:SI 0 "register_operand" "=D,u")
2017 (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
2018 (match_operand:SI 2 "const_int_operand" "")))
2019 (clobber (match_scratch:HI 3 "=X,d"))]
2020 "reload_completed && z_replacement_completed == 2
2021 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
2022 [(set (match_dup 5) (match_dup 6))
2023 (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
2024 (set (match_dup 6) (match_dup 5))]
2025 "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2026 if (X_REG_P (operands[0]))
2028 operands[5] = operands[6] = gen_rtx (REG, HImode, HARD_D_REGNUM);
2032 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2033 operands[5] = operands[3];
2038 [(set (match_operand:SI 0 "register_operand" "=D")
2039 (plus:SI (match_operand:SI 1 "register_operand" "%0")
2040 (match_operand:SI 2 "general_operand" "mui")))
2041 (clobber (match_scratch:HI 3 "=X"))]
2042 "reload_completed && z_replacement_completed == 2
2043 && (GET_CODE (operands[2]) != CONST_INT ||
2044 (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
2045 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2046 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2047 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2048 (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2049 (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2050 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2051 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
2052 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2053 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2054 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2055 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2058 ;; Instruction generated to propagate the carry of a 16-bit add
2059 ;; to the upper 16-bit part (in register X).
2061 (define_insn "*addsi_carry"
2062 [(set (match_operand:HI 0 "register_operand" "=x")
2063 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2065 (reg:HI CC_REGNUM)))]
2071 ops[0] = gen_label_rtx ();
2072 output_asm_insn (\"bcc\\t%l0\", ops);
2073 output_asm_insn (\"in%0\", operands);
2074 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2082 (define_expand "addhi3"
2083 [(set (match_operand:HI 0 "register_operand" "")
2084 (plus:HI (match_operand:HI 1 "register_operand" "")
2085 (match_operand:HI 2 "general_operand" "")))]
2089 if (TARGET_M6811 && SP_REG_P (operands[0]))
2091 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2092 gen_rtx (SET, VOIDmode,
2094 gen_rtx (PLUS, HImode,
2095 operand1, operand2)),
2096 gen_rtx (CLOBBER, VOIDmode,
2097 gen_rtx (SCRATCH, HImode)))));
2102 (define_split /* "*addhi3_strict_low_part" */
2103 [(set (strict_low_part (match_operand:QI 0 "register_operand" "+dxy"))
2104 (plus:QI (match_operand:QI 1 "register_operand" "")
2105 (match_operand:QI 2 "general_operand" "")))]
2106 "0 && z_replacement_completed == 2"
2108 (plus:QI (match_dup 1) (match_dup 2)))]
2111 (define_split /* "*addhi3_strict_low_part" */
2112 [(set (match_operand:HI 0 "register_operand" "=dA")
2113 (plus:HI (match_operand:HI 1 "register_operand" "%0")
2114 (match_operand:HI 2 "general_operand" "")))
2115 (clobber (match_scratch:HI 3 ""))]
2116 "0 && z_replacement_completed == 2 && !SP_REG_P (operands[0])"
2118 (plus:HI (match_dup 1) (match_dup 2)))]
2121 (define_insn "*addhi3_68hc12"
2122 [(set (match_operand:HI 0 "register_operand" "=*d,A*w,A*w,A")
2123 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw,0")
2124 (match_operand:HI 2 "general_operand" "imA*wu,id,id,!muA")))]
2129 const char* insn_code;
2131 if (which_alternative >= 3)
2133 if (A_REG_P (operands[2]))
2136 output_asm_insn (\"xgd%2\", operands);
2137 output_asm_insn (\"lea%0 d,%0\", operands);
2143 if (D_REG_P (operands[0]))
2145 if (X_REG_P (operands[2]))
2147 m68hc11_notice_keep_cc (operands[0]);
2148 output_asm_insn (\"xgdx\", operands);
2149 output_asm_insn (\"leax\\td,%2\", operands);
2152 else if (Y_REG_P (operands[2]))
2154 m68hc11_notice_keep_cc (operands[0]);
2155 output_asm_insn (\"xgdy\", operands);
2156 output_asm_insn (\"leay\\td,%2\", operands);
2159 else if (SP_REG_P (operands[2]))
2161 output_asm_insn (\"sts\\t%t0\", operands);
2162 return \"addd\\t%t0\";
2164 return \"addd\\t%2\";
2167 if (GET_CODE (operands[2]) == CONST_INT)
2168 val = INTVAL (operands[2]);
2172 if (val != -1 || val != 1 || !rtx_equal_p (operands[0], operands[1]))
2174 m68hc11_notice_keep_cc (operands[0]);
2175 switch (REGNO (operands[0]))
2178 return \"leax\\t%i2,%1\";
2181 return \"leay\\t%i2,%1\";
2183 case HARD_SP_REGNUM:
2184 return \"leas\\t%i2,%1\";
2187 fatal_insn (\"Invalid operands in the instruction\", insn);
2192 insn_code = X_REG_P (operands[0]) ? \"inx\"
2193 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2198 insn_code = X_REG_P (operands[0]) ? \"dex\"
2199 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2202 /* For X and Y increment, the flags are not complete. Only the Z flag
2203 is updated. For SP increment, flags are not changed. */
2204 if (SP_REG_P (operands[0]))
2206 cc_status = cc_prev_status;
2207 if (INTVAL (operands[2]) < 0)
2211 output_asm_insn (\"pshx\", operands);
2225 output_asm_insn (insn_code, operands);
2232 ;; Specific pattern to add to the stack pointer.
2233 ;; We also take care of the clobbering of the IY register.
2235 (define_insn "addhi_sp"
2236 [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2237 (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2238 (match_operand:HI 2 "general_operand" "P,im,u,im")))
2239 (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2245 if (GET_CODE (operands[2]) == CONST_INT
2246 && (val = INTVAL (operands[2])) != 0
2247 && (CONST_OK_FOR_LETTER_P (val, 'P')
2248 || (val > 0 && val <= 8)))
2250 if (optimize && Y_REG_P (operands[3])
2251 && dead_register_here (insn, gen_rtx (REG, HImode, HARD_X_REGNUM)))
2252 operands[3] = gen_rtx (REG, HImode, HARD_X_REGNUM);
2253 while (val > 1 || val < -1)
2257 if (!H_REG_P (operands[3]))
2260 output_asm_insn (\"pul%3\", operands);
2265 output_asm_insn (\"pshx\", operands);
2273 output_asm_insn (\"ins\", operands);
2278 output_asm_insn (\"des\", operands);
2282 cc_status = cc_prev_status;
2286 /* Need to transfer to SP to IY and then to D register.
2287 Register IY is lost, this is specified by the (clobber) statement. */
2288 output_asm_insn (\"ts%3\", operands);
2289 output_asm_insn (\"xgd%3\", operands);
2290 output_asm_insn (\"addd\\t%2\", operands);
2291 output_asm_insn (\"xgd%3\", operands);
2293 /* The status flags correspond to the addd. xgdy and tys do not
2294 modify the flags. */
2299 ;; Translate d = d + d into d = d << 1
2300 ;; We have to do this because adding a register to itself is not possible.
2301 ;; ??? It's not clear whether this is really necessary.
2304 [(set (match_operand:HI 0 "hard_reg_operand" "=dA")
2305 (plus:HI (match_dup 0)
2308 [(set (match_dup 0) (ashift:HI (match_dup 0) (const_int 1)))]
2311 (define_insn "*addhi3"
2312 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d*A")
2313 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0")
2314 (match_operand:HI 2 "general_operand" "N,i,I,mi*A*d,!u*d*w")))]
2318 const char* insn_code;
2322 if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2324 output_asm_insn (\"sts\\t%t0\", operands);
2325 output_asm_insn (\"addd\\t%t0\", operands);
2326 return \"addd\\t#1\";
2328 if (GET_CODE (operands[2]) != CONST_INT)
2330 /* Adding to an address register or with another/same register
2331 is not possible. This must be replaced. */
2332 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2335 return \"addd\\t%2\";
2337 val = INTVAL (operands[2]);
2338 if (!SP_REG_P (operands[0]))
2340 if (D_REG_P (operands[0]))
2342 if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2345 return \"adda\\t%h2\";
2349 return \"addd\\t%2\";
2352 else if (GET_CODE (operands[2]) != CONST_INT
2353 || INTVAL (operands[2]) < -4
2354 || INTVAL (operands[2]) > 4)
2359 insn_code = X_REG_P (operands[0]) ? \"inx\"
2360 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2365 insn_code = X_REG_P (operands[0]) ? \"dex\"
2366 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2369 /* For X and Y increment, the flags are not complete. Only the Z flag
2370 is updated. For SP increment, flags are not changed. */
2371 if (SP_REG_P (operands[0]))
2373 cc_status = cc_prev_status;
2374 if (INTVAL (operands[2]) < 0)
2378 output_asm_insn (\"pshx\", operands);
2382 else if (optimize && dead_register_here (insn, ix_reg))
2386 output_asm_insn (\"pulx\", operands);
2398 output_asm_insn (insn_code, operands);
2404 (define_insn "*addhi3_zext"
2405 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2406 (plus:HI (zero_extend:HI
2407 (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2408 (match_operand:HI 2 "hard_reg_operand" "0,0")))]
2413 if (A_REG_P (operands[0]))
2415 else if (A_REG_P (operands[1]))
2416 return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2418 return \"addb\\t%b1\\n\\tadca\\t#0\";
2422 ;; Translate d = d + d into d = << 1
2423 ;; We have to do this because adding a register to itself is not possible.
2424 ;; ??? It's not clear whether this is really necessary.
2427 [(set (match_operand:QI 0 "hard_reg_operand" "=dA")
2428 (plus:QI (match_dup 0)
2430 "0 && reload_completed"
2431 [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2434 (define_insn "addqi3"
2435 [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2436 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2437 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2441 if (GET_CODE (operands[2]) == CONST_INT)
2443 if (INTVAL (operands[2]) == 1)
2445 if (DA_REG_P (operands[0]))
2449 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2454 else if (A_REG_P (operands[0]))
2456 /* This applies on the 16-bit register. This should be ok since
2457 this is not a strict_low_part increment. */
2462 return \"inc\\t%b0\";
2465 else if (INTVAL (operands[2]) == -1)
2467 if (DA_REG_P (operands[0]))
2471 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2475 else if (A_REG_P (operands[0]))
2477 /* This applies on the 16-bit register. This should be ok since
2478 this is not a strict_low_part decrement. */
2483 return \"dec\\t%b0\";
2487 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2489 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2490 return \"addb\\t%b2\";
2492 return \"adda\\t%b2\";
2496 ;; add with carry is used for 32-bit add.
2498 (define_insn "*adcq"
2499 [(set (match_operand:QI 0 "register_operand" "=q")
2500 (plus:QI (plus:QI (reg:QI CC_REGNUM)
2501 (match_operand:QI 1 "register_operand" "%0"))
2502 (match_operand:QI 2 "general_operand" "ium")))]
2506 ;;--------------------------------------------------------------------
2507 ;;- Subtract instructions.
2508 ;;--------------------------------------------------------------------
2510 (define_expand "subdi3"
2511 [(set (match_operand:DI 0 "nonimmediate_operand" "")
2512 (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2513 (match_operand:DI 2 "general_operand" "")))]
2515 "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2519 ;; 32-bit Subtract (see addsi3)
2520 ;; Subtract with a constant are handled by addsi3.
2525 (define_expand "subsi3"
2526 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2527 (minus:SI (match_operand:SI 1 "register_operand" "")
2528 (match_operand:SI 2 "general_operand" "")))
2529 (clobber (match_scratch:HI 3 ""))])]
2533 (define_insn "*subsi3"
2534 [(set (match_operand:SI 0 "register_operand" "=D,D")
2535 (minus:SI (match_operand:SI 1 "general_operand" "0,!mui")
2536 (match_operand:SI 2 "general_operand" "!mui,!D")))
2537 (clobber (match_scratch:HI 3 "=X,X"))]
2541 (define_insn "*subsi3_zero_extendhi"
2542 [(set (match_operand:SI 0 "register_operand" "=D")
2543 (minus:SI (match_operand:SI 1 "register_operand" "0")
2544 (zero_extend:SI (match_operand:HI 2 "general_operand" "d!mui"))))
2545 (clobber (match_scratch:HI 3 "=X"))]
2551 ops[0] = gen_label_rtx ();
2552 output_asm_insn (\"subd\\t%2\", operands);
2553 output_asm_insn (\"bcc\\t%l0\", ops);
2554 output_asm_insn (\"dex\", ops);
2555 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2560 (define_insn "*subsi3_zero_extendqi"
2561 [(set (match_operand:SI 0 "register_operand" "=D")
2562 (minus:SI (match_operand:SI 1 "register_operand" "0")
2563 (zero_extend:SI (match_operand:QI 2 "general_operand" "!dmui"))))
2564 (clobber (match_scratch:HI 3 "=X"))]
2570 ops[0] = gen_label_rtx ();
2571 output_asm_insn (\"subb\\t%b2\", operands);
2572 output_asm_insn (\"sbca\\t#0\", operands);
2573 output_asm_insn (\"bcc\\t%l0\", ops);
2574 output_asm_insn (\"dex\", ops);
2575 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2581 ;; reg:HI 1 -> d reg:QI 6 -> B
2582 ;; reg:QI 7 -> ccr reg:QI 5 -> A
2584 (define_split /* "*subsi3" */
2585 [(set (match_operand:SI 0 "register_operand" "=D")
2586 (minus:SI (match_operand:SI 1 "register_operand" "0")
2587 (match_operand:SI 2 "general_operand" "mui")))
2588 (clobber (match_scratch:HI 3 "=X"))]
2589 "reload_completed && z_replacement_completed == 2
2590 && X_REG_P (operands[1])"
2591 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2592 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2593 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2594 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2595 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2596 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2597 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2598 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2599 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2600 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2601 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2603 (define_split /* "*subsi3" */
2604 [(set (match_operand:SI 0 "register_operand" "=D")
2605 (minus:SI (match_operand:SI 1 "general_operand" "mui")
2606 (match_operand:SI 2 "register_operand" "D")))
2607 (clobber (match_scratch:HI 3 "=X"))]
2608 "reload_completed && z_replacement_completed == 2
2609 && X_REG_P (operands[2])"
2610 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2611 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2612 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2613 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2614 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2615 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2616 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2617 (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2618 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2619 operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2620 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2621 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2624 ;; - 16-bit Subtract.
2626 (define_expand "subhi3"
2627 [(set (match_operand:HI 0 "register_operand" "=r")
2628 (minus:HI (match_operand:HI 1 "register_operand" "0")
2629 (match_operand:HI 2 "general_operand" "g")))]
2633 if (TARGET_M6811 && SP_REG_P (operands[0]))
2635 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2636 gen_rtx (SET, VOIDmode,
2638 gen_rtx (MINUS, HImode,
2639 operand1, operand2)),
2640 gen_rtx (CLOBBER, VOIDmode,
2641 gen_rtx (SCRATCH, HImode, 0)))));
2647 ;; Subtract from stack. This is better if we provide a pattern.
2649 (define_insn "*subhi3_sp"
2650 [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2651 (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2652 (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2653 (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2657 if (X_REG_P (operands[2]))
2659 operands[2] = m68hc11_soft_tmp_reg;
2660 output_asm_insn (\"stx\\t%2\", operands);
2662 else if (Y_REG_P (operands[2]))
2664 operands[2] = m68hc11_soft_tmp_reg;
2665 output_asm_insn (\"sty\\t%2\", operands);
2667 else if (D_REG_P (operands[2]))
2669 operands[2] = m68hc11_soft_tmp_reg;
2670 output_asm_insn (\"std\\t%2\", operands);
2673 if (D_REG_P (operands[3]))
2675 output_asm_insn (\"xgdx\", operands);
2676 output_asm_insn (\"tsx\", operands);
2677 output_asm_insn (\"xgdx\", operands);
2678 output_asm_insn (\"subd\\t%2\", operands);
2679 output_asm_insn (\"xgdx\", operands);
2681 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2682 modify the flags. */
2683 output_asm_insn (\"txs\", operands);
2687 /* Need to transfer to SP to X,Y and then to D register.
2688 Register X,Y is lost, this is specified by the (clobber) statement. */
2689 output_asm_insn (\"ts%3\", operands);
2690 output_asm_insn (\"xgd%3\", operands);
2691 output_asm_insn (\"subd\\t%2\", operands);
2692 output_asm_insn (\"xgd%3\", operands);
2694 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2695 modify the flags. */
2700 (define_insn "*subhi3"
2701 [(set (match_operand:HI 0 "register_operand" "=d,*A,d*A")
2702 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
2703 (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,!u")))]
2707 /* Adding to an address register or with another/same register
2708 is not possible. This must be replaced. */
2709 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2712 return \"subd\\t%2\";
2715 (define_insn "*subhi3_zext"
2716 [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2717 (minus:HI (match_operand:HI 1 "hard_reg_operand" "0,0")
2718 (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2723 if (A_REG_P (operands[2]))
2727 ops[0] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
2728 ops[1] = operands[2];
2729 m68hc11_gen_movqi (insn, ops);
2730 return \"subb\\t%T0\\n\\tsbca\\t#0\";
2732 return \"subb\\t%b2\\n\\tsbca\\t#0\";
2735 (define_insn "subqi3"
2736 [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2737 (minus:QI (match_operand:QI 1 "hard_reg_operand" "0,0")
2738 (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2742 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2744 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2745 return \"subb\\t%b2\";
2747 return \"suba\\t%b2\";
2751 ;; subtract with carry is used for 32-bit subtract.
2753 (define_insn "*subcq"
2754 [(set (match_operand:QI 0 "register_operand" "=q")
2755 (minus:QI (minus:QI (reg:QI CC_REGNUM)
2756 (match_operand:QI 1 "register_operand" "0"))
2757 (match_operand:QI 2 "general_operand" "ium")))]
2761 ;;--------------------------------------------------------------------
2762 ;;- Multiply instructions.
2763 ;;--------------------------------------------------------------------
2765 ;; 32 and 64-bit multiply are handled by the library
2768 (define_expand "mulsi3"
2769 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2770 (mult:SI (match_operand:SI 1 "general_operand" "")
2771 (match_operand:SI 2 "general_operand" "")))]
2773 "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2776 (define_expand "mulhi3"
2777 [(parallel [(set (match_operand:HI 0 "register_operand" "")
2778 (mult:HI (match_operand:HI 1 "register_operand" "")
2779 (match_operand:HI 2 "register_operand" "")))
2780 (clobber (match_scratch:HI 3 ""))])]
2784 (define_insn "mulhi3_m68hc11"
2785 [(set (match_operand:HI 0 "register_operand" "=d")
2786 (mult:HI (match_operand:HI 1 "register_operand" "%0")
2787 (match_operand:HI 2 "register_operand" "x")))
2788 (clobber (match_scratch:HI 3 "=X"))]
2793 /* D * X -> D (X and Y are preserved by this function call). */
2794 return \"jsr\\t___mulhi3\";
2797 (define_insn "mulhi3_m68hc12"
2798 [(set (match_operand:HI 0 "register_operand" "=d,d")
2799 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2800 (match_operand:HI 2 "register_operand" "y,x")))
2801 (clobber (match_scratch:HI 3 "=2,2"))]
2806 if (X_REG_P (operands[2]))
2807 return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2812 (define_insn "umulhisi3"
2813 [(set (match_operand:SI 0 "register_operand" "=D,D")
2814 (mult:SI (zero_extend:SI
2815 (match_operand:HI 1 "register_operand" "%d,d"))
2817 (match_operand:HI 2 "register_operand" "y,x"))))
2818 (clobber (match_scratch:HI 3 "=2,X"))]
2822 if (X_REG_P (operands [2]))
2823 output_asm_insn (\"exg\\tx,y\", operands);
2825 /* Can't use the carry after that; other flags are ok when testing
2826 the 32-bit result. */
2827 cc_status.flags |= CC_NO_OVERFLOW;
2828 return \"emul\\n\\texg\\tx,y\";
2831 (define_insn "mulhisi3"
2832 [(set (match_operand:SI 0 "register_operand" "=D,D")
2833 (mult:SI (sign_extend:SI
2834 (match_operand:HI 1 "register_operand" "%d,d"))
2836 (match_operand:HI 2 "register_operand" "y,x"))))
2837 (clobber (match_scratch:HI 3 "=2,X"))]
2841 if (X_REG_P (operands [2]))
2842 output_asm_insn (\"exg\\tx,y\", operands);
2844 /* Can't use the carry after that; other flags are ok when testing
2845 the 32-bit result. */
2846 cc_status.flags |= CC_NO_OVERFLOW;
2847 return \"emuls\\n\\texg\\tx,y\";
2850 (define_insn "umulqihi3"
2851 [(set (match_operand:HI 0 "register_operand" "=d")
2852 (mult:HI (zero_extend:HI
2853 (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2855 (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2859 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2861 output_asm_insn (\"tba\", operands);
2867 if (D_REG_P (operands[2]))
2869 rtx temp = operands[2];
2870 operands[2] = operands[1];
2874 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
2875 ops[1] = operands[2];
2876 m68hc11_gen_movqi (insn, ops);
2878 if (!D_REG_P (operands[1]))
2880 output_asm_insn (\"ldab\\t%b1\", operands);
2888 (define_insn "mulqi3"
2889 [(set (match_operand:QI 0 "register_operand" "=d")
2890 (mult:QI (match_operand:QI 1 "nonimmediate_operand" "dum")
2891 (match_operand:QI 2 "nonimmediate_operand" "dum")))]
2895 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2897 output_asm_insn (\"tba\", operands);
2901 if (D_REG_P (operands[2]))
2903 rtx temp = operands[2];
2904 operands[2] = operands[1];
2908 output_asm_insn (\"ldaa\\t%b2\", operands);
2910 if (!D_REG_P (operands[1]))
2912 output_asm_insn (\"ldab\\t%b1\", operands);
2920 (define_insn "mulqihi3"
2921 [(set (match_operand:HI 0 "register_operand" "=d,d")
2922 (mult:HI (sign_extend:HI
2923 (match_operand:QI 1 "register_operand" "%0,0"))
2925 (match_operand:QI 2 "nonimmediate_operand" "dm,*A"))))]
2931 /* Special case when multiplying the register with itself. */
2932 if (D_REG_P (operands[2]))
2934 output_asm_insn (\"tba\", operands);
2938 if (!H_REG_P (operands[2]))
2940 output_asm_insn (\"ldaa\\t%b2\", operands);
2946 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
2947 ops[1] = operands[2];
2948 m68hc11_gen_movqi (insn, ops);
2950 return \"jsr\\t___mulqi3\";
2953 ;;--------------------------------------------------------------------
2954 ;;- Divide instructions.
2955 ;;--------------------------------------------------------------------
2957 (define_insn "divmodhi4"
2958 [(set (match_operand:HI 0 "register_operand" "=d,d")
2959 (div:HI (match_operand:HI 1 "register_operand" "0,0")
2960 (match_operand:HI 2 "general_operand" "A,ium")))
2961 (set (match_operand:HI 3 "register_operand" "=&x,&x")
2962 (mod:HI (match_dup 1) (match_dup 2)))]
2966 if (!X_REG_P (operands[2]))
2968 if (Y_REG_P (operands[2]))
2970 output_asm_insn (\"sty\\t%t1\", operands);
2971 output_asm_insn (\"ldx\\t%t1\", operands);
2975 output_asm_insn (\"ldx\\t%2\", operands);
2980 /* Flags are ok after that. */
2981 return \"idivs\\n\\txgdx\";
2986 return \"bsr\\t__divmodhi4\";
2990 (define_insn "udivmodhi4"
2991 [(set (match_operand:HI 0 "register_operand" "=d,d")
2992 (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
2993 (match_operand:HI 2 "general_operand" "A,ium")))
2994 (set (match_operand:HI 3 "register_operand" "=x,x")
2995 (umod:HI (match_dup 1) (match_dup 2)))]
2999 if (!X_REG_P (operands[2]))
3001 if (Y_REG_P (operands[2]))
3003 output_asm_insn (\"sty\\t%t1\", operands);
3004 output_asm_insn (\"ldx\\t%t1\", operands);
3008 output_asm_insn (\"ldx\\t%2\", operands);
3012 /* Z V and C flags are set but N is unchanged.
3013 Since this is an unsigned divide, we can probably keep the flags
3014 and indicate this. */
3015 cc_status.flags |= CC_NOT_NEGATIVE;
3016 return \"idiv\\n\\txgdx\";
3019 ;;--------------------------------------------------------------------
3020 ;;- and instructions.
3021 ;;--------------------------------------------------------------------
3023 (define_insn "anddi3"
3024 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3025 (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3026 (match_operand:DI 2 "general_operand" "imu,imu")))
3027 (clobber (match_scratch:HI 3 "=d,d"))]
3031 (define_insn "andsi3"
3032 [(set (match_operand:SI 0 "register_operand" "=D")
3033 (and:SI (match_operand:SI 1 "register_operand" "%0")
3034 (match_operand:SI 2 "general_operand" "Dimu")))]
3038 (define_insn "andhi3"
3039 [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A")
3040 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
3041 (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))]
3045 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3048 if (GET_CODE (operands[2]) == CONST_INT)
3050 int val = INTVAL (operands[2]) & 0x0FFFF;
3051 char lowpart_zero = 0;
3052 char lowpart_unknown = 0;
3053 char highpart_zero = 0;
3054 char highpart_unknown = 0;
3058 cc_status = cc_prev_status;
3062 /* First, try to clear the low and high part.
3063 If that's possible, the second 'and' will give
3064 the good status flags and we can avoid a tsthi. */
3065 if ((val & 0x0FF) == 0)
3067 if (D_REG_P (operands[0]))
3068 output_asm_insn (\"clrb\", operands);
3070 output_asm_insn (\"clr\\t%b0\", operands);
3073 if ((val & 0x0FF00) == 0)
3075 if (D_REG_P (operands[0]))
3076 output_asm_insn (\"clra\", operands);
3078 output_asm_insn (\"clr\\t%h0\", operands);
3082 if ((val & 0x0FF) == 0x0FF)
3084 lowpart_unknown = 1;
3086 else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3090 ops[0] = operands[0];
3091 ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
3092 output_asm_insn (\"bclr\\t%b0, %1\", ops);
3094 else if ((val & 0x0FF) != 0)
3096 output_asm_insn (\"andb\\t%b2\", operands);
3099 if ((val & 0x0FF00) == 0x0FF00)
3101 highpart_unknown = 1;
3103 else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3107 ops[0] = operands[0];
3108 ops[1] = gen_rtx (CONST_INT, VOIDmode, ((~val) & 0x0FF00) >> 8);
3109 output_asm_insn (\"bclr\\t%h0, %1\", ops);
3111 else if ((val & 0x0FF00) != 0)
3113 output_asm_insn (\"anda\\t%h2\", operands);
3116 if (highpart_unknown || lowpart_unknown)
3118 else if (highpart_zero == 0 && lowpart_zero == 0)
3125 return \"andb\\t%b2\\n\\tanda\\t%h2\";
3128 (define_insn "andqi3"
3129 [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q")
3130 (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0")
3131 (match_operand:QI 2 "general_operand" "i,i,!um,?*A,!ium,?*A*d,!ium*A")))]
3135 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3138 if (GET_CODE (operands[2]) == CONST_INT)
3140 int val = INTVAL (operands[2]) & 0x0FF;
3144 cc_status = cc_prev_status;
3149 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3151 else if (DA_REG_P (operands[0]))
3154 return \"clr\\t%b0\";
3156 if (!H_REG_P (operands[0]))
3159 ops[0] = operands[0];
3160 ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
3161 output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3165 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3166 return \"andb\\t%b2\";
3167 else if (DA_REG_P (operands[0]))
3168 return \"anda\\t%b2\";
3170 fatal_insn (\"Invalid operand in the instruction\", insn);
3173 ;;--------------------------------------------------------------------
3174 ;;- Bit set or instructions.
3175 ;;--------------------------------------------------------------------
3177 (define_insn "iordi3"
3178 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3179 (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3180 (match_operand:DI 2 "general_operand" "imu,imu")))
3181 (clobber (match_scratch:HI 3 "=d,d"))]
3185 (define_insn "iorsi3"
3186 [(set (match_operand:SI 0 "register_operand" "=D")
3187 (ior:SI (match_operand:SI 1 "register_operand" "%0")
3188 (match_operand:SI 2 "general_operand" "Dimu")))]
3192 (define_insn "iorhi3"
3193 [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A")
3194 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
3195 (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))]
3199 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3202 if (GET_CODE (operands[2]) == CONST_INT)
3204 int val = INTVAL (operands[2]) & 0x0FFFF;
3208 cc_status = cc_prev_status;
3211 if ((val & 0x0FF) != 0)
3213 if (!H_REG_P (operands[0]))
3214 output_asm_insn (\"bset\\t%b0, %b2\", operands);
3216 output_asm_insn (\"orab\\t%b2\", operands);
3219 if ((val & 0x0FF00) != 0)
3221 if (!H_REG_P (operands[0]))
3222 output_asm_insn (\"bset\\t%h0, %h2\", operands);
3224 output_asm_insn (\"oraa\\t%h2\", operands);
3232 return \"orab\\t%b2\\n\\toraa\\t%h2\";
3235 (define_insn "iorqi3"
3236 [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q")
3237 (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0")
3238 (match_operand:QI 2 "general_operand" "i,i,!um,!*A,!ium,?*A*d,!ium*A")))]
3242 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3245 if (GET_CODE (operands[2]) == CONST_INT)
3247 int val = INTVAL (operands[2]) & 0x0FF;
3251 cc_status = cc_prev_status;
3254 if (!H_REG_P (operands[0]))
3256 return \"bset\\t%b0, %2\";
3259 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3260 return \"orab\\t%b2\";
3261 else if (DA_REG_P (operands[0]))
3262 return \"oraa\\t%b2\";
3264 fatal_insn (\"Invalid operand in the instruction\", insn);
3267 ;;--------------------------------------------------------------------
3268 ;;- xor instructions.
3269 ;;--------------------------------------------------------------------
3271 (define_insn "xordi3"
3272 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3273 (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3274 (match_operand:DI 2 "general_operand" "imu,imu")))
3275 (clobber (match_scratch:HI 3 "=d,d"))]
3279 (define_insn "xorsi3"
3280 [(set (match_operand:SI 0 "register_operand" "=D")
3281 (xor:SI (match_operand:SI 1 "register_operand" "%0")
3282 (match_operand:SI 2 "general_operand" "Dimu")))]
3286 (define_insn "xorhi3"
3287 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3288 (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
3289 (match_operand:HI 2 "general_operand" "im,!u*A,!ium*A")))]
3293 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3296 if (GET_CODE (operands[2]) == CONST_INT)
3298 int val = INTVAL (operands[2]) & 0x0FFFF;
3302 cc_status = cc_prev_status;
3305 if ((val & 0x0FF) != 0)
3307 output_asm_insn (\"eorb\\t%b2\", operands);
3309 else if ((val & 0x0FF) == 0x0FF)
3311 output_asm_insn (\"comb\", operands);
3314 if ((val & 0x0FF00) != 0)
3316 output_asm_insn (\"eora\\t%h2\", operands);
3318 else if ((val & 0x0FF00) == 0x0FF00)
3320 output_asm_insn (\"coma\", operands);
3328 return \"eorb\\t%b2\\n\\teora\\t%h2\";
3331 (define_insn "xorqi3"
3332 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3333 (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
3334 (match_operand:QI 2 "general_operand" "i,!um,!*A,!ium,?*A*d,!ium*A")))]
3338 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3341 if (GET_CODE (operands[2]) == CONST_INT)
3343 int val = INTVAL (operands[2]) & 0x0FF;
3347 cc_status = cc_prev_status;
3352 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3358 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3359 return \"eorb\\t%b2\";
3360 else if (DA_REG_P (operands[0]))
3361 return \"eora\\t%b2\";
3363 fatal_insn (\"Invalid operand in the instruction\", insn);
3366 ;;--------------------------------------------------------------------
3367 ;;- Bit set or instructions.
3368 ;;--------------------------------------------------------------------
3370 (define_insn "*logicalsi3_zexthi"
3371 [(set (match_operand:SI 0 "register_operand" "=D,D")
3372 (match_operator:SI 3 "m68hc11_logical_operator"
3374 (match_operand:HI 1 "general_operand" "imdA,!udimA"))
3375 (match_operand:SI 2 "general_operand" "Dimu,!Dimu")]))]
3379 (define_insn "*logicalsi3_zextqi"
3380 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3381 (match_operator:SI 3 "m68hc11_logical_operator"
3383 (match_operand:QI 1 "general_operand" "d,*A,imu"))
3384 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3389 [(set (match_operand:SI 0 "register_operand" "=D,D")
3390 (match_operator:SI 3 "m68hc11_logical_operator"
3392 (match_operand:QI 1 "general_operand" "dxy,imu"))
3393 (match_operand:SI 2 "general_operand" "imuD,imuD")]))]
3394 "z_replacement_completed == 2"
3395 [(set (reg:QI A_REGNUM) (match_dup 4))
3396 (set (reg:QI D_REGNUM) (match_dup 7))
3397 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3398 (set (reg:HI X_REGNUM) (match_dup 6))]
3399 "PUT_MODE (operands[3], QImode);
3400 if (X_REG_P (operands[2]))
3402 operands[5] = operands[1];
3403 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3404 operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM);
3405 operands[7] = gen_rtx (REG, QImode, HARD_D_REGNUM);
3406 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3410 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3411 operands[7] = operands[1];
3412 operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3413 operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3414 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3419 [(set (match_operand:SI 0 "register_operand" "=D,D")
3420 (match_operator:SI 3 "m68hc11_logical_operator"
3422 (match_operand:HI 1 "general_operand" "dA,imu"))
3423 (match_operand:SI 2 "general_operand" "imuD,imuD")]))]
3425 [(set (reg:HI D_REGNUM) (match_dup 4))
3426 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3427 (set (reg:HI X_REGNUM) (match_dup 6))]
3428 "PUT_MODE (operands[3], HImode);
3429 if (X_REG_P (operands[2]))
3431 operands[5] = operands[1];
3432 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3433 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3434 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3438 operands[4] = operands[1];
3439 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3440 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3444 (define_insn "*logicallhi3_zexthi_ashift8"
3445 [(set (match_operand:HI 0 "register_operand" "=d")
3446 (match_operator:HI 3 "m68hc11_logical_operator"
3448 (match_operand:QI 1 "general_operand" "imud"))
3450 (match_operand:HI 2 "general_operand" "dimu")
3455 (define_insn "*logicalhi3_zexthi"
3456 [(set (match_operand:HI 0 "register_operand" "=d,d")
3457 (match_operator:HI 3 "m68hc11_logical_operator"
3459 (match_operand:QI 1 "general_operand" "imd*A,?u"))
3460 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3465 [(set (match_operand:HI 0 "register_operand" "=d")
3466 (match_operator:HI 3 "m68hc11_logical_operator"
3468 (match_operand:QI 1 "general_operand" "imud"))
3469 (match_operand:HI 2 "general_operand" "dimu")]))]
3470 "z_replacement_completed == 2"
3471 [(set (reg:QI B_REGNUM) (match_dup 6))
3472 (set (reg:QI A_REGNUM) (match_dup 4))
3473 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3475 PUT_MODE (operands[3], QImode);
3476 if (D_REG_P (operands[2]))
3478 operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM);
3479 operands[5] = operands[1];
3480 operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3484 operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3485 operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3486 if (D_REG_P (operands[1]))
3487 operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3489 operands[6] = operands[1];
3494 [(set (match_operand:HI 0 "register_operand" "=d")
3495 (match_operator:HI 3 "m68hc11_logical_operator"
3497 (match_operand:QI 1 "general_operand" "imud"))
3499 (match_operand:HI 2 "general_operand" "dimu")
3501 "z_replacement_completed == 2"
3502 [(set (reg:QI A_REGNUM) (match_dup 4))
3503 (set (reg:QI B_REGNUM) (match_dup 5))]
3505 if (GET_CODE (operands[3]) == AND)
3507 emit_insn (gen_movhi (operands[0], const0_rtx));
3512 operands[5] = operands[1];
3513 if (D_REG_P (operands[2]))
3515 operands[4] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3519 operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3524 (define_insn "*logicalsi3_silshr16"
3525 [(set (match_operand:SI 0 "register_operand" "=D,D")
3526 (match_operator:SI 3 "m68hc11_logical_operator"
3528 (match_operand:SI 1 "general_operand" "uim,?D")
3530 (match_operand:SI 2 "general_operand" "uim,0")]))]
3535 [(set (match_operand:SI 0 "register_operand" "=D,D")
3536 (match_operator:SI 3 "m68hc11_logical_operator"
3538 (match_operand:SI 1 "general_operand" "uim,?D")
3540 (match_operand:SI 2 "general_operand" "uim,0")]))]
3542 [(set (reg:HI D_REGNUM) (match_dup 4))
3543 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3544 (set (reg:HI X_REGNUM) (match_dup 6))]
3545 "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3546 if (X_REG_P (operands[2]))
3548 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3549 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3553 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3554 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3556 PUT_MODE (operands[3], HImode);
3560 (define_insn "*logicalsi3_silshl16"
3561 [(set (match_operand:SI 0 "register_operand" "=D,D")
3562 (match_operator:SI 3 "m68hc11_logical_operator"
3564 (match_operand:SI 1 "general_operand" "uim,?D")
3566 (match_operand:SI 2 "general_operand" "0,0")]))]
3571 [(set (match_operand:SI 0 "register_operand" "=D,D")
3572 (match_operator:SI 3 "m68hc11_logical_operator"
3574 (match_operand:SI 1 "general_operand" "uim,?D")
3576 (match_operand:SI 2 "general_operand" "0,0")]))]
3577 "z_replacement_completed == 2"
3578 [(parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
3579 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
3580 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 4)]))
3581 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
3582 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
3583 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3584 PUT_MODE (operands[3], HImode);")
3587 ;;--------------------------------------------------------------------
3588 ;;- 64/32-bit Logical Operations. Patterns are defined so that GCC
3589 ;; can optimize correctly. These insns are split by the `final'
3590 ;; pass (# pattern). They are split to fall in the corresponding
3591 ;; 16-bit logical patterns.
3592 ;;--------------------------------------------------------------------
3594 ;; Split 64-bit logical operations (AND, OR, XOR).
3596 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=mu")
3597 (match_operator:DI 4 "m68hc11_logical_operator"
3598 [(match_operand:DI 1 "reg_or_some_mem_operand" "%imu")
3599 (match_operand:DI 2 "general_operand" "imu")]))
3600 (clobber (match_scratch:HI 3 "=d"))]
3603 "m68hc11_split_logical (SImode, GET_CODE (operands[4]), operands);
3606 ;; Split 32-bit logical operations (AND, OR, XOR).
3608 [(set (match_operand:SI 0 "register_operand" "=D")
3609 (match_operator:SI 3 "m68hc11_logical_operator"
3610 [(match_operand:SI 1 "register_operand" "%0")
3611 (match_operand:SI 2 "general_operand" "Dimu")]))]
3614 "m68hc11_split_logical (HImode, GET_CODE (operands[3]), operands);
3617 ;;--------------------------------------------------------------------
3618 ;; 16-bit Arithmetic and logical operations on X and Y:
3620 ;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3622 ;; Operations on X or Y registers are split here. Instructions are
3624 ;; - xgdx/xgdy instruction pattern,
3625 ;; - The same operation on register D,
3626 ;; - xgdx/xgdy instruction pattern.
3627 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3628 ;; We also handle the case were the address register is used in both source
3629 ;; operands, such as:
3631 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3633 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3637 [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
3638 (match_operator:HI 3 "m68hc11_arith_operator"
3639 [(match_operand:HI 1 "hard_addr_reg_operand" "0")
3640 (match_operand:HI 2 "general_operand" "dAuim")]))]
3641 "z_replacement_completed == 2
3642 /* If we are adding a small constant to X or Y, it's
3643 better to use one or several inx/iny instructions. */
3644 && !(GET_CODE (operands[3]) == PLUS
3646 && (immediate_operand (operands[2], HImode)
3647 || hard_reg_operand (operands[2], HImode)))
3648 || (GET_CODE (operands[2]) == CONST_INT
3649 && INTVAL (operands[2]) >= -4
3650 && INTVAL (operands[2]) <= 4)))"
3651 [(set (match_dup 4) (match_dup 5))
3652 (set (match_dup 8) (match_dup 7))
3653 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3654 (set (match_dup 0) (reg:HI D_REGNUM))])
3655 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3656 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3657 (set (match_dup 0) (reg:HI D_REGNUM))])]
3659 /* Save the operand2 in a temporary location and use it. */
3660 if ((H_REG_P (operands[2])
3661 || reg_mentioned_p (operands[0], operands[2]))
3662 && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3664 operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
3665 operands[6] = operands[4];
3666 if (!H_REG_P (operands[2]))
3668 operands[5] = operands[0];
3669 operands[7] = operands[2];
3670 operands[8] = operands[0];
3674 operands[5] = operands[2];
3675 operands[8] = operands[7] = operands[0];
3680 operands[4] = operands[5] = operands[0];
3681 operands[6] = operands[2];
3682 operands[8] = operands[7] = operands[0];
3687 [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
3688 (match_operator:HI 3 "m68hc11_arith_operator"
3689 [(match_operand:HI 1 "general_operand" "mu")
3690 (match_operand:HI 2 "general_operand" "dAuim")]))]
3691 "z_replacement_completed == 2
3692 /* If we are adding a small constant to X or Y, it's
3693 better to use one or several inx/iny instructions. */
3694 && !(GET_CODE (operands[3]) == PLUS
3696 && (immediate_operand (operands[2], HImode)
3697 || hard_reg_operand (operands[2], HImode)))
3698 || (GET_CODE (operands[2]) == CONST_INT
3699 && INTVAL (operands[2]) >= -4
3700 && INTVAL (operands[2]) <= 4)))"
3701 [(set (match_dup 0) (match_dup 1))
3702 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3703 (set (match_dup 0) (reg:HI D_REGNUM))])
3704 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
3705 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3706 (set (match_dup 0) (reg:HI D_REGNUM))])]
3711 ;; Next split handles the logical operations on D register with
3712 ;; another hard register for the second operand. For this, we
3713 ;; have to save the second operand in a scratch location and use
3714 ;; it instead. This must be supported because in some (rare) cases
3715 ;; the second operand can come in a hard register and the reload
3716 ;; pass doesn't know how to reload it in a memory location.
3718 ;; PLUS MINUS AND IOR XOR
3720 ;; The shift operators are special and must not appear here.
3723 [(set (match_operand:HI 0 "d_register_operand" "=d")
3724 (match_operator:HI 3 "m68hc11_non_shift_operator"
3725 [(match_operand:HI 1 "d_register_operand" "%0")
3726 (match_operand:HI 2 "hard_reg_operand" "*d*A")]))]
3727 "z_replacement_completed == 2 && !SP_REG_P (operands[2])"
3728 [(set (match_dup 4) (match_dup 2))
3729 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
3730 "operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);")
3732 ;;--------------------------------------------------------------------
3733 ;; 16-bit Unary operations on X and Y:
3737 ;; Operations on X or Y registers are split here. Instructions are
3739 ;; - xgdx/xgdy instruction pattern,
3740 ;; - The same operation on register D,
3741 ;; - xgdx/xgdy instruction pattern.
3742 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3743 ;; We also handle the case were the address register is used in both source
3744 ;; operands, such as:
3746 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3748 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3751 [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A")
3752 (match_operator:HI 2 "m68hc11_unary_operator"
3753 [(match_operand 1 "general_operand" "uim*d*A")]))]
3754 "z_replacement_completed == 2"
3755 [(set (match_dup 4) (match_dup 5))
3756 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3757 (set (match_dup 0) (reg:HI D_REGNUM))])
3758 (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
3759 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3760 (set (match_dup 0) (reg:HI D_REGNUM))])]
3763 if ((H_REG_P (operands[1])
3764 && !rtx_equal_p (operands[0], operands[1]))
3765 || reg_mentioned_p (operands[0], operands[1]))
3767 /* Move to the destination register, before the xgdx. */
3768 operands[4] = gen_rtx (REG, GET_MODE (operands[1]),
3769 REGNO (operands[0]));
3770 operands[5] = operands[1];
3772 /* Apply the operation on D. */
3773 operands[3] = gen_rtx (REG, GET_MODE (operands[1]), HARD_D_REGNUM);
3777 /* Generate a copy to same register (nop). */
3778 operands[4] = operands[5] = operands[0];
3779 operands[3] = operands[1];
3784 ;; 8-bit operations on address registers.
3786 ;; We have to take care that the address register is not used for the
3787 ;; source of operand2. If operand2 is the D register, we have to save
3788 ;; that register in a temporary location.
3790 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3793 [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy")
3794 (match_operator:QI 3 "m68hc11_arith_operator"
3795 [(match_operand:QI 1 "hard_addr_reg_operand" "%0")
3796 (match_operand:QI 2 "general_operand" "dxyuim")]))]
3797 "z_replacement_completed == 2
3798 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
3799 incqi pattern generates a better code. */
3800 && !(GET_CODE (operands[3]) == PLUS
3801 && GET_CODE (operands[2]) == CONST_INT
3802 && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
3803 [(set (match_dup 5) (match_dup 6))
3804 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
3805 (set (match_dup 4) (reg:HI D_REGNUM))])
3806 (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
3807 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
3808 (set (match_dup 4) (reg:HI D_REGNUM))])]
3809 "operands[4] = gen_rtx (REG, HImode, REGNO (operands[0]));
3811 /* For the second operand is a hard register or if the address
3812 register appears in the source, we have to save the operand[2]
3813 value in a temporary location and then use that temp.
3814 Otherwise, it's ok and we generate a (set (D) (D)) that
3815 will result in a nop. */
3816 if (H_REG_P (operands[2]))
3818 operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
3819 operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));
3820 operands[7] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
3822 else if (reg_mentioned_p (operands[0], operands[2]))
3824 operands[5] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
3825 operands[6] = operands[2];
3826 operands[7] = operands[5];
3830 operands[5] = operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM);
3831 operands[7] = operands[2];
3836 ;; Next split handles the logical operations on D register with
3837 ;; another hard register for the second operand. For this, we
3838 ;; have to save the second operand in a scratch location and use
3839 ;; it instead. This must be supported because in some (rare) cases
3840 ;; the second operand can come in a hard register and the reload
3841 ;; pass doesn't know how to reload it in a memory location.
3843 ;; PLUS MINUS AND IOR XOR
3845 ;; The shift operators are special and must not appear here.
3848 [(set (match_operand:QI 0 "d_register_operand" "=d")
3849 (match_operator:QI 3 "m68hc11_non_shift_operator"
3850 [(match_operand:QI 1 "d_register_operand" "%0")
3851 (match_operand:QI 2 "hard_reg_operand" "*d*x*y")]))]
3853 [(set (match_dup 5) (match_dup 6))
3854 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
3855 "operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
3856 operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
3857 operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));")
3859 ;;--------------------------------------------------------------------
3860 ;; 8-bit Unary operations on X and Y:
3864 ;; Operations on X or Y registers are split here. Instructions are
3866 ;; - xgdx/xgdy instruction pattern,
3867 ;; - The same operation on register D,
3868 ;; - xgdx/xgdy instruction pattern.
3869 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3870 ;; We also handle the case were the address register is used in both source
3871 ;; operands, such as:
3873 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3875 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3878 [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy")
3879 (match_operator:QI 2 "m68hc11_unary_operator"
3880 [(match_operand:QI 1 "general_operand" "uim*d*x*y")]))]
3881 "z_replacement_completed == 2"
3882 [(set (match_dup 4) (match_dup 5))
3883 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
3884 (set (match_dup 3) (reg:HI D_REGNUM))])
3885 (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
3886 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
3887 (set (match_dup 3) (reg:HI D_REGNUM))])]
3890 operands[3] = gen_rtx (REG, HImode, REGNO (operands[0]));
3891 if ((H_REG_P (operands[1])
3892 && !rtx_equal_p (operands[0], operands[1]))
3893 || reg_mentioned_p (operands[0], operands[1]))
3895 /* Move to the destination register, before the xgdx. */
3896 operands[4] = operands[0];
3897 operands[5] = operands[1];
3899 /* Apply the operation on D. */
3900 operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM);
3904 operands[4] = operands[5] = operands[0];
3905 operands[6] = operands[1];
3910 ;;--------------------------------------------------------------------
3912 ;;--------------------------------------------------------------------
3914 (define_expand "negdi2"
3915 [(set (match_operand:DI 0 "nonimmediate_operand" "")
3916 (neg:DI (match_operand:DI 1 "general_operand" "")))]
3918 "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
3922 (define_insn "negsi2"
3923 [(set (match_operand:SI 0 "register_operand" "=D")
3924 (neg:SI (match_operand:SI 1 "register_operand" "0")))]
3930 /* With -Os or without -O, use a special library call. */
3931 if (optimize_size || optimize == 0)
3932 return \"bsr\\t___negsi2\";
3934 /* 32-bit complement and add 1. The comb/coma set the carry and they
3935 are smaller (use it for low-part). The eorb/eora leave the carry
3936 unchanged but are bigger (use it for high-part). */
3937 output_asm_insn (\"comb\\n\\tcoma\\n\\taddd\\t#1\\n\\txgdx\", operands);
3938 output_asm_insn (\"eorb\\t#0xFF\\n\\teora\\t#0xFF\", operands);
3939 return \"adcb\\t#0\\n\\tadca\\t#0\\n\\txgdx\";
3942 (define_insn "neghi2"
3943 [(set (match_operand:HI 0 "register_operand" "=d,d,*A")
3944 (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
3947 coma\\n\\tcomb\\n\\taddd\\t#1
3948 clra\\n\\tclrb\\n\\tsubd\\t%1
3949 xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
3951 (define_insn "negqi2"
3952 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
3953 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
3962 ;; - 32-bit complement. GCC knows how to translate them but providing a
3963 ;; pattern generates better/smaller code.
3965 (define_expand "one_cmpldi2"
3966 [(set (match_operand:DI 0 "nonimmediate_operand" "")
3967 (not:DI (match_operand:DI 1 "general_operand" "")))]
3969 "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
3972 (define_insn "one_cmplsi2"
3973 [(set (match_operand:SI 0 "non_push_operand" "=D")
3974 (not:SI (match_operand:SI 1 "general_operand" "0")))]
3976 "bsr\\t___one_cmplsi2")
3978 (define_insn "one_cmplhi2"
3979 [(set (match_operand:HI 0 "non_push_operand" "=d,m,!u,*A")
3980 (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
3984 com\\t%b0\\n\\tcom\\t%h0
3985 com\\t%b0\\n\\tcom\\t%h0
3988 (define_insn "one_cmplqi2"
3989 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,!*A")
3990 (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
3998 (define_split /* "*one_cmplsi2" */
3999 [(set (match_operand:SI 0 "non_push_operand" "=Dum")
4000 (not:SI (match_operand:SI 1 "non_push_operand" "0")))]
4001 "z_replacement_completed == 2
4002 && (!D_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4003 [(set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM)))
4004 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
4005 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
4006 (set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM)))
4007 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
4008 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
4011 /* The result pattern only works for D register.
4012 Generate 2 one_cmplhi2 instructions. */
4013 if (!D_REG_P (operands[0]))
4017 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4018 ops[1] = m68hc11_gen_highpart (HImode, operands[0]);
4019 emit_insn (gen_one_cmplhi2 (ops[0], ops[0]));
4020 emit_insn (gen_one_cmplhi2 (ops[1], ops[1]));
4025 ;;--------------------------------------------------------------------
4026 ;;- arithmetic shifts
4027 ;;--------------------------------------------------------------------
4029 ;; Provide some 64-bit shift patterns.
4030 (define_expand "ashldi3"
4031 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4032 (ashift:DI (match_operand:DI 1 "general_operand" "")
4033 (match_operand:HI 2 "general_operand" "")))
4034 (clobber (match_scratch:HI 3 ""))])]
4038 if (GET_CODE (operands[2]) != CONST_INT
4039 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4045 (define_insn "*ashldi3_const32"
4046 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4047 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4049 (clobber (match_scratch:HI 2 "=&A,d,d"))]
4054 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,um")
4055 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi")
4057 (clobber (match_scratch:HI 2 "=&A,d"))]
4060 "/* Move the lowpart in the highpart first in case the shift
4061 is applied on the source. */
4062 if (IS_STACK_PUSH (operands[0]))
4064 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4065 const0_rtx, operands[2]);
4067 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4068 m68hc11_gen_lowpart (SImode, operands[1]),
4070 if (!IS_STACK_PUSH (operands[0]))
4072 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4073 const0_rtx, operands[2]);
4077 (define_insn "*ashldi3_const1"
4078 [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4079 (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4081 (clobber (match_scratch:HI 2 "=d,d,d"))]
4086 [(set (match_operand:DI 0 "non_push_operand" "=um")
4087 (ashift:DI (match_operand:DI 1 "general_operand" "umi")
4089 (clobber (match_scratch:HI 2 "=d"))]
4090 "z_replacement_completed == 2"
4091 [(set (match_dup 2) (match_dup 3))
4092 (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4093 (set (match_dup 4) (match_dup 2))
4095 (set (match_dup 2) (match_dup 5))
4096 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
4097 (set (match_dup 6) (match_dup 2))
4099 (set (match_dup 2) (match_dup 7))
4100 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
4101 (set (match_dup 8) (match_dup 2))
4103 (set (match_dup 2) (match_dup 9))
4104 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
4105 (set (match_dup 10) (match_dup 2))]
4106 "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4107 operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4108 operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4110 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4111 operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4112 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4114 operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4115 operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4116 operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4118 operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4119 operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4120 operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4122 (define_insn "addsi_silshr16"
4123 [(set (match_operand:SI 0 "register_operand" "=D")
4124 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim")
4126 (match_operand:SI 2 "general_operand" "0")))]
4131 [(set (match_operand:SI 0 "register_operand" "=D")
4132 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim")
4134 (match_operand:SI 2 "general_operand" "0")))]
4135 "z_replacement_completed == 2"
4136 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4137 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4138 "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4140 (define_insn "addsi_ashift16"
4141 [(set (match_operand:SI 0 "register_operand" "=D")
4143 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4145 (match_operand:SI 1 "general_operand" "0")))
4146 (clobber (match_scratch:HI 3 "=X"))]
4151 [(set (match_operand:SI 0 "register_operand" "=D")
4153 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4155 (match_operand:SI 1 "general_operand" "0")))
4156 (clobber (match_scratch:HI 3 "=X"))]
4157 "0 && reload_completed && z_replacement_completed == 2"
4158 [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4161 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4164 (define_insn "addsi_andshr16"
4165 [(set (match_operand:SI 0 "register_operand" "=D")
4166 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4168 (match_operand:SI 2 "general_operand" "0")))]
4173 [(set (match_operand:SI 0 "register_operand" "=D")
4174 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4176 (match_operand:SI 2 "general_operand" "0")))]
4177 "z_replacement_completed == 2"
4178 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4179 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4180 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4183 ;; 32-bit shifts are made by a small library routine that uses
4184 ;; a specific passing convention for parameters (for efficiency reasons).
4186 ;; [D + X] -> Value to be shifted
4189 ;; The shift count is clobbered by the routine.
4191 (define_expand "ashlsi3"
4193 [(set (match_operand:SI 0 "register_operand" "")
4194 (match_operand:SI 1 "general_operand" ""))
4195 (clobber (scratch:HI))])
4197 [(set (match_dup 0) (ashift:SI (match_dup 0)
4198 (match_operand:HI 2 "nonmemory_operand" "")))
4199 (clobber (scratch:HI))])]
4204 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,um")
4205 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D")
4207 (clobber (match_scratch:HI 3 "=X,X"))]
4209 [(set (match_dup 2) (match_dup 3))
4210 (set (match_dup 4) (const_int 0))]
4211 "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4212 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4213 operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4215 (define_insn "*ashlsi3_const16"
4216 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4217 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4219 (clobber (match_scratch:HI 2 "=X,X,X"))]
4223 (define_insn "*ashlsi3_const16_zexthi"
4224 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4225 (ashift:SI (zero_extend:HI
4226 (match_operand:HI 1 "general_operand" "duim*A"))
4228 (clobber (match_scratch:HI 2 "=X"))]
4232 (define_split /* "*ashlsi3_const16_zexthi"*/
4233 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4234 (ashift:SI (zero_extend:HI
4235 (match_operand:HI 1 "general_operand" "duim*a"))
4237 (clobber (match_scratch:HI 2 "=X"))]
4239 [(set (reg:HI X_REGNUM) (match_dup 1))
4240 (set (reg:HI D_REGNUM) (const_int 0))]
4243 (define_insn "*ashlsi3_const1"
4244 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,!*u,?*um")
4245 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,*um,0,0,*um")
4247 (clobber (match_scratch:HI 2 "=X,X,&d,&d,&d"))]
4252 if (X_REG_P (operands[1]))
4254 return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4260 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4261 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
4262 m68hc11_gen_movhi (insn, ops);
4263 output_asm_insn (\"lsld\", ops);
4264 if (!X_REG_P (operands[0]))
4267 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4268 m68hc11_gen_movhi (insn, ops);
4270 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4271 m68hc11_gen_movhi (insn, ops);
4275 /* Load the high part in X in case the source operand
4276 uses X as a memory pointer. */
4277 ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM);
4278 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4279 m68hc11_gen_movhi (insn, ops);
4280 output_asm_insn (\"xgdx\", ops);
4282 output_asm_insn (\"rolb\", ops);
4283 output_asm_insn (\"rola\", ops);
4284 if (!X_REG_P (operands[0]))
4287 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4288 m68hc11_gen_movhi (insn, ops);
4292 output_asm_insn (\"xgdx\", ops);
4298 (define_insn "*ashlsi3_const"
4299 [(set (match_operand:SI 0 "register_operand" "+D")
4300 (ashift:SI (match_dup 0)
4301 (match_operand:HI 1 "const_int_operand" "")))
4302 (clobber (match_scratch:HI 2 "=y"))]
4307 return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4310 (define_insn "*ashlsi3"
4311 [(set (match_operand:SI 0 "register_operand" "+D,D")
4312 (ashift:SI (match_dup 0)
4313 (match_operand:HI 1 "general_operand" "y,m")))
4314 (clobber (match_scratch:HI 2 "=1,X"))]
4320 /* There is a reload problem if we don't accept 'm' for the shift value.
4321 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4322 and this conflicts with all reloads. Since X, Y, Z are used there
4323 is not enough register in class A_REGS.
4325 Assuming that 'operands[1]' does not refer to the stack (which
4326 is true for 68hc11 only, we save temporary the value of Y. */
4327 if (!Y_REG_P (operands[2]))
4331 ops[0] = operands[1];
4332 output_asm_insn (\"pshy\", operands);
4333 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4335 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4337 output_asm_insn (\"ldy\\t%0\", ops);
4338 output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4341 return \"bsr\\t___ashlsi3\";
4344 (define_expand "ashlhi3"
4345 [(set (match_operand:HI 0 "register_operand" "")
4346 (ashift:HI (match_operand:HI 1 "register_operand" "")
4347 (match_operand:HI 2 "general_operand" "")))]
4351 if (GET_CODE (operands[2]) != CONST_INT)
4353 rtx scratch = gen_reg_rtx (HImode);
4354 emit_move_insn (scratch, operands[2]);
4355 emit_insn (gen_rtx (PARALLEL, VOIDmode,
4356 gen_rtvec (2, gen_rtx (SET, VOIDmode,
4358 gen_rtx_ASHIFT (HImode,
4359 operand1, scratch)),
4360 gen_rtx (CLOBBER, VOIDmode, scratch))));
4365 (define_insn "*ashlhi3_const1"
4366 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4367 (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4372 if (A_REG_P (operands[0]))
4375 if (D_REG_P (operands[0]))
4380 output_asm_insn (\"asl\\t%b0\", operands);
4381 output_asm_insn (\"rol\\t%h0\", operands);
4387 (define_insn "*ashlhi3_2"
4388 [(set (match_operand:HI 0 "register_operand" "=d")
4389 (ashift:HI (match_operand:HI 1 "register_operand" "0")
4390 (match_operand:HI 2 "register_operand" "+x")))
4391 (clobber (match_dup 2))]
4396 return \"bsr\\t___lshlhi3\";
4399 (define_insn "*ashlhi3"
4400 [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4401 (ashift:HI (match_dup 0)
4402 (match_operand:HI 1 "register_operand" "+x")))
4403 (clobber (match_dup 1))]
4408 return \"bsr\\t___lshlhi3\";
4411 (define_insn "*ashlhi3"
4412 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4413 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4414 (match_operand:HI 2 "const_int_operand" "")))]
4420 if (A_REG_P (operands[0]))
4423 i = INTVAL (operands[2]);
4427 output_asm_insn (\"tba\", operands);
4430 output_asm_insn (\"rora\", operands);
4431 output_asm_insn (\"anda\\t#0\", operands);
4432 output_asm_insn (\"rora\", operands);
4437 output_asm_insn (\"asla\", operands);
4442 for (i = 0; i < INTVAL (operands[2]) - 1; i++)
4444 output_asm_insn (\"asld\", operands);
4449 (define_expand "ashlqi3"
4450 [(set (match_operand:QI 0 "register_operand" "")
4451 (ashift:QI (match_operand:QI 1 "register_operand" "")
4452 (match_operand:QI 2 "general_operand" "")))]
4456 (define_insn "*ashlqi3_const1"
4457 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4458 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4468 (define_insn "*ashlqi3_const"
4469 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4470 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4471 (match_operand:QI 2 "const_int_operand" "")))]
4476 const char* insn_code;
4478 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4479 insn_code = \"aslb\";
4480 else if (DA_REG_P (operands[0]))
4481 insn_code = \"asla\";
4485 i = INTVAL (operands[2]);
4488 if (DA_REG_P (operands[0]))
4495 if (DA_REG_P (operands[0]))
4497 output_asm_insn (\"rora\", operands);
4498 output_asm_insn (\"ldaa\\t#0\", operands);
4503 output_asm_insn (\"rorb\", operands);
4504 output_asm_insn (\"ldab\\t#0\", operands);
4510 if (DA_REG_P (operands[0]))
4512 output_asm_insn (\"rora\", operands);
4513 output_asm_insn (\"rora\", operands);
4514 output_asm_insn (\"rora\", operands);
4515 return \"anda\\t#0xC0\";
4519 output_asm_insn (\"rorb\", operands);
4520 output_asm_insn (\"rorb\", operands);
4521 output_asm_insn (\"rorb\", operands);
4522 return \"andb\\t#0xC0\";
4527 output_asm_insn (insn_code, operands);
4532 (define_insn "*ashlqi3"
4533 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4534 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4535 (match_operand:QI 2 "nonimmediate_operand"
4536 "m*u*d*A,m*u*d*A,m*u")))]
4542 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4545 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
4546 ops[1] = operands[2];
4547 m68hc11_gen_movqi (insn, ops);
4550 return \"bsr\\t___lshlqi3\";
4553 (define_expand "ashrhi3"
4554 [(set (match_operand:HI 0 "register_operand" "")
4555 (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4556 (match_operand:HI 2 "general_operand" "")))]
4560 if (GET_CODE (operands[2]) != CONST_INT)
4562 rtx scratch = gen_reg_rtx (HImode);
4564 emit_move_insn (scratch, operands[2]);
4565 emit_insn (gen_rtx (PARALLEL, VOIDmode,
4566 gen_rtvec (2, gen_rtx (SET, VOIDmode,
4568 gen_rtx_ASHIFTRT (HImode,
4569 operand1, scratch)),
4570 gen_rtx (CLOBBER, VOIDmode, scratch))));
4575 (define_insn "*ashrhi3_const1"
4576 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4577 (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4582 if (A_REG_P (operands[0]))
4586 if (D_REG_P (operands[0]))
4588 return \"asra\\n\\trorb\";
4591 output_asm_insn (\"asr\\t%h0\", operands);
4592 output_asm_insn (\"ror\\t%b0\", operands);
4597 (define_insn "*ashrhi3_const"
4598 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4599 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4600 (match_operand:HI 2 "const_int_operand" "")))]
4605 int val = INTVAL (operands[2]);
4607 if (A_REG_P (operands[0]))
4612 ops[0] = gen_label_rtx ();
4614 output_asm_insn (\"clrb\", operands);
4615 output_asm_insn (\"rola\", operands);
4617 /* Clear A without clearing the carry flag. */
4618 output_asm_insn (\"tba\", operands);
4619 output_asm_insn (\"bcc\\t%l0\", ops);
4620 output_asm_insn (\"coma\", operands);
4621 output_asm_insn (\"comb\", operands);
4624 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4625 CODE_LABEL_NUMBER (ops[0]));
4630 ops[0] = gen_label_rtx ();
4632 output_asm_insn (\"tab\", operands);
4633 output_asm_insn (\"clra\", operands);
4634 output_asm_insn (\"tstb\", operands);
4635 output_asm_insn (\"bge\\t%l0\", ops);
4636 output_asm_insn (\"deca\", operands);
4638 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4639 CODE_LABEL_NUMBER (ops[0]));
4645 output_asm_insn (\"asrb\", operands);
4653 ops[0] = gen_label_rtx ();
4654 output_asm_insn (\"rolb\", operands);
4655 output_asm_insn (\"rola\", operands);
4656 output_asm_insn (\"tab\", operands);
4657 output_asm_insn (\"anda\\t#0\", operands);
4658 output_asm_insn (\"bcc\\t%l0\", ops);
4659 output_asm_insn (\"coma\", ops);
4661 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4662 CODE_LABEL_NUMBER (ops[0]));
4667 output_asm_insn (\"asra\", operands);
4668 output_asm_insn (\"rorb\", operands);
4676 (define_insn "*ashrhi3"
4677 [(set (match_operand:HI 0 "register_operand" "=d,x")
4678 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4679 (match_operand:HI 2 "register_operand" "+x,+d")))
4680 (clobber (match_dup 2))]
4685 if (D_REG_P (operands[2]))
4686 output_asm_insn (\"xgd%0\", operands);
4688 output_asm_insn (\"bsr\\t___ashrhi3\", operands);
4689 if (D_REG_P (operands[2]))
4690 output_asm_insn (\"xgd%0\", operands);
4695 (define_expand "ashrsi3"
4697 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
4698 (clobber (scratch:HI))])
4700 [(set (match_operand:SI 0 "register_operand" "")
4701 (ashiftrt:SI (match_dup 0)
4702 (match_operand:HI 2 "general_operand" "")))
4703 (clobber (scratch:HI))])]
4707 (define_insn "*ashrsi3_const"
4708 [(set (match_operand:SI 0 "register_operand" "+D")
4709 (ashiftrt:SI (match_dup 0)
4710 (match_operand:HI 1 "const_int_operand" "")))
4711 (clobber (match_scratch:HI 2 "=y"))]
4716 return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
4719 (define_insn "*ashrsi3"
4720 [(set (match_operand:SI 0 "register_operand" "+D,D")
4721 (ashiftrt:SI (match_dup 0)
4722 (match_operand:HI 1 "general_operand" "y,m")))
4723 (clobber (match_scratch:HI 2 "=1,X"))]
4728 /* There is a reload problem if we don't accept 'm' for the shift value.
4729 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4730 and this conflicts with all reloads. Since X, Y, Z are used there
4731 is not enough register in class A_REGS.
4733 Assuming that 'operands[1]' does not refer to the stack (which
4734 is true for 68hc11 only, we save temporary the value of Y. */
4735 if (!Y_REG_P (operands[2]))
4739 ops[0] = operands[1];
4740 output_asm_insn (\"pshy\", operands);
4741 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4743 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4745 output_asm_insn (\"ldy\\t%0\", ops);
4746 output_asm_insn (\"bsr\\t___ashrsi3\", operands);
4749 return \"bsr\\t___ashrsi3\";
4752 (define_expand "ashrqi3"
4753 [(set (match_operand:QI 0 "register_operand" "")
4754 (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
4755 (match_operand:QI 2 "general_operand" "")))]
4759 (define_insn "*ashrqi3_const1"
4760 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4761 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4771 (define_insn "*ashrqi3_const"
4772 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4773 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
4774 (match_operand:QI 2 "const_int_operand" "")))]
4779 const char* insn_code;
4781 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4782 insn_code = \"asrb\";
4783 else if (DA_REG_P (operands[0]))
4784 insn_code = \"asra\";
4788 i = INTVAL (operands[2]);
4793 output_asm_insn (insn_code, operands);
4798 (define_insn "*ashrqi3"
4799 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4800 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
4801 (match_operand:QI 2 "nonimmediate_operand"
4802 "m*u*d*A,m*u*d*A,m*u")))]
4808 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4811 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
4812 ops[1] = operands[2];
4813 m68hc11_gen_movqi (insn, ops);
4816 return \"bsr\\t___ashrqi3\";
4819 ;;--------------------------------------------------------------------
4820 ;; logical shift instructions
4821 ;;--------------------------------------------------------------------
4822 (define_expand "lshrdi3"
4823 [(parallel [(set (match_operand:DI 0 "general_operand" "")
4824 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
4825 (match_operand:HI 2 "general_operand" "")))
4826 (clobber (match_scratch:HI 3 ""))])]
4830 if (GET_CODE (operands[2]) != CONST_INT
4831 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
4832 && INTVAL (operands[2]) != 1))
4838 (define_insn "*lshrdi3_const32"
4839 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4840 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4842 (clobber (match_scratch:HI 2 "=&A,d,d"))]
4847 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,um")
4848 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
4850 (clobber (match_scratch:HI 2 "=&A,d"))]
4853 "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4854 m68hc11_gen_highpart (SImode, operands[1]),
4856 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4857 const0_rtx, operands[2]);
4860 (define_insn "*lshrdi3_const63"
4861 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
4862 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
4863 (match_operand:DI 2 "const_int_operand" "")))
4864 (clobber (match_scratch:HI 3 "=d,d"))]
4865 "INTVAL (operands[2]) >= 48"
4869 [(set (match_operand:DI 0 "nonimmediate_operand" "=um")
4870 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
4871 (match_operand:DI 2 "const_int_operand" "")))
4872 (clobber (match_scratch:HI 3 "=d"))]
4873 "z_replacement_completed && INTVAL (operands[2]) >= 56"
4874 [(set (reg:QI D_REGNUM) (match_dup 9))
4875 (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
4876 (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
4877 (set (match_dup 4) (reg:HI D_REGNUM))
4878 (set (reg:QI D_REGNUM) (const_int 0))
4879 (set (match_dup 5) (reg:HI D_REGNUM))
4880 (set (match_dup 6) (reg:HI D_REGNUM))
4881 (set (match_dup 7) (reg:HI D_REGNUM))]
4882 "operands[8] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 56);
4883 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4884 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
4885 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4887 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
4888 operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
4889 operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
4891 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
4892 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
4893 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
4896 [(set (match_operand:DI 0 "nonimmediate_operand" "=um")
4897 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
4898 (match_operand:DI 2 "const_int_operand" "")))
4899 (clobber (match_scratch:HI 3 "=d"))]
4900 "z_replacement_completed && INTVAL (operands[2]) >= 48
4901 && INTVAL (operands[2]) < 56"
4902 [(set (reg:HI D_REGNUM) (match_dup 9))
4903 (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
4904 (set (match_dup 4) (reg:HI D_REGNUM))
4905 (set (reg:HI D_REGNUM) (const_int 0))
4906 (set (match_dup 5) (reg:HI D_REGNUM))
4907 (set (match_dup 6) (reg:HI D_REGNUM))
4908 (set (match_dup 7) (reg:HI D_REGNUM))]
4909 "operands[8] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 48);
4910 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4911 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
4912 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4914 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
4915 operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
4916 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
4917 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
4918 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
4920 (define_insn "*lshrdi_const1"
4921 [(set (match_operand:DI 0 "non_push_operand" "=m,u")
4922 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
4924 (clobber (match_scratch:HI 2 "=d,d"))]
4929 [(set (match_operand:DI 0 "non_push_operand" "=um")
4930 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi")
4932 (clobber (match_scratch:HI 2 "=d"))]
4933 "z_replacement_completed == 2"
4934 [(set (match_dup 2) (match_dup 3))
4935 (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
4936 (set (match_dup 4) (match_dup 2))
4938 (set (match_dup 2) (match_dup 5))
4939 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
4940 (set (match_dup 6) (match_dup 2))
4942 (set (match_dup 2) (match_dup 7))
4943 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
4944 (set (match_dup 8) (match_dup 2))
4946 (set (match_dup 2) (match_dup 9))
4947 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
4948 (set (match_dup 10) (match_dup 2))]
4949 "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
4950 operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
4951 operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
4953 operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
4954 operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
4955 operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
4957 operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
4958 operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
4959 operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
4961 operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
4962 operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
4963 operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
4965 (define_expand "lshrsi3"
4967 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
4968 (clobber (scratch:HI))])
4970 [(set (match_operand:SI 0 "register_operand" "")
4971 (lshiftrt:SI (match_dup 0)
4972 (match_operand:HI 2 "general_operand" "")))
4973 (clobber (scratch:HI))])]
4978 [(set (match_operand:SI 0 "non_push_operand" "=D,um")
4979 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,D")
4981 (clobber (match_scratch:HI 3 "=X,X"))]
4982 "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
4983 [(set (match_dup 2) (match_dup 3))
4984 (set (match_dup 4) (const_int 0))]
4985 "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
4986 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4987 operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4989 (define_insn "*lshrsi3_const16"
4990 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
4991 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
4993 (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5001 (define_insn "*lshrsi3_const1"
5002 [(set (match_operand:SI 0 "non_push_operand" "=D,m,*u")
5003 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "D*um,*um,*um")
5005 (clobber (match_scratch:HI 2 "=X,&d,&d"))]
5010 if (X_REG_P (operands[1]))
5012 return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5018 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5019 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
5020 m68hc11_gen_movhi (insn, ops);
5021 output_asm_insn (\"lsrd\", ops);
5022 if (!X_REG_P (operands[0]))
5025 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5026 m68hc11_gen_movhi (insn, ops);
5028 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5029 m68hc11_gen_movhi (insn, ops);
5033 /* Load the lowpart in X in case the operands is some N,x. */
5034 ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM);
5035 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5036 m68hc11_gen_movhi (insn, ops);
5037 output_asm_insn (\"xgdx\", ops);
5039 output_asm_insn (\"rora\", ops);
5040 output_asm_insn (\"rorb\", ops);
5041 if (!X_REG_P (operands[0]))
5044 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5045 m68hc11_gen_movhi (insn, ops);
5051 (define_insn "*lshrsi3_const"
5052 [(set (match_operand:SI 0 "register_operand" "+D")
5053 (lshiftrt:SI (match_dup 0)
5054 (match_operand:HI 1 "const_int_operand" "")))
5055 (clobber (match_scratch:HI 2 "=y"))]
5060 return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5063 (define_insn "*lshrsi3"
5064 [(set (match_operand:SI 0 "register_operand" "+D,D")
5065 (lshiftrt:SI (match_dup 0)
5066 (match_operand:HI 1 "general_operand" "y,m")))
5067 (clobber (match_scratch:HI 2 "=1,X"))]
5072 /* There is a reload problem if we don't accept 'm' for the shift value.
5073 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5074 and this conflicts with all reloads. Since X, Y, Z are used there
5075 is not enough register in class A_REGS.
5077 Assuming that 'operands[1]' does not refer to the stack (which
5078 is true for 68hc11 only, we save temporary the value of Y. */
5079 if (!Y_REG_P (operands[2]))
5083 ops[0] = operands[1];
5084 output_asm_insn (\"pshy\", operands);
5085 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5087 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5089 output_asm_insn (\"ldy\\t%0\", ops);
5090 output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5093 return \"bsr\\t___lshrsi3\";
5096 (define_expand "lshrhi3"
5097 [(set (match_operand:HI 0 "register_operand" "")
5098 (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5099 (match_operand:HI 2 "general_operand" "")))]
5103 if (GET_CODE (operands[2]) != CONST_INT)
5105 rtx scratch = gen_reg_rtx (HImode);
5106 operand1 = force_reg (HImode, operand1);
5108 emit_move_insn (scratch, operands[2]);
5109 emit_insn (gen_rtx (PARALLEL, VOIDmode,
5110 gen_rtvec (2, gen_rtx (SET, VOIDmode,
5112 gen_rtx_LSHIFTRT (HImode,
5113 operand1, scratch)),
5114 gen_rtx (CLOBBER, VOIDmode, scratch))));
5119 (define_insn "lshrhi3_const1"
5120 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5121 (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5126 if (A_REG_P (operands[0]))
5129 if (D_REG_P (operands[0]))
5133 return \"lsr\\t%h0\\n\\tror\\t%b0\";
5136 (define_insn "lshrhi3_const"
5137 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5138 (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5139 (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5143 int val = INTVAL (operands[2]);
5145 if (A_REG_P (operands[0]))
5153 if (!H_REG_P (operands[1]))
5155 output_asm_insn (\"clra\", operands);
5156 output_asm_insn (\"ldab\\t%h1\", operands);
5158 else if (A_REG_P (operands[1]))
5160 output_asm_insn (\"st%1\\t%t0\", operands);
5161 output_asm_insn (\"ldab\\t%t0\", operands);
5162 output_asm_insn (\"clra\", operands);
5166 output_asm_insn (\"tab\", operands);
5167 output_asm_insn (\"clra\", operands);
5173 output_asm_insn (\"rolb\", operands);
5174 output_asm_insn (\"tab\", operands);
5175 output_asm_insn (\"rolb\", operands);
5179 output_asm_insn (\"rolb\", operands);
5180 output_asm_insn (\"rolb\", operands);
5181 output_asm_insn (\"rolb\", operands);
5182 output_asm_insn (\"andb\\t#3\", operands);
5189 output_asm_insn (\"lsrb\", operands);
5196 if (!D_REG_P (operands[1]))
5197 m68hc11_gen_movhi (insn, operands);
5201 output_asm_insn (\"rolb\", operands);
5202 output_asm_insn (\"tab\", operands);
5203 output_asm_insn (\"rolb\", operands);
5204 output_asm_insn (\"rola\", operands);
5205 output_asm_insn (\"rola\", operands);
5206 output_asm_insn (\"anda\\t#1\", operands);
5214 output_asm_insn (\"lsrd\", operands);
5220 (define_insn "*lshrhi3"
5221 [(set (match_operand:HI 0 "register_operand" "=d,x")
5222 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5223 (match_operand:HI 2 "register_operand" "+x,+d")))
5224 (clobber (match_dup 2))]
5229 if (D_REG_P (operands[2]))
5230 output_asm_insn (\"xgd%0\", operands);
5232 output_asm_insn (\"bsr\\t___lshrhi3\", operands);
5233 if (D_REG_P (operands[2]))
5234 output_asm_insn (\"xgd%0\", operands);
5239 (define_expand "lshrqi3"
5240 [(set (match_operand:QI 0 "register_operand" "")
5241 (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5242 (match_operand:QI 2 "general_operand" "")))]
5246 (define_insn "*lshrqi3_const1"
5247 [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5248 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5258 (define_insn "*lshrqi3_const"
5259 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5260 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5261 (match_operand:QI 2 "const_int_operand" "")))]
5266 const char* insn_code;
5268 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5269 insn_code = \"lsrb\";
5270 else if (DA_REG_P (operands[0]))
5271 insn_code = \"lsra\";
5275 i = INTVAL (operands[2]);
5278 if (DA_REG_P (operands[0]))
5285 if (DA_REG_P (operands[0]))
5287 output_asm_insn (\"rola\", operands);
5288 output_asm_insn (\"ldaa\\t#0\", operands);
5293 output_asm_insn (\"rolb\", operands);
5294 output_asm_insn (\"ldab\\t#0\", operands);
5300 if (DA_REG_P (operands[0]))
5302 output_asm_insn (\"rola\", operands);
5303 output_asm_insn (\"rola\", operands);
5304 output_asm_insn (\"rola\", operands);
5305 return \"anda\\t#3\";
5309 output_asm_insn (\"rolb\", operands);
5310 output_asm_insn (\"rolb\", operands);
5311 output_asm_insn (\"rolb\", operands);
5312 return \"andb\\t#3\";
5317 output_asm_insn (insn_code, operands);
5322 (define_insn "*lshrqi3"
5323 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5324 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5325 (match_operand:QI 2 "nonimmediate_operand"
5326 "m*u*d*A,m*u*d*A,m*u")))]
5332 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5336 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
5337 ops[1] = operands[2];
5338 m68hc11_gen_movqi (insn, ops);
5340 if (!optimize || optimize_size)
5342 return \"bsr\\t___lshrqi3\";
5345 ops[0] = gen_label_rtx ();
5346 ops[1] = gen_label_rtx ();
5347 output_asm_insn (\"ble\\t%l1\", ops);
5349 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
5350 CODE_LABEL_NUMBER (ops[0]));
5352 output_asm_insn (\"lsrb\", operands);
5353 output_asm_insn (\"deca\", operands);
5354 output_asm_insn (\"bne\\t%l0\", ops);
5356 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
5357 CODE_LABEL_NUMBER (ops[1]));
5361 (define_insn "*rotlqi3_with_carry"
5362 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5363 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5364 (reg:QI CC_REGNUM)))]
5368 if (DA_REG_P (operands[0]))
5374 (define_insn "*rotlhi3_with_carry"
5375 [(set (match_operand:HI 0 "register_operand" "=d")
5376 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5377 (reg:HI CC_REGNUM)))]
5382 return \"rolb\\n\\trola\";
5385 (define_insn "*rotrhi3_with_carry"
5386 [(set (match_operand:HI 0 "register_operand" "=d")
5387 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5388 (reg:HI CC_REGNUM)))]
5393 return \"rora\\n\\trorb\";
5396 (define_insn "rotlqi3"
5397 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5398 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5399 (match_operand:QI 2 "const_int_operand" "i,i")))]
5403 m68hc11_gen_rotate (ROTATE, insn, operands);
5407 (define_insn "rotlhi3"
5408 [(set (match_operand:HI 0 "register_operand" "=d")
5409 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5410 (match_operand:HI 2 "const_int_operand" "i")))]
5414 m68hc11_gen_rotate (ROTATE, insn, operands);
5418 (define_insn "rotrqi3"
5419 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5420 (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5421 (match_operand:QI 2 "const_int_operand" "i,i")))]
5425 m68hc11_gen_rotate (ROTATERT, insn, operands);
5429 (define_insn "rotrhi3"
5430 [(set (match_operand:HI 0 "register_operand" "=d")
5431 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5432 (match_operand:HI 2 "const_int_operand" "i")))]
5436 m68hc11_gen_rotate (ROTATERT, insn, operands);
5440 ;;--------------------------------------------------------------------
5441 ;;- Jumps and transfers
5442 ;;--------------------------------------------------------------------
5445 (label_ref (match_operand 0 "" "")))]
5449 (define_expand "beq"
5451 (if_then_else (eq (cc0)
5453 (label_ref (match_operand 0 "" ""))
5458 m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
5459 m68hc11_compare_op1,
5464 (define_expand "bne"
5466 (if_then_else (ne (cc0)
5468 (label_ref (match_operand 0 "" ""))
5473 m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
5474 m68hc11_compare_op1,
5479 (define_expand "bgt"
5481 (if_then_else (gt (cc0)
5483 (label_ref (match_operand 0 "" ""))
5488 m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
5489 m68hc11_compare_op1,
5494 (define_expand "bgtu"
5496 (if_then_else (gtu (cc0)
5498 (label_ref (match_operand 0 "" ""))
5503 m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
5504 m68hc11_compare_op1,
5509 (define_expand "blt"
5511 (if_then_else (lt (cc0)
5513 (label_ref (match_operand 0 "" ""))
5518 m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
5519 m68hc11_compare_op1,
5524 (define_expand "bltu"
5526 (if_then_else (ltu (cc0)
5528 (label_ref (match_operand 0 "" ""))
5533 m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
5534 m68hc11_compare_op1,
5539 (define_expand "bge"
5541 (if_then_else (ge (cc0)
5543 (label_ref (match_operand 0 "" ""))
5548 m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
5549 m68hc11_compare_op1,
5554 (define_expand "bgeu"
5556 (if_then_else (geu (cc0)
5558 (label_ref (match_operand 0 "" ""))
5563 m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
5564 m68hc11_compare_op1,
5569 (define_expand "ble"
5571 (if_then_else (le (cc0)
5573 (label_ref (match_operand 0 "" ""))
5578 m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
5579 m68hc11_compare_op1,
5584 (define_expand "bleu"
5586 (if_then_else (leu (cc0)
5588 (label_ref (match_operand 0 "" ""))
5593 m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
5594 m68hc11_compare_op1,
5600 ;; Test and branch instructions for 68HC12 for EQ and NE.
5601 ;; 'z' must not appear in the constraints because the z replacement
5602 ;; pass does not know how to restore the replacement register.
5604 (define_insn "*tbeq"
5606 (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
5608 (label_ref (match_operand 1 "" ""))
5613 /* If the flags are already set correctly, use 'bne/beq' which are
5614 smaller and a little bit faster. This happens quite often due
5615 to reloading of operands[0]. In that case, flags are set correctly
5616 due to the load instruction. */
5617 if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5618 return \"beq\\t%l1\";
5620 return \"tbeq\\t%0,%l1\";
5623 (define_insn "*tbne"
5625 (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
5627 (label_ref (match_operand 1 "" ""))
5632 if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5633 return \"bne\\t%l1\";
5635 return \"tbne\\t%0,%l1\";
5639 ;; Test and branch with 8-bit register. Register must be B (or A).
5641 (define_insn "*tbeq8"
5643 (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
5645 (label_ref (match_operand 1 "" ""))
5650 if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5651 return \"beq\\t%l1\";
5653 return \"tbeq\\tb,%l1\";
5656 (define_insn "*tbne8"
5658 (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
5660 (label_ref (match_operand 1 "" ""))
5665 if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5666 return \"bne\\t%l1\";
5668 return \"tbne\\tb,%l1\";
5673 (if_then_else (eq (cc0)
5675 (label_ref (match_operand 0 "" ""))
5682 (if_then_else (ne (cc0)
5684 (label_ref (match_operand 0 "" ""))
5691 (if_then_else (gt (cc0)
5693 (label_ref (match_operand 0 "" ""))
5698 (define_insn "*bgtu"
5700 (if_then_else (gtu (cc0)
5702 (label_ref (match_operand 0 "" ""))
5709 (if_then_else (lt (cc0)
5711 (label_ref (match_operand 0 "" ""))
5716 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5717 return \"bmi\\t%l0\";
5719 return \"blt\\t%l0\";
5722 (define_insn "*bltu"
5724 (if_then_else (ltu (cc0)
5726 (label_ref (match_operand 0 "" ""))
5733 (if_then_else (ge (cc0)
5735 (label_ref (match_operand 0 "" ""))
5740 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5741 return \"bpl\\t%l0\";
5743 return \"bge\\t%l0\";
5746 (define_insn "*bgeu"
5748 (if_then_else (geu (cc0)
5750 (label_ref (match_operand 0 "" ""))
5757 (if_then_else (le (cc0)
5759 (label_ref (match_operand 0 "" ""))
5764 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5765 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
5767 return \"ble\\t%l0\";
5770 (define_insn "*bleu"
5772 (if_then_else (leu (cc0)
5774 (label_ref (match_operand 0 "" ""))
5779 ;;--------------------------------------------------------------------
5780 ;;- Negative test and branch
5781 ;;--------------------------------------------------------------------
5784 (if_then_else (eq (cc0)
5787 (label_ref (match_operand 0 "" ""))))]
5793 (if_then_else (ne (cc0)
5796 (label_ref (match_operand 0 "" ""))))]
5802 (if_then_else (gt (cc0)
5805 (label_ref (match_operand 0 "" ""))))]
5809 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5810 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
5812 return \"ble\\t%l0\";
5817 (if_then_else (gtu (cc0)
5820 (label_ref (match_operand 0 "" ""))))]
5826 (if_then_else (lt (cc0)
5829 (label_ref (match_operand 0 "" ""))))]
5833 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5834 return \"bpl\\t%l0\";
5836 return \"bge\\t%l0\";
5841 (if_then_else (ltu (cc0)
5844 (label_ref (match_operand 0 "" ""))))]
5850 (if_then_else (ge (cc0)
5853 (label_ref (match_operand 0 "" ""))))]
5857 if (cc_prev_status.flags & CC_NO_OVERFLOW)
5858 return \"bmi\\t%l0\";
5860 return \"blt\\t%l0\";
5865 (if_then_else (geu (cc0)
5868 (label_ref (match_operand 0 "" ""))))]
5874 (if_then_else (le (cc0)
5877 (label_ref (match_operand 0 "" ""))))]
5883 (if_then_else (leu (cc0)
5886 (label_ref (match_operand 0 "" ""))))]
5890 ;;--------------------------------------------------------------------
5892 ;;--------------------------------------------------------------------
5894 ;;- Call a function that returns no value.
5896 [(call (match_operand:QI 0 "memory_operand" "m")
5897 (match_operand:SI 1 "general_operand" "g"))]
5898 ;; Operand 1 not really used on the m68hc11.
5902 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
5904 if (SYMBOL_REF_FLAG (XEXP (operands[0], 0)) == 1)
5907 return \"bsr\\t%0\";
5911 return \"jsr\\t%0\";
5915 (define_insn "call_value"
5916 [(set (match_operand 0 "" "=g")
5917 (call (match_operand:QI 1 "memory_operand" "m")
5918 (match_operand:SI 2 "general_operand" "g")))]
5922 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
5924 if (SYMBOL_REF_FLAG (XEXP (operands[1], 0)) == 1)
5927 return \"bsr\\t%1\";
5931 return \"jsr\\t%1\";
5935 ;; Call subroutine returning any type.
5937 (define_expand "untyped_call"
5938 [(parallel [(call (match_operand 0 "" "")
5940 (match_operand 1 "" "")
5941 (match_operand 2 "" "")])]
5947 emit_call_insn (gen_call (operands[0], const0_rtx));
5949 for (i = 0; i < XVECLEN (operands[2], 0); i++)
5951 rtx set = XVECEXP (operands[2], 0, i);
5952 emit_move_insn (SET_DEST (set), SET_SRC (set));
5955 /* The optimizer does not know that the call sets the function value
5956 registers we stored in the result block. We avoid problems by
5957 claiming that all hard registers are used and clobbered at this
5959 emit_insn (gen_blockage ());
5964 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
5965 ;; all of memory. This blocks insns from being moved across this point.
5967 (define_insn "blockage"
5968 [(unspec_volatile [(const_int 0)] 0)]
5977 (define_expand "prologue"
5986 (define_expand "epilogue"
5995 ;; Used for frameless functions which save no regs and allocate no locals.
5996 (define_expand "return"
5998 "reload_completed && m68hc11_total_frame_size () == 0"
6003 if (current_function_return_rtx)
6004 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6006 /* Emit use notes only when HAVE_return is true. */
6007 if (m68hc11_total_frame_size () != 0)
6010 if (ret_size && ret_size <= 2)
6012 emit_insn (gen_rtx (PARALLEL, VOIDmode,
6013 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6014 gen_rtx_USE (VOIDmode,
6015 gen_rtx_REG (HImode, 1)))));
6020 emit_insn (gen_rtx (PARALLEL, VOIDmode,
6021 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6022 gen_rtx_USE (VOIDmode,
6023 gen_rtx_REG (SImode, 0)))));
6028 (define_insn "*return_void"
6033 rtx next = next_active_insn (insn);
6036 && GET_CODE (next) == JUMP_INSN
6037 && GET_CODE (PATTERN (next)) == RETURN)
6039 if (current_function_interrupt || current_function_trap)
6044 (define_insn "*return_16bit"
6046 (use (reg:HI D_REGNUM))]
6047 "reload_completed && m68hc11_total_frame_size () == 0"
6050 rtx next = next_active_insn (insn);
6053 && GET_CODE (next) == JUMP_INSN
6054 && GET_CODE (PATTERN (next)) == RETURN)
6056 if (current_function_interrupt || current_function_trap)
6061 (define_insn "*return_32bit"
6064 "reload_completed && m68hc11_total_frame_size () == 0"
6067 rtx next = next_active_insn (insn);
6070 && GET_CODE (next) == JUMP_INSN
6071 && GET_CODE (PATTERN (next)) == RETURN)
6073 if (current_function_interrupt || current_function_trap)
6078 (define_insn "indirect_jump"
6079 [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6083 ;;--------------------------------------------------------------------
6085 ;;--------------------------------------------------------------------
6087 ;; Operand 0 is the address of the table element to use
6088 ;; operand 1 is the CODE_LABEL for the table
6089 ;;--------------------------------------------------------------------
6090 (define_expand "tablejump"
6091 [(parallel [(set (pc) (match_operand 0 "" ""))
6092 (use (label_ref (match_operand 1 "" "")))])]
6096 (define_insn "*jump_indirect"
6098 (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6099 (use (label_ref (match_operand 1 "" "")))])]
6103 ;;--------------------------------------------------------------------
6105 ;;--------------------------------------------------------------------
6108 ;; This peephole catches the address computations generated by the reload
6111 [(set (match_operand:HI 0 "hard_reg_operand" "xy")
6112 (match_operand:HI 1 "const_int_operand" ""))
6113 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6114 (set (match_dup 0) (reg:HI D_REGNUM))])
6115 (set (reg:HI D_REGNUM)
6116 (plus (reg:HI D_REGNUM)
6117 (match_operand:HI 2 "general_operand" "")))
6118 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6119 (set (match_dup 0) (reg:HI D_REGNUM))])]
6120 "(INTVAL (operands[1]) & 0x0FF) == 0"
6123 int value_loaded = 1;
6125 if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
6129 ops[0] = operands[0];
6130 ops[1] = operands[2];
6131 m68hc11_gen_movhi (insn, ops);
6132 output_asm_insn (\"xgd%0\", operands);
6134 else if (Y_REG_P (operands[0]))
6136 if (reg_mentioned_p (iy_reg, operands[2]))
6137 output_asm_insn (\"ldy\\t%2\", operands);
6140 output_asm_insn (\"xgdy\", operands);
6144 output_asm_insn (\"ldd\\t%2\", operands);
6147 if (value_loaded == 0)
6148 output_asm_insn (\"ldd\\t%2\", operands);
6149 if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
6150 output_asm_insn (\"inca\", operands);
6151 else if (INTVAL (operands[1]) & 0x0ff00 == 0xff00)
6152 output_asm_insn (\"deca\", operands);
6153 else if (INTVAL (operands[1]) != 0)
6154 output_asm_insn (\"adda\\t%h1\", operands);
6156 if (X_REG_P (operands[0]))
6158 else if (Y_REG_P (operands[0]))
6166 [(set (match_operand:HI 0 "hard_reg_operand" "h")
6167 (match_operand:HI 1 "non_push_operand" "g"))
6168 (set (match_operand:HI 2 "hard_reg_operand" "h")
6170 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
6171 && !S_REG_P (operands[2])"
6176 ops[0] = operands[2];
6177 ops[1] = operands[1];
6178 m68hc11_gen_movhi (insn, ops);
6184 [(set (match_operand:HI 0 "hard_reg_operand" "h")
6185 (match_operand:HI 1 "hard_reg_operand" "h"))
6186 (set (match_operand:HI 2 "non_push_operand" "g")
6188 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
6189 && !S_REG_P (operands[2])"
6194 ops[0] = operands[2];
6195 ops[1] = operands[1];
6196 m68hc11_gen_movhi (insn, ops);
6202 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
6203 ;; the set, so we don't need to emit anything. 'ins1' refers to the
6207 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
6208 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6209 (set (match_dup 0) (reg:HI D_REGNUM))])]
6210 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
6213 cc_status = cc_prev_status;
6218 ;; Same as above but due to some split, there may be a noop set
6221 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
6222 (set (match_dup 0) (match_dup 0))
6223 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6224 (set (match_dup 0) (reg:HI D_REGNUM))])]
6225 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
6228 cc_status = cc_prev_status;
6234 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
6235 ;; and we must, at least, setup X/Y with value of D.
6238 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
6239 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6240 (set (match_dup 0) (reg:HI D_REGNUM))])]
6246 ops[0] = operands[0];
6247 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6248 m68hc11_gen_movhi (insn, ops);
6254 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6255 ;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
6258 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6259 (set (match_dup 0) (reg:HI D_REGNUM))])
6260 (set (reg:HI D_REGNUM) (match_dup 0))]
6261 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
6264 cc_status = cc_prev_status;
6270 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6271 ;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
6274 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6275 (set (match_dup 0) (reg:HI D_REGNUM))])
6276 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
6277 "REGNO (operands[0]) == REGNO (operands[1])
6278 && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
6281 cc_status = cc_prev_status;
6287 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6288 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
6291 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6292 (set (match_dup 0) (reg:HI D_REGNUM))])
6293 (set (reg:HI D_REGNUM) (match_dup 0))]
6299 ops[0] = operands[0];
6300 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6301 m68hc11_gen_movhi (insn, ops);
6307 ;;; Same peephole with a QI set. The copy is made as 16-bit to comply
6311 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6312 (set (match_dup 0) (reg:HI D_REGNUM))])
6313 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
6314 "REGNO (operands[0]) == REGNO (operands[1])"
6319 ops[0] = operands[0];
6320 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6321 m68hc11_gen_movhi (insn, ops);
6327 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
6330 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6331 (set (match_dup 0) (reg:HI D_REGNUM))])
6332 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6333 (set (match_dup 0) (reg:HI D_REGNUM))])]
6337 cc_status = cc_prev_status;
6343 [(set (match_operand:HI 0 "hard_reg_operand" "")
6344 (match_operand:HI 1 "stack_register_operand" ""))
6345 (set (match_operand:HI 2 "hard_reg_operand" "")
6346 (match_operand:HI 3 "memory_operand" "m"))
6348 (match_operand:HI 4 "memory_operand" "m"))]
6349 "IS_STACK_POP (operands[4])
6350 && (GET_CODE (operands[3]) == MEM &&
6351 rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
6356 ops[0] = operands[2];
6357 ops[1] = gen_rtx (MEM, HImode,
6358 gen_rtx (POST_INC, HImode, stack_pointer_rtx));
6359 m68hc11_gen_movhi (insn, ops);
6365 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
6368 [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
6369 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
6373 return \"sts\\t%t0\\n\\tld%0\\t%t0\";