1 ;;- Machine description file for Motorola 68HC11 and 68HC12.
2 ;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
3 ;;- Free Software Foundation, Inc.
4 ;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
23 ;; A first 68HC11 port was made by Otto Lind (otto@coactive.com)
24 ;; on gcc 2.6.3. I have used it as a starting point for this port.
25 ;; However, this new port is a complete re-write. Its internal
26 ;; design is completely different. The generated code is not
27 ;; compatible with the gcc 2.6.3 port.
29 ;; The gcc 2.6.3 port is available at:
31 ;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
34 ;;- Instruction patterns. When multiple patterns apply,
35 ;;- the first one in the file is chosen.
37 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
39 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
40 ;;- updates for most instructions.
43 ;; The following constraints are used:
45 ;; Single pair registers:
46 ;; a register 'a' 8-bit
47 ;; b register 'b' 8-bit
48 ;; d register 'd' 16-bit
49 ;; t pseudo soft register 'TMP' 16-bit
50 ;; v register 'd' for 68hc11, 16-bit
52 ;; (used for scratch register)
53 ;; w register 'sp' 16-bit
54 ;; x register 'x' 16-bit
55 ;; y register 'y' 16-bit
56 ;; z register 'z' 16-bit (fake r for 68HC11 and 68HC12)
57 ;; D register 'd+x' 32-bit
59 ;; Group of registers:
60 ;; q register 'a' or 'b' or 'd' 8-bit
61 ;; u pseudo soft register 16-bit
62 ;; A register 'x', 'y', 'z' 16-bit
63 ;; B register 'x', 'y' 16-bit
64 ;; h register 'd', 'x', 'y', 'z' 16-bit
68 ;; Q an operand which is in memory but whose address is constant
69 ;; (i.e., a (MEM (SYMBOL_REF x))). This constraint is used by
70 ;; bset/bclr instructions together with linker relaxation. The
71 ;; operand can be translated to a page0 addressing mode if the
72 ;; symbol address is in page0 (0..255).
74 ;; R an operand which is in memory and whose address is expressed
75 ;; with 68HC11/68HC12 indexed addressing mode. In general this
76 ;; is any valid (MEM) except a (MEM (SYMBOL_REF x)).
78 ;; U an operand which is in memory and if it uses the 68HC12 indexed
79 ;; addressing mode, the offset is in the range -16..+15. This is
80 ;; used by 68HC12 movb/movw instructions since they do not accept
81 ;; the full 16-bit offset range (as other insn do).
84 ;; Immediate integer operand constraints:
85 ;; `L' is for range -65536 to 65536
86 ;; `M' is for values whose 16-bit low part is 0
87 ;; 'N' is for +1 or -1.
88 ;; 'O' is for 16 (for rotate using swap).
89 ;; 'P' is for range -8 to 2 (used by addhi_sp)
91 ;; In many cases, it's not possible to use the 'g' or 'r' constraints.
93 ;; Operands modifiers:
95 ;; %b Get the low part of the operand (to obtain a QImode)
96 ;; This modifier must always be used for QImode operations
97 ;; because a correction must be applied when the operand
98 ;; is a soft register (ex: *ZD1). Otherwise, we generate
99 ;; *ZD1 and this is the high part of the register. For other
100 ;; kinds of operands, if the operand is already QImode, no
101 ;; additional correction is made.
102 ;; %h Get the high part of the operand (to obtain a QImode)
103 ;; %t Represents the temporary/scratch register *_.tmp
104 ;; The scratch register is used in some cases when GCC puts
105 ;; some values in bad registers.
107 ;; 32/64-bit Patterns:
108 ;; The 68HC11 does not support 32/64-bit operations. Most of the
109 ;; 32/64-bit patterns are defined to split the instruction in
110 ;; 16-bits patterns. Providing split patterns generates better code
111 ;; than letting GCC implement the 32/64-bit operation itself.
116 ;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
117 ;; otherwise some insn are not satisfied.
119 ;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
120 ;; be valid only when z_replacement_completed == 2 because once these
121 ;; swap instructions are generated, a flow/cse pass fails to handle
122 ;; them correctly (it would treat the X, Y or D register as dead sometimes).
124 ;; o Some split pattern generate instructions that operate on 'a' or 'b'
125 ;; register directly (high part and low part of D respectively).
126 ;; Such split pattern must also be valid when z_replacement_completed == 2
127 ;; because flow/cse is not aware that D is composed of {a, b}.
129 ;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
130 ;; the high part of a soft register must be expanded after z_replacement
133 ;;---------------------------------------------------------------------------
138 (X_REGNUM 0) ; Index X register
139 (D_REGNUM 1) ; Data register
140 (Y_REGNUM 2) ; Index Y register
141 (SP_REGNUM 3) ; Stack pointer
142 (PC_REGNUM 4) ; Program counter
143 (A_REGNUM 5) ; A (high part of D)
144 (B_REGNUM 6) ; B (low part of D)
145 (CC_REGNUM 7) ; Condition code register
146 (SOFT_TMP_REGNUM 10) ; TMP soft register
147 (SOFT_Z_REGNUM 11) ; Z soft register
148 (SOFT_XY_REGNUM 12) ; XY soft register
151 (include "predicates.md")
153 ;;--------------------------------------------------------------------
155 ;;--------------------------------------------------------------------
157 ;; The test and compare insn must not accept a memory operand with
158 ;; an auto-inc mode. If we do this, the reload can emit move insns
159 ;; after the test or compare. Such move will set the flags and therefore
160 ;; break the comparison. This can happen if the auto-inc register
161 ;; does not happen to be a hard register (i.e., reloading occurs).
162 ;; An offsetable memory operand should be ok. The 'tst_operand' and
163 ;; 'cmp_operand' predicates take care of this rule.
166 (define_insn "tsthi_1"
168 (compare (match_operand:HI 0 "tst_operand" "dx,*y")
173 if (D_REG_P (operands[0]) && !TARGET_M6812)
174 return \"std\\t%t0\";
176 return \"cp%0\\t#0\";
180 ;; Split pattern for (tst:QI) on an address register.
184 (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
186 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
187 [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
188 (set (match_dup 1) (reg:HI D_REGNUM))])
189 (set (cc0) (compare (reg:QI D_REGNUM)
191 (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
192 (set (match_dup 1) (reg:HI D_REGNUM))])]
193 "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
195 (define_insn "tstqi_1"
197 (compare (match_operand:QI 0 "tst_operand" "m,d,*A,!u")
202 if (A_REG_P (operands[0]))
205 else if (D_REG_P (operands[0]))
208 else if (dead_register_here (insn, d_reg))
209 return \"ldab\\t%b0\";
212 return \"tst\\t%b0\";
216 ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
217 ;; during the Z register replacement. They are used when an operand
218 ;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
219 ;; In that case, we have to preserve the values of the replacement
220 ;; register (as well as the CC0 since the insns are compare insns).
221 ;; To do this, the replacement register is pushed on the stack and
222 ;; restored after the real compare. A pattern+split is defined to
223 ;; avoid problems with the flow+cse register pass which are made
224 ;; after Z register replacement.
226 (define_insn_and_split "tstqi_z_used"
227 [(set (cc0) (compare (match_operand:QI 0 "tst_operand" "m")
229 (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
230 (use (reg:HI SOFT_Z_REGNUM))]
233 "z_replacement_completed == 2"
234 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
235 (set (match_dup 1) (match_dup 2))
236 (set (cc0) (compare (match_dup 0)
238 (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
239 "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
242 ;;--------------------------------------------------------------------
244 ;;--------------------------------------------------------------------
247 ;; Comparison of a hard register with another one is provided because
248 ;; it helps GCC to avoid to spill a pseudo hard register.
249 ;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
250 ;; (except that we loose the information that the value is saved in it).
252 ;; The split pattern transforms the comparison into a save of one hard
253 ;; register and a comparison with the temporary.
257 (compare (match_operand:HI 0 "hard_reg_operand" "")
258 (match_operand:HI 1 "hard_reg_operand" "")))]
260 && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
261 [(set (match_dup 2) (match_dup 1))
263 (compare (match_dup 0) (match_dup 2)))]
264 "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
268 (compare (match_operand:HI 0 "hard_reg_operand" "")
269 (match_operand:HI 1 "hard_reg_operand" "")))]
271 && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
272 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
274 (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
277 (define_insn "cmphi_1_hc12"
279 (compare (match_operand:HI 0 "tst_operand"
280 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
281 (match_operand:HI 1 "general_operand"
282 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
286 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
288 cc_status.flags |= CC_REVERSED;
289 return \"cp%1\\t%0\";
291 else if (SP_REG_P (operands[1]))
292 return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
293 else if (H_REG_P (operands[1]))
294 return \"psh%1\n\\tcp%0\\t2,sp+\";
296 return \"cp%0\\t%1\";
299 (define_insn "cmphi_1_hc11"
301 (compare (match_operand:HI 0 "tst_operand"
302 "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
303 (match_operand:HI 1 "cmp_operand"
304 "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
308 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
310 cc_status.flags |= CC_REVERSED;
311 return \"cp%1\\t%0\";
313 else if (H_REG_P (operands[1]))
316 return \"cp%0\\t%1\";
319 (define_insn_and_split "cmphi_z_used"
321 (compare (match_operand:HI 0 "tst_operand" "dxy,m")
322 (match_operand:HI 1 "cmp_operand" "mi,dxy")))
323 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
324 (use (reg:HI SOFT_Z_REGNUM))]
327 "z_replacement_completed == 2"
328 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
329 (set (match_dup 2) (match_dup 3))
330 (set (cc0) (compare (match_dup 0) (match_dup 1)))
331 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
332 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
335 ;; 8-bit comparison with address register.
336 ;; There is no such comparison instruction, we have to temporarily switch
337 ;; the address register and the D register and do the comparison with D.
338 ;; The xgdx and xgdy instructions preserve the flags.
342 (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
343 (match_operand:QI 1 "cmp_operand" "")))]
344 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
345 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
346 (set (match_dup 3) (reg:HI D_REGNUM))])
348 (compare (reg:QI D_REGNUM) (match_dup 1)))
349 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
350 (set (match_dup 3) (reg:HI D_REGNUM))])]
351 "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
355 (compare (match_operand:QI 0 "hard_reg_operand" "")
356 (match_operand:QI 1 "hard_reg_operand" "")))]
358 [(set (match_dup 3) (match_dup 4))
360 (compare (match_dup 0) (match_dup 2)))]
361 "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
362 operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
363 operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
365 (define_insn "bitcmpqi"
367 (compare (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
368 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d"))
378 (define_split /* "bitcmpqi" */
380 (compare (and:QI (match_operand:QI 0 "tst_operand" "")
381 (match_operand:QI 1 "hard_addr_reg_operand" ""))
383 "z_replacement_completed == 2"
384 [(set (match_dup 3) (match_dup 2))
385 (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
386 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
387 operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
388 operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
390 (define_insn_and_split "bitcmpqi_z_used"
392 (compare (and:QI (match_operand:QI 0 "tst_operand" "d,m")
393 (match_operand:QI 1 "cmp_operand" "m,d"))
395 (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
396 (use (reg:HI SOFT_Z_REGNUM))]
399 "z_replacement_completed == 2"
400 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
401 (set (match_dup 2) (match_dup 3))
402 (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
403 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
404 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
406 (define_insn "bitcmphi"
408 (compare (and:HI (match_operand:HI 0 "tst_operand" "d")
409 (match_operand:HI 1 "const_int_operand" "i"))
411 "(INTVAL (operands[1]) & 0x0ff) == 0
412 || (INTVAL (operands[1]) & 0x0ff00) == 0"
415 if ((INTVAL (operands[1]) & 0x0ff) == 0)
416 return \"bita\\t%h1\";
418 return \"bitb\\t%1\";
421 (define_insn "bitcmpqi_12"
423 (compare (zero_extract:HI (match_operand:HI 0 "tst_operand" "d")
424 (match_operand:HI 1 "const_int_operand" "i")
425 (match_operand:HI 2 "const_int_operand" "i"))
427 "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
428 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
429 && (unsigned) INTVAL (operands[2]) >= 8)"
434 int startpos = INTVAL (operands[2]);
435 int bitsize = INTVAL (operands[1]);
440 mask = (1 << (startpos + bitsize)) - 1;
441 mask &= ~((1 << startpos) - 1);
443 ops[0] = GEN_INT (mask);
444 output_asm_insn (\"bita\\t%0\", ops);
448 mask = (1 << (startpos + bitsize)) - 1;
449 mask &= ~((1 << startpos) - 1);
451 ops[0] = GEN_INT (mask);
452 output_asm_insn (\"bitb\\t%0\", ops);
457 (define_insn "cmpqi_1"
459 (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
460 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
464 if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
468 else if (D_REG_P (operands[0]))
470 return \"cmpb\\t%b1\";
472 cc_status.flags |= CC_REVERSED;
473 return \"cmpb\\t%b0\";
476 (define_insn_and_split "cmpqi_z_used"
478 (compare (match_operand:QI 0 "tst_operand" "dxy,m")
479 (match_operand:QI 1 "cmp_operand" "m,dxy")))
480 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
481 (use (reg:HI SOFT_Z_REGNUM))]
484 "z_replacement_completed == 2"
485 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
486 (set (match_dup 2) (match_dup 3))
487 (set (cc0) (compare (match_dup 0) (match_dup 1)))
488 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
489 "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
491 ;;--------------------------------------------------------------------
492 ;;- Move strict_low_part
493 ;;--------------------------------------------------------------------
495 ;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
496 ;; The replacement must be made at the very end because we loose the
497 ;; (strict_low_part ...) information. This is correct for our machine
498 ;; description but not for GCC optimization passes.
500 (define_insn_and_split "movstrictsi"
501 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
502 (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
505 "z_replacement_completed == 2"
506 [(set (match_dup 0) (match_dup 1))]
509 (define_insn_and_split "movstricthi"
510 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
511 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
514 "z_replacement_completed == 2"
515 [(set (match_dup 0) (match_dup 1))]
518 (define_insn_and_split "movstrictqi"
519 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
520 (match_operand:QI 1 "general_operand" "d,imudA"))]
523 "z_replacement_completed == 2"
524 [(set (match_dup 0) (match_dup 1))]
527 ;;--------------------------------------------------------------------
528 ;;- 64-bit Move Operations.
529 ;; The movdi and movdf patterns are identical except for the mode.
530 ;; They are also very similar to those for movsi and movsf.
532 ;; For 68HC11, we need a scratch register (either D, X, Y)
533 ;; because there is no memory->memory moves. It must be defined with
534 ;; earlyclobber (&) so that it does not appear in the source or destination
535 ;; address. Providing patterns for movdi/movdf allows GCC to generate
536 ;; better code. [Until now, the scratch register is limited to D because
537 ;; otherwise we can run out of registers in the A_REGS class for reload].
539 ;; For 68HC12, the scratch register is not necessary. To use the same
540 ;; pattern and same split, we use the 'v' constraint. This tells the
541 ;; reload to use the _.tmp register (which is not used at all).
542 ;; The insn will be split in one or several memory moves (movw).
543 ;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
544 ;;--------------------------------------------------------------------
545 (define_expand "movdi"
546 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
547 (match_operand:DI 1 "general_operand" ""))
548 (clobber (match_scratch:HI 2 ""))])]
551 /* For push/pop, emit a REG_INC note to make sure the reload
552 inheritance and reload CSE pass notice the change of the stack
554 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
558 insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
559 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
566 ;; Separate push from normal moves to avoid reloading problems
567 ;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
568 ;; We can also accept more scratch registers.
569 (define_insn_and_split "*pushdi_internal"
570 [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
571 (match_operand:DI 1 "general_operand" "i,U,m,!u"))
572 (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
577 "m68hc11_split_move (operands[0], operands[1], operands[2]);
580 (define_insn_and_split "movdi_internal"
581 [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
582 (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
583 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
588 "m68hc11_split_move (operands[0], operands[1], operands[2]);
591 (define_expand "movdf"
592 [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
593 (match_operand:DF 1 "general_operand" ""))
594 (clobber (match_scratch:HI 2 ""))])]
596 "/* For push/pop, emit a REG_INC note to make sure the reload
597 inheritance and reload CSE pass notice the change of the stack
599 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
603 insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
604 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
611 ;; See pushdi_internal
612 (define_insn_and_split "*pushdf_internal"
613 [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
614 (match_operand:DF 1 "general_operand" "i,U,m,!u"))
615 (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
620 "m68hc11_split_move (operands[0], operands[1], operands[2]);
623 (define_insn_and_split "movdf_internal"
624 [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
625 (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
626 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
631 "m68hc11_split_move (operands[0], operands[1], operands[2]);
634 ;;--------------------------------------------------------------------
635 ;;- 32-bit Move Operations.
636 ;; The movsi and movsf patterns are identical except for the mode.
637 ;; When we move to/from a hard register (d+x), we don't need a scratch.
638 ;; Otherwise, a scratch register is used as intermediate register for
639 ;; the move. The '&' constraint is necessary to make sure the reload
640 ;; pass does not give us a register that dies in the insn and is used
641 ;; for input/output operands.
642 ;;--------------------------------------------------------------------
643 (define_expand "movsi"
644 [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
645 (match_operand:SI 1 "general_operand" ""))
646 (clobber (match_scratch:HI 2 ""))])]
648 "/* For push/pop, emit a REG_INC note to make sure the reload
649 inheritance and reload CSE pass notice the change of the stack
651 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
655 insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
656 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
663 (define_insn_and_split "*pushsi_internal"
664 [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
665 (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
666 (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
671 "m68hc11_split_move (operands[0], operands[1], operands[2]);
674 (define_insn_and_split "movsi_internal"
675 [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
676 (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
677 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
682 "m68hc11_split_move (operands[0], operands[1], operands[2]);
685 (define_expand "movsf"
686 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
687 (match_operand:SF 1 "general_operand" ""))
688 (clobber (match_scratch:HI 2 ""))])]
690 "/* For push/pop, emit a REG_INC note to make sure the reload
691 inheritance and reload CSE pass notice the change of the stack
693 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
697 insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
698 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
705 (define_insn_and_split "*pushsf_internal"
706 [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
707 (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
708 (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
713 "m68hc11_split_move (operands[0], operands[1], operands[2]);
716 (define_insn_and_split "movsf_internal"
717 [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
718 (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
719 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
724 "m68hc11_split_move (operands[0], operands[1], operands[2]);
728 ;;--------------------------------------------------------------------
729 ;;- 16-bit Move Operations.
730 ;; We don't need a scratch register.
731 ;;--------------------------------------------------------------------
733 (define_insn "*movhi2_push"
734 [(set (match_operand:HI 0 "push_operand" "=<,<,<")
735 (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
736 "TARGET_M6811 && !TARGET_M6812"
739 cc_status = cc_prev_status;
740 if (D_REG_P (operands[1]))
742 output_asm_insn (\"pshb\", operands);
745 else if (X_REG_P (operands[1]))
749 else if (Y_REG_P (operands[1]))
753 fatal_insn (\"Invalid register in the instruction\", insn);
756 (define_insn "*movhi2_pop"
757 [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
758 (match_operand:HI 1 "pop_operand" ">,>"))]
762 cc_status = cc_prev_status;
763 if (D_REG_P (operands[0]))
765 output_asm_insn (\"pula\", operands);
768 else if (X_REG_P (operands[0]))
772 else if (Y_REG_P (operands[0]))
776 fatal_insn (\"Invalid register in the instruction\", insn);
779 (define_expand "movhi"
780 [(set (match_operand:HI 0 "nonimmediate_operand" "")
781 (match_operand:HI 1 "general_operand" ""))]
785 if (reload_in_progress)
787 if (m68hc11_reload_operands (operands))
792 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
794 if (GET_CODE (operands[0]) == MEM &&
795 (GET_CODE (operands[1]) == MEM
796 || GET_CODE (operands[1]) == CONST_INT))
798 operands[1] = force_reg (HImode, operands[1]);
800 else if (IS_STACK_PUSH (operands[0])
801 && GET_CODE (operands[1]) != REG)
803 operands[1] = force_reg (HImode, operands[1]);
806 /* For push/pop, emit a REG_INC note to make sure the reload
807 inheritance and reload CSE pass notice the change of the stack
809 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
813 insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
814 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
821 (define_insn "*movhi_68hc12"
822 [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
823 (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
827 m68hc11_gen_movhi (insn, operands);
831 (define_insn "movhi_const0"
832 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
838 clr\\t%b0\\n\\tclr\\t%h0")
840 (define_insn "*movhi_m68hc11"
841 [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
842 (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
846 m68hc11_gen_movhi (insn, operands);
850 ;;--------------------------------------------------------------------
851 ;;- 8-bit Move Operations.
852 ;; We don't need a scratch register.
853 ;;--------------------------------------------------------------------
855 ;; The *a alternative also clears the high part of the register.
856 ;; This should be ok since this is not the (strict_low_part) set.
858 (define_insn "movqi_const0"
859 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
870 ;; 8-bit operations on address registers.
872 ;; Switch temporary to the D register and load the value in B.
873 ;; This is possible as long as the address register does not
874 ;; appear in the source operand.
877 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
878 (match_operand:QI 1 "general_operand" ""))]
879 "z_replacement_completed == 2
880 && !reg_mentioned_p (operands[0], operands[1])
881 && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
882 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
883 (set (match_dup 2) (reg:HI D_REGNUM))])
884 (set (reg:QI D_REGNUM) (match_dup 1))
885 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
886 (set (match_dup 2) (reg:HI D_REGNUM))])]
887 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
890 ;; 8-bit operations on address registers.
893 [(set (match_operand:QI 0 "nonimmediate_operand" "")
894 (match_operand:QI 1 "hard_addr_reg_operand" ""))]
895 "z_replacement_completed == 2
896 && !reg_mentioned_p (operands[1], operands[0])
897 && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
898 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
899 (set (match_dup 2) (reg:HI D_REGNUM))])
900 (set (match_dup 0) (reg:QI D_REGNUM))
901 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
902 (set (match_dup 2) (reg:HI D_REGNUM))])]
903 "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
905 (define_insn "*movqi2_push"
906 [(set (match_operand:QI 0 "push_operand" "=<,<")
907 (match_operand:QI 1 "general_operand" "d,!*A"))]
911 if (A_REG_P (operands[1]))
914 cc_status = cc_prev_status;
919 (define_expand "movqi"
920 [(set (match_operand:QI 0 "nonimmediate_operand" "")
921 (match_operand:QI 1 "general_operand" ""))]
925 if (reload_in_progress)
927 if (m68hc11_reload_operands (operands))
932 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
934 if (GET_CODE (operands[0]) == MEM
935 && (GET_CODE (operands[1]) == MEM
936 || GET_CODE (operands[1]) == CONST_INT))
938 operands[1] = force_reg (QImode, operands[1]);
940 else if (IS_STACK_PUSH (operands[0])
941 && GET_CODE (operands[1]) != REG)
943 operands[1] = force_reg (QImode, operands[1]);
946 /* For push/pop, emit a REG_INC note to make sure the reload
947 inheritance and reload CSE pass notice the change of the stack
949 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
953 insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
954 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
961 (define_insn "*movqi_68hc12"
962 [(set (match_operand:QI 0 "nonimmediate_operand"
963 "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
964 (match_operand:QI 1 "general_operand"
965 "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
969 m68hc11_gen_movqi (insn, operands);
973 (define_insn "*movqi_m68hc11"
974 [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
975 (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
979 m68hc11_gen_movqi (insn, operands);
983 ;;--------------------------------------------------------------------
985 ;;--------------------------------------------------------------------
986 ;; Swapping registers is used for split patterns.
987 (define_insn "swap_areg"
988 [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
989 (match_operand:HI 1 "hard_reg_operand" "=A,d"))
990 (set (match_dup 1) (match_dup 0))]
994 m68hc11_output_swap (insn, operands);
998 ;;--------------------------------------------------------------------
999 ;;- Truncation insns.
1000 ;;--------------------------------------------------------------------
1002 ;; Truncation are not necessary because GCC knows how to truncate,
1003 ;; specially when values lie in consecutive registers.
1006 (define_expand "floatunssisf2"
1007 [(set (match_operand:SF 0 "nonimmediate_operand" "")
1008 (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1010 "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
1011 SFmode, SImode, 2, operands);
1014 (define_expand "floatunssidf2"
1015 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1016 (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1018 "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
1019 DFmode, SImode, 2, operands);
1022 ;;--------------------------------------------------------------------
1023 ;;- Zero extension insns.
1024 ;;--------------------------------------------------------------------
1027 ;; 64-bit extend. The insn will be split into 16-bit instructions just
1028 ;; before the final pass. We need a scratch register for the split.
1029 ;; The final value can be generated on the stack directly. This is more
1030 ;; efficient and useful for conversions made during parameter passing rules.
1032 (define_insn "zero_extendqidi2"
1033 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1035 (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
1036 (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
1041 [(set (match_operand:DI 0 "push_operand" "")
1042 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1043 (clobber (match_scratch:HI 2 "=&dB"))]
1044 "z_replacement_completed == 2"
1048 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1049 rtx push = m68hc11_gen_lowpart (HImode, low);
1050 rtx src = operands[1];
1052 /* Source operand must be in a hard register. */
1055 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1056 emit_move_insn (src, operands[1]);
1059 /* Source is in D, we can push B then one word of 0 and we do
1060 a correction on the stack pointer. */
1063 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1064 emit_move_insn (operands[2], const0_rtx);
1065 if (D_REG_P (operands[2]))
1067 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1071 emit_move_insn (push, operands[2]);
1072 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1073 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1079 /* Source is in X or Y. It's better to push the 16-bit register
1080 and then to some stack adjustment. */
1081 src = gen_rtx_REG (HImode, REGNO (src));
1082 emit_move_insn (push, src);
1083 emit_move_insn (operands[2], const0_rtx);
1084 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1085 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1087 emit_move_insn (push, operands[2]);
1088 emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
1089 gen_rtx_REG (HImode, HARD_SP_REGNUM),
1092 emit_move_insn (push, operands[2]);
1093 emit_move_insn (push, operands[2]);
1094 emit_move_insn (push, operands[2]);
1099 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1100 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
1101 (clobber (match_scratch:HI 2 "=&dB"))]
1102 "z_replacement_completed == 2"
1106 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1107 rtx low2 = m68hc11_gen_lowpart (HImode, low);
1108 rtx src = operands[1];
1110 /* Source operand must be in a hard register. */
1113 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1114 emit_move_insn (src, operands[1]);
1117 emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1118 emit_move_insn (operands[2], const0_rtx);
1119 src = gen_rtx_REG (QImode, REGNO (operands[2]));
1120 emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1122 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1123 low = m68hc11_gen_highpart (SImode, operands[0]);
1124 emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1125 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1129 (define_insn "zero_extendhidi2"
1130 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
1132 (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1133 (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
1138 [(set (match_operand:DI 0 "non_push_operand" "")
1140 (match_operand:HI 1 "nonimmediate_operand" "")))
1141 (clobber (match_scratch:HI 2 ""))]
1142 "z_replacement_completed == 2"
1146 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1147 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1148 rtx src = operands[1];
1150 /* Make sure the source is in a hard register. */
1154 emit_move_insn (src, operands[1]);
1157 /* Move the low part first for the push. */
1158 emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1160 /* Now, use the scratch register to fill in the zeros. */
1161 emit_move_insn (operands[2], const0_rtx);
1162 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1163 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1164 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1168 (define_insn "zero_extendsidi2"
1169 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1171 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1172 (clobber (match_scratch:HI 2 "=d,d,d,d"))]
1177 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1179 (match_operand:SI 1 "nonimmediate_operand" "")))
1180 (clobber (match_scratch:HI 2 ""))]
1181 "z_replacement_completed == 2"
1185 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1186 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1188 /* Move the low part first so that this is ok for a push. */
1189 m68hc11_split_move (low, operands[1], operands[2]);
1191 /* Use the scratch register to clear the high part of the destination. */
1192 emit_move_insn (operands[2], const0_rtx);
1193 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1194 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1199 ;; For 16->32bit unsigned extension, we don't allow generation on the stack
1200 ;; because it's less efficient.
1202 (define_insn "zero_extendhisi2"
1203 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
1205 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1206 (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
1211 [(set (match_operand:SI 0 "non_push_operand" "")
1213 (match_operand:HI 1 "nonimmediate_operand" "")))
1214 (clobber (match_scratch:HI 2 ""))]
1219 rtx src = operands[1];
1221 if (!H_REG_P (src) && !H_REG_P (operands[0]))
1224 emit_move_insn (src, operands[1]);
1226 emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1227 emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1231 (define_insn "zero_extendqisi2"
1232 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
1234 (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
1239 [(set (match_operand:SI 0 "non_push_operand" "")
1240 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1241 "reload_completed && !X_REG_P (operands[0])"
1242 [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1243 (set (match_dup 3) (const_int 0))]
1245 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
1246 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
1249 [(set (match_operand:SI 0 "hard_reg_operand" "")
1250 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1251 "z_replacement_completed == 2 && X_REG_P (operands[0])"
1252 [(set (match_dup 2) (match_dup 3))
1253 (set (match_dup 4) (const_int 0))
1254 (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1256 if (X_REG_P (operands[1]))
1258 emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
1259 gen_rtx_REG (HImode, HARD_X_REGNUM)));
1260 emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
1261 gen_rtx_REG (QImode, HARD_D_REGNUM)));
1262 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
1267 if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
1269 emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1272 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
1275 operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1276 operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1277 if (A_REG_P (operands[1]))
1279 operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1280 operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
1281 operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
1285 operands[5] = operands[2] =
1286 operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1287 operands[6] = operands[1];
1291 (define_insn "zero_extendqihi2"
1292 [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
1294 (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1298 if (A_REG_P (operands[0]))
1301 if (H_REG_P (operands[0]))
1303 output_asm_insn (\"clra\", operands);
1304 if (operands[0] != operands[1]
1305 && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1307 if (X_REG_P (operands[1])
1308 || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1310 output_asm_insn (\"stx\\t%t1\", operands);
1311 output_asm_insn (\"ldab\\t%T0\", operands);
1313 else if (Y_REG_P (operands[1])
1314 || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1316 output_asm_insn (\"sty\\t%t1\", operands);
1317 output_asm_insn (\"ldab\\t%T0\", operands);
1321 output_asm_insn (\"ldab\\t%b1\", operands);
1323 cc_status.flags |= CC_NOT_NEGATIVE;
1327 /* Status refers to the clra insn. Status is ok for others
1328 * since we have loaded the value in B.
1335 if (A_REG_P (operands[1]))
1337 output_asm_insn (\"st%1\\t%0\", operands);
1338 output_asm_insn (\"clr\\t%h0\", operands);
1343 output_asm_insn (\"clr\\t%h0\", operands);
1344 output_asm_insn (\"stab\\t%b0\", operands);
1345 cc_status.flags |= CC_NOT_NEGATIVE;
1352 ;;--------------------------------------------------------------------
1353 ;;- Sign extension insns.
1354 ;;--------------------------------------------------------------------
1356 (define_insn "extendqisi2"
1357 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1358 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
1365 /* The 68HC12 has a sign-extension instruction. Use it when the
1366 destination is the register (X,D). First sign-extend the low
1367 part and fill X with the sign-extension of the high part. */
1368 if (TARGET_M6812 && X_REG_P (operands[0]))
1370 if (!D_REG_P (operands[1]))
1372 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1373 ops[1] = operands[1];
1374 m68hc11_gen_movqi (insn, ops);
1376 return \"sex\\tb,d\\n\\tsex\\ta,x\";
1379 ops[2] = gen_label_rtx ();
1381 if (X_REG_P (operands[1]))
1383 output_asm_insn (\"xgdx\", operands);
1386 else if (X_REG_P (operands[0]))
1388 /* X can be used as an indexed addressing in the source.
1389 Get the value before clearing it. */
1390 if (reg_mentioned_p (ix_reg, operands[1]))
1392 output_asm_insn (\"ldab\\t%b1\", operands);
1395 output_asm_insn (\"ldx\\t#0\", operands);
1398 output_asm_insn (\"clra\", operands);
1399 if (!X_REG_P (operands[0]))
1401 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1402 ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1404 if (IS_STACK_PUSH (operands[0]))
1406 output_asm_insn (\"pshb\", ops);
1407 output_asm_insn (\"tstb\", ops);
1411 output_asm_insn (\"stab\\t%b1\", ops);
1414 else if (D_REG_P (operands[1]) || need_tst)
1416 output_asm_insn (\"tstb\", operands);
1420 output_asm_insn (\"ldab\\t%b1\", operands);
1422 output_asm_insn (\"bpl\\t%l2\", ops);
1423 output_asm_insn (\"deca\", operands);
1424 if (X_REG_P (operands[0]))
1425 output_asm_insn (\"dex\", operands);
1427 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1429 if (!X_REG_P (operands[0]))
1431 if (IS_STACK_PUSH (operands[0]))
1433 output_asm_insn (\"psha\", ops);
1434 output_asm_insn (\"psha\", ops);
1435 output_asm_insn (\"psha\", ops);
1439 output_asm_insn (\"staa\\t%h0\", ops);
1441 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1442 if (dead_register_here (insn, d_reg))
1444 output_asm_insn (\"tab\", ops);
1445 output_asm_insn (\"std\\t%0\", ops);
1449 output_asm_insn (\"staa\\t%b0\", ops);
1450 output_asm_insn (\"staa\\t%h0\", ops);
1460 (define_insn "extendqihi2"
1461 [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1462 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
1468 if (A_REG_P (operands[0]))
1471 ops[0] = gen_label_rtx ();
1472 if (D_REG_P (operands[0]))
1476 if (!D_REG_P (operands[1]))
1478 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1479 ops[1] = operands[1];
1480 m68hc11_gen_movqi (insn, ops);
1482 return \"sex\\tb,d\";
1484 output_asm_insn (\"clra\", operands);
1485 if (H_REG_P (operands[1]))
1487 output_asm_insn (\"tstb\", operands);
1491 output_asm_insn (\"ldab\\t%b1\", operands);
1493 output_asm_insn (\"bpl\\t%l0\", ops);
1494 output_asm_insn (\"deca\", operands);
1496 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1497 CODE_LABEL_NUMBER (ops[0]));
1501 output_asm_insn (\"clr\\t%h0\", operands);
1502 if (m68hc11_register_indirect_p (operands[1], HImode))
1504 ops[1] = operands[1];
1505 output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1510 output_asm_insn (\"tst\\t%b1\", operands);
1511 output_asm_insn (\"bpl\\t%l0\", ops);
1513 output_asm_insn (\"dec\\t%h0\", operands);
1514 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1515 CODE_LABEL_NUMBER (ops[0]));
1522 ;; Split the special case where the source of the sign extend is
1523 ;; either Y or Z. In that case, we can't move the source in the D
1524 ;; register directly. The movhi pattern handles this move by using
1525 ;; a temporary scratch memory location.
1528 [(set (match_operand:SI 0 "register_operand" "")
1529 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
1530 "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
1531 [(set (reg:HI D_REGNUM) (match_dup 1))
1532 (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
1535 (define_insn "extendhisi2"
1536 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
1537 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
1544 if (Y_REG_P (operands[1]))
1547 if (X_REG_P (operands[1]))
1549 output_asm_insn (\"xgdx\", operands);
1554 /* X can be used as an indexed addressing in the source.
1555 Get the value before clearing it. */
1556 x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1559 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1560 ops[1] = operands[1];
1561 m68hc11_gen_movhi (insn, ops);
1566 if (TARGET_M6812 && 0)
1568 /* This sequence of code is larger than the one for 68HC11.
1569 Don't use it; keep it for documentation. */
1570 if (!D_REG_P (operands[1]) && !x_reg_used)
1572 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1573 ops[1] = operands[1];
1574 m68hc11_gen_movhi (insn, ops);
1576 output_asm_insn (\"sex\\ta,x\", operands);
1577 output_asm_insn (\"xgdx\", operands);
1578 output_asm_insn (\"sex\\ta,d\", operands);
1582 output_asm_insn (\"ldx\\t#0\", operands);
1583 if (D_REG_P (operands[1]) || x_reg_used)
1585 output_asm_insn (\"tsta\", operands);
1589 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1590 ops[1] = operands[1];
1591 m68hc11_gen_movhi (insn, ops);
1594 ops[0] = gen_label_rtx ();
1595 output_asm_insn (\"bpl\\t%l0\", ops);
1596 output_asm_insn (\"dex\", operands);
1597 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1603 ;;--------------------------------------------------------------------
1604 ;;- Min and Max instructions (68HC12).
1605 ;;--------------------------------------------------------------------
1606 (define_insn "uminqi3"
1607 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1608 (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1609 (match_operand:QI 2 "general_operand" "m,d")))]
1610 "TARGET_M6812 && TARGET_MIN_MAX"
1613 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1614 The mina/minm use A as the source or destination. This is the
1615 high part of D. There is no way to express that in the pattern
1616 so we must use 'exg a,b' to put the operand in the good register. */
1618 if (D_REG_P (operands[0]))
1620 return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1624 return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1628 (define_insn "umaxqi3"
1629 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1630 (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1631 (match_operand:QI 2 "general_operand" "m,d")))]
1632 "TARGET_M6812 && TARGET_MIN_MAX"
1635 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1636 The maxa/maxm use A as the source or destination. This is the
1637 high part of D. There is no way to express that in the pattern
1638 so we must use 'exg a,b' to put the operand in the good register. */
1640 if (D_REG_P (operands[0]))
1642 return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1646 return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1650 (define_insn "uminhi3"
1651 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1652 (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1653 (match_operand:HI 2 "general_operand" "m,d")))]
1654 "TARGET_M6812 && TARGET_MIN_MAX"
1657 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1659 if (D_REG_P (operands[0]))
1661 return \"emind\\t%2\";
1665 return \"eminm\\t%0\";
1669 (define_insn "umaxhi3"
1670 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1671 (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1672 (match_operand:HI 2 "general_operand" "m,d")))]
1673 "TARGET_M6812 && TARGET_MIN_MAX"
1676 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1678 if (D_REG_P (operands[0]))
1680 return \"emaxd\\t%2\";
1684 return \"emaxm\\t%0\";
1689 ;;--------------------------------------------------------------------
1690 ;;- Add instructions.
1691 ;;--------------------------------------------------------------------
1692 ;; 64-bit: Use a library call because what GCC generates is huge.
1694 (define_expand "adddi3"
1695 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1696 (plus:DI (match_operand:DI 1 "general_operand" "")
1697 (match_operand:DI 2 "general_operand" "")))]
1699 "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1705 (define_expand "addsi3"
1706 [(parallel [(set (match_operand:SI 0 "register_operand" "")
1707 (plus:SI (match_operand:SI 1 "general_operand" "")
1708 (match_operand:SI 2 "general_operand" "")))
1709 (clobber (match_scratch:HI 3 ""))])]
1713 (define_insn "*addsi3_zero_extendhi"
1714 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1715 (plus:SI (zero_extend:SI
1716 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1717 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1718 (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1724 if (X_REG_P (operands[2]))
1726 ops[0] = operands[1];
1730 if (X_REG_P (operands[1]))
1732 output_asm_insn (\"xgdx\", ops);
1734 else if (!D_REG_P (operands[1]))
1736 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1737 ops[1] = operands[1];
1738 m68hc11_gen_movhi (insn, ops);
1740 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1741 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1743 ops[2] = gen_label_rtx ();
1745 /* ldx preserves the carry, propagate it by incrementing X directly. */
1746 output_asm_insn (\"addd\\t%0\", ops);
1747 if (!X_REG_P (operands[2]))
1748 output_asm_insn (\"ldx\\t%1\", ops);
1750 output_asm_insn (\"bcc\\t%l2\", ops);
1751 output_asm_insn (\"inx\", ops);
1754 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1759 (define_split /* "*addsi3_zero_extendqi" */
1760 [(set (match_operand:SI 0 "register_operand" "")
1761 (plus:SI (zero_extend:SI
1762 (match_operand:QI 1 "general_operand" ""))
1763 (match_operand:SI 2 "memory_operand" "")))
1764 (clobber (match_scratch:HI 3 "=X,X"))]
1766 [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
1767 (parallel [(set (match_dup 0)
1768 (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
1769 (clobber (match_dup 3))])]
1772 (define_insn "*addsi3_zero_extendqi"
1773 [(set (match_operand:SI 0 "register_operand" "=D,D")
1774 (plus:SI (zero_extend:SI
1775 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1776 (match_operand:SI 2 "general_operand" "miD,!muiD")))
1777 (clobber (match_scratch:HI 3 "=X,X"))]
1783 if (GET_CODE (operands[2]) == MEM)
1786 if (X_REG_P (operands[2]))
1788 if (H_REG_P (operands[1]))
1790 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
1791 ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
1792 m68hc11_gen_movhi (insn, ops);
1796 ops[0] = operands[1];
1798 ops[1] = const0_rtx;
1802 if (X_REG_P (operands[1]))
1804 output_asm_insn (\"xgdx\", ops);
1806 else if (!D_REG_P (operands[1]))
1808 ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
1809 ops[1] = operands[1];
1810 m68hc11_gen_movqi (insn, ops);
1813 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1815 ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1816 output_asm_insn (\"clra\", ops);
1819 /* ldx preserves the carry, propagate it by incrementing X directly. */
1820 output_asm_insn (\"addb\\t%b0\", ops);
1821 output_asm_insn (\"adca\\t%h1\", ops);
1822 if (!X_REG_P (operands[2]))
1823 output_asm_insn (\"ldx\\t%2\", ops);
1825 /* If the above adca was adding some constant, we don't need to propagate
1826 the carry unless the constant was 0xff. */
1827 if (X_REG_P (operands[2])
1828 || GET_CODE (ops[1]) != CONST_INT
1829 || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1831 ops[3] = gen_label_rtx ();
1833 output_asm_insn (\"bcc\\t%l3\", ops);
1834 output_asm_insn (\"inx\", ops);
1836 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
1837 CODE_LABEL_NUMBER (ops[3]));
1843 (define_insn "*addsi3"
1844 [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
1845 (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
1846 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
1847 (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1852 const char* add_insn;
1853 const char* inc_insn;
1854 const char* incb_mem;
1855 const char* inch_mem;
1858 if (which_alternative > 2)
1863 val = INTVAL (operands[2]);
1864 if ((val & 0x0ffffL) == 0)
1866 if (!H_REG_P (operands[0]))
1868 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1869 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1870 output_asm_insn (\"ldd\\t%0\", ops);
1871 output_asm_insn (\"addd\\t%1\", ops);
1872 output_asm_insn (\"std\\t%0\", ops);
1884 if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1891 ops[1] = operands[2];
1892 add_insn = \"addd\\t%1\";
1893 inc_insn = \"inx\\t\";
1894 incb_mem = \"inc\\t%b1\";
1895 inch_mem = \"inc\\t%h1\";
1899 ops[1] = GEN_INT (- val);
1900 add_insn = \"subd\\t%1\";
1902 incb_mem = \"dec\\t%b1\";
1903 inch_mem = \"dec\\t%h1\";
1906 ops[2] = gen_label_rtx ();
1907 if (!H_REG_P (operands[0]))
1909 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1910 output_asm_insn (\"ldd\\t%0\", ops);
1912 output_asm_insn (add_insn, ops);
1913 if (!H_REG_P (operands[0]))
1915 output_asm_insn (\"std\\t%0\", ops);
1917 output_asm_insn (\"bcc\\t%l2\", ops);
1918 if (H_REG_P (operands[0]))
1920 output_asm_insn (inc_insn, ops);
1924 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1926 if (INTVAL (operands[2]) < 0)
1928 output_asm_insn (\"ldd\\t%1\", ops);
1929 output_asm_insn (\"addd\\t#-1\", ops);
1930 output_asm_insn (\"std\\t%1\", ops);
1934 output_asm_insn (incb_mem, ops);
1935 output_asm_insn (\"bne\\t%l2\", ops);
1936 output_asm_insn (inch_mem, ops);
1939 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1946 [(set (match_operand:SI 0 "register_operand" "")
1947 (plus:SI (match_operand:SI 1 "register_operand" "")
1948 (match_operand:SI 2 "const_int_operand" "")))
1949 (clobber (match_scratch:HI 3 ""))]
1950 "reload_completed && z_replacement_completed == 2
1951 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
1952 [(set (match_dup 5) (match_dup 6))
1953 (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
1954 (set (match_dup 6) (match_dup 5))]
1955 "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
1956 if (X_REG_P (operands[0]))
1958 operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
1962 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
1963 operands[5] = operands[3];
1968 [(set (match_operand:SI 0 "register_operand" "")
1969 (plus:SI (match_operand:SI 1 "register_operand" "")
1970 (match_operand:SI 2 "general_operand" "")))
1971 (clobber (match_scratch:HI 3 "=X"))]
1972 "reload_completed && z_replacement_completed == 2
1973 && (GET_CODE (operands[2]) != CONST_INT ||
1974 (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
1975 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
1976 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
1977 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
1978 (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
1979 (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
1980 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
1981 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
1982 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
1983 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
1984 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
1985 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
1988 ;; Instruction generated to propagate the carry of a 16-bit add
1989 ;; to the upper 16-bit part (in register X).
1991 (define_insn "*addsi_carry"
1992 [(set (match_operand:HI 0 "register_operand" "=x")
1993 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
1995 (reg:HI CC_REGNUM)))]
2001 ops[0] = gen_label_rtx ();
2002 output_asm_insn (\"bcc\\t%l0\", ops);
2003 output_asm_insn (\"in%0\", operands);
2004 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2012 (define_expand "addhi3"
2013 [(set (match_operand:HI 0 "register_operand" "")
2014 (plus:HI (match_operand:HI 1 "register_operand" "")
2015 (match_operand:HI 2 "general_operand" "")))]
2019 if (TARGET_M6811 && SP_REG_P (operands[0]))
2021 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
2022 gen_rtx_SET (VOIDmode,
2024 gen_rtx_PLUS (HImode,
2025 operand1, operand2)),
2026 gen_rtx_CLOBBER (VOIDmode,
2027 gen_rtx_SCRATCH (HImode)))));
2032 (define_insn "*addhi3_68hc12"
2033 [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
2034 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
2035 (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
2040 const char* insn_code;
2042 if (which_alternative >= 4)
2044 if (A_REG_P (operands[2]))
2047 output_asm_insn (\"xgd%2\", operands);
2048 output_asm_insn (\"lea%0 d,%0\", operands);
2054 if (D_REG_P (operands[0]))
2056 if (X_REG_P (operands[2]))
2058 m68hc11_notice_keep_cc (operands[0]);
2059 output_asm_insn (\"xgdx\", operands);
2060 output_asm_insn (\"leax\\td,%2\", operands);
2063 else if (Y_REG_P (operands[2]))
2065 m68hc11_notice_keep_cc (operands[0]);
2066 output_asm_insn (\"xgdy\", operands);
2067 output_asm_insn (\"leay\\td,%2\", operands);
2070 else if (SP_REG_P (operands[2]))
2072 output_asm_insn (\"sts\\t%t0\", operands);
2073 return \"addd\\t%t0\";
2075 return \"addd\\t%2\";
2078 if (GET_CODE (operands[2]) == CONST_INT)
2079 val = INTVAL (operands[2]);
2083 if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
2085 m68hc11_notice_keep_cc (operands[0]);
2086 switch (REGNO (operands[0]))
2089 return \"leax\\t%i2,%1\";
2092 return \"leay\\t%i2,%1\";
2094 case HARD_SP_REGNUM:
2095 return \"leas\\t%i2,%1\";
2098 fatal_insn (\"Invalid operands in the instruction\", insn);
2103 insn_code = X_REG_P (operands[0]) ? \"inx\"
2104 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2109 insn_code = X_REG_P (operands[0]) ? \"dex\"
2110 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2113 /* For X and Y increment, the flags are not complete. Only the Z flag
2114 is updated. For SP increment, flags are not changed. */
2115 if (SP_REG_P (operands[0]))
2117 cc_status = cc_prev_status;
2118 if (INTVAL (operands[2]) < 0)
2122 output_asm_insn (\"pshx\", operands);
2136 output_asm_insn (insn_code, operands);
2143 ;; Specific pattern to add to the stack pointer.
2144 ;; We also take care of the clobbering of the IY register.
2146 (define_insn "addhi_sp"
2147 [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2148 (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2149 (match_operand:HI 2 "general_operand" "P,im,u,im")))
2150 (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2156 if (optimize && Y_REG_P (operands[3])
2157 && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
2158 operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
2160 if (GET_CODE (operands[2]) == CONST_INT
2161 && (val = INTVAL (operands[2])) != 0
2162 && (CONST_OK_FOR_LETTER_P (val, 'P')
2163 || (val > 0 && val <= 8)))
2165 while (val > 1 || val < -1)
2169 if (!H_REG_P (operands[3]))
2172 output_asm_insn (\"pul%3\", operands);
2177 output_asm_insn (\"pshx\", operands);
2185 output_asm_insn (\"ins\", operands);
2190 output_asm_insn (\"des\", operands);
2194 cc_status = cc_prev_status;
2198 /* Need to transfer to SP to X/Y and then to D register.
2199 Register X/Y is lost, this is specified by the (clobber) statement. */
2200 output_asm_insn (\"ts%3\", operands);
2201 if (GET_CODE (operands[2]) == CONST_INT
2202 && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
2203 && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
2205 output_asm_insn (\"ldab\\t%2\", operands);
2206 output_asm_insn (\"ab%3\", operands);
2211 output_asm_insn (\"xgd%3\", operands);
2212 output_asm_insn (\"addd\\t%2\", operands);
2213 output_asm_insn (\"xgd%3\", operands);
2216 /* The status flags correspond to the addd. xgdy and tys do not
2217 modify the flags. */
2221 (define_insn "*addhi3"
2222 [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
2223 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
2224 (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
2228 const char* insn_code;
2231 if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2233 output_asm_insn (\"sts\\t%t0\", operands);
2234 output_asm_insn (\"addd\\t%t0\", operands);
2235 return \"addd\\t#1\";
2237 if (GET_CODE (operands[2]) != CONST_INT)
2239 /* Adding to an address register or with another/same register
2240 is not possible. This must be replaced. */
2241 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2244 return \"addd\\t%2\";
2246 val = INTVAL (operands[2]);
2247 if (!SP_REG_P (operands[0]))
2249 if (D_REG_P (operands[0]))
2251 if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2254 return \"adda\\t%h2\";
2258 return \"addd\\t%2\";
2261 else if (GET_CODE (operands[2]) != CONST_INT
2262 || INTVAL (operands[2]) < -4
2263 || INTVAL (operands[2]) > 4)
2268 insn_code = X_REG_P (operands[0]) ? \"inx\"
2269 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2274 insn_code = X_REG_P (operands[0]) ? \"dex\"
2275 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2278 /* For X and Y increment, the flags are not complete. Only the Z flag
2279 is updated. For SP increment, flags are not changed. */
2280 if (SP_REG_P (operands[0]))
2282 cc_status = cc_prev_status;
2283 if (INTVAL (operands[2]) < 0)
2287 output_asm_insn (\"pshx\", operands);
2291 else if (optimize && dead_register_here (insn, ix_reg))
2295 output_asm_insn (\"pulx\", operands);
2307 output_asm_insn (insn_code, operands);
2313 (define_insn "*addhi3_zext"
2314 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2315 (plus:HI (zero_extend:HI
2316 (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2317 (match_operand:HI 2 "general_operand" "0,0")))]
2322 if (A_REG_P (operands[0]))
2324 else if (A_REG_P (operands[1]))
2325 return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2327 return \"addb\\t%b1\\n\\tadca\\t#0\";
2331 ;; Translate d = d + d into d = << 1
2332 ;; We have to do this because adding a register to itself is not possible.
2333 ;; ??? It's not clear whether this is really necessary.
2336 [(set (match_operand:QI 0 "hard_reg_operand" "")
2337 (plus:QI (match_dup 0)
2339 "0 && reload_completed"
2340 [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2343 (define_insn "addqi3"
2344 [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2345 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2346 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
2350 if (GET_CODE (operands[2]) == CONST_INT)
2352 if (INTVAL (operands[2]) == 1)
2354 if (DA_REG_P (operands[0]))
2358 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2363 else if (A_REG_P (operands[0]))
2365 /* This applies on the 16-bit register. This should be ok since
2366 this is not a strict_low_part increment. */
2371 return \"inc\\t%b0\";
2374 else if (INTVAL (operands[2]) == -1)
2376 if (DA_REG_P (operands[0]))
2380 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2384 else if (A_REG_P (operands[0]))
2386 /* This applies on the 16-bit register. This should be ok since
2387 this is not a strict_low_part decrement. */
2392 return \"dec\\t%b0\";
2396 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2398 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2399 return \"addb\\t%b2\";
2401 return \"adda\\t%b2\";
2405 ;; add with carry is used for 32-bit add.
2407 (define_insn "*adcq"
2408 [(set (match_operand:QI 0 "register_operand" "=q")
2409 (plus:QI (plus:QI (reg:QI CC_REGNUM)
2410 (match_operand:QI 1 "register_operand" "%0"))
2411 (match_operand:QI 2 "general_operand" "ium")))]
2415 ;;--------------------------------------------------------------------
2416 ;;- Subtract instructions.
2417 ;;--------------------------------------------------------------------
2419 (define_expand "subdi3"
2420 [(set (match_operand:DI 0 "nonimmediate_operand" "")
2421 (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2422 (match_operand:DI 2 "general_operand" "")))]
2424 "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2428 ;; 32-bit Subtract (see addsi3)
2429 ;; Subtract with a constant are handled by addsi3.
2434 (define_expand "subsi3"
2435 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2436 (minus:SI (match_operand:SI 1 "register_operand" "")
2437 (match_operand:SI 2 "general_operand" "")))
2438 (clobber (match_scratch:HI 3 ""))])]
2442 (define_insn "*subsi3"
2443 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
2444 (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2445 (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
2446 (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
2450 (define_insn "*subsi3_zero_extendhi"
2451 [(set (match_operand:SI 0 "register_operand" "=D")
2452 (minus:SI (match_operand:SI 1 "register_operand" "0")
2453 (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
2454 (clobber (match_scratch:HI 3 "=X"))]
2460 if (A_REG_P (operands[2]))
2463 ops[0] = gen_rtx_MEM (HImode,
2464 gen_rtx_PRE_DEC (HImode,
2465 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2467 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2469 ops[1] = operands[2];
2470 m68hc11_gen_movhi (insn, ops);
2472 operands[2] = gen_rtx_MEM (HImode,
2473 gen_rtx_POST_INC (HImode,
2474 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
2476 operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2478 ops[0] = gen_label_rtx ();
2479 output_asm_insn (\"subd\\t%2\", operands);
2480 output_asm_insn (\"bcc\\t%l0\", ops);
2481 output_asm_insn (\"dex\", ops);
2482 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2487 (define_insn "*subsi3_zero_extendqi"
2488 [(set (match_operand:SI 0 "register_operand" "=D")
2489 (minus:SI (match_operand:SI 1 "register_operand" "0")
2490 (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
2491 (clobber (match_scratch:HI 3 "=X"))]
2497 if (A_REG_P (operands[2]))
2499 ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
2500 ops[1] = operands[2];
2501 m68hc11_gen_movhi (insn, ops);
2502 operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2504 ops[0] = gen_label_rtx ();
2505 output_asm_insn (\"subb\\t%b2\", operands);
2506 output_asm_insn (\"sbca\\t#0\", operands);
2507 output_asm_insn (\"bcc\\t%l0\", ops);
2508 output_asm_insn (\"dex\", ops);
2509 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2515 ;; reg:HI 1 -> d reg:QI 6 -> B
2516 ;; reg:QI 7 -> ccr reg:QI 5 -> A
2518 (define_split /* "*subsi3" */
2519 [(set (match_operand:SI 0 "register_operand" "")
2520 (minus:SI (match_operand:SI 1 "register_operand" "")
2521 (match_operand:SI 2 "general_operand" "")))
2522 (clobber (match_scratch:HI 3 "=X"))]
2523 "reload_completed && z_replacement_completed == 2
2524 && X_REG_P (operands[1])"
2525 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2526 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2527 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2528 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2529 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2530 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2531 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
2532 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2533 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2534 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2535 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2537 (define_split /* "*subsi3" */
2538 [(set (match_operand:SI 0 "register_operand" "")
2539 (minus:SI (match_operand:SI 1 "general_operand" "")
2540 (match_operand:SI 2 "register_operand" "")))
2541 (clobber (match_scratch:HI 3 "=X"))]
2542 "reload_completed && z_replacement_completed == 2
2543 && X_REG_P (operands[2])"
2544 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2545 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2546 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2547 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2548 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2549 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2550 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2551 (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2552 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2553 operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2554 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2555 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2557 (define_split /* "*subsi3" */
2558 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2559 (minus:SI (match_operand:SI 1 "general_operand" "")
2560 (match_operand:SI 2 "general_operand" "")))
2561 (clobber (match_scratch:HI 3 "=d"))]
2562 "reload_completed && z_replacement_completed == 2
2563 && !X_REG_P (operands[0])"
2564 [(set (match_dup 3) (match_dup 4))
2565 (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2566 (set (match_dup 4) (match_dup 3))
2567 (set (match_dup 3) (match_dup 6))
2568 (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2569 (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2570 (set (match_dup 6) (match_dup 3))]
2571 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2572 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2573 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2574 operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2575 operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2576 operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2579 ;; - 16-bit Subtract.
2581 (define_expand "subhi3"
2582 [(set (match_operand:HI 0 "register_operand" "=r")
2583 (minus:HI (match_operand:HI 1 "register_operand" "0")
2584 (match_operand:HI 2 "general_operand" "g")))]
2589 ;; Subtract from stack. This is better if we provide a pattern.
2591 (define_insn "*subhi3_sp"
2592 [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2593 (minus:HI (match_operand:HI 1 "register_operand" "0,0")
2594 (match_operand:HI 2 "general_operand" "im*d,!u*A")))
2595 (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2599 if (X_REG_P (operands[2]))
2601 operands[2] = m68hc11_soft_tmp_reg;
2602 output_asm_insn (\"stx\\t%2\", operands);
2604 else if (Y_REG_P (operands[2]))
2606 operands[2] = m68hc11_soft_tmp_reg;
2607 output_asm_insn (\"sty\\t%2\", operands);
2609 else if (D_REG_P (operands[2]))
2611 operands[2] = m68hc11_soft_tmp_reg;
2612 output_asm_insn (\"std\\t%2\", operands);
2615 if (D_REG_P (operands[3]))
2619 save_x = !dead_register_here (insn, ix_reg);
2621 output_asm_insn (\"xgdx\", operands);
2622 output_asm_insn (\"tsx\", operands);
2623 output_asm_insn (\"xgdx\", operands);
2624 output_asm_insn (\"subd\\t%2\", operands);
2625 output_asm_insn (\"xgdx\", operands);
2627 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2628 modify the flags. */
2629 output_asm_insn (\"txs\", operands);
2636 /* Need to transfer to SP to X,Y and then to D register.
2637 Register X,Y is lost, this is specified by the (clobber) statement. */
2638 output_asm_insn (\"ts%3\", operands);
2639 output_asm_insn (\"xgd%3\", operands);
2640 output_asm_insn (\"subd\\t%2\", operands);
2641 output_asm_insn (\"xgd%3\", operands);
2643 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
2644 modify the flags. */
2649 (define_insn "*subhi3"
2650 [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
2651 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
2652 (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
2656 /* Adding to an address register or with another/same register
2657 is not possible. This must be replaced. */
2658 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2661 return \"subd\\t%2\";
2664 (define_insn "*subhi3_zext"
2665 [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2666 (minus:HI (match_operand:HI 1 "general_operand" "0,0")
2667 (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2672 if (A_REG_P (operands[2]))
2676 ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
2677 ops[1] = operands[2];
2678 m68hc11_gen_movqi (insn, ops);
2679 return \"subb\\t%T0\\n\\tsbca\\t#0\";
2681 return \"subb\\t%b2\\n\\tsbca\\t#0\";
2684 (define_insn "subqi3"
2685 [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2686 (minus:QI (match_operand:QI 1 "general_operand" "0,0")
2687 (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
2691 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2693 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2694 return \"subb\\t%b2\";
2696 return \"suba\\t%b2\";
2700 ;; subtract with carry is used for 32-bit subtract.
2702 (define_insn "*subcq"
2703 [(set (match_operand:QI 0 "register_operand" "=q")
2704 (minus:QI (minus:QI (reg:QI CC_REGNUM)
2705 (match_operand:QI 1 "register_operand" "0"))
2706 (match_operand:QI 2 "general_operand" "ium")))]
2710 ;;--------------------------------------------------------------------
2711 ;;- Multiply instructions.
2712 ;;--------------------------------------------------------------------
2714 ;; 32 and 64-bit multiply are handled by the library
2717 (define_expand "mulsi3"
2718 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2719 (mult:SI (match_operand:SI 1 "general_operand" "")
2720 (match_operand:SI 2 "general_operand" "")))]
2722 "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2725 (define_expand "mulhi3"
2726 [(parallel [(set (match_operand:HI 0 "register_operand" "")
2727 (mult:HI (match_operand:HI 1 "register_operand" "")
2728 (match_operand:HI 2 "register_operand" "")))
2729 (clobber (match_scratch:HI 3 ""))])]
2733 (define_insn "mulhi3_m68hc11"
2734 [(set (match_operand:HI 0 "register_operand" "=d")
2735 (mult:HI (match_operand:HI 1 "register_operand" "%0")
2736 (match_operand:HI 2 "register_operand" "x")))
2737 (clobber (match_scratch:HI 3 "=X"))]
2742 /* D * X -> D (X and Y are preserved by this function call). */
2743 return \"jsr\\t___mulhi3\";
2746 (define_insn "mulhi3_m68hc12"
2747 [(set (match_operand:HI 0 "register_operand" "=d,d")
2748 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2749 (match_operand:HI 2 "register_operand" "y,x")))
2750 (clobber (match_scratch:HI 3 "=2,2"))]
2755 if (X_REG_P (operands[2]))
2756 return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2761 (define_insn "umulhisi3"
2762 [(set (match_operand:SI 0 "register_operand" "=D,D")
2763 (mult:SI (zero_extend:SI
2764 (match_operand:HI 1 "register_operand" "%d,d"))
2766 (match_operand:HI 2 "register_operand" "y,x"))))
2767 (clobber (match_scratch:HI 3 "=2,X"))]
2771 if (X_REG_P (operands [2]))
2772 output_asm_insn (\"exg\\tx,y\", operands);
2774 /* Can't use the carry after that; other flags are ok when testing
2775 the 32-bit result. */
2776 cc_status.flags |= CC_NO_OVERFLOW;
2777 return \"emul\\n\\texg\\tx,y\";
2780 (define_insn "mulhisi3"
2781 [(set (match_operand:SI 0 "register_operand" "=D,D")
2782 (mult:SI (sign_extend:SI
2783 (match_operand:HI 1 "register_operand" "%d,d"))
2785 (match_operand:HI 2 "register_operand" "y,x"))))
2786 (clobber (match_scratch:HI 3 "=2,X"))]
2790 if (X_REG_P (operands [2]))
2791 output_asm_insn (\"exg\\tx,y\", operands);
2793 /* Can't use the carry after that; other flags are ok when testing
2794 the 32-bit result. */
2795 cc_status.flags |= CC_NO_OVERFLOW;
2796 return \"emuls\\n\\texg\\tx,y\";
2799 (define_insn "umulqihi3"
2800 [(set (match_operand:HI 0 "register_operand" "=d")
2801 (mult:HI (zero_extend:HI
2802 (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2804 (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2808 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2810 output_asm_insn (\"tba\", operands);
2816 if (D_REG_P (operands[2]))
2818 rtx temp = operands[2];
2819 operands[2] = operands[1];
2823 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2824 ops[1] = operands[2];
2825 m68hc11_gen_movqi (insn, ops);
2827 if (!D_REG_P (operands[1]))
2829 output_asm_insn (\"ldab\\t%b1\", operands);
2837 (define_insn "mulqi3"
2838 [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
2839 (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
2840 (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
2844 if (A_REG_P (operands[0]))
2847 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2849 output_asm_insn (\"tba\", operands);
2853 if (D_REG_P (operands[2]))
2855 rtx temp = operands[2];
2856 operands[2] = operands[1];
2860 output_asm_insn (\"ldaa\\t%b2\", operands);
2862 if (!D_REG_P (operands[1]))
2864 output_asm_insn (\"ldab\\t%b1\", operands);
2873 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
2874 (mult:QI (match_operand:QI 1 "general_operand" "")
2875 (match_operand:QI 2 "general_operand" "")))]
2876 "z_replacement_completed == 2"
2877 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2878 (set (match_dup 3) (reg:HI D_REGNUM))])
2879 (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
2880 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
2881 (set (match_dup 3) (reg:HI D_REGNUM))])]
2883 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
2884 if (A_REG_P (operands[1]))
2885 operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2887 operands[5] = operands[1];
2888 if (A_REG_P (operands[2]))
2889 operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
2891 operands[6] = operands[2];
2894 (define_insn "mulqihi3"
2895 [(set (match_operand:HI 0 "register_operand" "=d,d,d")
2896 (mult:HI (sign_extend:HI
2897 (match_operand:QI 1 "register_operand" "%0,0,0"))
2899 (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
2905 /* Special case when multiplying the register with itself. */
2906 if (D_REG_P (operands[2]))
2908 output_asm_insn (\"tba\", operands);
2912 if (!H_REG_P (operands[2]))
2914 output_asm_insn (\"ldaa\\t%b2\", operands);
2920 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
2921 ops[1] = operands[2];
2922 m68hc11_gen_movqi (insn, ops);
2924 return \"jsr\\t___mulqi3\";
2927 ;;--------------------------------------------------------------------
2928 ;;- Divide instructions.
2929 ;;--------------------------------------------------------------------
2931 (define_insn "divmodhi4"
2932 [(set (match_operand:HI 0 "register_operand" "=d,d")
2933 (div:HI (match_operand:HI 1 "register_operand" "0,0")
2934 (match_operand:HI 2 "general_operand" "A,ium")))
2935 (set (match_operand:HI 3 "register_operand" "=&x,&x")
2936 (mod:HI (match_dup 1) (match_dup 2)))]
2940 if (!X_REG_P (operands[2]))
2942 if (Y_REG_P (operands[2]))
2944 output_asm_insn (\"sty\\t%t1\", operands);
2945 output_asm_insn (\"ldx\\t%t1\", operands);
2949 output_asm_insn (\"ldx\\t%2\", operands);
2954 /* Flags are ok after that. */
2955 return \"idivs\\n\\txgdx\";
2960 return \"bsr\\t__divmodhi4\";
2964 (define_insn "udivmodhi4"
2965 [(set (match_operand:HI 0 "register_operand" "=d,d")
2966 (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
2967 (match_operand:HI 2 "general_operand" "A,ium")))
2968 (set (match_operand:HI 3 "register_operand" "=x,x")
2969 (umod:HI (match_dup 1) (match_dup 2)))]
2973 if (!X_REG_P (operands[2]))
2975 if (Y_REG_P (operands[2]))
2977 output_asm_insn (\"sty\\t%t1\", operands);
2978 output_asm_insn (\"ldx\\t%t1\", operands);
2982 output_asm_insn (\"ldx\\t%2\", operands);
2986 /* Z V and C flags are set but N is unchanged.
2987 Since this is an unsigned divide, we can probably keep the flags
2988 and indicate this. */
2989 cc_status.flags |= CC_NOT_NEGATIVE;
2990 return \"idiv\\n\\txgdx\";
2993 ;;--------------------------------------------------------------------
2994 ;;- and instructions.
2995 ;;--------------------------------------------------------------------
2997 (define_insn_and_split "anddi3"
2998 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
2999 (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3000 (match_operand:DI 2 "general_operand" "imu,imu")))
3001 (clobber (match_scratch:HI 3 "=d,d"))]
3006 "m68hc11_split_logical (SImode, AND, operands);
3009 (define_insn_and_split "andsi3"
3010 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3011 (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3012 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3013 (clobber (match_scratch:HI 3 "=X,d"))]
3018 "m68hc11_split_logical (HImode, AND, operands);
3021 (define_expand "andhi3"
3022 [(set (match_operand:HI 0 "register_operand" "")
3023 (and:HI (match_operand:HI 1 "register_operand" "")
3024 (match_operand:HI 2 "general_operand" "")))]
3028 (define_insn "*andhi3_mem"
3029 [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3030 (and:HI (match_dup 0)
3031 (match_operand:HI 1 "immediate_operand" "i,i")))
3032 (clobber (match_scratch:HI 2 "=X,xy"))]
3033 "TARGET_RELAX && !TARGET_M6812"
3036 int val = INTVAL (operands[1]) & 0x0FFFF;
3040 cc_status = cc_prev_status;
3046 /* The bclr instruction uses an inverted mask. */
3047 operands[1] = GEN_INT ((~val) & 0x0FFFF);
3049 /* When destination is a global variable, generate a .relax instruction
3050 and load the address in the clobber register. That load can be
3051 eliminated by the linker if the address is in page0. */
3052 if (which_alternative == 1)
3056 ops[0] = operands[2];
3057 ops[1] = XEXP (operands[0], 0);
3058 ops[2] = gen_label_rtx ();
3059 output_asm_insn (\".relax\\t%l2\", ops);
3060 m68hc11_gen_movhi (insn, ops);
3061 if ((val & 0x0FF) != 0x0FF)
3062 output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
3064 if ((val & 0x0FF00) != 0x0FF00)
3065 output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
3067 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3068 CODE_LABEL_NUMBER (ops[2]));
3072 if ((val & 0x0FF) != 0x0FF)
3073 output_asm_insn (\"bclr\\t%b0, %b1\", operands);
3075 if ((val & 0x0FF00) != 0x0FF00)
3076 output_asm_insn (\"bclr\\t%h0, %h1\", operands);
3081 (define_insn "*andhi3_const"
3082 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3083 (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3084 (match_operand:HI 2 "const_int_operand" "")))]
3088 int val = INTVAL (operands[2]) & 0x0FFFF;
3089 int lowpart_zero = 0;
3090 int highpart_zero = 0;
3091 int lowpart_unknown = 0;
3092 int highpart_unknown = 0;
3094 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3099 cc_status = cc_prev_status;
3103 /* First, try to clear the low and high part.
3104 If that's possible, the second 'and' will give
3105 the good status flags and we can avoid a tsthi. */
3106 if ((val & 0x0FF) == 0)
3108 if (D_REG_P (operands[0]))
3109 output_asm_insn (\"clrb\", operands);
3111 output_asm_insn (\"clr\\t%b0\", operands);
3114 if ((val & 0x0FF00) == 0)
3116 if (D_REG_P (operands[0]))
3117 output_asm_insn (\"clra\", operands);
3119 output_asm_insn (\"clr\\t%h0\", operands);
3123 if ((val & 0x0FF) == 0x0FF)
3125 lowpart_unknown = 1;
3127 else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3131 ops[0] = operands[0];
3132 ops[1] = GEN_INT ((~val) & 0x0FF);
3133 output_asm_insn (\"bclr\\t%b0, %1\", ops);
3135 else if ((val & 0x0FF) != 0)
3137 output_asm_insn (\"andb\\t%b2\", operands);
3140 if ((val & 0x0FF00) == 0x0FF00)
3142 highpart_unknown = 1;
3144 else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3148 ops[0] = operands[0];
3149 ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
3150 output_asm_insn (\"bclr\\t%h0, %1\", ops);
3152 else if ((val & 0x0FF00) != 0)
3154 output_asm_insn (\"anda\\t%h2\", operands);
3157 if (highpart_unknown || lowpart_unknown)
3159 else if (highpart_zero == 0 && lowpart_zero == 0)
3165 (define_insn "*andhi3_gen"
3166 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3167 (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3168 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3172 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3176 return \"anda\\t%h2\\n\\tandb\\t%b2\";
3179 (define_expand "andqi3"
3180 [(set (match_operand:QI 0 "register_operand" "")
3181 (and:QI (match_operand:QI 1 "register_operand" "")
3182 (match_operand:QI 2 "general_operand" "")))]
3186 (define_insn "*andqi3_mem"
3187 [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3188 (and:QI (match_dup 0)
3189 (match_operand:QI 1 "const_int_operand" "i,i")))
3190 (clobber (match_scratch:HI 2 "=X,xy"))]
3191 "TARGET_RELAX && !TARGET_M6812"
3194 int val = INTVAL (operands[1]) & 0x0FF;
3198 cc_status = cc_prev_status;
3202 /* The bclr instruction uses an inverted mask. */
3203 operands[1] = GEN_INT ((~val) & 0x0FF);
3205 /* When destination is a global variable, generate a .relax instruction
3206 and load the address in the clobber register. That load can be
3207 eliminated by the linker if the address is in page0. */
3208 if (which_alternative == 1)
3212 ops[0] = operands[2];
3213 ops[1] = XEXP (operands[0], 0);
3214 ops[2] = gen_label_rtx ();
3215 output_asm_insn (\".relax\\t%l2\", ops);
3216 m68hc11_gen_movhi (insn, ops);
3217 output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3218 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3219 CODE_LABEL_NUMBER (ops[2]));
3222 return \"bclr\\t%b0, %1\";
3225 (define_insn "*andqi3_const"
3226 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3227 (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3228 (match_operand:QI 2 "const_int_operand" "")))]
3232 int val = INTVAL (operands[2]) & 0x0FF;
3234 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3239 cc_status = cc_prev_status;
3242 if (!H_REG_P (operands[0]))
3246 ops[0] = operands[0];
3247 ops[1] = GEN_INT ((~val) & 0x0FF);
3248 output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3251 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3252 return \"andb\\t%b2\";
3253 else if (DA_REG_P (operands[0]))
3254 return \"anda\\t%b2\";
3256 fatal_insn (\"Invalid operand in the instruction\", insn);
3259 (define_insn "*andqi3_gen"
3260 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3261 (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3262 (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
3266 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3269 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3270 return \"andb\\t%b2\";
3271 else if (DA_REG_P (operands[0]))
3272 return \"anda\\t%b2\";
3274 fatal_insn (\"Invalid operand in the instruction\", insn);
3277 ;;--------------------------------------------------------------------
3278 ;;- Bit set or instructions.
3279 ;;--------------------------------------------------------------------
3281 (define_insn_and_split "iordi3"
3282 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3283 (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3284 (match_operand:DI 2 "general_operand" "imu,imu")))
3285 (clobber (match_scratch:HI 3 "=d,d"))]
3290 "m68hc11_split_logical (SImode, IOR, operands);
3293 (define_insn_and_split "iorsi3"
3294 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3295 (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3296 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3297 (clobber (match_scratch:HI 3 "=X,d"))]
3302 "m68hc11_split_logical (HImode, IOR, operands);
3305 (define_expand "iorhi3"
3306 [(set (match_operand:HI 0 "register_operand" "")
3307 (ior:HI (match_operand:HI 1 "register_operand" "")
3308 (match_operand:HI 2 "splitable_operand" "")))]
3312 (define_insn "*iorhi3_mem"
3313 [(set (match_operand:HI 0 "memory_operand" "=R,Q")
3314 (ior:HI (match_dup 0)
3315 (match_operand:HI 1 "const_int_operand" "")))
3316 (clobber (match_scratch:HI 2 "=X,xy"))]
3317 "TARGET_RELAX && !TARGET_M6812"
3320 int val = INTVAL (operands[1]) & 0x0FFFF;
3324 cc_status = cc_prev_status;
3328 if (which_alternative == 1)
3332 ops[0] = operands[2];
3333 ops[1] = XEXP (operands[0], 0);
3334 ops[2] = gen_label_rtx ();
3335 output_asm_insn (\".relax\\t%l2\", ops);
3336 m68hc11_gen_movhi (insn, ops);
3337 if ((val & 0x0FF) != 0)
3338 output_asm_insn (\"bset\\t1,%2, %b1\", operands);
3340 if ((val & 0x0FF00) != 0)
3341 output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3342 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3343 CODE_LABEL_NUMBER (ops[2]));
3347 if ((val & 0x0FF) != 0)
3348 output_asm_insn (\"bset\\t%b0, %b1\", operands);
3350 if ((val & 0x0FF00) != 0)
3351 output_asm_insn (\"bset\\t%h0, %h1\", operands);
3356 (define_insn "*iorhi3_const"
3357 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3358 (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3359 (match_operand:HI 2 "const_int_operand" "")))]
3363 int val = INTVAL (operands[2]) & 0x0FFFF;
3365 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3370 cc_status = cc_prev_status;
3374 if ((val & 0x0FF) != 0)
3376 if (!H_REG_P (operands[0]))
3377 output_asm_insn (\"bset\\t%b0, %b2\", operands);
3379 output_asm_insn (\"orab\\t%b2\", operands);
3382 if ((val & 0x0FF00) != 0)
3384 if (!H_REG_P (operands[0]))
3385 output_asm_insn (\"bset\\t%h0, %h2\", operands);
3387 output_asm_insn (\"oraa\\t%h2\", operands);
3394 (define_insn "*iorhi3_gen"
3395 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3396 (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3397 (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
3401 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3405 return \"oraa\\t%h2\\n\\torab\\t%b2\";
3408 (define_expand "iorqi3"
3409 [(set (match_operand:QI 0 "register_operand" "")
3410 (ior:QI (match_operand:QI 1 "register_operand" "")
3411 (match_operand:QI 2 "general_operand" "")))]
3415 (define_insn "*iorqi3_mem"
3416 [(set (match_operand:QI 0 "memory_operand" "=R,Q")
3417 (ior:QI (match_dup 0)
3418 (match_operand:QI 1 "const_int_operand" "")))
3419 (clobber (match_scratch:HI 2 "=X,xy"))]
3420 "TARGET_RELAX && !TARGET_M6812"
3423 int val = INTVAL (operands[1]) & 0x0FF;
3427 cc_status = cc_prev_status;
3430 if (which_alternative == 1)
3434 ops[0] = operands[2];
3435 ops[1] = XEXP (operands[0], 0);
3436 ops[2] = gen_label_rtx ();
3437 output_asm_insn (\".relax\\t%l2\", ops);
3438 m68hc11_gen_movhi (insn, ops);
3439 output_asm_insn (\"bset\\t0,%2, %1\", operands);
3440 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3441 CODE_LABEL_NUMBER (ops[2]));
3444 return \"bset\\t%b0, %1\";
3447 (define_insn "*iorqi3_const"
3448 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3449 (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3450 (match_operand:QI 2 "const_int_operand" "")))]
3454 int val = INTVAL (operands[2]) & 0x0FF;
3456 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3461 cc_status = cc_prev_status;
3464 if (!H_REG_P (operands[0]))
3466 return \"bset\\t%b0, %2\";
3469 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3470 return \"orab\\t%b2\";
3471 else if (DA_REG_P (operands[0]))
3472 return \"oraa\\t%b2\";
3474 fatal_insn (\"Invalid operand in the instruction\", insn);
3477 (define_insn "*iorqi3_gen"
3478 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3479 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3480 (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
3484 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3487 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3488 return \"orab\\t%b2\";
3489 else if (DA_REG_P (operands[0]))
3490 return \"oraa\\t%b2\";
3492 fatal_insn (\"Invalid operand in the instruction\", insn);
3496 ;;--------------------------------------------------------------------
3497 ;;- xor instructions.
3498 ;;--------------------------------------------------------------------
3500 (define_insn_and_split "xordi3"
3501 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3502 (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3503 (match_operand:DI 2 "general_operand" "imu,imu")))
3504 (clobber (match_scratch:HI 3 "=d,d"))]
3509 "m68hc11_split_logical (SImode, XOR, operands);
3512 (define_insn_and_split "xorsi3"
3513 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3514 (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3515 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3516 (clobber (match_scratch:HI 3 "=X,d"))]
3521 "m68hc11_split_logical (HImode, XOR, operands);
3524 (define_insn "xorhi3"
3525 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3526 (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
3527 (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
3531 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3534 if (GET_CODE (operands[2]) == CONST_INT)
3536 int val = INTVAL (operands[2]) & 0x0FFFF;
3540 cc_status = cc_prev_status;
3543 if ((val & 0x0FF) != 0)
3545 output_asm_insn (\"eorb\\t%b2\", operands);
3547 else if ((val & 0x0FF) == 0x0FF)
3549 output_asm_insn (\"comb\", operands);
3552 if ((val & 0x0FF00) != 0)
3554 output_asm_insn (\"eora\\t%h2\", operands);
3556 else if ((val & 0x0FF00) == 0x0FF00)
3558 output_asm_insn (\"coma\", operands);
3566 return \"eora\\t%h2\\n\\teorb\\t%b2\";
3569 (define_insn "xorqi3"
3570 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3571 (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
3572 (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
3576 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3579 if (GET_CODE (operands[2]) == CONST_INT)
3581 int val = INTVAL (operands[2]) & 0x0FF;
3585 cc_status = cc_prev_status;
3590 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3596 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3597 return \"eorb\\t%b2\";
3598 else if (DA_REG_P (operands[0]))
3599 return \"eora\\t%b2\";
3601 fatal_insn (\"Invalid operand in the instruction\", insn);
3604 ;;--------------------------------------------------------------------
3605 ;;- Bit set or instructions.
3606 ;;--------------------------------------------------------------------
3608 (define_insn_and_split "*logicalsi3_zexthi"
3609 [(set (match_operand:SI 0 "register_operand" "=D")
3610 (match_operator:SI 3 "m68hc11_logical_operator"
3612 (match_operand:HI 1 "general_operand" "imudA"))
3613 (match_operand:SI 2 "general_operand" "Dimu")]))]
3617 [(set (reg:HI D_REGNUM) (match_dup 4))
3618 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3619 (set (reg:HI X_REGNUM) (match_dup 6))]
3620 "PUT_MODE (operands[3], HImode);
3621 if (X_REG_P (operands[2]))
3623 operands[5] = operands[1];
3624 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3625 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3626 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3630 operands[4] = operands[1];
3631 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3632 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3634 /* For an AND, make sure the high 16-bit part is cleared. */
3635 if (GET_CODE (operands[3]) == AND)
3637 operands[6] = const0_rtx;
3641 (define_insn_and_split "*logicalsi3_zextqi"
3642 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3643 (match_operator:SI 3 "m68hc11_logical_operator"
3645 (match_operand:QI 1 "general_operand" "d,*A,imu"))
3646 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3649 "z_replacement_completed == 2"
3650 [(set (reg:QI A_REGNUM) (match_dup 4))
3651 (set (reg:QI D_REGNUM) (match_dup 7))
3652 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3653 (set (reg:HI X_REGNUM) (match_dup 6))]
3654 "PUT_MODE (operands[3], QImode);
3655 if (X_REG_P (operands[2]))
3657 operands[5] = operands[1];
3658 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3659 operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3660 operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
3661 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3665 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3666 operands[7] = operands[1];
3667 operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3668 operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3669 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3671 /* For an AND, make sure the high 24-bit part is cleared. */
3672 if (GET_CODE (operands[3]) == AND)
3674 operands[4] = const0_rtx;
3675 operands[6] = const0_rtx;
3679 (define_insn_and_split "*logicalhi3_zexthi_ashift8"
3680 [(set (match_operand:HI 0 "register_operand" "=d")
3681 (match_operator:HI 3 "m68hc11_logical_operator"
3683 (match_operand:QI 1 "general_operand" "imud*A"))
3685 (match_operand:HI 2 "general_operand" "imud*A")
3689 "z_replacement_completed == 2"
3690 [(set (reg:QI A_REGNUM) (match_dup 4))
3691 (set (reg:QI B_REGNUM) (match_dup 5))]
3693 if (GET_CODE (operands[3]) == AND)
3695 emit_insn (gen_movhi (operands[0], const0_rtx));
3700 operands[5] = operands[1];
3701 if (D_REG_P (operands[2]))
3703 operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3707 operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3712 (define_insn_and_split "*logicalhi3_zexthi"
3713 [(set (match_operand:HI 0 "register_operand" "=d,d")
3714 (match_operator:HI 3 "m68hc11_logical_operator"
3716 (match_operand:QI 1 "general_operand" "imd*A,?u"))
3717 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
3720 "z_replacement_completed == 2"
3721 [(set (reg:QI B_REGNUM) (match_dup 6))
3722 (set (reg:QI A_REGNUM) (match_dup 4))
3723 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
3725 PUT_MODE (operands[3], QImode);
3726 if (D_REG_P (operands[2]))
3728 operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
3729 operands[5] = operands[1];
3730 operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3734 operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3735 operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3736 if (D_REG_P (operands[1]))
3737 operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
3739 operands[6] = operands[1];
3741 /* For an AND, make sure the high 8-bit part is cleared. */
3742 if (GET_CODE (operands[3]) == AND)
3744 operands[4] = const0_rtx;
3749 (define_insn_and_split "*logicalsi3_silshr16"
3750 [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
3751 (match_operator:SI 3 "m68hc11_logical_operator"
3753 (match_operand:SI 1 "general_operand" "uim,uim,0,0")
3755 (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
3759 [(set (reg:HI D_REGNUM) (match_dup 4))
3760 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3761 (set (reg:HI X_REGNUM) (match_dup 6))]
3762 "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3763 if (X_REG_P (operands[2]))
3765 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3766 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3770 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3771 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3773 PUT_MODE (operands[3], HImode);
3775 /* For an AND, make sure the high 16-bit part is cleared. */
3776 if (GET_CODE (operands[3]) == AND)
3778 operands[6] = const0_rtx;
3782 (define_insn_and_split "*logicalsi3_silshl16"
3783 [(set (match_operand:SI 0 "register_operand" "=D,D")
3784 (match_operator:SI 3 "m68hc11_logical_operator"
3786 (match_operand:SI 1 "general_operand" "uim,?D")
3788 (match_operand:SI 2 "general_operand" "0,0")]))]
3791 "z_replacement_completed == 2"
3792 [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3793 (set (reg:HI D_REGNUM) (match_dup 5))]
3794 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
3795 PUT_MODE (operands[3], HImode);
3797 if (GET_CODE (operands[3]) == AND)
3798 operands[5] = const0_rtx;
3800 operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3803 (define_insn_and_split "*logicalsi3_silshl16_zext"
3804 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3805 (match_operator:SI 3 "m68hc11_logical_operator"
3808 (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
3810 (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
3813 ;; Must split before z register replacement
3815 [(set (match_dup 4) (match_dup 5))
3816 (set (match_dup 6) (match_dup 7))]
3818 /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
3819 if (GET_CODE (operands[1]) == HARD_D_REGNUM
3820 && GET_CODE (operands[3]) != AND)
3822 /* This particular case is too early to be split before
3823 Z register replacement because the cse-reg pass we do
3824 does not recognize the 'swap_areg'. It is ok to handle
3826 if (z_replacement_completed != 2)
3830 emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
3831 emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
3832 gen_rtx_REG (HImode, HARD_X_REGNUM)));
3834 operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
3835 operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
3836 operands[5] = operands[2];
3837 operands[7] = operands[1];
3839 if (GET_CODE (operands[3]) == AND)
3840 operands[5] = operands[7] = const0_rtx;
3843 ;;--------------------------------------------------------------------
3844 ;; 16-bit Arithmetic and logical operations on X and Y:
3846 ;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3848 ;; Operations on X or Y registers are split here. Instructions are
3850 ;; - xgdx/xgdy instruction pattern,
3851 ;; - The same operation on register D,
3852 ;; - xgdx/xgdy instruction pattern.
3853 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3854 ;; We also handle the case were the address register is used in both source
3855 ;; operands, such as:
3857 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3859 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3863 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3864 (match_operator:HI 3 "m68hc11_arith_operator"
3865 [(match_operand:HI 1 "hard_addr_reg_operand" "")
3866 (match_operand:HI 2 "general_operand" "")]))]
3867 "z_replacement_completed == 2
3868 /* If we are adding a small constant to X or Y, it's
3869 better to use one or several inx/iny instructions. */
3870 && !(GET_CODE (operands[3]) == PLUS
3872 && (immediate_operand (operands[2], HImode)
3873 || hard_reg_operand (operands[2], HImode)))
3874 || (GET_CODE (operands[2]) == CONST_INT
3875 && INTVAL (operands[2]) >= -4
3876 && INTVAL (operands[2]) <= 4)))"
3877 [(set (match_dup 9) (match_dup 0))
3878 (set (match_dup 4) (match_dup 5))
3879 (set (match_dup 8) (match_dup 7))
3880 (set (match_dup 0) (match_dup 1))
3881 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3882 (set (match_dup 0) (reg:HI D_REGNUM))])
3883 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3884 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3885 (set (match_dup 0) (reg:HI D_REGNUM))])]
3887 operands[9] = operands[0];
3888 /* For 68HC12, push the value on the stack and do the operation
3891 && m68hc11_non_shift_operator (operands[3], HImode)
3892 && (H_REG_P (operands[2])
3893 || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3894 && reg_mentioned_p (operands[0], operands[2]))))
3896 operands[4] = gen_rtx_MEM (HImode,
3897 gen_rtx_PRE_DEC (HImode,
3898 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3899 operands[6] = gen_rtx_MEM (HImode,
3900 gen_rtx_POST_INC (HImode,
3901 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3902 operands[5] = operands[2];
3903 operands[8] = operands[7] = operands[0];
3905 /* Save the operand2 in a temporary location and use it. */
3906 else if ((H_REG_P (operands[2])
3907 || reg_mentioned_p (operands[0], operands[2]))
3908 && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
3910 if (GET_CODE (operands[3]) == MINUS
3911 && reg_mentioned_p (operands[0], operands[2]))
3913 operands[9] = gen_rtx_MEM (HImode,
3914 gen_rtx_PRE_DEC (HImode,
3915 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3916 operands[1] = gen_rtx_MEM (HImode,
3917 gen_rtx_POST_INC (HImode,
3918 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
3919 operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3920 operands[4] = operands[7] = operands[0];
3921 operands[6] = operands[8];
3922 operands[5] = operands[2];
3926 operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
3927 operands[6] = operands[4];
3928 if (!H_REG_P (operands[2]))
3930 operands[5] = operands[0];
3931 operands[7] = operands[2];
3932 operands[8] = operands[0];
3936 operands[5] = operands[2];
3937 operands[8] = operands[7] = operands[0];
3943 operands[4] = operands[5] = operands[0];
3944 operands[6] = operands[2];
3945 operands[8] = operands[7] = operands[0];
3950 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
3951 (match_operator:HI 3 "m68hc11_arith_operator"
3952 [(match_operand:HI 1 "general_operand" "")
3953 (match_operand:HI 2 "general_operand" "")]))]
3954 "z_replacement_completed == 2
3955 /* If we are adding a small constant to X or Y, it's
3956 better to use one or several inx/iny instructions. */
3957 && !(GET_CODE (operands[3]) == PLUS
3959 && (immediate_operand (operands[2], HImode)
3960 || hard_reg_operand (operands[2], HImode)))
3961 || (GET_CODE (operands[2]) == CONST_INT
3962 && INTVAL (operands[2]) >= -4
3963 && INTVAL (operands[2]) <= 4)))"
3964 [(set (match_dup 0) (match_dup 1))
3965 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3966 (set (match_dup 0) (reg:HI D_REGNUM))])
3967 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
3968 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3969 (set (match_dup 0) (reg:HI D_REGNUM))])]
3974 ;; Next split handles the logical operations on D register with
3975 ;; another hard register for the second operand. For this, we
3976 ;; have to save the second operand in a scratch location and use
3977 ;; it instead. This must be supported because in some (rare) cases
3978 ;; the second operand can come in a hard register and the reload
3979 ;; pass doesn't know how to reload it in a memory location.
3981 ;; PLUS MINUS AND IOR XOR
3983 ;; The shift operators are special and must not appear here.
3986 [(set (match_operand:HI 0 "d_register_operand" "")
3987 (match_operator:HI 3 "m68hc11_non_shift_operator"
3988 [(match_operand:HI 1 "d_register_operand" "")
3989 (match_operand:HI 2 "hard_reg_operand" "")]))]
3991 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
3992 [(set (match_dup 4) (match_dup 2))
3993 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
3994 "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
3997 ;; For 68HC12, push the operand[2] value on the stack and do the
3998 ;; logical/arithmetic operation with a pop.
4001 [(set (match_operand:HI 0 "d_register_operand" "")
4002 (match_operator:HI 3 "m68hc11_non_shift_operator"
4003 [(match_operand:HI 1 "d_register_operand" "")
4004 (match_operand:HI 2 "hard_reg_operand" "")]))]
4006 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4007 [(set (match_dup 4) (match_dup 2))
4008 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4009 "operands[4] = gen_rtx_MEM (HImode,
4010 gen_rtx_PRE_DEC (HImode,
4011 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4012 operands[5] = gen_rtx_MEM (HImode,
4013 gen_rtx_POST_INC (HImode,
4014 gen_rtx_REG (HImode, HARD_SP_REGNUM)));
4017 ;;--------------------------------------------------------------------
4018 ;; 16-bit Unary operations on X and Y:
4022 ;; Operations on X or Y registers are split here. Instructions are
4024 ;; - xgdx/xgdy instruction pattern,
4025 ;; - The same operation on register D,
4026 ;; - xgdx/xgdy instruction pattern.
4027 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4028 ;; We also handle the case were the address register is used in both source
4029 ;; operands, such as:
4031 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4033 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4036 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
4037 (match_operator:HI 2 "m68hc11_unary_operator"
4038 [(match_operand 1 "general_operand" "")]))]
4039 "z_replacement_completed == 2"
4040 [(set (match_dup 4) (match_dup 5))
4041 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4042 (set (match_dup 0) (reg:HI D_REGNUM))])
4043 (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4044 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4045 (set (match_dup 0) (reg:HI D_REGNUM))])]
4048 if ((H_REG_P (operands[1])
4049 && !rtx_equal_p (operands[0], operands[1]))
4050 || reg_mentioned_p (operands[0], operands[1]))
4052 /* Move to the destination register, before the xgdx. */
4053 operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
4054 REGNO (operands[0]));
4055 operands[5] = operands[1];
4057 /* Apply the operation on D. */
4058 operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
4062 /* Generate a copy to same register (nop). */
4063 operands[4] = operands[5] = operands[0];
4064 operands[3] = operands[1];
4069 ;; 8-bit operations on address registers.
4071 ;; We have to take care that the address register is not used for the
4072 ;; source of operand2. If operand2 is the D register, we have to save
4073 ;; that register in a temporary location.
4075 ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4078 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4079 (match_operator:QI 3 "m68hc11_arith_operator"
4080 [(match_operand:QI 1 "hard_addr_reg_operand" "")
4081 (match_operand:QI 2 "general_operand" "")]))]
4082 "z_replacement_completed == 2
4083 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
4084 incqi pattern generates a better code. */
4085 && !(GET_CODE (operands[3]) == PLUS
4086 && GET_CODE (operands[2]) == CONST_INT
4087 && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4088 [(set (match_dup 5) (match_dup 6))
4089 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4090 (set (match_dup 4) (reg:HI D_REGNUM))])
4091 (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4092 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4093 (set (match_dup 4) (reg:HI D_REGNUM))])]
4094 "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
4096 /* For the second operand is a hard register or if the address
4097 register appears in the source, we have to save the operand[2]
4098 value in a temporary location and then use that temp.
4099 Otherwise, it's ok and we generate a (set (D) (D)) that
4100 will result in a nop. */
4101 if (H_REG_P (operands[2]))
4103 operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4104 operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
4105 operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4107 else if (reg_mentioned_p (operands[0], operands[2]))
4109 operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4110 operands[6] = operands[2];
4111 operands[7] = operands[5];
4115 operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4116 operands[7] = operands[2];
4121 ;; Next split handles the logical operations on D register with
4122 ;; another hard register for the second operand. For this, we
4123 ;; have to save the second operand in a scratch location and use
4124 ;; it instead. This must be supported because in some (rare) cases
4125 ;; the second operand can come in a hard register and the reload
4126 ;; pass doesn't know how to reload it in a memory location.
4128 ;; PLUS MINUS AND IOR XOR
4130 ;; The shift operators are special and must not appear here.
4133 [(set (match_operand:QI 0 "d_register_operand" "")
4134 (match_operator:QI 3 "m68hc11_non_shift_operator"
4135 [(match_operand:QI 1 "d_register_operand" "")
4136 (match_operand:QI 2 "hard_reg_operand" "")]))]
4138 [(set (match_dup 5) (match_dup 6))
4139 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4140 "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
4141 operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
4142 operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
4144 ;;--------------------------------------------------------------------
4145 ;; 8-bit Unary operations on X and Y:
4149 ;; Operations on X or Y registers are split here. Instructions are
4151 ;; - xgdx/xgdy instruction pattern,
4152 ;; - The same operation on register D,
4153 ;; - xgdx/xgdy instruction pattern.
4154 ;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4155 ;; We also handle the case were the address register is used in both source
4156 ;; operands, such as:
4158 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4160 ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4163 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
4164 (match_operator:QI 2 "m68hc11_unary_operator"
4165 [(match_operand:QI 1 "general_operand" "")]))]
4166 "z_replacement_completed == 2"
4167 [(set (match_dup 4) (match_dup 5))
4168 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4169 (set (match_dup 3) (reg:HI D_REGNUM))])
4170 (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4171 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4172 (set (match_dup 3) (reg:HI D_REGNUM))])]
4175 operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
4176 if ((H_REG_P (operands[1])
4177 && !rtx_equal_p (operands[0], operands[1]))
4178 || reg_mentioned_p (operands[0], operands[1]))
4180 /* Move to the destination register, before the xgdx. */
4181 operands[4] = operands[0];
4182 operands[5] = operands[1];
4184 /* Apply the operation on D. */
4185 operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
4189 operands[4] = operands[5] = operands[0];
4190 operands[6] = operands[1];
4195 ;;--------------------------------------------------------------------
4197 ;;--------------------------------------------------------------------
4199 (define_expand "negdi2"
4200 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4201 (neg:DI (match_operand:DI 1 "general_operand" "")))]
4203 "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4207 (define_insn "negsi2"
4208 [(set (match_operand:SI 0 "register_operand" "=D")
4209 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
4217 /* With -Os or without -O, use a special library call. */
4218 if (optimize_size || optimize == 0)
4219 return \"bsr\\t___negsi2\";
4221 ops[0] = gen_label_rtx ();
4223 /* 32-bit complement and add 1. */
4224 output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4225 output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4226 output_asm_insn (\"bne\\t%l0\", ops);
4227 output_asm_insn (\"inx\", operands);
4228 (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4232 (define_insn "neghi2"
4233 [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
4234 (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4237 coma\\n\\tcomb\\n\\taddd\\t#1
4238 clra\\n\\tclrb\\n\\tsubd\\t%1
4239 xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4241 (define_insn "negqi2"
4242 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4243 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
4252 ;; - 32-bit complement. GCC knows how to translate them but providing a
4253 ;; pattern generates better/smaller code.
4255 (define_expand "one_cmpldi2"
4256 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4257 (not:DI (match_operand:DI 1 "general_operand" "")))]
4259 "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4262 (define_insn "one_cmplsi2"
4263 [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4264 (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4265 (clobber (match_scratch:HI 2 "=X,d,X"))]
4268 bsr\\t___one_cmplsi2
4272 (define_insn "one_cmplhi2"
4273 [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
4274 (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
4278 com\\t%b0\\n\\tcom\\t%h0
4280 com\\t%b0\\n\\tcom\\t%h0")
4282 (define_insn "one_cmplqi2"
4283 [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
4284 (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
4292 (define_split /* "*one_cmplsi2" */
4293 [(set (match_operand:SI 0 "non_push_operand" "")
4294 (not:SI (match_dup 0)))
4295 (clobber (match_scratch:HI 1 ""))]
4296 "z_replacement_completed == 2
4297 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4298 [(set (match_dup 2) (not:HI (match_dup 2)))
4299 (set (match_dup 3) (not:HI (match_dup 3)))]
4300 "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4301 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
4303 (define_split /* "*one_cmplsi2" */
4304 [(set (match_operand:SI 0 "non_push_operand" "")
4305 (not:SI (match_operand:SI 1 "non_push_operand" "")))
4306 (clobber (match_operand:HI 2 "d_register_operand" ""))]
4307 "z_replacement_completed == 2
4308 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4309 [(set (match_dup 2) (match_dup 3))
4310 (set (match_dup 2) (not:HI (match_dup 2)))
4311 (set (match_dup 4) (match_dup 2))
4312 (set (match_dup 2) (match_dup 5))
4313 (set (match_dup 2) (not:HI (match_dup 2)))
4314 (set (match_dup 6) (match_dup 2))]
4315 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4316 operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4317 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4318 operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
4320 ;;--------------------------------------------------------------------
4321 ;;- arithmetic shifts
4322 ;;--------------------------------------------------------------------
4324 ;; Provide some 64-bit shift patterns.
4325 (define_expand "ashldi3"
4326 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4327 (ashift:DI (match_operand:DI 1 "general_operand" "")
4328 (match_operand:HI 2 "general_operand" "")))
4329 (clobber (match_scratch:HI 3 ""))])]
4333 if (GET_CODE (operands[2]) != CONST_INT
4334 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4340 (define_insn_and_split "*ashldi3_const32"
4341 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4342 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
4344 (clobber (match_scratch:HI 2 "=&A,d,d"))]
4349 "/* Move the lowpart in the highpart first in case the shift
4350 is applied on the source. */
4351 if (IS_STACK_PUSH (operands[0]))
4353 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4354 const0_rtx, operands[2]);
4356 /* Adjust first operand if it uses SP so that we take into
4357 account the above push. Can occur only for 68HC12. */
4358 if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
4360 operands[1] = adjust_address (operands[1],
4361 GET_MODE (operands[0]), 4);
4363 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4364 m68hc11_gen_lowpart (SImode, operands[1]),
4366 if (!IS_STACK_PUSH (operands[0]))
4368 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4369 const0_rtx, operands[2]);
4373 (define_insn_and_split "*ashldi3_const1"
4374 [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4375 (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
4377 (clobber (match_scratch:HI 2 "=d,d,d"))]
4380 "z_replacement_completed == 2"
4381 [(set (match_dup 2) (match_dup 3))
4382 (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4383 (set (match_dup 4) (match_dup 2))
4385 (set (match_dup 2) (match_dup 5))
4386 (parallel [(set (match_dup 2)
4387 (rotate:HI (match_dup 2) (const_int 1)))
4388 (clobber (reg:HI CC_REGNUM))])
4389 (set (match_dup 6) (match_dup 2))
4391 (set (match_dup 2) (match_dup 7))
4392 (parallel [(set (match_dup 2)
4393 (rotate:HI (match_dup 2) (const_int 1)))
4394 (clobber (reg:HI CC_REGNUM))])
4395 (set (match_dup 8) (match_dup 2))
4397 (set (match_dup 2) (match_dup 9))
4398 (parallel [(set (match_dup 2)
4399 (rotate:HI (match_dup 2) (const_int 1)))
4400 (clobber (reg:HI CC_REGNUM))])
4401 (set (match_dup 10) (match_dup 2))]
4402 "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4403 operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4404 operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4406 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4407 operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4408 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4410 operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4411 operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4412 operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4414 operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4415 operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4416 operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4418 (define_insn "addsi_silshr16"
4419 [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
4420 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
4422 (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
4427 [(set (match_operand:SI 0 "register_operand" "")
4428 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4430 (match_operand:SI 2 "general_operand" "")))]
4431 "z_replacement_completed == 2 && !X_REG_P (operands[1])"
4432 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4433 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4435 (reg:HI CC_REGNUM)))]
4436 "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4439 [(set (match_operand:SI 0 "register_operand" "")
4440 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4442 (match_operand:SI 2 "general_operand" "")))]
4443 "z_replacement_completed == 2 && X_REG_P (operands[1])"
4444 [(set (reg:HI D_REGNUM) (match_dup 5))
4445 (set (reg:HI X_REGNUM) (match_dup 3))
4446 (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4447 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4449 (reg:HI CC_REGNUM)))]
4450 "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4451 if (X_REG_P (operands[2]))
4453 operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4454 operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4458 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4459 operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4463 (define_insn "addsi_ashift16"
4464 [(set (match_operand:SI 0 "register_operand" "=D")
4466 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4468 (match_operand:SI 1 "general_operand" "0")))
4469 (clobber (match_scratch:HI 3 "=X"))]
4474 [(set (match_operand:SI 0 "register_operand" "")
4476 (mult:SI (match_operand:SI 2 "general_operand" "")
4478 (match_operand:SI 1 "general_operand" "")))
4479 (clobber (match_scratch:HI 3 "=X"))]
4480 "0 && reload_completed && z_replacement_completed == 2"
4481 [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
4484 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4487 (define_insn_and_split "addsi_andshr16"
4488 [(set (match_operand:SI 0 "register_operand" "=D")
4489 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4491 (match_operand:SI 2 "general_operand" "0")))]
4494 "z_replacement_completed == 2"
4495 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4496 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
4497 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4500 ;; 32-bit shifts are made by a small library routine that uses
4501 ;; a specific passing convention for parameters (for efficiency reasons).
4503 ;; [D + X] -> Value to be shifted
4506 ;; The shift count is clobbered by the routine.
4508 (define_expand "ashlsi3"
4510 [(set (match_operand:SI 0 "register_operand" "")
4511 (match_operand:SI 1 "general_operand" ""))
4512 (clobber (scratch:HI))])
4514 [(set (match_dup 0) (ashift:SI (match_dup 0)
4515 (match_operand:HI 2 "nonmemory_operand" "")))
4516 (clobber (scratch:HI))])]
4521 [(set (match_operand:SI 0 "nonimmediate_operand" "")
4522 (ashift:SI (match_operand:SI 1 "general_operand" "")
4524 (clobber (match_scratch:HI 3 ""))]
4526 [(set (match_dup 2) (match_dup 3))
4527 (set (match_dup 4) (const_int 0))]
4528 "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4529 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4530 operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4532 (define_insn "*ashlsi3_const16"
4533 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4534 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
4536 (clobber (match_scratch:HI 2 "=X,X,X"))]
4540 (define_insn_and_split "*ashlsi3_const16_zexthi"
4541 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4542 (ashift:SI (zero_extend:HI
4543 (match_operand:HI 1 "general_operand" "duim*A"))
4545 (clobber (match_scratch:HI 2 "=X"))]
4549 [(set (reg:HI X_REGNUM) (match_dup 1))
4550 (set (reg:HI D_REGNUM) (const_int 0))]
4553 (define_insn "*ashlsi3_const1"
4554 [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
4555 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
4557 (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
4562 if (X_REG_P (operands[1]))
4564 return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4570 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4571 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
4572 m68hc11_gen_movhi (insn, ops);
4573 output_asm_insn (\"lsld\", ops);
4574 if (!X_REG_P (operands[0]))
4577 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4578 m68hc11_gen_movhi (insn, ops);
4580 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4581 m68hc11_gen_movhi (insn, ops);
4585 /* Load the high part in X in case the source operand
4586 uses X as a memory pointer. */
4587 ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
4588 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4589 m68hc11_gen_movhi (insn, ops);
4590 output_asm_insn (\"xgdx\", ops);
4592 output_asm_insn (\"rolb\", ops);
4593 output_asm_insn (\"rola\", ops);
4594 if (!X_REG_P (operands[0]))
4597 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4598 m68hc11_gen_movhi (insn, ops);
4602 output_asm_insn (\"xgdx\", ops);
4608 (define_insn "*ashlsi3_const"
4609 [(set (match_operand:SI 0 "register_operand" "+D")
4610 (ashift:SI (match_dup 0)
4611 (match_operand:HI 1 "const_int_operand" "")))
4612 (clobber (match_scratch:HI 2 "=y"))]
4613 "TARGET_M6811 /* See *ashlsi3 note. */"
4617 return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
4620 (define_insn "*ashlsi3"
4621 [(set (match_operand:SI 0 "register_operand" "+D,D")
4622 (ashift:SI (match_dup 0)
4623 (match_operand:HI 1 "general_operand" "y,mi")))
4624 (clobber (match_scratch:HI 2 "=1,X"))]
4630 /* There is a reload problem if we don't accept 'm' for the shift value.
4631 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4632 and this conflicts with all reloads. Since X, Y, Z are used there
4633 is not enough register in class A_REGS.
4635 Assuming that 'operands[1]' does not refer to the stack (which
4636 is true for 68hc11 only, we save temporary the value of Y.
4638 For 68HC12 we must also accept a constant because Z register is
4639 disabled when compiling with -fomit-frame-pointer. We can come up
4640 with a reload problem and the *lshrsi3_const pattern was disabled
4642 if (!Y_REG_P (operands[2]))
4645 int y_dead = dead_register_here (insn, iy_reg);
4647 ops[0] = operands[1];
4650 output_asm_insn (\"pshy\", operands);
4651 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4652 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
4654 output_asm_insn (\"ldy\\t%0\", ops);
4655 output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4656 return y_dead == 0 ? \"puly\" : \"\";
4658 return \"bsr\\t___ashlsi3\";
4661 (define_expand "ashlhi3"
4662 [(set (match_operand:HI 0 "register_operand" "")
4663 (ashift:HI (match_operand:HI 1 "register_operand" "")
4664 (match_operand:HI 2 "general_operand" "")))]
4668 if (GET_CODE (operands[2]) != CONST_INT)
4670 rtx scratch = gen_reg_rtx (HImode);
4671 emit_move_insn (scratch, operands[2]);
4672 emit_insn (gen_rtx_PARALLEL (VOIDmode,
4673 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4675 gen_rtx_ASHIFT (HImode,
4676 operand1, scratch)),
4677 gen_rtx_CLOBBER (VOIDmode, scratch))));
4682 (define_insn "*ashlhi3_const1"
4683 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4684 (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4689 if (A_REG_P (operands[0]))
4692 if (D_REG_P (operands[0]))
4697 output_asm_insn (\"asl\\t%b0\", operands);
4698 output_asm_insn (\"rol\\t%h0\", operands);
4704 (define_insn "*ashlhi3_2"
4705 [(set (match_operand:HI 0 "register_operand" "=d,*x")
4706 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4707 (match_operand:HI 2 "register_operand" "+x,+d")))
4708 (clobber (match_dup 2))]
4712 if (A_REG_P (operands[0]))
4716 return \"bsr\\t___lshlhi3\";
4719 (define_insn "*ashlhi3"
4720 [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4721 (ashift:HI (match_dup 0)
4722 (match_operand:HI 1 "register_operand" "+x")))
4723 (clobber (match_dup 1))]
4728 return \"bsr\\t___lshlhi3\";
4731 (define_insn "*ashlhi3"
4732 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4733 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4734 (match_operand:HI 2 "const_int_operand" "")))]
4740 if (A_REG_P (operands[0]))
4743 i = INTVAL (operands[2]);
4747 output_asm_insn (\"tba\", operands);
4750 output_asm_insn (\"rora\", operands);
4751 output_asm_insn (\"anda\\t#0\", operands);
4752 output_asm_insn (\"rora\", operands);
4757 output_asm_insn (\"asla\", operands);
4762 for (i = 0; i < INTVAL (operands[2]) - 1; i++)
4764 output_asm_insn (\"asld\", operands);
4769 (define_expand "ashlqi3"
4770 [(set (match_operand:QI 0 "register_operand" "")
4771 (ashift:QI (match_operand:QI 1 "register_operand" "")
4772 (match_operand:QI 2 "general_operand" "")))]
4776 (define_insn "*ashlqi3_const1"
4777 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4778 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
4788 (define_insn "*ashlqi3_const"
4789 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4790 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4791 (match_operand:QI 2 "const_int_operand" "")))]
4796 const char* insn_code;
4798 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4799 insn_code = \"aslb\";
4800 else if (DA_REG_P (operands[0]))
4801 insn_code = \"asla\";
4805 i = INTVAL (operands[2]);
4808 if (DA_REG_P (operands[0]))
4815 if (DA_REG_P (operands[0]))
4817 output_asm_insn (\"rora\", operands);
4818 output_asm_insn (\"ldaa\\t#0\", operands);
4823 output_asm_insn (\"rorb\", operands);
4824 output_asm_insn (\"ldab\\t#0\", operands);
4830 if (DA_REG_P (operands[0]))
4832 output_asm_insn (\"rora\", operands);
4833 output_asm_insn (\"rora\", operands);
4834 output_asm_insn (\"rora\", operands);
4835 return \"anda\\t#0xC0\";
4839 output_asm_insn (\"rorb\", operands);
4840 output_asm_insn (\"rorb\", operands);
4841 output_asm_insn (\"rorb\", operands);
4842 return \"andb\\t#0xC0\";
4847 output_asm_insn (insn_code, operands);
4852 (define_insn "*ashlqi3"
4853 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4854 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4855 (match_operand:QI 2 "nonimmediate_operand"
4856 "m*u*d*A,m*u*d*A,m*u")))]
4862 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4865 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
4866 ops[1] = operands[2];
4867 m68hc11_gen_movqi (insn, ops);
4870 return \"bsr\\t___lshlqi3\";
4873 (define_expand "ashrhi3"
4874 [(set (match_operand:HI 0 "register_operand" "")
4875 (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4876 (match_operand:HI 2 "general_operand" "")))]
4880 if (GET_CODE (operands[2]) != CONST_INT)
4882 rtx scratch = gen_reg_rtx (HImode);
4884 emit_move_insn (scratch, operands[2]);
4885 emit_insn (gen_rtx_PARALLEL (VOIDmode,
4886 gen_rtvec (2, gen_rtx_SET (VOIDmode,
4888 gen_rtx_ASHIFTRT (HImode,
4889 operand1, scratch)),
4890 gen_rtx_CLOBBER (VOIDmode, scratch))));
4895 (define_insn "*ashrhi3_const1"
4896 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4897 (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4902 if (A_REG_P (operands[0]))
4906 if (D_REG_P (operands[0]))
4908 return \"asra\\n\\trorb\";
4911 output_asm_insn (\"asr\\t%h0\", operands);
4912 output_asm_insn (\"ror\\t%b0\", operands);
4917 (define_insn "*ashrhi3_const"
4918 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4919 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4920 (match_operand:HI 2 "const_int_operand" "")))]
4925 int val = INTVAL (operands[2]);
4927 if (A_REG_P (operands[0]))
4932 ops[0] = gen_label_rtx ();
4934 output_asm_insn (\"clrb\", operands);
4935 output_asm_insn (\"rola\", operands);
4937 /* Clear A without clearing the carry flag. */
4938 output_asm_insn (\"tba\", operands);
4939 output_asm_insn (\"bcc\\t%l0\", ops);
4940 output_asm_insn (\"coma\", operands);
4941 output_asm_insn (\"comb\", operands);
4944 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4945 CODE_LABEL_NUMBER (ops[0]));
4950 ops[0] = gen_label_rtx ();
4952 output_asm_insn (\"tab\", operands);
4953 output_asm_insn (\"clra\", operands);
4954 output_asm_insn (\"tstb\", operands);
4955 output_asm_insn (\"bge\\t%l0\", ops);
4956 output_asm_insn (\"deca\", operands);
4958 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4959 CODE_LABEL_NUMBER (ops[0]));
4965 output_asm_insn (\"asrb\", operands);
4973 ops[0] = gen_label_rtx ();
4974 output_asm_insn (\"rolb\", operands);
4975 output_asm_insn (\"rola\", operands);
4976 output_asm_insn (\"tab\", operands);
4977 output_asm_insn (\"anda\\t#0\", operands);
4978 output_asm_insn (\"bcc\\t%l0\", ops);
4979 output_asm_insn (\"coma\", ops);
4981 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4982 CODE_LABEL_NUMBER (ops[0]));
4987 output_asm_insn (\"asra\", operands);
4988 output_asm_insn (\"rorb\", operands);
4996 (define_insn "*ashrhi3"
4997 [(set (match_operand:HI 0 "register_operand" "=d,*x")
4998 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4999 (match_operand:HI 2 "register_operand" "+x,+d")))
5000 (clobber (match_dup 2))]
5004 if (A_REG_P (operands[0]))
5007 output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5011 (define_expand "ashrsi3"
5013 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5014 (clobber (scratch:HI))])
5016 [(set (match_operand:SI 0 "register_operand" "")
5017 (ashiftrt:SI (match_dup 0)
5018 (match_operand:HI 2 "general_operand" "")))
5019 (clobber (scratch:HI))])]
5023 (define_insn "*ashrsi3_const"
5024 [(set (match_operand:SI 0 "register_operand" "+D")
5025 (ashiftrt:SI (match_dup 0)
5026 (match_operand:HI 1 "const_int_operand" "")))
5027 (clobber (match_scratch:HI 2 "=y"))]
5028 "TARGET_M6811 /* See *ashrsi3 note. */"
5032 return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
5035 (define_insn "*ashrsi3"
5036 [(set (match_operand:SI 0 "register_operand" "+D,D")
5037 (ashiftrt:SI (match_dup 0)
5038 (match_operand:HI 1 "general_operand" "y,mi")))
5039 (clobber (match_scratch:HI 2 "=1,X"))]
5044 /* There is a reload problem if we don't accept 'm' for the shift value.
5045 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5046 and this conflicts with all reloads. Since X, Y, Z are used there
5047 is not enough register in class A_REGS.
5049 Assuming that 'operands[1]' does not refer to the stack (which
5050 is true for 68hc11 only, we save temporary the value of Y.
5052 For 68HC12 we must also accept a constant because Z register is
5053 disabled when compiling with -fomit-frame-pointer. We can come up
5054 with a reload problem and the *lshrsi3_const pattern was disabled
5056 if (!Y_REG_P (operands[2]))
5059 int y_dead = dead_register_here (insn, iy_reg);
5061 ops[0] = operands[1];
5064 output_asm_insn (\"pshy\", operands);
5065 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5066 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5068 output_asm_insn (\"ldy\\t%0\", ops);
5069 output_asm_insn (\"bsr\\t___ashrsi3\", operands);
5070 return y_dead == 0 ? \"puly\" : \"\";
5072 return \"bsr\\t___ashrsi3\";
5075 (define_expand "ashrqi3"
5076 [(set (match_operand:QI 0 "register_operand" "")
5077 (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5078 (match_operand:QI 2 "general_operand" "")))]
5082 (define_insn "*ashrqi3_const1"
5083 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5084 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5094 (define_insn "*ashrqi3_const"
5095 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5096 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5097 (match_operand:QI 2 "const_int_operand" "")))]
5102 const char* insn_code;
5104 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5105 insn_code = \"asrb\";
5106 else if (DA_REG_P (operands[0]))
5107 insn_code = \"asra\";
5111 i = INTVAL (operands[2]);
5116 output_asm_insn (insn_code, operands);
5121 (define_insn "*ashrqi3"
5122 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5123 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5124 (match_operand:QI 2 "nonimmediate_operand"
5125 "m*u*d*A,m*u*d*A,m*u")))]
5131 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5134 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5135 ops[1] = operands[2];
5136 m68hc11_gen_movqi (insn, ops);
5139 return \"bsr\\t___ashrqi3\";
5142 ;;--------------------------------------------------------------------
5143 ;; logical shift instructions
5144 ;;--------------------------------------------------------------------
5145 (define_expand "lshrdi3"
5146 [(parallel [(set (match_operand:DI 0 "general_operand" "")
5147 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5148 (match_operand:HI 2 "general_operand" "")))
5149 (clobber (match_scratch:HI 3 ""))])]
5153 if (GET_CODE (operands[2]) != CONST_INT
5154 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5155 && INTVAL (operands[2]) != 1))
5161 (define_insn_and_split "*lshrdi3_const32"
5162 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5163 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
5165 (clobber (match_scratch:HI 2 "=&A,d,d"))]
5170 "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5171 m68hc11_gen_highpart (SImode, operands[1]),
5173 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5174 const0_rtx, operands[2]);
5177 (define_insn "*lshrdi3_const63"
5178 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5179 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5180 (match_operand:DI 2 "const_int_operand" "")))
5181 (clobber (match_scratch:HI 3 "=d,d"))]
5182 "INTVAL (operands[2]) >= 48"
5186 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5187 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5188 (match_operand:DI 2 "const_int_operand" "")))
5189 (clobber (match_scratch:HI 3 "=d"))]
5190 "z_replacement_completed && INTVAL (operands[2]) >= 56"
5191 [(set (reg:QI D_REGNUM) (match_dup 9))
5192 (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5193 (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5194 (set (match_dup 4) (reg:HI D_REGNUM))
5195 (set (reg:QI D_REGNUM) (const_int 0))
5196 (set (match_dup 5) (reg:HI D_REGNUM))
5197 (set (match_dup 6) (reg:HI D_REGNUM))
5198 (set (match_dup 7) (reg:HI D_REGNUM))]
5199 "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
5200 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5201 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5202 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5204 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5205 operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5206 operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5208 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5209 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5210 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5213 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5214 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5215 (match_operand:DI 2 "const_int_operand" "")))
5216 (clobber (match_scratch:HI 3 "=d"))]
5217 "z_replacement_completed && INTVAL (operands[2]) >= 48
5218 && INTVAL (operands[2]) < 56"
5219 [(set (reg:HI D_REGNUM) (match_dup 9))
5220 (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5221 (set (match_dup 4) (reg:HI D_REGNUM))
5222 (set (reg:HI D_REGNUM) (const_int 0))
5223 (set (match_dup 5) (reg:HI D_REGNUM))
5224 (set (match_dup 6) (reg:HI D_REGNUM))
5225 (set (match_dup 7) (reg:HI D_REGNUM))]
5226 "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
5227 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5228 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5229 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5231 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5232 operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5233 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5234 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5235 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5237 (define_insn_and_split "*lshrdi_const1"
5238 [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5239 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
5241 (clobber (match_scratch:HI 2 "=d,d"))]
5244 "z_replacement_completed == 2"
5245 [(set (match_dup 2) (match_dup 3))
5246 (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5247 (set (match_dup 4) (match_dup 2))
5249 (set (match_dup 2) (match_dup 5))
5250 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5251 (clobber (reg:HI CC_REGNUM))])
5252 (set (match_dup 6) (match_dup 2))
5254 (set (match_dup 2) (match_dup 7))
5255 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5256 (clobber (reg:HI CC_REGNUM))])
5257 (set (match_dup 8) (match_dup 2))
5259 (set (match_dup 2) (match_dup 9))
5260 (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
5261 (clobber (reg:HI CC_REGNUM))])
5262 (set (match_dup 10) (match_dup 2))]
5263 "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5264 operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5265 operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5267 operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5268 operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5269 operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5271 operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5272 operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5273 operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5275 operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5276 operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5277 operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5279 (define_expand "lshrsi3"
5281 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5282 (clobber (scratch:HI))])
5284 [(set (match_operand:SI 0 "register_operand" "")
5285 (lshiftrt:SI (match_dup 0)
5286 (match_operand:HI 2 "general_operand" "")))
5287 (clobber (scratch:HI))])]
5292 [(set (match_operand:SI 0 "non_push_operand" "")
5293 (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
5295 (clobber (match_scratch:HI 3 ""))]
5296 "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5297 [(set (match_dup 2) (match_dup 3))
5298 (set (match_dup 4) (const_int 0))]
5299 "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5300 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5301 operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5303 (define_insn "*lshrsi3_const16"
5304 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5305 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
5307 (clobber (match_scratch:HI 2 "=X,X,X,X"))]
5315 (define_insn "*lshrsi3_const1"
5316 [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
5317 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
5319 (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
5324 if (X_REG_P (operands[1]))
5326 return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5332 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5333 ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
5334 m68hc11_gen_movhi (insn, ops);
5335 output_asm_insn (\"lsrd\", ops);
5336 if (!X_REG_P (operands[0]))
5339 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5340 m68hc11_gen_movhi (insn, ops);
5342 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5343 m68hc11_gen_movhi (insn, ops);
5347 /* Load the lowpart in X in case the operands is some N,x. */
5348 ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
5349 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5350 m68hc11_gen_movhi (insn, ops);
5351 output_asm_insn (\"xgdx\", ops);
5353 output_asm_insn (\"rora\", ops);
5354 output_asm_insn (\"rorb\", ops);
5355 if (!X_REG_P (operands[0]))
5358 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5359 m68hc11_gen_movhi (insn, ops);
5365 (define_insn "*lshrsi3_const"
5366 [(set (match_operand:SI 0 "register_operand" "+D")
5367 (lshiftrt:SI (match_dup 0)
5368 (match_operand:HI 1 "const_int_operand" "")))
5369 (clobber (match_scratch:HI 2 "=y"))]
5370 "TARGET_M6811 /* See *lshrsi3 note. */"
5374 return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
5377 (define_insn "*lshrsi3"
5378 [(set (match_operand:SI 0 "register_operand" "+D,D")
5379 (lshiftrt:SI (match_dup 0)
5380 (match_operand:HI 1 "general_operand" "y,mi")))
5381 (clobber (match_scratch:HI 2 "=1,X"))]
5386 /* There is a reload problem if we don't accept 'm' for the shift value.
5387 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5388 and this conflicts with all reloads. Since X, Y, Z are used there
5389 is not enough register in class A_REGS.
5391 Assuming that 'operands[1]' does not refer to the stack (which
5392 is true for 68hc11 only, we save temporary the value of Y.
5394 For 68HC12 we must also accept a constant because Z register is
5395 disabled when compiling with -fomit-frame-pointer. We can come up
5396 with a reload problem and the *lshrsi3_const pattern was disabled
5398 if (!Y_REG_P (operands[2]))
5401 int y_dead = dead_register_here (insn, iy_reg);
5403 ops[0] = operands[1];
5406 output_asm_insn (\"pshy\", operands);
5407 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5408 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
5410 output_asm_insn (\"ldy\\t%0\", ops);
5411 output_asm_insn (\"bsr\\t___lshrsi3\", operands);
5412 return y_dead == 0 ? \"puly\" : \"\";
5414 return \"bsr\\t___lshrsi3\";
5417 (define_expand "lshrhi3"
5418 [(set (match_operand:HI 0 "register_operand" "")
5419 (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5420 (match_operand:HI 2 "general_operand" "")))]
5424 if (GET_CODE (operands[2]) != CONST_INT)
5426 rtx scratch = gen_reg_rtx (HImode);
5427 operand1 = force_reg (HImode, operand1);
5429 emit_move_insn (scratch, operands[2]);
5430 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5431 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5433 gen_rtx_LSHIFTRT (HImode,
5434 operand1, scratch)),
5435 gen_rtx_CLOBBER (VOIDmode, scratch))));
5440 (define_insn "lshrhi3_const1"
5441 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5442 (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5447 if (A_REG_P (operands[0]))
5450 if (D_REG_P (operands[0]))
5454 return \"lsr\\t%h0\\n\\tror\\t%b0\";
5457 (define_insn "lshrhi3_const"
5458 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5459 (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5460 (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5464 int val = INTVAL (operands[2]);
5466 if (A_REG_P (operands[0]))
5474 if (!H_REG_P (operands[1]))
5476 output_asm_insn (\"clra\", operands);
5477 output_asm_insn (\"ldab\\t%h1\", operands);
5479 else if (A_REG_P (operands[1]))
5481 output_asm_insn (\"st%1\\t%t0\", operands);
5482 output_asm_insn (\"ldab\\t%t0\", operands);
5483 output_asm_insn (\"clra\", operands);
5487 output_asm_insn (\"tab\", operands);
5488 output_asm_insn (\"clra\", operands);
5494 output_asm_insn (\"rolb\", operands);
5495 output_asm_insn (\"tab\", operands);
5496 output_asm_insn (\"rolb\", operands);
5500 output_asm_insn (\"rolb\", operands);
5501 output_asm_insn (\"rolb\", operands);
5502 output_asm_insn (\"rolb\", operands);
5503 output_asm_insn (\"andb\\t#3\", operands);
5510 output_asm_insn (\"lsrb\", operands);
5517 if (!D_REG_P (operands[1]))
5518 m68hc11_gen_movhi (insn, operands);
5522 output_asm_insn (\"rolb\", operands);
5523 output_asm_insn (\"tab\", operands);
5524 output_asm_insn (\"rolb\", operands);
5525 output_asm_insn (\"rola\", operands);
5526 output_asm_insn (\"rola\", operands);
5527 output_asm_insn (\"anda\\t#1\", operands);
5535 output_asm_insn (\"lsrd\", operands);
5541 (define_insn "*lshrhi3"
5542 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5543 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
5544 (match_operand:HI 2 "register_operand" "+x,+d")))
5545 (clobber (match_dup 2))]
5549 if (A_REG_P (operands[0]))
5552 return \"bsr\\t___lshrhi3\";
5555 (define_expand "lshrqi3"
5556 [(set (match_operand:QI 0 "register_operand" "")
5557 (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5558 (match_operand:QI 2 "general_operand" "")))]
5562 (define_insn "*lshrqi3_const1"
5563 [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
5564 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
5574 (define_insn "*lshrqi3_const"
5575 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5576 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5577 (match_operand:QI 2 "const_int_operand" "")))]
5582 const char* insn_code;
5584 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5585 insn_code = \"lsrb\";
5586 else if (DA_REG_P (operands[0]))
5587 insn_code = \"lsra\";
5591 i = INTVAL (operands[2]);
5594 if (DA_REG_P (operands[0]))
5601 if (DA_REG_P (operands[0]))
5603 output_asm_insn (\"rola\", operands);
5604 output_asm_insn (\"ldaa\\t#0\", operands);
5609 output_asm_insn (\"rolb\", operands);
5610 output_asm_insn (\"ldab\\t#0\", operands);
5616 if (DA_REG_P (operands[0]))
5618 output_asm_insn (\"rola\", operands);
5619 output_asm_insn (\"rola\", operands);
5620 output_asm_insn (\"rola\", operands);
5621 return \"anda\\t#3\";
5625 output_asm_insn (\"rolb\", operands);
5626 output_asm_insn (\"rolb\", operands);
5627 output_asm_insn (\"rolb\", operands);
5628 return \"andb\\t#3\";
5633 output_asm_insn (insn_code, operands);
5638 (define_insn "*lshrqi3"
5639 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5640 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5641 (match_operand:QI 2 "nonimmediate_operand"
5642 "m*u*d*A,m*u*d*A,m*u")))]
5648 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5652 ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
5653 ops[1] = operands[2];
5654 m68hc11_gen_movqi (insn, ops);
5656 if (!optimize || optimize_size)
5658 return \"bsr\\t___lshrqi3\";
5661 ops[0] = gen_label_rtx ();
5662 ops[1] = gen_label_rtx ();
5663 output_asm_insn (\"ble\\t%l1\", ops);
5665 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5666 CODE_LABEL_NUMBER (ops[0]));
5668 output_asm_insn (\"lsrb\", operands);
5669 output_asm_insn (\"deca\", operands);
5670 output_asm_insn (\"bne\\t%l0\", ops);
5672 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
5673 CODE_LABEL_NUMBER (ops[1]));
5677 (define_insn "*rotlqi3_with_carry"
5678 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5679 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5680 (reg:QI CC_REGNUM)))]
5684 if (DA_REG_P (operands[0]))
5690 (define_insn "*rotlhi3_with_carry"
5691 [(set (match_operand:HI 0 "register_operand" "=d")
5692 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5694 (clobber (reg:HI CC_REGNUM))]
5699 return \"rolb\\n\\trola\";
5702 (define_insn "*rotrhi3_with_carry"
5703 [(set (match_operand:HI 0 "register_operand" "=d")
5704 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5706 (clobber (reg:HI CC_REGNUM))]
5711 return \"rora\\n\\trorb\";
5714 (define_insn "rotlqi3"
5715 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5716 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5717 (match_operand:QI 2 "const_int_operand" "i,i")))]
5721 m68hc11_gen_rotate (ROTATE, insn, operands);
5725 (define_insn "rotrqi3"
5726 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5727 (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5728 (match_operand:QI 2 "const_int_operand" "i,i")))]
5732 m68hc11_gen_rotate (ROTATERT, insn, operands);
5736 (define_expand "rotlhi3"
5737 [(set (match_operand:HI 0 "register_operand" "")
5738 (rotate:HI (match_operand:HI 1 "register_operand" "")
5739 (match_operand:HI 2 "general_operand" "")))]
5743 if (GET_CODE (operands[2]) != CONST_INT)
5745 rtx scratch = gen_reg_rtx (HImode);
5746 operand1 = force_reg (HImode, operand1);
5748 emit_move_insn (scratch, operands[2]);
5749 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5750 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5752 gen_rtx_ROTATE (HImode,
5753 operand1, scratch)),
5754 gen_rtx_CLOBBER (VOIDmode, scratch))));
5759 (define_insn "rotlhi3_const"
5760 [(set (match_operand:HI 0 "register_operand" "=d")
5761 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5762 (match_operand:HI 2 "const_int_operand" "i")))]
5766 m68hc11_gen_rotate (ROTATE, insn, operands);
5770 (define_insn "*rotlhi3"
5771 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5772 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
5773 (match_operand:HI 2 "general_operand" "+x,+d")))
5774 (clobber (match_dup 2))]
5778 if (A_REG_P (operands[0]))
5781 return \"bsr\\t___rotlhi3\";
5784 (define_expand "rotrhi3"
5785 [(set (match_operand:HI 0 "register_operand" "")
5786 (rotatert:HI (match_operand:HI 1 "general_operand" "")
5787 (match_operand:HI 2 "general_operand" "")))]
5791 if (GET_CODE (operands[2]) != CONST_INT)
5793 rtx scratch = gen_reg_rtx (HImode);
5794 operand1 = force_reg (HImode, operand1);
5796 emit_move_insn (scratch, operands[2]);
5797 emit_insn (gen_rtx_PARALLEL (VOIDmode,
5798 gen_rtvec (2, gen_rtx_SET (VOIDmode,
5800 gen_rtx_ROTATERT (HImode,
5801 operand1, scratch)),
5802 gen_rtx_CLOBBER (VOIDmode, scratch))));
5807 (define_insn "rotrhi3_const"
5808 [(set (match_operand:HI 0 "register_operand" "=d")
5809 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5810 (match_operand:HI 2 "const_int_operand" "i")))]
5814 m68hc11_gen_rotate (ROTATERT, insn, operands);
5818 (define_insn "*rotrhi3"
5819 [(set (match_operand:HI 0 "register_operand" "=d,*x")
5820 (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
5821 (match_operand:HI 2 "general_operand" "+x,+d")))
5822 (clobber (match_dup 2))]
5826 if (A_REG_P (operands[0]))
5829 return \"bsr\\t___rotrhi3\";
5832 ;; Split a shift operation on an address register in a shift
5834 (define_split /* "*rotrhi3_addr" */
5835 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
5836 (match_operator:HI 3 "m68hc11_shift_operator"
5837 [(match_operand:HI 1 "register_operand" "")
5838 (match_operand:HI 2 "register_operand" "")]))
5839 (clobber (match_dup 2))]
5840 "z_replacement_completed == 2"
5841 [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5842 (set (match_dup 0) (reg:HI D_REGNUM))])
5843 (parallel [(set (reg:HI D_REGNUM)
5844 (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
5845 (clobber (match_dup 0))])
5846 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
5847 (set (match_dup 0) (reg:HI D_REGNUM))])]
5850 ;;--------------------------------------------------------------------
5851 ;;- 68HC12 Decrement/Increment and branch
5852 ;;--------------------------------------------------------------------
5853 ;; These patterns are used by loop optimization as well as peephole2
5854 ;; They must handle reloading themselves and the scratch register
5855 ;; is used for that. Even if we accept memory operand, we must not
5856 ;; accept them on the predicate because it might create too many reloads.
5857 ;; (specially on HC12 due to its auto-incdec addressing modes).
5859 (define_expand "decrement_and_branch_until_zero"
5860 [(parallel [(set (pc)
5862 (ne (plus:HI (match_operand:HI 0 "register_operand" "")
5865 (label_ref (match_operand 1 "" ""))
5868 (plus:HI (match_dup 0)
5870 (clobber (match_scratch:HI 2 ""))])]
5874 (define_expand "doloop_end"
5875 [(use (match_operand 0 "" "")) ; loop pseudo
5876 (use (match_operand 1 "" "")) ; iterations; zero if unknown
5877 (use (match_operand 2 "" "")) ; max iterations
5878 (use (match_operand 3 "" "")) ; loop level
5879 (use (match_operand 4 "" ""))] ; label
5883 /* Reject non-constant loops as it generates bigger code due to
5884 the handling of the loop register. We can do better by using
5885 the peephole2 dbcc/ibcc patterns. */
5886 if (INTVAL (operands[1]) == 0)
5891 /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
5892 the operator and its operands are not relevant. */
5893 if (GET_MODE (operands[0]) == HImode)
5895 emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
5902 if (GET_MODE (operands[0]) == QImode)
5904 emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
5915 ;; Decrement-and-branch insns.
5916 (define_insn "m68hc12_dbcc_dec_hi"
5919 (match_operator 1 "m68hc11_eq_compare_operator"
5920 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5922 (label_ref (match_operand 2 "" ""))
5925 (plus:HI (match_dup 0) (const_int -1)))
5926 (clobber (match_scratch:HI 3 "=X,dxy"))]
5930 if (!H_REG_P (operands[0]))
5934 if (GET_CODE (operands[1]) == EQ)
5935 return \"dbeq\\t%0,%l2\";
5937 return \"dbne\\t%0,%l2\";
5940 ;; Decrement-and-branch insns.
5941 (define_insn "m68hc12_dbcc_inc_hi"
5944 (match_operator 1 "m68hc11_eq_compare_operator"
5945 [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
5947 (label_ref (match_operand 2 "" ""))
5950 (plus:HI (match_dup 0) (const_int 1)))
5951 (clobber (match_scratch:HI 3 "=X,dxy"))]
5955 if (!H_REG_P (operands[0]))
5959 if (GET_CODE (operands[1]) == EQ)
5960 return \"ibeq\\t%0,%l2\";
5962 return \"ibeq\\t%0,%l2\";
5965 ;; Decrement-and-branch (QImode).
5966 (define_insn "m68hc12_dbcc_dec_qi"
5969 (match_operator 1 "m68hc11_eq_compare_operator"
5970 [(match_operand:QI 0 "register_operand" "+d,m*u*A")
5972 (label_ref (match_operand 2 "" ""))
5975 (plus:QI (match_dup 0) (const_int -1)))
5976 (clobber (match_scratch:QI 3 "=X,d"))]
5980 if (!D_REG_P (operands[0]))
5984 if (GET_CODE (operands[1]) == EQ)
5985 return \"dbeq\\tb,%l2\";
5987 return \"dbne\\tb,%l2\";
5990 ;; Increment-and-branch (QImode).
5991 (define_insn "m68hc12_dbcc_inc_qi"
5994 (match_operator 1 "m68hc11_eq_compare_operator"
5995 [(match_operand:QI 0 "register_operand" "+d,m*u*A")
5997 (label_ref (match_operand 2 "" ""))
6000 (plus:QI (match_dup 0) (const_int 1)))
6001 (clobber (match_scratch:QI 3 "=X,d"))]
6005 if (!D_REG_P (operands[0]))
6009 if (GET_CODE (operands[1]) == EQ)
6010 return \"ibeq\\tb,%l2\";
6012 return \"ibeq\\tb,%l2\";
6015 ;; Split the above to handle the case where operand 0 is in memory
6016 ;; (a register that couldn't get a hard register)
6020 (match_operator 3 "m68hc11_eq_compare_operator"
6021 [(match_operand:HI 0 "general_operand" "")
6022 (match_operand:HI 1 "const_int_operand" "")])
6023 (label_ref (match_operand 4 "" ""))
6026 (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6027 (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
6028 "TARGET_M6812 && reload_completed"
6029 [(set (match_dup 5) (match_dup 0))
6030 (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
6031 (set (match_dup 0) (match_dup 5))
6033 (if_then_else (match_op_dup 3
6034 [(match_dup 5) (const_int 0)])
6035 (label_ref (match_dup 4)) (pc)))]
6038 ;; Split the above to handle the case where operand 0 is in memory
6039 ;; (a register that couldn't get a hard register)
6043 (match_operator 3 "m68hc11_eq_compare_operator"
6044 [(match_operand:QI 0 "general_operand" "")
6045 (match_operand:QI 1 "const_int_operand" "")])
6046 (label_ref (match_operand 4 "" ""))
6049 (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
6050 (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
6051 "TARGET_M6812 && reload_completed"
6052 [(set (match_dup 5) (match_dup 0))
6053 (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
6054 (set (match_dup 0) (match_dup 5))
6056 (if_then_else (match_op_dup 3
6057 [(match_dup 5) (const_int 0)])
6058 (label_ref (match_dup 4)) (pc)))]
6061 ;;--------------------------------------------------------------------
6062 ;;- Jumps and transfers
6063 ;;--------------------------------------------------------------------
6066 (label_ref (match_operand 0 "" "")))]
6070 (define_expand "cbranchsi4"
6072 (compare (match_operand:SI 1 "tst_operand" "")
6073 (match_operand:SI 2 "cmp_operand" "")))
6075 (if_then_else (match_operator 0 "ordered_comparison_operator"
6076 [(cc0) (const_int 0)])
6077 (label_ref (match_operand 3 "" ""))
6082 if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
6083 operands[1] = force_reg (SImode, operands[1]);
6085 m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
6086 operands[2], operands[3]);
6090 (define_expand "cbranchhi4"
6092 (compare (match_operand:HI 1 "tst_operand" "")
6093 (match_operand:HI 2 "cmp_operand" "")))
6095 (if_then_else (match_operator 0 "ordered_comparison_operator"
6096 [(cc0) (const_int 0)])
6097 (label_ref (match_operand 3 "" ""))
6102 if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
6103 operands[1] = force_reg (HImode, operands[1]);
6105 m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
6106 operands[2], operands[3]);
6110 (define_expand "cbranchqi4"
6112 (compare (match_operand:QI 1 "tst_operand" "")
6113 (match_operand:QI 2 "cmp_operand" "")))
6115 (if_then_else (match_operator 0 "ordered_comparison_operator"
6116 [(cc0) (const_int 0)])
6117 (label_ref (match_operand 3 "" ""))
6122 if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
6123 operands[1] = force_reg (QImode, operands[1]);
6125 m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
6126 operands[2], operands[3]);
6132 ;; Test and branch instructions for 68HC12 for EQ and NE.
6133 ;; 'z' must not appear in the constraints because the z replacement
6134 ;; pass does not know how to restore the replacement register.
6136 (define_insn "*tbeq"
6138 (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
6140 (label_ref (match_operand 1 "" ""))
6145 /* If the flags are already set correctly, use 'bne/beq' which are
6146 smaller and a little bit faster. This happens quite often due
6147 to reloading of operands[0]. In that case, flags are set correctly
6148 due to the load instruction. */
6149 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6150 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6151 return \"beq\\t%l1\";
6153 return \"tbeq\\t%0,%l1\";
6156 (define_insn "*tbne"
6158 (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6160 (label_ref (match_operand 1 "" ""))
6165 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6166 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6167 return \"bne\\t%l1\";
6169 return \"tbne\\t%0,%l1\";
6173 ;; Test and branch with 8-bit register. Register must be B (or A).
6175 (define_insn "*tbeq8"
6177 (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6179 (label_ref (match_operand 1 "" ""))
6184 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6185 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6186 return \"beq\\t%l1\";
6188 return \"tbeq\\tb,%l1\";
6191 (define_insn "*tbne8"
6193 (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6195 (label_ref (match_operand 1 "" ""))
6200 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6201 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
6202 return \"bne\\t%l1\";
6204 return \"tbne\\tb,%l1\";
6209 (if_then_else (eq (cc0)
6211 (label_ref (match_operand 0 "" ""))
6218 (if_then_else (ne (cc0)
6220 (label_ref (match_operand 0 "" ""))
6227 (if_then_else (gt (cc0)
6229 (label_ref (match_operand 0 "" ""))
6234 (define_insn "*bgtu"
6236 (if_then_else (gtu (cc0)
6238 (label_ref (match_operand 0 "" ""))
6245 (if_then_else (lt (cc0)
6247 (label_ref (match_operand 0 "" ""))
6252 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6253 return \"bmi\\t%l0\";
6255 return \"blt\\t%l0\";
6258 (define_insn "*bltu"
6260 (if_then_else (ltu (cc0)
6262 (label_ref (match_operand 0 "" ""))
6269 (if_then_else (ge (cc0)
6271 (label_ref (match_operand 0 "" ""))
6276 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6277 return \"bpl\\t%l0\";
6279 return \"bge\\t%l0\";
6282 (define_insn "*bgeu"
6284 (if_then_else (geu (cc0)
6286 (label_ref (match_operand 0 "" ""))
6293 (if_then_else (le (cc0)
6295 (label_ref (match_operand 0 "" ""))
6300 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6301 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6303 return \"ble\\t%l0\";
6306 (define_insn "*bleu"
6308 (if_then_else (leu (cc0)
6310 (label_ref (match_operand 0 "" ""))
6315 ;;--------------------------------------------------------------------
6316 ;;- Negative test and branch
6317 ;;--------------------------------------------------------------------
6320 (if_then_else (eq (cc0)
6323 (label_ref (match_operand 0 "" ""))))]
6329 (if_then_else (ne (cc0)
6332 (label_ref (match_operand 0 "" ""))))]
6338 (if_then_else (gt (cc0)
6341 (label_ref (match_operand 0 "" ""))))]
6345 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6346 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6348 return \"ble\\t%l0\";
6353 (if_then_else (gtu (cc0)
6356 (label_ref (match_operand 0 "" ""))))]
6362 (if_then_else (lt (cc0)
6365 (label_ref (match_operand 0 "" ""))))]
6369 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6370 return \"bpl\\t%l0\";
6372 return \"bge\\t%l0\";
6377 (if_then_else (ltu (cc0)
6380 (label_ref (match_operand 0 "" ""))))]
6386 (if_then_else (ge (cc0)
6389 (label_ref (match_operand 0 "" ""))))]
6393 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6394 return \"bmi\\t%l0\";
6396 return \"blt\\t%l0\";
6401 (if_then_else (geu (cc0)
6404 (label_ref (match_operand 0 "" ""))))]
6410 (if_then_else (le (cc0)
6413 (label_ref (match_operand 0 "" ""))))]
6419 (if_then_else (leu (cc0)
6422 (label_ref (match_operand 0 "" ""))))]
6426 ;;--------------------------------------------------------------------
6428 ;;--------------------------------------------------------------------
6430 ;;- Call a function that returns no value.
6432 [(call (match_operand:QI 0 "memory_operand" "m")
6433 (match_operand:SI 1 "general_operand" "g"))]
6434 ;; Operand 1 not really used on the m68hc11.
6438 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6440 if (m68hc11_is_far_symbol (operands[0]))
6444 output_asm_insn (\"call\\t%0\", operands);
6449 output_asm_insn (\"pshb\", operands);
6450 output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
6451 output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
6452 return \"jsr\\t__call_a32\";
6455 if (m68hc11_is_trap_symbol (operands[0]))
6458 return \"bsr\\t%0\";
6462 return \"jsr\\t%0\";
6466 (define_insn "call_value"
6467 [(set (match_operand 0 "" "=g")
6468 (call (match_operand:QI 1 "memory_operand" "m")
6469 (match_operand:SI 2 "general_operand" "g")))]
6473 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6475 if (m68hc11_is_far_symbol (operands[1]))
6479 output_asm_insn (\"call\\t%1\", operands);
6484 output_asm_insn (\"pshb\", operands);
6485 output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
6486 output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
6487 return \"jsr\\t__call_a32\";
6490 if (m68hc11_is_trap_symbol (operands[1]))
6493 return \"bsr\\t%1\";
6497 return \"jsr\\t%1\";
6501 ;; Call subroutine returning any type.
6503 (define_expand "untyped_call"
6504 [(parallel [(call (match_operand 0 "" "")
6506 (match_operand 1 "" "")
6507 (match_operand 2 "" "")])]
6513 emit_call_insn (gen_call (operands[0], const0_rtx));
6515 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6517 rtx set = XVECEXP (operands[2], 0, i);
6518 emit_move_insn (SET_DEST (set), SET_SRC (set));
6521 /* The optimizer does not know that the call sets the function value
6522 registers we stored in the result block. We avoid problems by
6523 claiming that all hard registers are used and clobbered at this
6525 emit_insn (gen_blockage ());
6530 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6531 ;; all of memory. This blocks insns from being moved across this point.
6533 (define_insn "blockage"
6534 [(unspec_volatile [(const_int 0)] 0)]
6543 (define_expand "prologue"
6552 (define_expand "epilogue"
6561 ;; Used for frameless functions which save no regs and allocate no locals.
6562 (define_expand "return"
6564 "reload_completed && m68hc11_total_frame_size () == 0"
6569 if (crtl->return_rtx)
6570 ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
6572 /* Emit use notes only when HAVE_return is true. */
6573 if (m68hc11_total_frame_size () != 0)
6576 if (ret_size && ret_size <= 2)
6578 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6579 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6580 gen_rtx_USE (VOIDmode,
6581 gen_rtx_REG (HImode, 1)))));
6586 emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
6587 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6588 gen_rtx_USE (VOIDmode,
6589 gen_rtx_REG (SImode, 0)))));
6594 (define_insn "*return_void"
6599 rtx next = next_active_insn (insn);
6602 && GET_CODE (next) == JUMP_INSN
6603 && GET_CODE (PATTERN (next)) == RETURN)
6605 if (current_function_interrupt || current_function_trap)
6607 else if (!current_function_far)
6609 else if (TARGET_M6812)
6615 if (crtl->return_rtx)
6616 ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
6619 return \"jmp\\t__return_void\";
6621 return \"jmp\\t__return_16\";
6623 return \"jmp\\t__return_32\";
6624 return \"jmp\\t__return_16\";
6628 (define_insn "*return_16bit"
6630 (use (reg:HI D_REGNUM))]
6631 "reload_completed && m68hc11_total_frame_size () == 0"
6634 rtx next = next_active_insn (insn);
6637 && GET_CODE (next) == JUMP_INSN
6638 && GET_CODE (PATTERN (next)) == RETURN)
6640 if (current_function_interrupt || current_function_trap)
6642 else if (!current_function_far)
6644 else if (TARGET_M6812)
6647 return \"jmp\\t__return_16\";
6650 (define_insn "*return_32bit"
6653 "reload_completed && m68hc11_total_frame_size () == 0"
6656 rtx next = next_active_insn (insn);
6659 && GET_CODE (next) == JUMP_INSN
6660 && GET_CODE (PATTERN (next)) == RETURN)
6662 if (current_function_interrupt || current_function_trap)
6664 else if (!current_function_far)
6666 else if (TARGET_M6812)
6669 return \"jmp\\t__return_32\";
6672 (define_insn "indirect_jump"
6673 [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6677 ;;--------------------------------------------------------------------
6679 ;;--------------------------------------------------------------------
6681 ;; Operand 0 is the address of the table element to use
6682 ;; operand 1 is the CODE_LABEL for the table
6683 ;;--------------------------------------------------------------------
6684 (define_expand "tablejump"
6685 [(parallel [(set (pc) (match_operand 0 "" ""))
6686 (use (label_ref (match_operand 1 "" "")))])]
6690 (define_insn "*jump_indirect"
6692 (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6693 (use (label_ref (match_operand 1 "" "")))])]
6697 ;;--------------------------------------------------------------------
6699 ;;--------------------------------------------------------------------
6701 ;;--------------------------------------------------------------------
6702 ;;- 68HC12 dbcc/ibcc peepholes
6703 ;;--------------------------------------------------------------------
6705 ;; Replace: "addd #-1; bne L1" into "dbne d,L1"
6706 ;; "addd #-1; beq L1" into "dbeq d,L1"
6707 ;; "addd #1; bne L1" into "ibne d,L1"
6708 ;; "addd #1; beq L1" into "ibeq d,L1"
6711 [(set (match_operand:HI 0 "hard_reg_operand" "")
6712 (plus:HI (match_dup 0)
6713 (match_operand:HI 1 "const_int_operand" "")))
6715 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6718 (label_ref (match_operand 3 "" "")) (pc)))]
6719 "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6721 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6722 (label_ref (match_dup 3)) (pc)))
6723 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
6724 (clobber (match_dup 4))])]
6725 "operands[4] = gen_rtx_SCRATCH(HImode);
6726 operands[5] = GEN_INT (-INTVAL (operands[1]));")
6730 ;; Replace: "addb #-1; bne L1" into "dbne b,L1"
6731 ;; "addb #-1; beq L1" into "dbeq b,L1"
6734 [(set (match_operand:QI 0 "hard_reg_operand" "")
6735 (plus:QI (match_dup 0)
6736 (match_operand:QI 1 "const_int_operand" "")))
6738 (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
6741 (label_ref (match_operand 3 "" "")) (pc)))]
6742 "TARGET_M6812 && D_REG_P (operands[0])
6743 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
6745 (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
6746 (label_ref (match_dup 3)) (pc)))
6747 (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
6748 (clobber (match_dup 4))])]
6749 "operands[4] = gen_rtx_SCRATCH(QImode);
6750 operands[5] = GEN_INT (-INTVAL (operands[1]));")
6753 ;;--------------------------------------------------------------------
6755 ;;--------------------------------------------------------------------
6758 ;; Replace "leas 2,sp" with a "pulx" or a "puly".
6759 ;; On 68HC12, this is one cycle slower but one byte smaller.
6760 ;; pr target/6899: This peephole was not valid because a register CSE
6761 ;; pass removes the pulx/puly. The 'use' clause ensure that the pulx is
6765 [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6766 (match_scratch:HI 0 "xy")]
6767 "TARGET_M6812 && optimize_size"
6768 [(set (match_dup 0) (match_dup 1))
6769 (use (match_dup 0))]
6770 "operands[1] = gen_rtx_MEM (HImode,
6771 gen_rtx_POST_INC (HImode,
6772 gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
6774 ;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
6776 ;; PR 14542: emit a use to pretend we need the value of initial register.
6777 ;; Otherwise verify_local_live_at_start will die due to a live change
6778 ;; of that register.
6781 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6782 (match_operand:HI 0 "hard_reg_operand" ""))
6784 (match_operand:HI 1 "hard_reg_operand" ""))
6785 (set (mem:HI (reg:HI SP_REGNUM))
6788 [(use (match_dup 0))
6789 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6791 (set (match_dup 0) (match_dup 1))]
6795 ;; Change: "ldd 0,sp; pulx" into "puld"
6796 ;; This sequence usually appears at end a functions.
6798 [(set (match_operand:HI 0 "hard_reg_operand" "")
6799 (mem:HI (reg:HI SP_REGNUM)))
6801 (set (match_operand:HI 1 "hard_reg_operand" "")
6802 (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
6803 "peep2_reg_dead_p (2, operands[1])"
6804 [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
6805 (use (match_dup 0))]
6808 ;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
6809 ;; Appears to allocate local variables.
6811 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6812 (match_operand:HI 0 "hard_reg_operand" ""))
6813 (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
6815 (set (mem:QI (reg:HI SP_REGNUM))
6818 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6822 ;; Likewise for HI mode
6824 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6825 (match_operand:HI 0 "hard_reg_operand" ""))
6826 (set (mem:HI (reg:HI SP_REGNUM))
6829 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6832 ;;--------------------------------------------------------------------
6834 ;;--------------------------------------------------------------------
6836 ;; Optimize memory<->memory moves when the value is also loaded in
6840 [(set (match_operand:QI 0 "memory_operand" "")
6841 (match_operand:QI 1 "memory_operand" ""))
6842 (set (reg:QI D_REGNUM)
6843 (match_operand:QI 2 "memory_operand" ""))]
6844 "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
6845 || (GET_CODE (XEXP (operands[0], 0)) == REG
6846 && GET_CODE (XEXP (operands[2], 0)) == POST_INC
6847 && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
6848 [(set (reg:QI D_REGNUM) (match_dup 1))
6849 (set (match_dup 2) (reg:QI D_REGNUM))]
6853 ;; Remove a possible move before a compare instruction when that
6854 ;; move will go in a dead register. Compare with the source then.
6857 [(set (match_operand:HI 0 "hard_reg_operand" "")
6858 (match_operand:HI 1 "hard_reg_operand" ""))
6860 (compare (match_dup 0)
6861 (match_operand:HI 2 "cmp_operand" "")))]
6862 "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
6863 && peep2_reg_dead_p (2, operands[0])
6864 && !reg_mentioned_p (operands[0], operands[2])"
6865 [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
6869 ;; Optimize loading a constant to memory when that same constant
6870 ;; is loaded to a hard register. Switch the two to use the register
6871 ;; for memory initialization. In most cases, the constant is 0.
6874 [(set (match_operand:HI 0 "memory_operand" "")
6875 (match_operand:HI 1 "immediate_operand" ""))
6876 (set (match_operand:HI 2 "hard_reg_operand" "")
6878 "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
6879 && !reg_mentioned_p (operands[2], operands[0])"
6880 [(set (match_dup 2) (match_dup 1))
6881 (set (match_dup 0) (match_dup 2))]
6885 ;; Reorganize to optimize address computations.
6888 [(set (match_operand:HI 0 "hard_reg_operand" "")
6889 (match_operand:HI 1 "const_int_operand" ""))
6891 (plus:HI (match_dup 0)
6892 (match_operand:HI 2 "general_operand" "")))]
6893 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
6894 [(set (match_dup 0) (match_dup 2))
6895 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
6899 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
6902 [(set (match_operand:HI 0 "hard_reg_operand" "")
6903 (match_operand:HI 1 "const_int_operand" ""))
6905 (plus:HI (match_dup 0)
6906 (match_operand:HI 2 "general_operand" "")))
6907 (match_scratch:QI 3 "d")]
6908 "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
6909 [(set (match_dup 3) (match_dup 4))
6910 (set (match_dup 0) (match_dup 2))
6911 (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
6912 "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
6915 ;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
6918 [(set (match_operand:HI 0 "hard_reg_operand" "")
6919 (match_operand:HI 1 "const_int_operand" ""))
6921 (plus:HI (match_dup 0)
6922 (match_operand:HI 2 "general_operand" "")))]
6924 [(set (match_dup 0) (match_dup 2))
6925 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
6929 ;; Optimize an address register increment and a compare to use
6930 ;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
6931 ;; before reload, but can be enabled after).
6934 [(set (match_operand:HI 0 "hard_reg_operand" "")
6935 (plus:HI (match_dup 0)
6936 (match_operand:HI 1 "const_int_operand" "")))
6938 (compare (match_operand:QI 2 "memory_operand" "")
6940 "TARGET_AUTO_INC_DEC
6941 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6942 && reg_mentioned_p (operands[0], operands[2])"
6944 (compare (match_dup 3)
6946 "if (INTVAL (operands[1]) == 1)
6947 operands[3] = gen_rtx_MEM (QImode,
6948 gen_rtx_PRE_INC (HImode, operands[0]));
6950 operands[3] = gen_rtx_MEM (QImode,
6951 gen_rtx_PRE_DEC (HImode, operands[0]));
6955 ;; Likewise for compare.
6958 [(set (match_operand:HI 0 "hard_reg_operand" "")
6959 (plus:HI (match_dup 0)
6960 (match_operand:HI 1 "const_int_operand" "")))
6962 (compare (match_operand:QI 2 "hard_reg_operand" "")
6963 (match_operand:QI 3 "memory_operand" "")))]
6964 "TARGET_AUTO_INC_DEC
6965 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6966 && reg_mentioned_p (operands[0], operands[3])"
6967 [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
6968 "if (INTVAL (operands[1]) == 1)
6969 operands[4] = gen_rtx_MEM (QImode,
6970 gen_rtx_PRE_INC (HImode, operands[0]));
6972 operands[4] = gen_rtx_MEM (QImode,
6973 gen_rtx_PRE_DEC (HImode, operands[0]));
6977 [(set (match_operand:HI 0 "hard_reg_operand" "")
6978 (plus:HI (match_dup 0)
6979 (match_operand:HI 1 "const_int_operand" "")))
6981 (compare (match_operand:QI 2 "memory_operand" "")
6982 (match_operand:QI 3 "hard_reg_operand" "")))]
6983 "TARGET_AUTO_INC_DEC
6984 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6985 && reg_mentioned_p (operands[0], operands[2])"
6986 [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
6987 "if (INTVAL (operands[1]) == 1)
6988 operands[4] = gen_rtx_MEM (QImode,
6989 gen_rtx_PRE_INC (HImode, operands[0]));
6991 operands[4] = gen_rtx_MEM (QImode,
6992 gen_rtx_PRE_DEC (HImode, operands[0]));
6996 ;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
6997 ;; (avoids many temporary moves because we can't add sp to another reg easily)
7000 [(set (match_operand:HI 0 "hard_reg_operand" "")
7001 (match_operand:HI 1 "const_int_operand" ""))
7002 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7004 [(set (match_dup 0) (reg:HI SP_REGNUM))
7005 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7009 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7012 [(set (match_operand:HI 0 "hard_reg_operand" "")
7013 (match_operand:HI 1 "const_int_operand" ""))
7015 (plus:HI (match_dup 0)
7016 (match_operand:HI 2 "general_operand" "")))]
7017 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
7018 [(set (match_dup 0) (match_dup 2))
7019 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
7027 [(set (match_operand:SI 0 "hard_reg_operand" "")
7028 (ashift:SI (match_operand:SI 1 "general_operand" "")
7030 (clobber (match_scratch:HI 2 ""))])
7031 (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
7032 (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
7033 "!X_REG_P (operands[1])
7034 && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
7035 && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
7036 [(set (reg:HI D_REGNUM) (match_dup 5))
7037 (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
7038 (set (match_dup 3) (reg:HI D_REGNUM))
7039 (set (reg:HI D_REGNUM) (match_dup 6))
7040 (parallel [(set (reg:HI D_REGNUM)
7041 (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
7042 (clobber (reg:HI CC_REGNUM))])
7043 (set (match_dup 4) (reg:HI D_REGNUM))]
7044 "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
7045 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
7048 ;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
7051 [(set (match_operand:HI 0 "hard_reg_operand" "")
7052 (match_operand:HI 1 "memory_operand" ""))
7053 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
7055 (match_scratch:HI 2 "x")]
7056 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
7057 [(set (match_dup 2) (match_dup 1))
7058 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
7062 ;; Remove one load when copying a value to/from memory and also
7063 ;; to a register. Take care not clobbering a possible register used
7065 ;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
7068 [(set (match_operand:HI 0 "hard_reg_operand" "")
7069 (match_operand:HI 1 "general_operand" ""))
7070 (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
7071 (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
7072 "peep2_reg_dead_p (2, operands[0])
7073 && !side_effects_p (operands[1])
7074 && !side_effects_p (operands[2])
7075 && !reg_mentioned_p (operands[3], operands[2])"
7076 [(set (match_dup 3) (match_dup 1))
7077 (set (match_dup 2) (match_dup 3))]
7081 ;; Replace a "ldd <mem>; addd #N; std <mem>" into a
7082 ;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
7083 ;; and the constant is small.
7086 [(set (match_operand:HI 0 "hard_reg_operand" "")
7087 (match_operand:HI 1 "general_operand" ""))
7088 (set (match_dup 0) (plus:HI (match_dup 0)
7089 (match_operand:HI 2 "const_int_operand" "")))
7090 (set (match_operand:HI 3 "nonimmediate_operand" "")
7092 (match_scratch:HI 4 "xy")]
7093 "D_REG_P (operands[0])
7095 || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
7096 && peep2_reg_dead_p (3, operands[0])"
7097 [(set (match_dup 4) (match_dup 1))
7098 (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
7099 (set (match_dup 3) (match_dup 4))]
7100 "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
7101 if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
7103 ;;--------------------------------------------------------------------
7105 ;;--------------------------------------------------------------------
7106 ;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
7108 ;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
7109 ;; Register D must be dead and there must be no register side effects for mem.
7110 ;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
7111 ;; The good side effect is that it makes the sequence atomic.
7114 [(set (match_operand:QI 0 "hard_reg_operand" "")
7115 (match_operand:QI 1 "nonimmediate_operand" ""))
7116 (set (match_dup 0) (ior:QI (match_dup 0)
7117 (match_operand:QI 2 "const_int_operand" "")))
7118 (set (match_dup 1) (match_dup 0))]
7119 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7120 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7121 && peep2_reg_dead_p (3, operands[0])"
7122 [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
7126 [(set (match_operand:HI 0 "hard_reg_operand" "")
7127 (match_operand:HI 1 "nonimmediate_operand" ""))
7128 (set (match_dup 0) (ior:HI (match_dup 0)
7129 (match_operand:HI 2 "const_int_operand" "")))
7130 (set (match_dup 1) (match_dup 0))]
7131 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7132 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7133 && peep2_reg_dead_p (3, operands[0])"
7134 [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
7137 ;;--------------------------------------------------------------------
7139 ;;--------------------------------------------------------------------
7140 ;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
7141 ;; See Bset peephole2.
7144 [(set (match_operand:QI 0 "hard_reg_operand" "")
7145 (match_operand:QI 1 "nonimmediate_operand" ""))
7146 (set (match_dup 0) (and:QI (match_dup 0)
7147 (match_operand:QI 2 "const_int_operand" "")))
7148 (set (match_dup 1) (match_dup 0))]
7149 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
7150 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7151 && peep2_reg_dead_p (3, operands[0])"
7152 [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
7156 [(set (match_operand:HI 0 "hard_reg_operand" "")
7157 (match_operand:HI 1 "nonimmediate_operand" ""))
7158 (set (match_dup 0) (and:HI (match_dup 0)
7159 (match_operand:HI 2 "const_int_operand" "")))
7160 (set (match_dup 1) (match_dup 0))]
7161 "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
7162 && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
7163 && peep2_reg_dead_p (3, operands[0])"
7164 [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
7168 ;;--------------------------------------------------------------------
7169 ;;- Compare peephole2
7170 ;;--------------------------------------------------------------------
7172 [(set (match_operand:HI 0 "hard_reg_operand" "")
7173 (match_operand:HI 1 "hard_reg_operand" ""))
7174 (set (match_dup 1) (plus:HI (match_dup 1)
7175 (match_operand:HI 2 "const_int_operand" "")))
7176 (set (cc0) (compare (match_dup 0)
7178 "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
7179 [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
7180 (set (cc0) (compare (match_dup 1) (match_dup 2)))]
7184 [(set (match_operand:HI 0 "hard_reg_operand" "")
7185 (match_operand:HI 1 "hard_reg_operand" ""))
7186 (set (match_operand:HI 2 "hard_reg_operand" "")
7187 (plus:HI (match_dup 2)
7188 (match_operand:HI 3 "const_int_operand" "")))
7189 (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
7190 (set (cc0) (compare (match_operand:HI 5 "hard_reg_operand" "")
7192 "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
7193 && !reg_mentioned_p (operands[2], operands[4])
7195 && ((rtx_equal_p (operands[5], operands[0])
7196 && rtx_equal_p (operands[2], operands[1]))
7198 || (rtx_equal_p (operands[5], operands[1])
7199 && rtx_equal_p (operands[2], operands[0])))"
7200 [(set (match_dup 2) (match_dup 1))
7201 (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
7202 (set (match_dup 4) (match_dup 2))
7203 (set (cc0) (compare (match_dup 2) (match_dup 3)))]
7207 ;;--------------------------------------------------------------------
7209 ;;--------------------------------------------------------------------
7211 ;; Optimize initialization of 2 hard regs from the same memory location
7212 ;; Since we can't copy easily X, Y and D to each other, load the 2 registers
7213 ;; from the same memory location.
7216 [(set (match_operand:HI 0 "hard_reg_operand" "")
7217 (match_operand:HI 1 "memory_operand" ""))
7218 (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7220 && !side_effects_p (operands[1])
7221 && !reg_mentioned_p (operands[0], operands[1])"
7222 [(set (match_dup 0) (match_dup 1))
7223 (set (match_dup 2) (match_dup 1))]
7226 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7229 [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7230 (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7231 (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7232 (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
7233 (match_scratch:HI 4 "d")]
7235 [(set (match_dup 4) (const_int 0))
7236 (set (match_dup 0) (match_dup 4))
7237 (set (match_dup 1) (match_dup 4))
7238 (set (match_dup 2) (match_dup 4))
7239 (set (match_dup 3) (match_dup 4))]
7243 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7246 [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
7247 (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
7248 (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
7249 (match_scratch:HI 3 "d")]
7251 [(set (match_dup 3) (const_int 0))
7252 (set (match_dup 0) (match_dup 3))
7253 (set (match_dup 1) (match_dup 3))
7254 (set (match_dup 2) (match_dup 3))]
7258 ;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
7261 [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
7262 (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
7263 (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
7264 (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
7265 (match_scratch:HI 4 "x")]
7266 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
7267 [(set (match_dup 4) (const_int 0))
7268 (set (match_dup 1) (match_dup 4))
7269 (set (match_dup 2) (match_dup 4))
7270 (set (match_dup 3) (match_dup 4))]
7274 ;; This peephole catches the address computations generated by the reload
7277 [(set (match_operand:HI 0 "hard_reg_operand" "xy")
7278 (match_operand:HI 1 "const_int_operand" ""))
7279 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7280 (set (match_dup 0) (reg:HI D_REGNUM))])
7281 (set (reg:HI D_REGNUM)
7282 (plus (reg:HI D_REGNUM)
7283 (match_operand:HI 2 "general_operand" "")))
7284 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7285 (set (match_dup 0) (reg:HI D_REGNUM))])]
7286 "(INTVAL (operands[1]) & 0x0FF) == 0"
7289 int value_loaded = 1;
7291 if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
7295 ops[0] = operands[0];
7296 ops[1] = operands[2];
7297 m68hc11_gen_movhi (insn, ops);
7298 output_asm_insn (\"xgd%0\", operands);
7300 else if (Y_REG_P (operands[0]))
7302 if (reg_mentioned_p (iy_reg, operands[2]))
7303 output_asm_insn (\"ldy\\t%2\", operands);
7306 output_asm_insn (\"xgdy\", operands);
7310 output_asm_insn (\"ldd\\t%2\", operands);
7313 if (value_loaded == 0)
7314 output_asm_insn (\"ldd\\t%2\", operands);
7315 if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
7316 output_asm_insn (\"inca\", operands);
7317 else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
7318 output_asm_insn (\"deca\", operands);
7319 else if (INTVAL (operands[1]) != 0)
7320 output_asm_insn (\"adda\\t%h1\", operands);
7322 if (X_REG_P (operands[0]))
7324 else if (Y_REG_P (operands[0]))
7332 [(set (match_operand:HI 0 "hard_reg_operand" "h")
7333 (match_operand:HI 1 "non_push_operand" "g"))
7334 (set (match_operand:HI 2 "hard_reg_operand" "h")
7336 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7337 && !S_REG_P (operands[2])"
7342 ops[0] = operands[2];
7343 ops[1] = operands[1];
7344 m68hc11_gen_movhi (insn, ops);
7350 [(set (match_operand:HI 0 "hard_reg_operand" "h")
7351 (match_operand:HI 1 "hard_reg_operand" "h"))
7352 (set (match_operand:HI 2 "non_push_operand" "g")
7354 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
7355 && !S_REG_P (operands[2])"
7360 ops[0] = operands[2];
7361 ops[1] = operands[1];
7362 m68hc11_gen_movhi (insn, ops);
7368 ;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
7369 ;; the set, so we don't need to emit anything. 'ins1' refers to the
7373 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7374 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7375 (set (match_dup 0) (reg:HI D_REGNUM))])]
7376 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7379 cc_status = cc_prev_status;
7384 ;; Same as above but due to some split, there may be a noop set
7387 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7388 (set (match_dup 0) (match_dup 0))
7389 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7390 (set (match_dup 0) (reg:HI D_REGNUM))])]
7391 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
7394 cc_status = cc_prev_status;
7400 ;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
7401 ;; and we must, at least, setup X/Y with value of D.
7404 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
7405 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7406 (set (match_dup 0) (reg:HI D_REGNUM))])]
7412 ops[0] = operands[0];
7413 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7414 m68hc11_gen_movhi (insn, ops);
7420 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7421 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7424 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7425 (set (match_dup 0) (reg:HI D_REGNUM))])
7426 (set (reg:HI D_REGNUM) (match_dup 0))]
7427 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7430 cc_status = cc_prev_status;
7436 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7437 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7440 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7441 (set (match_dup 0) (reg:HI D_REGNUM))])
7442 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7443 "REGNO (operands[0]) == REGNO (operands[1])
7444 && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
7447 cc_status = cc_prev_status;
7453 ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
7454 ;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
7457 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7458 (set (match_dup 0) (reg:HI D_REGNUM))])
7459 (set (reg:HI D_REGNUM) (match_dup 0))]
7465 ops[0] = operands[0];
7466 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7467 m68hc11_gen_movhi (insn, ops);
7473 ;;; Same peephole with a QI set. The copy is made as 16-bit to comply
7477 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7478 (set (match_dup 0) (reg:HI D_REGNUM))])
7479 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
7480 "REGNO (operands[0]) == REGNO (operands[1])"
7485 ops[0] = operands[0];
7486 ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
7487 m68hc11_gen_movhi (insn, ops);
7493 ;;; Catch two consecutive xgdx or xgdy, emit nothing.
7496 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
7497 (set (match_dup 0) (reg:HI D_REGNUM))])
7498 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
7499 (set (match_dup 0) (reg:HI D_REGNUM))])]
7503 cc_status = cc_prev_status;
7509 [(set (match_operand:HI 0 "hard_reg_operand" "")
7510 (match_operand:HI 1 "stack_register_operand" ""))
7511 (set (match_operand:HI 2 "hard_reg_operand" "")
7512 (match_operand:HI 3 "memory_operand" "m"))
7514 (match_operand:HI 4 "memory_operand" "m"))]
7515 "IS_STACK_POP (operands[4])
7516 && (GET_CODE (operands[3]) == MEM &&
7517 rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
7522 ops[0] = operands[2];
7523 ops[1] = gen_rtx_MEM (HImode,
7524 gen_rtx_POST_INC (HImode, stack_pointer_rtx));
7525 m68hc11_gen_movhi (insn, ops);
7531 ;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
7534 [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
7535 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
7539 return \"sts\\t%t0\\n\\tld%0\\t%t0\";
7544 [(set (match_operand:HI 0 "hard_reg_operand" "")
7545 (match_operand:HI 1 "memory_operand" ""))
7546 (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
7548 && !side_effects_p (operands[1])
7549 && !reg_mentioned_p (operands[0], operands[1])"
7554 ops[0] = operands[0];
7555 ops[1] = operands[1];
7556 m68hc11_gen_movhi (insn, ops);
7557 ops[0] = operands[2];
7558 m68hc11_gen_movhi (insn, ops);
7562 ;; Peephole for Z register replacement.
7563 ;; Avoid to use _.tmp register when comparing D and X if we can compare
7564 ;; with soft register
7566 [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
7567 (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
7568 (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
7569 (reg:HI SOFT_TMP_REGNUM)))]
7570 "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
7575 ops[0] = operands[0];
7576 ops[1] = operands[1];
7577 m68hc11_gen_movhi (insn, ops);
7578 return \"cp%2\\t%1\";