]> gcc.gnu.org Git - gcc.git/blame - gcc/config/m68hc11/m68hc11.md
cvt.c (cp_convert_to_pointer): Call force_fit_type for null pointers.
[gcc.git] / gcc / config / m68hc11 / m68hc11.md
CommitLineData
385c9217 1;;- Machine description file for Motorola 68HC11 and 68HC12.
e03f5d43 2;;- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
ae9bd481 3;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
385c9217
SC
4
5;; This file is part of GNU CC.
6
7;; GNU CC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 2, or (at your option)
10;; any later version.
11
12;; GNU CC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU CC; see the file COPYING. If not, write to
19;; the Free Software Foundation, 59 Temple Place - Suite 330,
20;; Boston, MA 02111-1307, USA.
21
22;; Note:
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.
28;;
29;; The gcc 2.6.3 port is available at:
30;;
31;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
32;;
33
34;;- Instruction patterns. When multiple patterns apply,
35;;- the first one in the file is chosen.
36;;-
37;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
38;;-
39;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
40;;- updates for most instructions.
41
42;;
43;; The following constraints are used:
44;;
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
51;; NO_REG for 68hc12
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
58;;
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
65;;
66;; Other constraints:
67;;
932657df
SC
68;; Q an operand which is in memory but whose address is constant
69;; (ie, 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).
73;;
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)).
77;;
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).
385c9217
SC
82;;
83;;
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)
90;;
91;; In many cases, it's not possible to use the 'g' or 'r' constraints.
92;;
93;; Operands modifiers:
94;;
95;; %b Get the low part of the operand (to obtain a QImode)
96;; This modified 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.
106;;
107;; 32/64-bit Patterns:
932657df 108;; The 68HC11 does not support 32/64-bit operations. Most of the
385c9217 109;; 32/64-bit patterns are defined to split the instruction in
932657df 110;; 16-bits patterns. Providing split patterns generates better code
385c9217
SC
111;; than letting GCC implement the 32/64-bit operation itself.
112;;
113;;
114;; Notes:
115;;
116;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
117;; otherwise some insn are not satisfied.
118;;
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).
123;;
124;; o Some split pattern generate instructions that operate on 'a' or 'b'
932657df 125;; register directly (high part and low part of D respectively).
385c9217
SC
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}.
128;;
01beec65
SC
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
131;; pass.
132;;
133;;---------------------------------------------------------------------------
134;; Constants
135
136(define_constants [
137 ;; Register numbers
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])
385c9217
SC
147
148;;--------------------------------------------------------------------
149;;- Test
150;;--------------------------------------------------------------------
151;;
152;; The test and compare insn must not accept a memory operand with
153;; an auto-inc mode. If we do this, the reload can emit move insns
154;; after the test or compare. Such move will set the flags and therefore
155;; break the comparison. This can happen if the auto-inc register
156;; does not happen to be a hard register (ie, reloading occurs).
157;; An offsetable memory operand should be ok. The 'tst_operand' and
158;; 'cmp_operand' predicates take care of this rule.
159;;
160(define_expand "tstsi"
161 [(set (cc0)
162 (match_operand:SI 0 "tst_operand" ""))]
163 ""
164 "
165{
166 m68hc11_compare_op0 = operands[0];
167 m68hc11_compare_op1 = const0_rtx;
168 DONE;
169}")
170
171(define_expand "tsthi"
172 [(set (cc0)
173 (match_operand:HI 0 "tst_operand" ""))]
174 ""
175 "
176{
177 m68hc11_compare_op0 = operands[0];
178 m68hc11_compare_op1 = const0_rtx;
179 DONE;
180}")
181
182(define_insn "tsthi_1"
183 [(set (cc0)
c9b9c05c 184 (match_operand:HI 0 "tst_operand" "dx,*y"))]
385c9217
SC
185 ""
186 "*
187{
01beec65 188 if (D_REG_P (operands[0]) && !TARGET_M6812)
385c9217
SC
189 return \"std\\t%t0\";
190 else
191 return \"cp%0\\t#0\";
192}")
193
194(define_expand "tstqi"
195 [(set (cc0)
196 (match_operand:QI 0 "tst_operand" ""))]
197 ""
198 "
199{
200 m68hc11_compare_op0 = operands[0];
201 m68hc11_compare_op1 = const0_rtx;
202 DONE;
203}")
204
205;;
206;; Split pattern for (tst:QI) on an address register.
385c9217
SC
207;;
208(define_split
209 [(set (cc0)
a0df6910 210 (match_operand:QI 0 "hard_addr_reg_operand" ""))]
385c9217 211 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
a0df6910
SC
212 [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
213 (set (match_dup 1) (reg:HI D_REGNUM))])
214 (set (cc0) (reg:QI D_REGNUM))
215 (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
216 (set (match_dup 1) (reg:HI D_REGNUM))])]
217 "operands[1] = gen_rtx (REG, HImode, REGNO (operands[0]));")
385c9217
SC
218
219(define_insn "tstqi_1"
220 [(set (cc0)
a1fdc802 221 (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
385c9217 222 ""
a0df6910
SC
223 "*
224{
225 if (A_REG_P (operands[0]))
226 return \"#\";
227
228 else if (D_REG_P (operands[0]))
229 return \"tstb\";
230
231 else if (dead_register_here (insn, d_reg))
232 return \"ldab\\t%b0\";
233
234 else
235 return \"tst\\t%b0\";
236}")
385c9217
SC
237
238;;
239;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
240;; during the Z register replacement. They are used when an operand
241;; uses the Z register as an index register (ie, (MEM:QI (REG:HI Z))).
242;; In that case, we have to preserve the values of the replacement
243;; register (as well as the CC0 since the insns are compare insns).
244;; To do this, the replacement register is pushed on the stack and
245;; restored after the real compare. A pattern+split is defined to
246;; avoid problems with the flow+cse register pass which are made
247;; after Z register replacement.
248;;
249(define_insn "tstqi_z_used"
250 [(set (cc0)
251 (match_operand:QI 0 "tst_operand" "m"))
252 (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
253 (use (reg:HI 11))]
254 ""
76d06edc 255 "#")
385c9217
SC
256
257(define_split /* "tstqi_z_used" */
258 [(set (cc0)
a0df6910
SC
259 (match_operand:QI 0 "tst_operand" ""))
260 (use (match_operand:HI 1 "hard_reg_operand" ""))
385c9217
SC
261 (use (reg:HI 11))]
262 "z_replacement_completed == 2"
01beec65 263 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
385c9217
SC
264 (set (match_dup 1) (match_dup 2))
265 (set (cc0) (match_dup 0))
01beec65 266 (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
385c9217
SC
267 "operands[2] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
268
269
270;;--------------------------------------------------------------------
271;;- Compare
272;;--------------------------------------------------------------------
273
274(define_expand "cmpsi"
275 [(set (cc0)
276 (compare (match_operand:SI 0 "tst_operand" "")
277 (match_operand:SI 1 "cmp_operand" "")))]
278 ""
279 "
280{
281 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
282 operands[0] = force_reg (SImode, operands[0]);
283
284 m68hc11_compare_op0 = operands[0];
285 m68hc11_compare_op1 = operands[1];
286 DONE;
287}")
288
289;;
290;; Comparison of a hard register with another one is provided because
291;; it helps GCC to avoid to spill a pseudo hard register.
292;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
293;; (except that we loose the information that the value is saved in it).
294;;
295;; The split pattern transforms the comparison into a save of one hard
296;; register and a comparison with the temporary.
297;;
298(define_split
299 [(set (cc0)
a0df6910
SC
300 (compare (match_operand:HI 0 "hard_reg_operand" "")
301 (match_operand:HI 1 "hard_reg_operand" "")))]
385c9217
SC
302 "reload_completed"
303 [(set (match_dup 2) (match_dup 1))
304 (set (cc0)
305 (compare (match_dup 0) (match_dup 2)))]
306 "operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);")
307
308(define_expand "cmphi"
309 [(set (cc0)
310 (compare (match_operand:HI 0 "tst_operand" "")
311 (match_operand:HI 1 "cmp_operand" "")))]
312 ""
313 "
314{
315 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
316 operands[0] = force_reg (HImode, operands[0]);
317
318 m68hc11_compare_op0 = operands[0];
319 m68hc11_compare_op1 = operands[1];
320 DONE;
321}")
322
a0df6910 323(define_insn "cmphi_1_hc12"
385c9217
SC
324 [(set (cc0)
325 (compare (match_operand:HI 0 "tst_operand"
a0df6910 326 "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
385c9217 327 (match_operand:HI 1 "cmp_operand"
03997728 328 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
a0df6910
SC
329 "TARGET_M6812"
330 "*
331{
332 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
333 {
334 cc_status.flags |= CC_REVERSED;
335 return \"cp%1\\t%0\";
336 }
337 else if (H_REG_P (operands[1]))
338 return \"#\";
339 else
340 return \"cp%0\\t%1\";
341}")
342
343(define_insn "cmphi_1_hc11"
344 [(set (cc0)
345 (compare (match_operand:HI 0 "tst_operand"
346 "dx,y,xyd,?xy,d,m,!u,dxy,dxy")
347 (match_operand:HI 1 "cmp_operand"
348 "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
349 "TARGET_M6811"
385c9217
SC
350 "*
351{
03997728
SC
352 if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
353 {
354 cc_status.flags |= CC_REVERSED;
355 return \"cp%1\\t%0\";
356 }
357 else if (H_REG_P (operands[1]))
385c9217
SC
358 return \"#\";
359 else
360 return \"cp%0\\t%1\";
361}")
362
363(define_insn "cmphi_z_used"
364 [(set (cc0)
03997728
SC
365 (compare (match_operand:HI 0 "tst_operand" "dxy,m")
366 (match_operand:HI 1 "cmp_operand" "m,dxy")))
367 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
385c9217
SC
368 (use (reg:HI 11))]
369 ""
76d06edc 370 "#")
385c9217
SC
371
372(define_split /* "cmphi_z_used" */
373 [(set (cc0)
a0df6910
SC
374 (compare (match_operand:HI 0 "tst_operand" "")
375 (match_operand:HI 1 "cmp_operand" "")))
376 (use (match_operand:HI 2 "hard_reg_operand" ""))
385c9217
SC
377 (use (reg:HI 11))]
378 "z_replacement_completed == 2"
01beec65 379 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
385c9217
SC
380 (set (match_dup 2) (match_dup 3))
381 (set (cc0) (compare (match_dup 0) (match_dup 1)))
01beec65 382 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
385c9217
SC
383 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
384
385;;
386;; 8-bit comparison with address register.
387;; There is no such comparison instruction, we have to temporarily switch
388;; the address register and the D register and do the comparison with D.
389;; The xgdx and xgdy instructions preserve the flags.
390;;
391(define_split
392 [(set (cc0)
a0df6910
SC
393 (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
394 (match_operand:QI 1 "cmp_operand" "")))]
385c9217 395 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
01beec65
SC
396 [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
397 (set (match_dup 3) (reg:HI D_REGNUM))])
385c9217 398 (set (cc0)
01beec65
SC
399 (compare (reg:QI D_REGNUM) (match_dup 1)))
400 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
401 (set (match_dup 3) (reg:HI D_REGNUM))])]
385c9217
SC
402 "operands[3] = gen_rtx (REG, HImode, REGNO (operands[0]));")
403
404(define_split
405 [(set (cc0)
a0df6910
SC
406 (compare (match_operand:QI 0 "hard_reg_operand" "")
407 (match_operand:QI 1 "hard_reg_operand" "")))]
385c9217
SC
408 "reload_completed"
409 [(set (match_dup 3) (match_dup 4))
410 (set (cc0)
411 (compare (match_dup 0) (match_dup 2)))]
412 "operands[2] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
413 operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
414 operands[4] = gen_rtx (REG, HImode, REGNO (operands[1]));")
415
416(define_expand "cmpqi"
417 [(set (cc0)
418 (compare (match_operand:QI 0 "tst_operand" "")
419 (match_operand:QI 1 "cmp_operand" "")))]
420 ""
421 "
422{
423 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
424 operands[0] = force_reg (QImode, operands[0]);
425
426 m68hc11_compare_op0 = operands[0];
427 m68hc11_compare_op1 = operands[1];
428 DONE;
429}")
430
c418c5ab
SC
431(define_insn "bitcmpqi"
432 [(set (cc0)
d8de89e8
SC
433 (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
434 (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
c418c5ab
SC
435 ""
436 "@
d8de89e8 437 bitb\\t%b1
c418c5ab 438 #
d8de89e8
SC
439 bitb\\t%b1
440 bitb\\t%b0
441 bitb\\t%b0")
c418c5ab 442
d8de89e8 443(define_split /* "bitcmpqi" */
c418c5ab 444 [(set (cc0)
a0df6910
SC
445 (and:QI (match_operand:QI 0 "tst_operand" "")
446 (match_operand:QI 1 "hard_addr_reg_operand" "")))]
d8de89e8
SC
447 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
448 [(set (match_dup 3) (match_dup 2))
449 (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
450 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1]));
451 operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
452 operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);")
453
454(define_insn "bitcmpqi_z_used"
455 [(set (cc0)
456 (and:QI (match_operand:QI 0 "tst_operand" "d,m")
457 (match_operand:QI 1 "cmp_operand" "m,d")))
458 (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
c418c5ab
SC
459 (use (reg:HI 11))]
460 ""
461 "#")
462
463(define_split /* "bitcmpqi_z_used" */
464 [(set (cc0)
a0df6910
SC
465 (and:QI (match_operand:QI 0 "tst_operand" "")
466 (match_operand:QI 1 "cmp_operand" "")))
467 (use (match_operand:HI 2 "hard_reg_operand" ""))
c418c5ab
SC
468 (use (reg:HI 11))]
469 "z_replacement_completed == 2"
470 [(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 2))
471 (set (match_dup 2) (match_dup 3))
472 (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
473 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI 3))))]
474 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
475
476(define_insn "bitcmphi"
477 [(set (cc0)
478 (and:HI (match_operand:HI 0 "tst_operand" "d")
479 (match_operand:HI 1 "const_int_operand" "i")))]
480 "(INTVAL (operands[1]) & 0x0ff) == 0
481 || (INTVAL (operands[1]) & 0x0ff00) == 0"
482 "*
483{
484 if ((INTVAL (operands[1]) & 0x0ff) == 0)
485 return \"bita\\t%h1\";
486 else
487 return \"bitb\\t%1\";
488}")
489
490(define_insn "bitcmpqi_12"
491 [(set (cc0)
492 (zero_extract (match_operand:HI 0 "tst_operand" "d")
493 (match_operand:HI 1 "const_int_operand" "i")
494 (match_operand:HI 2 "const_int_operand" "i")))]
495 "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
496 || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
497 && (unsigned) INTVAL (operands[2]) >= 8)"
498 "*
499{
500 rtx ops[1];
501 int mask;
502 int startpos = INTVAL (operands[2]);
503 int bitsize = INTVAL (operands[1]);
504
505 if (startpos >= 8)
506 {
507 startpos -= 8;
508 mask = (1 << (startpos + bitsize)) - 1;
509 mask &= ~((1 << startpos) - 1);
510
511 ops[0] = GEN_INT (mask);
512 output_asm_insn (\"bita\\t%0\", ops);
513 }
514 else
515 {
516 mask = (1 << (startpos + bitsize)) - 1;
517 mask &= ~((1 << startpos) - 1);
518
519 ops[0] = GEN_INT (mask);
520 output_asm_insn (\"bitb\\t%0\", ops);
521 }
522 return \"\";
523}")
524
385c9217
SC
525(define_insn "cmpqi_1"
526 [(set (cc0)
c9b9c05c
SC
527 (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
528 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
385c9217 529 ""
03997728
SC
530 "*
531{
532 if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
533 {
534 return \"#\";
535 }
536 else if (D_REG_P (operands[0]))
537 {
538 return \"cmpb\\t%b1\";
539 }
540 cc_status.flags |= CC_REVERSED;
541 return \"cmpb\\t%b0\";
542}")
385c9217
SC
543
544(define_insn "cmpqi_z_used"
545 [(set (cc0)
03997728
SC
546 (compare (match_operand:QI 0 "tst_operand" "dxy,m")
547 (match_operand:QI 1 "cmp_operand" "m,dxy")))
548 (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
385c9217
SC
549 (use (reg:HI 11))]
550 ""
76d06edc 551 "#")
385c9217
SC
552
553(define_split /* cmpqi_z_used */
554 [(set (cc0)
65e6c005
JJ
555 (compare (match_operand:QI 0 "tst_operand" "")
556 (match_operand:QI 1 "cmp_operand" "")))
557 (use (match_operand:HI 2 "hard_reg_operand" ""))
385c9217
SC
558 (use (reg:HI 11))]
559 "z_replacement_completed == 2"
01beec65 560 [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
385c9217
SC
561 (set (match_dup 2) (match_dup 3))
562 (set (cc0) (compare (match_dup 0) (match_dup 1)))
01beec65 563 (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
385c9217
SC
564 "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);")
565
385c9217
SC
566;;--------------------------------------------------------------------
567;;- Move strict_low_part
568;;--------------------------------------------------------------------
569;;
570;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
571;; The replacement must be made at the very end because we loose the
572;; (strict_low_part ...) information. This is correct for our machine
573;; description but not for GCC optimization passes.
574;;
575(define_insn "movstrictsi"
a1fdc802 576 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
385c9217
SC
577 (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
578 ""
579 "#")
580
581(define_split
65e6c005
JJ
582 [(set (strict_low_part (match_operand:SI 0 "non_push_operand" ""))
583 (match_operand:SI 1 "general_operand" ""))]
385c9217
SC
584 "z_replacement_completed == 2"
585 [(set (match_dup 0) (match_dup 1))]
586 "")
587
588(define_insn "movstricthi"
a1fdc802
SC
589 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
590 (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
385c9217
SC
591 ""
592 "#")
593
594(define_split
65e6c005
JJ
595 [(set (strict_low_part (match_operand:HI 0 "non_push_operand" ""))
596 (match_operand:HI 1 "general_operand" ""))]
385c9217
SC
597 "z_replacement_completed == 2"
598 [(set (match_dup 0) (match_dup 1))]
599 "")
600
601(define_insn "movstrictqi"
a1fdc802
SC
602 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
603 (match_operand:QI 1 "general_operand" "d,imudA"))]
385c9217
SC
604 ""
605 "#")
606
607(define_split
65e6c005
JJ
608 [(set (strict_low_part (match_operand:QI 0 "non_push_operand" ""))
609 (match_operand:QI 1 "general_operand" ""))]
385c9217
SC
610 "z_replacement_completed == 2"
611 [(set (match_dup 0) (match_dup 1))]
612 "")
613
614;;--------------------------------------------------------------------
615;;- 64-bit Move Operations.
616;; The movdi and movdf patterns are identical except for the mode.
617;; They are also very similar to those for movsi and movsf.
618;;
619;; For 68HC11, we need a scratch register (either D, X, Y)
620;; because there is no memory->memory moves. It must be defined with
621;; earlyclobber (&) so that it does not appear in the source or destination
622;; address. Providing patterns for movdi/movdf allows GCC to generate
623;; better code. [Until now, the scratch register is limited to D becuse
624;; otherwise we can run out of registers in the A_REGS class for reload].
625;;
626;; For 68HC12, the scratch register is not necessary. To use the same
627;; pattern and same split, we use the 'v' constraint. This tells the
628;; reload to use the _.tmp register (which is not used at all).
629;; The insn will be split in one or several memory moves (movw).
630;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
631;;--------------------------------------------------------------------
00d0458c
SC
632(define_expand "movdi"
633 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
634 (match_operand:DI 1 "general_operand" ""))
635 (clobber (match_scratch:HI 2 ""))])]
636 ""
637 "
638 /* For push/pop, emit a REG_INC note to make sure the reload
639 inheritance and reload CSE pass notice the change of the stack
640 pointer. */
641 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
642 {
643 rtx insn;
644
645 insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
646 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
647 stack_pointer_rtx,
648 REG_NOTES (insn));
649 DONE;
650 }
651")
652
653(define_insn "movdi_internal"
65e6c005
JJ
654 [(set (match_operand:DI 0 "nonimmediate_operand" "=uS,U,!u,U,m,m,!u")
655 (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
656 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
385c9217
SC
657 ""
658 "#")
659
660(define_split
65e6c005
JJ
661 [(set (match_operand:DI 0 "nonimmediate_operand" "")
662 (match_operand:DI 1 "general_operand" ""))
663 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
664 "reload_completed"
665 [(const_int 0)]
666 "m68hc11_split_move (operands[0], operands[1], operands[2]);
667 DONE;")
668
00d0458c
SC
669(define_expand "movdf"
670 [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
671 (match_operand:DF 1 "general_operand" ""))
672 (clobber (match_scratch:HI 2 ""))])]
673 ""
674 "/* For push/pop, emit a REG_INC note to make sure the reload
675 inheritance and reload CSE pass notice the change of the stack
676 pointer. */
677 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
678 {
679 rtx insn;
680
681 insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
682 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
683 stack_pointer_rtx,
684 REG_NOTES (insn));
685 DONE;
686 }
687")
688
689(define_insn "movdf_internal"
65e6c005
JJ
690 [(set (match_operand:DF 0 "nonimmediate_operand" "=uS,U,!u,U,m,m,!u")
691 (match_operand:DF 1 "general_operand" "G,iU,iU,!u,mi,!u,!mu"))
692 (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
385c9217
SC
693 ""
694 "#")
695
696(define_split
65e6c005
JJ
697 [(set (match_operand:DF 0 "nonimmediate_operand" "")
698 (match_operand:DF 1 "general_operand" ""))
699 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
700 "reload_completed"
701 [(const_int 0)]
702 "m68hc11_split_move (operands[0], operands[1], operands[2]);
703 DONE;")
00d0458c 704
385c9217
SC
705;;--------------------------------------------------------------------
706;;- 32-bit Move Operations.
707;; The movsi and movsf patterns are identical except for the mode.
708;; When we move to/from a hard register (d+x), we don't need a scratch.
709;; Otherwise, a scratch register is used as intermediate register for
710;; the move. The '&' constraint is necessary to make sure the reload
711;; pass does not give us a register that dies in the insn and is used
712;; for input/output operands.
713;;--------------------------------------------------------------------
00d0458c
SC
714(define_expand "movsi"
715 [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
716 (match_operand:SI 1 "general_operand" ""))
717 (clobber (match_scratch:HI 2 ""))])]
718 ""
719 "/* For push/pop, emit a REG_INC note to make sure the reload
720 inheritance and reload CSE pass notice the change of the stack
721 pointer. */
722 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
723 {
724 rtx insn;
725
726 insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
727 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
728 stack_pointer_rtx,
729 REG_NOTES (insn));
730 DONE;
731 }
732")
733
734(define_insn "movsi_internal"
65e6c005
JJ
735 [(set (match_operand:SI 0 "nonimmediate_operand" "=uS,mu,?D,m,?D,?u,?u,!u,D")
736 (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
737 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
385c9217
SC
738 ""
739 "#")
740
741(define_split
65e6c005
JJ
742 [(set (match_operand:SI 0 "nonimmediate_operand" "")
743 (match_operand:SI 1 "general_operand" ""))
744 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
745 "reload_completed"
746 [(const_int 0)]
747 "m68hc11_split_move (operands[0], operands[1], operands[2]);
748 DONE;")
749
00d0458c
SC
750(define_expand "movsf"
751 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
752 (match_operand:SF 1 "general_operand" ""))
753 (clobber (match_scratch:HI 2 ""))])]
754 ""
755 "/* For push/pop, emit a REG_INC note to make sure the reload
756 inheritance and reload CSE pass notice the change of the stack
757 pointer. */
758 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
759 {
760 rtx insn;
761
762 insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
763 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
764 stack_pointer_rtx,
765 REG_NOTES (insn));
766 DONE;
767 }
768")
769
770(define_insn "movsf_internal"
65e6c005
JJ
771 [(set (match_operand:SF 0 "nonimmediate_operand" "=S!u,m,D,m,D,!u,!u,!u,D")
772 (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
773 (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
385c9217
SC
774 ""
775 "#")
776
777(define_split
65e6c005
JJ
778 [(set (match_operand:SF 0 "nonimmediate_operand" "")
779 (match_operand:SF 1 "general_operand" ""))
780 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
781 "reload_completed"
782 [(const_int 0)]
783 "m68hc11_split_move (operands[0], operands[1], operands[2]);
784 DONE;")
785
786
787;;--------------------------------------------------------------------
788;;- 16-bit Move Operations.
789;; We don't need a scratch register.
790;;--------------------------------------------------------------------
791
792(define_insn "*movhi2_push"
793 [(set (match_operand:HI 0 "push_operand" "=<,<")
794 (match_operand:HI 1 "general_operand" "xy,?d"))]
795 "TARGET_M6811 && !TARGET_M6812"
796 "*
797{
798 cc_status = cc_prev_status;
799 if (D_REG_P (operands[1]))
800 {
801 output_asm_insn (\"pshb\", operands);
802 return \"psha\";
803 }
804 else if (X_REG_P (operands[1]))
805 {
806 return \"pshx\";
807 }
808 else if (Y_REG_P (operands[1]))
809 {
810 return \"pshy\";
811 }
812 fatal_insn (\"Invalid register in the instruction\", insn);
813}")
814
815(define_insn "*movhi2_pop"
816 [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
817 (match_operand:HI 1 "pop_operand" ">,>"))]
818 "TARGET_M6811"
819 "*
820{
821 cc_status = cc_prev_status;
822 if (D_REG_P (operands[0]))
823 {
824 output_asm_insn (\"pula\", operands);
825 return \"pulb\";
826 }
827 else if (X_REG_P (operands[0]))
828 {
829 return \"pulx\";
830 }
831 else if (Y_REG_P (operands[0]))
832 {
833 return \"puly\";
834 }
835 fatal_insn (\"Invalid register in the instruction\", insn);
836}")
837
838(define_expand "movhi"
839 [(set (match_operand:HI 0 "nonimmediate_operand" "")
840 (match_operand:HI 1 "general_operand" ""))]
841 ""
842 "
843{
844 if (reload_in_progress)
845 {
846 if (m68hc11_reload_operands (operands))
847 {
848 DONE;
849 }
850 }
851 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
852 {
853 if (GET_CODE (operands[0]) == MEM &&
854 (GET_CODE (operands[1]) == MEM
855 || GET_CODE (operands[1]) == CONST_INT))
856 {
857 operands[1] = force_reg (HImode, operands[1]);
858 }
859 else if (IS_STACK_PUSH (operands[0])
860 && GET_CODE (operands[1]) != REG)
861 {
862 operands[1] = force_reg (HImode, operands[1]);
863 }
864 }
00d0458c
SC
865 /* For push/pop, emit a REG_INC note to make sure the reload
866 inheritance and reload CSE pass notice the change of the stack
867 pointer. */
868 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
869 {
870 rtx insn;
871
872 insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
873 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
874 stack_pointer_rtx,
875 REG_NOTES (insn));
876 DONE;
877 }
385c9217
SC
878}")
879
880(define_insn "movhi_const0"
881 [(set (match_operand:HI 0 "non_push_operand" "=d,A,um")
882 (const_int 0))]
883 ""
884 "@
885 clra\\n\\tclrb
886 ld%0\\t#0
887 clr\\t%b0\\n\\tclr\\t%h0")
888
889(define_insn "*movhi_68hc12"
76028b1f
SC
890 [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,U,U,m,!u")
891 (match_operand:HI 1 "general_operand" "U,rim,dAwi,!u,dAw,riU"))]
385c9217
SC
892 "TARGET_M6812"
893 "*
894{
895 m68hc11_gen_movhi (insn, operands);
896 return \"\";
897}")
898
899(define_insn "*movhi_m68hc11"
900 [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
901 (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
902 "TARGET_M6811"
903 "*
904{
905 m68hc11_gen_movhi (insn, operands);
906 return \"\";
907}")
908
909;;--------------------------------------------------------------------
910;;- 8-bit Move Operations.
911;; We don't need a scratch register.
912;;--------------------------------------------------------------------
913;;
914;; The *a alternative also clears the high part of the register.
915;; This should be ok since this is not the (strict_low_part) set.
916;;
917(define_insn "movqi_const0"
76028b1f 918 [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
385c9217
SC
919 (const_int 0))]
920 ""
921 "@
922 clrb
923 clr\\t%b0
76028b1f 924 clr\\t%b0
385c9217
SC
925 ld%0\\t#0
926 clr%0")
927
928;;
929;; 8-bit operations on address registers.
930;;
931;; Switch temporary to the D register and load the value in B.
932;; This is possible as long as the address register does not
933;; appear in the source operand.
934;;
935(define_split
65e6c005 936 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
385c9217
SC
937 (match_operand:QI 1 "general_operand" ""))]
938 "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode
939 && !reg_mentioned_p (operands[0], operands[1])
940 && !D_REG_P (operands[1])"
01beec65
SC
941 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
942 (set (match_dup 2) (reg:HI D_REGNUM))])
943 (set (reg:QI D_REGNUM) (match_dup 1))
944 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
945 (set (match_dup 2) (reg:HI D_REGNUM))])]
385c9217
SC
946 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));")
947
948;;
949;; 8-bit operations on address registers.
950;;
951(define_split
952 [(set (match_operand:QI 0 "nonimmediate_operand" "")
65e6c005 953 (match_operand:QI 1 "hard_addr_reg_operand" ""))]
385c9217
SC
954 "z_replacement_completed == 2 && GET_MODE (operands[1]) == QImode
955 && !reg_mentioned_p (operands[1], operands[0])
956 && !D_REG_P (operands[0])"
01beec65
SC
957 [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
958 (set (match_dup 2) (reg:HI D_REGNUM))])
959 (set (match_dup 0) (reg:QI D_REGNUM))
960 (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
961 (set (match_dup 2) (reg:HI D_REGNUM))])]
385c9217
SC
962 "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1]));")
963
964(define_insn "*movqi2_push"
965 [(set (match_operand:QI 0 "push_operand" "=<,<")
966 (match_operand:QI 1 "general_operand" "d,!*A"))]
967 ""
968 "*
969{
970 if (A_REG_P (operands[1]))
971 return \"#\";
972
973 cc_status = cc_prev_status;
974 return \"pshb\";
975}")
976
977
978(define_expand "movqi"
979 [(set (match_operand:QI 0 "nonimmediate_operand" "")
980 (match_operand:QI 1 "general_operand" ""))]
981 ""
982 "
983{
984 if (reload_in_progress)
985 {
986 if (m68hc11_reload_operands (operands))
987 {
988 DONE;
989 }
990 }
991 if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
992 {
993 if (GET_CODE (operands[0]) == MEM
994 && (GET_CODE (operands[1]) == MEM
995 || GET_CODE (operands[1]) == CONST_INT))
996 {
997 operands[1] = force_reg (QImode, operands[1]);
998 }
999 else if (IS_STACK_PUSH (operands[0])
1000 && GET_CODE (operands[1]) != REG)
1001 {
1002 operands[1] = force_reg (QImode, operands[1]);
1003 }
1004 }
00d0458c
SC
1005 /* For push/pop, emit a REG_INC note to make sure the reload
1006 inheritance and reload CSE pass notice the change of the stack
1007 pointer. */
1008 if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
1009 {
1010 rtx insn;
1011
1012 insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
1013 REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
1014 stack_pointer_rtx,
1015 REG_NOTES (insn));
1016 DONE;
1017 }
385c9217
SC
1018}")
1019
1020(define_insn "*movqi_68hc12"
c9b9c05c 1021 [(set (match_operand:QI 0 "nonimmediate_operand"
3c9a5efe 1022 "=U,d*AU*q,d*A*qU,*u,d*A*q,m,m")
c9b9c05c 1023 (match_operand:QI 1 "general_operand"
3c9a5efe 1024 "U,*ri*q,U,*ri*qU,m,d*q,!*A"))]
385c9217
SC
1025 "TARGET_M6812"
1026 "*
1027{
1028 m68hc11_gen_movqi (insn, operands);
1029 return \"\";
1030}")
1031
1032(define_insn "*movqi_m68hc11"
3c9a5efe
SC
1033 [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
1034 (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
385c9217
SC
1035 "TARGET_M6811"
1036 "*
1037{
1038 m68hc11_gen_movqi (insn, operands);
1039 return \"\";
1040}")
1041
1042;;--------------------------------------------------------------------
1043;;- Swap registers
1044;;--------------------------------------------------------------------
1045;; Swapping registers is used for split patterns.
1046(define_insn "swap_areg"
1047 [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
1048 (match_operand:HI 1 "hard_reg_operand" "=A,d"))
1049 (set (match_dup 1) (match_dup 0))]
1050 ""
1051 "*
1052{
1053 m68hc11_output_swap (insn, operands);
1054 return \"\";
1055}")
1056
1057;;--------------------------------------------------------------------
1058;;- Truncation insns.
1059;;--------------------------------------------------------------------
1060;;
1061;; Truncation are not necessary because GCC knows how to truncate,
1062;; specially when values lie in consecutive registers.
1063;;
1064
1065(define_expand "floatunssisf2"
1066 [(set (match_operand:SF 0 "nonimmediate_operand" "")
1067 (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
1068 ""
1069 "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
1070 SFmode, SImode, 2, operands);
1071 DONE;")
1072
1073(define_expand "floatunssidf2"
1074 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1075 (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
1076 ""
1077 "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
1078 DFmode, SImode, 2, operands);
1079 DONE;")
1080
1081;;--------------------------------------------------------------------
1082;;- Zero extension insns.
1083;;--------------------------------------------------------------------
1084
1085;;
1086;; 64-bit extend. The insn will be split into 16-bit instructions just
1087;; before the final pass. We need a scratch register for the split.
1088;; The final value can be generated on the stack directly. This is more
1089;; efficient and useful for conversions made during parameter passing rules.
1090;;
1091(define_insn "zero_extendqidi2"
1092 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
1093 (zero_extend:DI
1094 (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
76028b1f 1095 (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
385c9217
SC
1096 ""
1097 "#")
1098
1099(define_split
65e6c005
JJ
1100 [(set (match_operand:DI 0 "push_operand" "")
1101 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
385c9217
SC
1102 (clobber (match_scratch:HI 2 "=&dB"))]
1103 "z_replacement_completed == 2"
1104 [(const_int 0)]
1105 "
1106{
1107 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1108 rtx push = m68hc11_gen_lowpart (HImode, low);
1109 rtx src = operands[1];
1110
9caea35c 1111 /* Source operand must be in a hard register. */
385c9217
SC
1112 if (!H_REG_P (src))
1113 {
1114 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1115 emit_move_insn (src, operands[1]);
1116 }
1117
1118 /* Source is in D, we can push B then one word of 0 and we do
9caea35c 1119 a correction on the stack pointer. */
385c9217
SC
1120 if (D_REG_P (src))
1121 {
1122 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1123 emit_move_insn (operands[2], const0_rtx);
1124 if (D_REG_P (operands[2]))
1125 {
1126 emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
1127 }
1128 else
1129 {
1130 emit_move_insn (push, operands[2]);
1131 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1132 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1133 const1_rtx));
1134 }
1135 }
1136 else
1137 {
1138 /* Source is in X or Y. It's better to push the 16-bit register
1139 and then to some stack adjustment. */
1140 src = gen_rtx (REG, HImode, REGNO (src));
1141 emit_move_insn (push, src);
1142 emit_move_insn (operands[2], const0_rtx);
1143 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1144 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1145 const1_rtx));
1146 emit_move_insn (push, operands[2]);
1147 emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM),
1148 gen_rtx (REG, HImode, HARD_SP_REGNUM),
1149 const1_rtx));
1150 }
1151 emit_move_insn (push, operands[2]);
1152 emit_move_insn (push, operands[2]);
1153 emit_move_insn (push, operands[2]);
1154 DONE;
1155}")
1156
1157(define_split
65e6c005
JJ
1158 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1159 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
385c9217
SC
1160 (clobber (match_scratch:HI 2 "=&dB"))]
1161 "z_replacement_completed == 2"
1162 [(const_int 0)]
1163 "
1164{
1165 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1166 rtx low2 = m68hc11_gen_lowpart (HImode, low);
1167 rtx src = operands[1];
1168
9caea35c 1169 /* Source operand must be in a hard register. */
385c9217
SC
1170 if (!H_REG_P (src))
1171 {
1172 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1173 emit_move_insn (src, operands[1]);
1174 }
1175
1176 emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
1177 emit_move_insn (operands[2], const0_rtx);
1178 src = gen_rtx (REG, QImode, REGNO (operands[2]));
1179 emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
1180
1181 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1182 low = m68hc11_gen_highpart (SImode, operands[0]);
1183 emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
1184 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1185 DONE;
1186}")
1187
1188(define_insn "zero_extendhidi2"
76028b1f 1189 [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
385c9217 1190 (zero_extend:DI
76028b1f
SC
1191 (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
1192 (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
385c9217
SC
1193 ""
1194 "#")
1195
1196(define_split
65e6c005 1197 [(set (match_operand:DI 0 "non_push_operand" "")
385c9217 1198 (zero_extend:DI
65e6c005
JJ
1199 (match_operand:HI 1 "nonimmediate_operand" "")))
1200 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
1201 "z_replacement_completed == 2"
1202 [(const_int 0)]
1203 "
1204{
1205 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1206 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1207 rtx src = operands[1];
1208
1209 /* Make sure the source is in a hard register. */
1210 if (!H_REG_P (src))
1211 {
1212 src = operands[2];
1213 emit_move_insn (src, operands[1]);
1214 }
1215
1216 /* Move the low part first for the push. */
1217 emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
1218
1219 /* Now, use the scratch register to fill in the zeros. */
1220 emit_move_insn (operands[2], const0_rtx);
1221 emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
1222 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1223 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1224 DONE;
1225}")
1226
1227(define_insn "zero_extendsidi2"
1228 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
1229 (zero_extend:DI
1230 (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
1231 (clobber (match_scratch:HI 2 "=d,d,&dB,d"))]
1232 ""
1233 "#")
1234
1235(define_split
65e6c005 1236 [(set (match_operand:DI 0 "nonimmediate_operand" "")
385c9217 1237 (zero_extend:DI
65e6c005
JJ
1238 (match_operand:SI 1 "nonimmediate_operand" "")))
1239 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
1240 "z_replacement_completed == 2"
1241 [(const_int 0)]
1242 "
1243{
1244 rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
1245 rtx high = m68hc11_gen_highpart (SImode, operands[0]);
1246
1247 /* Move the low part first so that this is ok for a push. */
1248 m68hc11_split_move (low, operands[1], operands[2]);
1249
1250 /* Use the scratch register to clear the high part of the destination. */
1251 emit_move_insn (operands[2], const0_rtx);
1252 emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
1253 emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
1254 DONE;
1255}")
1256
1257;;
1258;; For 16->32bit unsigned extension, we don't allow generation on the stack
1259;; because it's less efficient.
1260;;
1261(define_insn "zero_extendhisi2"
76028b1f 1262 [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
385c9217 1263 (zero_extend:SI
76028b1f
SC
1264 (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
1265 (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
385c9217
SC
1266 ""
1267 "#")
1268
1269(define_split
65e6c005 1270 [(set (match_operand:SI 0 "non_push_operand" "")
385c9217 1271 (zero_extend:SI
65e6c005
JJ
1272 (match_operand:HI 1 "nonimmediate_operand" "")))
1273 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
1274 "reload_completed"
1275 [(const_int 0)]
1276 "
1277{
1278 rtx src = operands[1];
1279
1280 if (!H_REG_P (src) && !H_REG_P (operands[0]))
1281 {
1282 src = operands[2];
1283 emit_move_insn (src, operands[1]);
1284 }
1285 emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
1286 emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
1287 DONE;
1288}")
1289
1290(define_insn "zero_extendqisi2"
c9b9c05c 1291 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
385c9217 1292 (zero_extend:SI
c9b9c05c 1293 (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
385c9217
SC
1294 ""
1295 "#")
1296
1297(define_split
65e6c005
JJ
1298 [(set (match_operand:SI 0 "non_push_operand" "")
1299 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
385c9217 1300 "reload_completed && !X_REG_P (operands[0])"
01beec65
SC
1301 [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
1302 (set (match_dup 3) (const_int 0))]
385c9217
SC
1303 "
1304 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
01beec65 1305 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
385c9217
SC
1306
1307(define_split
65e6c005
JJ
1308 [(set (match_operand:SI 0 "hard_reg_operand" "")
1309 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
385c9217
SC
1310 "z_replacement_completed == 2 && X_REG_P (operands[0])"
1311 [(set (match_dup 2) (match_dup 3))
1312 (set (match_dup 4) (const_int 0))
1313 (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
1314 "
1315 if (X_REG_P (operands[1]))
1316 {
1317 emit_insn (gen_swap_areg (gen_rtx (REG, HImode, HARD_D_REGNUM),
1318 gen_rtx (REG, HImode, HARD_X_REGNUM)));
1319 emit_insn (gen_zero_extendqihi2 (gen_rtx (REG, HImode, HARD_D_REGNUM),
1320 gen_rtx (REG, QImode, HARD_D_REGNUM)));
1321 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM),
1322 const0_rtx);
1323 DONE;
1324 }
1325
1326 if (reg_mentioned_p (gen_rtx (REG, HImode, HARD_X_REGNUM), operands[1]))
1327 {
1328 emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
1329 operands[0]),
1330 operands[1]));
1331 emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), const0_rtx);
1332 DONE;
1333 }
1334 operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
1335 operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
1336 if (A_REG_P (operands[1]))
1337 {
1338 operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
1339 operands[3] = gen_rtx (REG, HImode, REGNO (operands[1]));
1340 operands[6] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
1341 }
1342 else
1343 {
1344 operands[5] = operands[2] =
1345 operands[3] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1346 operands[6] = operands[1];
1347 }
1348")
1349
1350(define_insn "zero_extendqihi2"
1351 [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!u,d,m,!u")
1352 (zero_extend:HI
1353 (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
1354 ""
1355 "*
1356{
385c9217
SC
1357 if (A_REG_P (operands[0]))
1358 return \"#\";
1359
1360 if (H_REG_P (operands[0]))
1361 {
1362 output_asm_insn (\"clra\", operands);
1363 if (operands[0] != operands[1]
1364 && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
1365 {
1366 if (X_REG_P (operands[1])
1367 || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
1368 {
1369 output_asm_insn (\"stx\\t%t1\", operands);
1370 output_asm_insn (\"ldab\\t%T0\", operands);
1371 }
1372 else if (Y_REG_P (operands[1])
1373 || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
1374 {
1375 output_asm_insn (\"sty\\t%t1\", operands);
1376 output_asm_insn (\"ldab\\t%T0\", operands);
1377 }
1378 else
1379 {
1380 output_asm_insn (\"ldab\\t%b1\", operands);
1381 }
1382 cc_status.flags |= CC_NOT_NEGATIVE;
1383 }
1384 else
1385 {
1386 /* Status refers to the clra insn. Status is ok for others
1387 * since we have loaded the value in B.
1388 */
1389 CC_STATUS_INIT;
1390 }
1391 return \"\";
1392 }
1393
1394 if (A_REG_P (operands[1]))
1395 {
1396 output_asm_insn (\"st%1\\t%0\", operands);
1397 output_asm_insn (\"clr\\t%h0\", operands);
1398 CC_STATUS_INIT;
1399 }
1400 else
1401 {
1402 output_asm_insn (\"clr\\t%h0\", operands);
1403 output_asm_insn (\"stab\\t%b0\", operands);
1404 cc_status.flags |= CC_NOT_NEGATIVE;
1405 }
1406
1407 return \"\";
1408}")
1409
1410
1411;;--------------------------------------------------------------------
1412;;- Sign extension insns.
1413;;--------------------------------------------------------------------
1414
1415(define_insn "extendqisi2"
76028b1f
SC
1416 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
1417 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
385c9217
SC
1418 ""
1419 "*
1420{
385c9217
SC
1421 rtx ops[3];
1422 int need_tst = 0;
1423
dc3c6806
SC
1424 /* The 68HC12 has a sign-extension instruction. Use it when the
1425 destination is the register (X,D). First sign-extend the low
1426 part and fill X with the sign-extension of the high part. */
1427 if (TARGET_M6812 && X_REG_P (operands[0]))
1428 {
1429 if (!D_REG_P (operands[1]))
1430 {
1431 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1432 ops[1] = operands[1];
1433 m68hc11_gen_movqi (insn, ops);
1434 }
1435 return \"sex\\tb,d\\n\\tsex\\ta,x\";
1436 }
1437
385c9217
SC
1438 ops[2] = gen_label_rtx ();
1439
1440 if (X_REG_P (operands[1]))
1441 {
1442 output_asm_insn (\"xgdx\", operands);
1443 need_tst = 1;
1444 }
1445 else if (X_REG_P (operands[0]))
1446 {
1447 /* X can be used as an indexed addressing in the source.
9caea35c 1448 Get the value before clearing it. */
385c9217
SC
1449 if (reg_mentioned_p (ix_reg, operands[1]))
1450 {
1451 output_asm_insn (\"ldab\\t%b1\", operands);
1452 need_tst = 1;
1453 }
1454 output_asm_insn (\"ldx\\t#0\", operands);
1455 }
1456
1457 output_asm_insn (\"clra\", operands);
1458 if (!X_REG_P (operands[0]))
1459 {
1460 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1461 ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
1462
1463 if (IS_STACK_PUSH (operands[0]))
1464 {
1465 output_asm_insn (\"pshb\", ops);
1466 output_asm_insn (\"tstb\", ops);
1467 }
1468 else
1469 {
1470 output_asm_insn (\"stab\\t%b1\", ops);
1471 }
1472 }
1473 else if (D_REG_P (operands[1]) || need_tst)
1474 {
1475 output_asm_insn (\"tstb\", operands);
1476 }
1477 else
1478 {
1479 output_asm_insn (\"ldab\\t%b1\", operands);
1480 }
1481 output_asm_insn (\"bpl\\t%l2\", ops);
1482 output_asm_insn (\"deca\", operands);
1483 if (X_REG_P (operands[0]))
1484 output_asm_insn (\"dex\", operands);
1485
1486 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1487
1488 if (!X_REG_P (operands[0]))
1489 {
1490 if (IS_STACK_PUSH (operands[0]))
1491 {
1492 output_asm_insn (\"psha\", ops);
1493 output_asm_insn (\"psha\", ops);
1494 output_asm_insn (\"psha\", ops);
1495 }
1496 else
1497 {
1498 output_asm_insn (\"staa\\t%h0\", ops);
1499
1500 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1501 if (dead_register_here (insn, d_reg))
1502 {
1503 output_asm_insn (\"tab\", ops);
1504 output_asm_insn (\"std\\t%0\", ops);
1505 }
1506 else
1507 {
1508 output_asm_insn (\"staa\\t%b0\", ops);
1509 output_asm_insn (\"staa\\t%h0\", ops);
1510 }
1511 }
1512 }
1513
1514 CC_STATUS_INIT;
1515 return \"\";
1516}")
1517
1518
1519(define_insn "extendqihi2"
76028b1f
SC
1520 [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
1521 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
385c9217
SC
1522 ""
1523 "*
1524{
1525 rtx ops[2];
1526
1527 if (A_REG_P (operands[0]))
1528 return \"#\";
1529
1530 ops[0] = gen_label_rtx ();
1531 if (D_REG_P (operands[0]))
1532 {
dc3c6806
SC
1533 if (TARGET_M6812)
1534 {
1535 if (!D_REG_P (operands[1]))
1536 {
1537 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1538 ops[1] = operands[1];
1539 m68hc11_gen_movqi (insn, ops);
1540 }
1541 return \"sex\\tb,d\";
1542 }
385c9217
SC
1543 output_asm_insn (\"clra\", operands);
1544 if (H_REG_P (operands[1]))
1545 {
1546 output_asm_insn (\"tstb\", operands);
1547 }
1548 else
1549 {
1550 output_asm_insn (\"ldab\\t%b1\", operands);
1551 }
1552 output_asm_insn (\"bpl\\t%l0\", ops);
1553 output_asm_insn (\"deca\", operands);
1554
1555 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1556 CODE_LABEL_NUMBER (ops[0]));
1557 }
1558 else
1559 {
1560 output_asm_insn (\"clr\\t%h0\", operands);
1561 if (m68hc11_register_indirect_p (operands[1], HImode))
1562 {
1563 ops[1] = operands[1];
1564 output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
1565 CC_STATUS_INIT;
1566 }
1567 else
1568 {
1569 output_asm_insn (\"tst\\t%b1\", operands);
1570 output_asm_insn (\"bpl\\t%l0\", ops);
1571 }
1572 output_asm_insn (\"dec\\t%h0\", operands);
1573 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1574 CODE_LABEL_NUMBER (ops[0]));
1575 }
1576
1577 return \"\";
1578}")
1579
1580;;
1581;; Split the special case where the source of the sign extend is
1582;; either Y or Z. In that case, we can't move the source in the D
1583;; register directly. The movhi pattern handles this move by using
1584;; a temporary scratch memory location.
1585;;
1586(define_split
65e6c005
JJ
1587 [(set (match_operand:SI 0 "register_operand" "")
1588 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
385c9217 1589 "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
01beec65
SC
1590 [(set (reg:HI D_REGNUM) (match_dup 1))
1591 (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
385c9217
SC
1592 "")
1593
1594(define_insn "extendhisi2"
9eee2c76 1595 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
0477256c 1596 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
385c9217
SC
1597 ""
1598 "*
1599{
dc3c6806 1600 rtx ops[2];
385c9217
SC
1601 int x_reg_used;
1602
1603 if (Y_REG_P (operands[1]))
1604 return \"#\";
1605
385c9217
SC
1606 if (X_REG_P (operands[1]))
1607 {
1608 output_asm_insn (\"xgdx\", operands);
1609 x_reg_used = 1;
1610 }
1611 else
1612 {
e03f5d43 1613 /* X can be used as an indexed addressing in the source.
9caea35c 1614 Get the value before clearing it. */
385c9217
SC
1615 x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
1616 if (x_reg_used)
1617 {
dc3c6806
SC
1618 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1619 ops[1] = operands[1];
1620 m68hc11_gen_movhi (insn, ops);
385c9217
SC
1621 }
1622 }
dc3c6806
SC
1623
1624 CC_STATUS_INIT;
1625 if (TARGET_M6812 && 0)
1626 {
1627 /* This sequence of code is larger than the one for 68HC11.
1628 Don't use it; keep it for documentation. */
1629 if (!D_REG_P (operands[1]) && !x_reg_used)
1630 {
1631 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1632 ops[1] = operands[1];
1633 m68hc11_gen_movhi (insn, ops);
1634 }
1635 output_asm_insn (\"sex\\ta,x\", operands);
1636 output_asm_insn (\"xgdx\", operands);
1637 output_asm_insn (\"sex\\ta,d\", operands);
1638 return \"xgdx\";
1639 }
1640
385c9217
SC
1641 output_asm_insn (\"ldx\\t#0\", operands);
1642 if (D_REG_P (operands[1]) || x_reg_used)
1643 {
1644 output_asm_insn (\"tsta\", operands);
1645 }
1646 else
1647 {
dc3c6806
SC
1648 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1649 ops[1] = operands[1];
1650 m68hc11_gen_movhi (insn, ops);
385c9217 1651 }
dc3c6806
SC
1652
1653 ops[0] = gen_label_rtx ();
385c9217
SC
1654 output_asm_insn (\"bpl\\t%l0\", ops);
1655 output_asm_insn (\"dex\", operands);
1656 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
1657
385c9217
SC
1658 return \"\";
1659}")
1660
1661
dc3c6806
SC
1662;;--------------------------------------------------------------------
1663;;- Min and Max instructions (68HC12).
1664;;--------------------------------------------------------------------
1665(define_insn "uminqi3"
1666 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1667 (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1668 (match_operand:QI 2 "general_operand" "m,d")))]
1669 "TARGET_M6812"
1670 "*
1671{
1672 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1673 The mina/minm use A as the source or destination. This is the
1674 high part of D. There is no way to express that in the pattern
1675 so we must use 'exg a,b' to put the operand in the good register. */
1676 CC_STATUS_INIT;
1677 if (D_REG_P (operands[0]))
1678 {
1679 return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
1680 }
1681 else
1682 {
1683 return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
1684 }
1685}")
1686
1687(define_insn "umaxqi3"
1688 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
1689 (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
1690 (match_operand:QI 2 "general_operand" "m,d")))]
1691 "TARGET_M6812"
1692 "*
1693{
1694 /* Flags are set according to (sub:QI (operand 1) (operand2)).
1695 The maxa/maxm use A as the source or destination. This is the
1696 high part of D. There is no way to express that in the pattern
1697 so we must use 'exg a,b' to put the operand in the good register. */
1698 CC_STATUS_INIT;
1699 if (D_REG_P (operands[0]))
1700 {
1701 return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
1702 }
1703 else
1704 {
1705 return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
1706 }
1707}")
1708
1709(define_insn "uminhi3"
1710 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1711 (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1712 (match_operand:HI 2 "general_operand" "m,d")))]
1713 "TARGET_M6812"
1714 "*
1715{
1716 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1717 CC_STATUS_INIT;
1718 if (D_REG_P (operands[0]))
1719 {
1720 return \"emind\\t%2\";
1721 }
1722 else
1723 {
1724 return \"eminm\\t%0\";
1725 }
1726}")
1727
1728(define_insn "umaxhi3"
1729 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
1730 (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
1731 (match_operand:HI 2 "general_operand" "m,d")))]
1732 "TARGET_M6812"
1733 "*
1734{
1735 /* Flags are set according to (sub:HI (operand 1) (operand2)). */
1736 CC_STATUS_INIT;
1737 if (D_REG_P (operands[0]))
1738 {
1739 return \"emaxd\\t%2\";
1740 }
1741 else
1742 {
1743 return \"emaxm\\t%0\";
1744 }
1745}")
1746
1747
385c9217
SC
1748;;--------------------------------------------------------------------
1749;;- Add instructions.
1750;;--------------------------------------------------------------------
1751;; 64-bit: Use a library call because what GCC generates is huge.
1752;;
1753(define_expand "adddi3"
1754 [(set (match_operand:DI 0 "nonimmediate_operand" "")
1755 (plus:DI (match_operand:DI 1 "general_operand" "")
1756 (match_operand:DI 2 "general_operand" "")))]
1757 ""
1758 "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
1759 DONE;")
1760
1761;;
1762;; - 32-bit Add.
1763;;
1764(define_expand "addsi3"
1765 [(parallel [(set (match_operand:SI 0 "register_operand" "")
840e2ff1 1766 (plus:SI (match_operand:SI 1 "general_operand" "")
385c9217
SC
1767 (match_operand:SI 2 "general_operand" "")))
1768 (clobber (match_scratch:HI 3 ""))])]
1769 ""
1770 "")
1771
385c9217
SC
1772(define_insn "*addsi3_zero_extendhi"
1773 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
1774 (plus:SI (zero_extend:SI
1775 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
1776 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
1777 (clobber (match_scratch:HI 3 "=X,X,X,X"))]
1778 ""
1779 "*
1780{
1781 rtx ops[3];
1782
1783 if (X_REG_P (operands[2]))
1784 {
1785 ops[0] = operands[1];
1786 }
1787 else
1788 {
1789 if (X_REG_P (operands[1]))
1790 {
1791 output_asm_insn (\"xgdx\", ops);
1792 }
1793 else if (!D_REG_P (operands[1]))
1794 {
1795 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
1796 ops[1] = operands[1];
1797 m68hc11_gen_movhi (insn, ops);
1798 }
1799 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1800 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1801 }
1802 ops[2] = gen_label_rtx ();
1803
9caea35c 1804 /* ldx preserves the carry, propagate it by incrementing X directly. */
385c9217
SC
1805 output_asm_insn (\"addd\\t%0\", ops);
1806 if (!X_REG_P (operands[2]))
1807 output_asm_insn (\"ldx\\t%1\", ops);
1808
1809 output_asm_insn (\"bcc\\t%l2\", ops);
1810 output_asm_insn (\"inx\", ops);
1811
1812 CC_STATUS_INIT;
1813 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1814 return \"\";
1815}")
1816
1817
1818(define_split /* "*addsi3_zero_extendqi" */
65e6c005 1819 [(set (match_operand:SI 0 "register_operand" "")
385c9217 1820 (plus:SI (zero_extend:SI
65e6c005
JJ
1821 (match_operand:QI 1 "general_operand" ""))
1822 (match_operand:SI 2 "memory_operand" "")))
385c9217
SC
1823 (clobber (match_scratch:HI 3 "=X,X"))]
1824 "reload_completed"
01beec65 1825 [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
385c9217 1826 (parallel [(set (match_dup 0)
01beec65 1827 (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
385c9217
SC
1828 (clobber (match_dup 3))])]
1829 "")
1830
1831(define_insn "*addsi3_zero_extendqi"
1832 [(set (match_operand:SI 0 "register_operand" "=D,D")
1833 (plus:SI (zero_extend:SI
1834 (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
1835 (match_operand:SI 2 "general_operand" "miD,!muiD")))
1836 (clobber (match_scratch:HI 3 "=X,X"))]
1837 ""
1838 "*
1839{
1840 rtx ops[4];
1841
1842 if (GET_CODE (operands[2]) == MEM)
1843 return \"#\";
1844
1845 if (X_REG_P (operands[2]))
1846 {
1847 if (H_REG_P (operands[1]))
1848 {
1849 ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
1850 ops[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
1851 m68hc11_gen_movhi (insn, ops);
1852 }
1853 else
1854 {
1855 ops[0] = operands[1];
1856 }
65e6c005 1857 ops[1] = const0_rtx;
385c9217
SC
1858 }
1859 else
1860 {
1861 if (X_REG_P (operands[1]))
1862 {
1863 output_asm_insn (\"xgdx\", ops);
1864 }
1865 else if (!D_REG_P (operands[1]))
1866 {
1867 ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM);
1868 ops[1] = operands[1];
1869 m68hc11_gen_movqi (insn, ops);
1870 }
1871
1872 ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
1873 ops[1] = ops[0];
1874 ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
1875 output_asm_insn (\"clra\", ops);
1876 }
1877
9caea35c 1878 /* ldx preserves the carry, propagate it by incrementing X directly. */
385c9217
SC
1879 output_asm_insn (\"addb\\t%b0\", ops);
1880 output_asm_insn (\"adca\\t%h1\", ops);
1881 if (!X_REG_P (operands[2]))
1882 output_asm_insn (\"ldx\\t%2\", ops);
1883
1884 /* If the above adca was adding some constant, we don't need to propagate
1885 the carry unless the constant was 0xff. */
1886 if (X_REG_P (operands[2])
1887 || GET_CODE (ops[1]) != CONST_INT
1888 || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
1889 {
1890 ops[3] = gen_label_rtx ();
1891
1892 output_asm_insn (\"bcc\\t%l3\", ops);
1893 output_asm_insn (\"inx\", ops);
1894
1895 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
1896 CODE_LABEL_NUMBER (ops[3]));
1897 }
1898 CC_STATUS_INIT;
1899 return \"\";
1900}")
1901
1902(define_insn "*addsi3"
ae9bd481 1903 [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
385c9217 1904 (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
ae9bd481 1905 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
385c9217
SC
1906 (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
1907 ""
1908 "*
1909{
1910 rtx ops[3];
1943c2c1
KG
1911 const char* add_insn;
1912 const char* inc_insn;
1913 const char* incb_mem;
1914 const char* inch_mem;
385c9217
SC
1915 HOST_WIDE_INT val;
1916
1917 if (which_alternative > 2)
1918 {
1919 return \"#\";
1920 }
1921
1922 val = INTVAL (operands[2]);
1923 if ((val & 0x0ffffL) == 0)
1924 {
1925 if (!H_REG_P (operands[0]))
1926 {
1927 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1928 ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
1929 output_asm_insn (\"ldd\\t%0\", ops);
1930 output_asm_insn (\"addd\\t%1\", ops);
1931 output_asm_insn (\"std\\t%0\", ops);
1932 return \"\";
1933 }
1934 else if (val == 1)
1935 {
1936 return \"inx\";
1937 }
1938 else
1939 {
1940 return \"#\";
1941 }
1942 }
1943 if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
1944 {
1945 return \"#\";
1946 }
1947
1948 if (val >= 0)
1949 {
1950 ops[1] = operands[2];
1951 add_insn = \"addd\\t%1\";
1952 inc_insn = \"inx\\t\";
1953 incb_mem = \"inc\\t%b1\";
1954 inch_mem = \"inc\\t%h1\";
1955 }
1956 else
1957 {
65e6c005 1958 ops[1] = GEN_INT (- val);
385c9217
SC
1959 add_insn = \"subd\\t%1\";
1960 inc_insn = \"dex\";
1961 incb_mem = \"dec\\t%b1\";
1962 inch_mem = \"dec\\t%h1\";
1963 }
1964
1965 ops[2] = gen_label_rtx ();
1966 if (!H_REG_P (operands[0]))
1967 {
1968 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
1969 output_asm_insn (\"ldd\\t%0\", ops);
1970 }
1971 output_asm_insn (add_insn, ops);
1972 if (!H_REG_P (operands[0]))
1973 {
1974 output_asm_insn (\"std\\t%0\", ops);
1975 }
1976 output_asm_insn (\"bcc\\t%l2\", ops);
1977 if (H_REG_P (operands[0]))
1978 {
1979 output_asm_insn (inc_insn, ops);
1980 }
1981 else
1982 {
1983 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
1984 ops[1] = ops[0];
1985 if (INTVAL (operands[2]) < 0)
1986 {
1987 output_asm_insn (\"ldd\\t%1\", ops);
1988 output_asm_insn (\"addd\\t#-1\", ops);
1989 output_asm_insn (\"std\\t%1\", ops);
1990 }
1991 else
1992 {
1993 output_asm_insn (incb_mem, ops);
1994 output_asm_insn (\"bne\\t%l2\", ops);
1995 output_asm_insn (inch_mem, ops);
1996 }
1997 }
1998 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
1999
2000 CC_STATUS_INIT;
2001 return \"\";
2002}")
2003
2004(define_split
65e6c005
JJ
2005 [(set (match_operand:SI 0 "register_operand" "")
2006 (plus:SI (match_operand:SI 1 "register_operand" "")
385c9217 2007 (match_operand:SI 2 "const_int_operand" "")))
65e6c005 2008 (clobber (match_scratch:HI 3 ""))]
385c9217
SC
2009 "reload_completed && z_replacement_completed == 2
2010 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
9eee2c76
SC
2011 [(set (match_dup 5) (match_dup 6))
2012 (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
2013 (set (match_dup 6) (match_dup 5))]
2014 "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2015 if (X_REG_P (operands[0]))
2016 {
2017 operands[5] = operands[6] = gen_rtx (REG, HImode, HARD_D_REGNUM);
2018 }
2019 else
2020 {
2021 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2022 operands[5] = operands[3];
2023 }
2024 ")
385c9217
SC
2025
2026(define_split
65e6c005
JJ
2027 [(set (match_operand:SI 0 "register_operand" "")
2028 (plus:SI (match_operand:SI 1 "register_operand" "")
2029 (match_operand:SI 2 "general_operand" "")))
385c9217
SC
2030 (clobber (match_scratch:HI 3 "=X"))]
2031 "reload_completed && z_replacement_completed == 2
2032 && (GET_CODE (operands[2]) != CONST_INT ||
2033 (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
01beec65
SC
2034 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
2035 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2036 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
2037 (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2038 (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2039 (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
2040 (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
385c9217
SC
2041 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2042 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2043 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2044 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2045
2046;;
2047;; Instruction generated to propagate the carry of a 16-bit add
2048;; to the upper 16-bit part (in register X).
2049;;
2050(define_insn "*addsi_carry"
2051 [(set (match_operand:HI 0 "register_operand" "=x")
2052 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
2053 (const_int 0))
01beec65 2054 (reg:HI CC_REGNUM)))]
385c9217
SC
2055 ""
2056 "*
2057{
2058 rtx ops[2];
2059
2060 ops[0] = gen_label_rtx ();
2061 output_asm_insn (\"bcc\\t%l0\", ops);
2062 output_asm_insn (\"in%0\", operands);
2063 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2064 CC_STATUS_INIT;
2065 return \"\";
2066}")
2067
2068;;
2069;; - 16-bit Add.
2070;;
2071(define_expand "addhi3"
2072 [(set (match_operand:HI 0 "register_operand" "")
2073 (plus:HI (match_operand:HI 1 "register_operand" "")
2074 (match_operand:HI 2 "general_operand" "")))]
2075 ""
2076 "
2077{
2078 if (TARGET_M6811 && SP_REG_P (operands[0]))
2079 {
2080 emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
2081 gen_rtx (SET, VOIDmode,
2082 operand0,
2083 gen_rtx (PLUS, HImode,
2084 operand1, operand2)),
2085 gen_rtx (CLOBBER, VOIDmode,
2086 gen_rtx (SCRATCH, HImode)))));
2087 DONE;
2088 }
2089}")
2090
385c9217 2091(define_insn "*addhi3_68hc12"
840e2ff1
SC
2092 [(set (match_operand:HI 0 "register_operand" "=xy,d,xy*z*w,xy*z*w,xy*z")
2093 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*zw,0")
2094 (match_operand:HI 2 "general_operand" "N,im*A*wu,id,id,!mu*A")))]
385c9217
SC
2095 "TARGET_M6812"
2096 "*
2097{
2098 int val;
2099 const char* insn_code;
2100
840e2ff1 2101 if (which_alternative >= 4)
01beec65
SC
2102 {
2103 if (A_REG_P (operands[2]))
2104 {
2105 CC_STATUS_INIT;
2106 output_asm_insn (\"xgd%2\", operands);
2107 output_asm_insn (\"lea%0 d,%0\", operands);
2108 return \"xgd%2\";
2109 }
2110 return \"#\";
2111 }
2112
385c9217
SC
2113 if (D_REG_P (operands[0]))
2114 {
2115 if (X_REG_P (operands[2]))
2116 {
01beec65 2117 m68hc11_notice_keep_cc (operands[0]);
385c9217
SC
2118 output_asm_insn (\"xgdx\", operands);
2119 output_asm_insn (\"leax\\td,%2\", operands);
2120 return \"xgdx\";
2121 }
2122 else if (Y_REG_P (operands[2]))
2123 {
01beec65 2124 m68hc11_notice_keep_cc (operands[0]);
385c9217
SC
2125 output_asm_insn (\"xgdy\", operands);
2126 output_asm_insn (\"leay\\td,%2\", operands);
2127 return \"xgdy\";
2128 }
2129 else if (SP_REG_P (operands[2]))
2130 {
2131 output_asm_insn (\"sts\\t%t0\", operands);
2132 return \"addd\\t%t0\";
2133 }
2134 return \"addd\\t%2\";
2135 }
2136
2137 if (GET_CODE (operands[2]) == CONST_INT)
2138 val = INTVAL (operands[2]);
2139 else
2140 val = 1000;
2141
840e2ff1 2142 if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
385c9217 2143 {
01beec65 2144 m68hc11_notice_keep_cc (operands[0]);
385c9217
SC
2145 switch (REGNO (operands[0]))
2146 {
2147 case HARD_X_REGNUM:
2148 return \"leax\\t%i2,%1\";
2149
2150 case HARD_Y_REGNUM:
2151 return \"leay\\t%i2,%1\";
2152
2153 case HARD_SP_REGNUM:
2154 return \"leas\\t%i2,%1\";
2155
2156 default:
2157 fatal_insn (\"Invalid operands in the instruction\", insn);
2158 }
2159 }
2160 if (val > 0)
2161 {
2162 insn_code = X_REG_P (operands[0]) ? \"inx\"
2163 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2164 }
2165 else
2166 {
2167 val = -val;
2168 insn_code = X_REG_P (operands[0]) ? \"dex\"
2169 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2170 }
2171
2172 /* For X and Y increment, the flags are not complete. Only the Z flag
9caea35c 2173 is updated. For SP increment, flags are not changed. */
385c9217
SC
2174 if (SP_REG_P (operands[0]))
2175 {
2176 cc_status = cc_prev_status;
2177 if (INTVAL (operands[2]) < 0)
2178 {
2179 while (val > 2)
2180 {
2181 output_asm_insn (\"pshx\", operands);
2182 val -= 2;
2183 }
2184 if (val == 0)
2185 return \"\";
2186 }
2187 }
2188 else
2189 {
2190 CC_STATUS_INIT;
2191 }
2192
2193 while (val)
2194 {
2195 output_asm_insn (insn_code, operands);
2196 val--;
2197 }
2198 return \"\";
2199}")
2200
2201;;
2202;; Specific pattern to add to the stack pointer.
2203;; We also take care of the clobbering of the IY register.
2204;;
2205(define_insn "addhi_sp"
2206 [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
2207 (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
2208 (match_operand:HI 2 "general_operand" "P,im,u,im")))
2209 (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
2210 "!TARGET_M6812"
2211 "*
2212{
2213 HOST_WIDE_INT val;
2214
840e2ff1
SC
2215 if (optimize && Y_REG_P (operands[3])
2216 && dead_register_here (insn, gen_rtx (REG, HImode, HARD_X_REGNUM)))
2217 operands[3] = gen_rtx (REG, HImode, HARD_X_REGNUM);
2218
385c9217
SC
2219 if (GET_CODE (operands[2]) == CONST_INT
2220 && (val = INTVAL (operands[2])) != 0
2221 && (CONST_OK_FOR_LETTER_P (val, 'P')
2222 || (val > 0 && val <= 8)))
2223 {
385c9217
SC
2224 while (val > 1 || val < -1)
2225 {
2226 if (val > 0)
2227 {
2228 if (!H_REG_P (operands[3]))
2229 break;
2230
2231 output_asm_insn (\"pul%3\", operands);
2232 val -= 2;
2233 }
2234 else
2235 {
2236 output_asm_insn (\"pshx\", operands);
2237 val += 2;
2238 }
2239 }
2240 while (val != 0)
2241 {
2242 if (val > 0)
2243 {
2244 output_asm_insn (\"ins\", operands);
2245 val--;
2246 }
2247 else
2248 {
2249 output_asm_insn (\"des\", operands);
2250 val++;
2251 }
2252 }
2253 cc_status = cc_prev_status;
2254 return \"\";
2255 }
2256
840e2ff1
SC
2257 /* Need to transfer to SP to X/Y and then to D register.
2258 Register X/Y is lost, this is specified by the (clobber) statement. */
385c9217 2259 output_asm_insn (\"ts%3\", operands);
840e2ff1
SC
2260 if (GET_CODE (operands[2]) == CONST_INT
2261 && ((val = INTVAL (operands[2]) >= 0 && val < 0x100))
2262 && dead_register_here (insn, gen_rtx (REG, HImode, HARD_D_REGNUM)))
2263 {
2264 output_asm_insn (\"ldab\\t%2\", operands);
2265 output_asm_insn (\"ab%3\", operands);
2266 CC_STATUS_INIT;
2267 }
2268 else
2269 {
2270 output_asm_insn (\"xgd%3\", operands);
2271 output_asm_insn (\"addd\\t%2\", operands);
2272 output_asm_insn (\"xgd%3\", operands);
2273 }
385c9217
SC
2274
2275 /* The status flags correspond to the addd. xgdy and tys do not
2276 modify the flags. */
2277 return \"t%3s\";
2278}")
2279
385c9217 2280(define_insn "*addhi3"
c9b9c05c 2281 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d*A")
01beec65 2282 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0")
0477256c 2283 (match_operand:HI 2 "general_operand" "N,i,I,mi*A*d,!u*d*w")))]
385c9217
SC
2284 "TARGET_M6811"
2285 "*
2286{
2287 const char* insn_code;
2288 int val;
385c9217
SC
2289
2290 if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
2291 {
2292 output_asm_insn (\"sts\\t%t0\", operands);
2293 output_asm_insn (\"addd\\t%t0\", operands);
2294 return \"addd\\t#1\";
2295 }
2296 if (GET_CODE (operands[2]) != CONST_INT)
2297 {
2298 /* Adding to an address register or with another/same register
9caea35c 2299 is not possible. This must be replaced. */
385c9217
SC
2300 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2301 return \"#\";
2302
2303 return \"addd\\t%2\";
2304 }
2305 val = INTVAL (operands[2]);
2306 if (!SP_REG_P (operands[0]))
2307 {
2308 if (D_REG_P (operands[0]))
2309 {
2310 if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
2311 {
2312 CC_STATUS_INIT;
2313 return \"adda\\t%h2\";
2314 }
2315 else
2316 {
2317 return \"addd\\t%2\";
2318 }
2319 }
2320 else if (GET_CODE (operands[2]) != CONST_INT
2321 || INTVAL (operands[2]) < -4
2322 || INTVAL (operands[2]) > 4)
2323 return \"#\";
2324 }
2325 if (val > 0)
2326 {
2327 insn_code = X_REG_P (operands[0]) ? \"inx\"
2328 : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
2329 }
2330 else
2331 {
2332 val = -val;
2333 insn_code = X_REG_P (operands[0]) ? \"dex\"
2334 : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
2335 }
2336
2337 /* For X and Y increment, the flags are not complete. Only the Z flag
2338 is updated. For SP increment, flags are not changed. */
2339 if (SP_REG_P (operands[0]))
2340 {
2341 cc_status = cc_prev_status;
2342 if (INTVAL (operands[2]) < 0)
2343 {
2344 while (val >= 2)
2345 {
2346 output_asm_insn (\"pshx\", operands);
2347 val -= 2;
2348 }
2349 }
2350 else if (optimize && dead_register_here (insn, ix_reg))
2351 {
2352 while (val >= 2)
2353 {
2354 output_asm_insn (\"pulx\", operands);
2355 val -= 2;
2356 }
2357 }
2358 }
2359 else
2360 {
2361 CC_STATUS_INIT;
2362 }
2363
2364 while (val)
2365 {
2366 output_asm_insn (insn_code, operands);
2367 val--;
2368 }
2369 return \"\";
2370}")
2371
2372(define_insn "*addhi3_zext"
2373 [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
2374 (plus:HI (zero_extend:HI
2375 (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
2376 (match_operand:HI 2 "hard_reg_operand" "0,0")))]
2377 ""
2378 "*
2379{
2380 CC_STATUS_INIT;
2381 if (A_REG_P (operands[0]))
2382 return \"ab%0\";
2383 else if (A_REG_P (operands[1]))
2384 return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
2385 else
2386 return \"addb\\t%b1\\n\\tadca\\t#0\";
2387}")
2388
2389;;
2390;; Translate d = d + d into d = << 1
2391;; We have to do this because adding a register to itself is not possible.
2392;; ??? It's not clear whether this is really necessary.
2393;;
2394(define_split
65e6c005 2395 [(set (match_operand:QI 0 "hard_reg_operand" "")
385c9217
SC
2396 (plus:QI (match_dup 0)
2397 (match_dup 0)))]
2398 "0 && reload_completed"
2399 [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
2400 "")
2401
2402(define_insn "addqi3"
c9b9c05c
SC
2403 [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
2404 (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
2405 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
385c9217
SC
2406 ""
2407 "*
2408{
2409 if (GET_CODE (operands[2]) == CONST_INT)
2410 {
2411 if (INTVAL (operands[2]) == 1)
2412 {
2413 if (DA_REG_P (operands[0]))
2414 {
2415 return \"inca\";
2416 }
2417 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2418 {
2419 return \"incb\";
2420
2421 }
2422 else if (A_REG_P (operands[0]))
2423 {
2424 /* This applies on the 16-bit register. This should be ok since
2425 this is not a strict_low_part increment. */
2426 return \"in%0\";
2427 }
2428 else
2429 {
2430 return \"inc\\t%b0\";
2431 }
2432 }
2433 else if (INTVAL (operands[2]) == -1)
2434 {
2435 if (DA_REG_P (operands[0]))
2436 {
2437 return \"deca\";
2438 }
2439 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2440 {
2441 return \"decb\";
2442 }
2443 else if (A_REG_P (operands[0]))
2444 {
2445 /* This applies on the 16-bit register. This should be ok since
2446 this is not a strict_low_part decrement. */
2447 return \"de%0\";
2448 }
2449 else
2450 {
2451 return \"dec\\t%b0\";
2452 }
2453 }
2454 }
2455 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2456 return \"#\";
2457 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2458 return \"addb\\t%b2\";
2459 else
2460 return \"adda\\t%b2\";
2461}")
2462
2463;;
2464;; add with carry is used for 32-bit add.
2465;;
2466(define_insn "*adcq"
2467 [(set (match_operand:QI 0 "register_operand" "=q")
01beec65 2468 (plus:QI (plus:QI (reg:QI CC_REGNUM)
76d06edc
SC
2469 (match_operand:QI 1 "register_operand" "%0"))
2470 (match_operand:QI 2 "general_operand" "ium")))]
385c9217 2471 ""
76d06edc 2472 "adc%0\\t%b2")
385c9217
SC
2473
2474;;--------------------------------------------------------------------
2475;;- Subtract instructions.
2476;;--------------------------------------------------------------------
2477
2478(define_expand "subdi3"
2479 [(set (match_operand:DI 0 "nonimmediate_operand" "")
2480 (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
2481 (match_operand:DI 2 "general_operand" "")))]
2482 ""
2483 "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
2484 DONE;")
2485
2486;;
2487;; 32-bit Subtract (see addsi3)
2488;; Subtract with a constant are handled by addsi3.
2489;;
2490;;
2491;; - 32-bit Add.
2492;;
2493(define_expand "subsi3"
2494 [(parallel [(set (match_operand:SI 0 "register_operand" "")
2495 (minus:SI (match_operand:SI 1 "register_operand" "")
2496 (match_operand:SI 2 "general_operand" "")))
2497 (clobber (match_scratch:HI 3 ""))])]
2498 ""
2499 "")
2500
2501(define_insn "*subsi3"
840e2ff1 2502 [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
ae9bd481
SC
2503 (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
2504 (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
840e2ff1 2505 (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
385c9217
SC
2506 ""
2507 "#")
2508
2509(define_insn "*subsi3_zero_extendhi"
2510 [(set (match_operand:SI 0 "register_operand" "=D")
2511 (minus:SI (match_operand:SI 1 "register_operand" "0")
2e3d3481 2512 (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
385c9217
SC
2513 (clobber (match_scratch:HI 3 "=X"))]
2514 ""
2515 "*
2516{
2517 rtx ops[2];
2518
2e3d3481
SC
2519 if (A_REG_P (operands[2]))
2520 {
2521 if (TARGET_M6812)
2522 ops[0] = gen_rtx (MEM, HImode,
2523 gen_rtx (PRE_DEC, HImode,
2524 gen_rtx (REG, HImode, HARD_SP_REGNUM)));
2525 else
2526 ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
2527
2528 ops[1] = operands[2];
2529 m68hc11_gen_movhi (insn, ops);
2530 if (TARGET_M6812)
2531 operands[2] = gen_rtx (MEM, HImode,
2532 gen_rtx (POST_INC, HImode,
2533 gen_rtx (REG, HImode, HARD_SP_REGNUM)));
2534 else
2535 operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
2536 }
385c9217
SC
2537 ops[0] = gen_label_rtx ();
2538 output_asm_insn (\"subd\\t%2\", operands);
2539 output_asm_insn (\"bcc\\t%l0\", ops);
2540 output_asm_insn (\"dex\", ops);
2541 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2542 CC_STATUS_INIT;
2543 return \"\";
2544}")
2545
2546(define_insn "*subsi3_zero_extendqi"
2547 [(set (match_operand:SI 0 "register_operand" "=D")
2548 (minus:SI (match_operand:SI 1 "register_operand" "0")
2e3d3481 2549 (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
385c9217
SC
2550 (clobber (match_scratch:HI 3 "=X"))]
2551 ""
2552 "*
2553{
2554 rtx ops[2];
2555
2e3d3481
SC
2556 if (A_REG_P (operands[2]))
2557 {
2558 ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
2559 ops[1] = operands[2];
2560 m68hc11_gen_movhi (insn, ops);
2561 operands[2] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
2562 }
385c9217
SC
2563 ops[0] = gen_label_rtx ();
2564 output_asm_insn (\"subb\\t%b2\", operands);
2565 output_asm_insn (\"sbca\\t#0\", operands);
2566 output_asm_insn (\"bcc\\t%l0\", ops);
2567 output_asm_insn (\"dex\", ops);
2568 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
2569 CC_STATUS_INIT;
2570 return \"\";
2571}")
2572
2573;;
2574;; reg:HI 1 -> d reg:QI 6 -> B
2575;; reg:QI 7 -> ccr reg:QI 5 -> A
2576;;
2577(define_split /* "*subsi3" */
65e6c005
JJ
2578 [(set (match_operand:SI 0 "register_operand" "")
2579 (minus:SI (match_operand:SI 1 "register_operand" "")
2580 (match_operand:SI 2 "general_operand" "")))
385c9217
SC
2581 (clobber (match_scratch:HI 3 "=X"))]
2582 "reload_completed && z_replacement_completed == 2
2583 && X_REG_P (operands[1])"
01beec65
SC
2584 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2585 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2586 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2587 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2588 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2589 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2590 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
385c9217
SC
2591 "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
2592 operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
2593 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2594 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2595
2596(define_split /* "*subsi3" */
65e6c005
JJ
2597 [(set (match_operand:SI 0 "register_operand" "")
2598 (minus:SI (match_operand:SI 1 "general_operand" "")
2599 (match_operand:SI 2 "register_operand" "")))
385c9217
SC
2600 (clobber (match_scratch:HI 3 "=X"))]
2601 "reload_completed && z_replacement_completed == 2
2602 && X_REG_P (operands[2])"
01beec65
SC
2603 [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
2604 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2605 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
2606 (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
2607 (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
2608 (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
2609 (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
385c9217
SC
2610 (set (reg:SI 0) (neg:SI (reg:SI 0)))]
2611 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
2612 operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
2613 operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
2614 operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
2615
840e2ff1 2616(define_split /* "*subsi3" */
65e6c005
JJ
2617 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2618 (minus:SI (match_operand:SI 1 "general_operand" "")
2619 (match_operand:SI 2 "general_operand" "")))
840e2ff1
SC
2620 (clobber (match_scratch:HI 3 "=d"))]
2621 "reload_completed && z_replacement_completed == 2
2622 && !X_REG_P (operands[0])"
2623 [(set (match_dup 3) (match_dup 4))
2624 (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
2625 (set (match_dup 4) (match_dup 3))
2626 (set (match_dup 3) (match_dup 6))
2627 (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
2628 (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
2629 (set (match_dup 6) (match_dup 3))]
2630 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
2631 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
2632 operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
2633 operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
2634 operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
2635 operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
2636
385c9217
SC
2637;;
2638;; - 16-bit Subtract.
2639;;
2640(define_expand "subhi3"
2641 [(set (match_operand:HI 0 "register_operand" "=r")
2642 (minus:HI (match_operand:HI 1 "register_operand" "0")
2643 (match_operand:HI 2 "general_operand" "g")))]
2644 ""
840e2ff1 2645 "")
385c9217
SC
2646
2647;;
2648;; Subtract from stack. This is better if we provide a pattern.
2649;;
2650(define_insn "*subhi3_sp"
2651 [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
2652 (minus:HI (match_operand:HI 1 "register_operand" "0,0")
0477256c 2653 (match_operand:HI 2 "general_operand" "im*d,!u*A")))
385c9217
SC
2654 (clobber (match_scratch:HI 3 "=A*d,A*d"))]
2655 ""
2656 "*
2657{
2658 if (X_REG_P (operands[2]))
2659 {
2660 operands[2] = m68hc11_soft_tmp_reg;
2661 output_asm_insn (\"stx\\t%2\", operands);
2662 }
2663 else if (Y_REG_P (operands[2]))
2664 {
2665 operands[2] = m68hc11_soft_tmp_reg;
2666 output_asm_insn (\"sty\\t%2\", operands);
2667 }
2668 else if (D_REG_P (operands[2]))
2669 {
2670 operands[2] = m68hc11_soft_tmp_reg;
2671 output_asm_insn (\"std\\t%2\", operands);
2672 }
2673
2674 if (D_REG_P (operands[3]))
2675 {
840e2ff1
SC
2676 int save_x;
2677
2678 save_x = !dead_register_here (insn, ix_reg);
2679 if (save_x)
2680 output_asm_insn (\"xgdx\", operands);
385c9217
SC
2681 output_asm_insn (\"tsx\", operands);
2682 output_asm_insn (\"xgdx\", operands);
2683 output_asm_insn (\"subd\\t%2\", operands);
2684 output_asm_insn (\"xgdx\", operands);
2685
2686 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
9caea35c 2687 modify the flags. */
385c9217 2688 output_asm_insn (\"txs\", operands);
840e2ff1
SC
2689 if (save_x)
2690 return \"xgdx\";
2691 else
2692 return \"\";
385c9217
SC
2693 }
2694
2695 /* Need to transfer to SP to X,Y and then to D register.
9caea35c 2696 Register X,Y is lost, this is specified by the (clobber) statement. */
385c9217
SC
2697 output_asm_insn (\"ts%3\", operands);
2698 output_asm_insn (\"xgd%3\", operands);
2699 output_asm_insn (\"subd\\t%2\", operands);
2700 output_asm_insn (\"xgd%3\", operands);
2701
2702 /* The status flags correspond to the addd. xgdx/y and tx/ys do not
9caea35c 2703 modify the flags. */
385c9217
SC
2704 return \"t%3s\";
2705}")
2706
2707
2708(define_insn "*subhi3"
0477256c
SC
2709 [(set (match_operand:HI 0 "register_operand" "=d,*A,d*A")
2710 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
2711 (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,!u")))]
385c9217
SC
2712 ""
2713 "*
2714{
2715 /* Adding to an address register or with another/same register
9caea35c 2716 is not possible. This must be replaced. */
385c9217
SC
2717 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2718 return \"#\";
2719
2720 return \"subd\\t%2\";
2721}")
2722
2723(define_insn "*subhi3_zext"
2724 [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
2725 (minus:HI (match_operand:HI 1 "hard_reg_operand" "0,0")
2726 (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
2727 ""
2728 "*
2729{
2730 CC_STATUS_INIT;
2731 if (A_REG_P (operands[2]))
2732 {
2733 rtx ops[2];
2734
2735 ops[0] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
2736 ops[1] = operands[2];
2737 m68hc11_gen_movqi (insn, ops);
2738 return \"subb\\t%T0\\n\\tsbca\\t#0\";
2739 }
2740 return \"subb\\t%b2\\n\\tsbca\\t#0\";
2741}")
2742
2743(define_insn "subqi3"
a1fdc802
SC
2744 [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
2745 (minus:QI (match_operand:QI 1 "hard_reg_operand" "0,0")
2746 (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
385c9217
SC
2747 ""
2748 "*
2749{
2750 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
2751 return \"#\";
2752 else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
2753 return \"subb\\t%b2\";
2754 else
2755 return \"suba\\t%b2\";
2756}")
2757
2758;;
2759;; subtract with carry is used for 32-bit subtract.
2760;;
2761(define_insn "*subcq"
2762 [(set (match_operand:QI 0 "register_operand" "=q")
01beec65 2763 (minus:QI (minus:QI (reg:QI CC_REGNUM)
76d06edc
SC
2764 (match_operand:QI 1 "register_operand" "0"))
2765 (match_operand:QI 2 "general_operand" "ium")))]
385c9217 2766 ""
76d06edc 2767 "sbc%0\\t%b2")
385c9217
SC
2768
2769;;--------------------------------------------------------------------
2770;;- Multiply instructions.
2771;;--------------------------------------------------------------------
2772;;
2773;; 32 and 64-bit multiply are handled by the library
2774;;
2775
3d0746ba
SC
2776(define_expand "mulsi3"
2777 [(set (match_operand:SI 0 "nonimmediate_operand" "")
2778 (mult:SI (match_operand:SI 1 "general_operand" "")
2779 (match_operand:SI 2 "general_operand" "")))]
2780 ""
2781 "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
2782 DONE;")
2783
2784(define_expand "mulhi3"
2785 [(parallel [(set (match_operand:HI 0 "register_operand" "")
2786 (mult:HI (match_operand:HI 1 "register_operand" "")
2787 (match_operand:HI 2 "register_operand" "")))
2788 (clobber (match_scratch:HI 3 ""))])]
2789 ""
2790 "")
2791
2792(define_insn "mulhi3_m68hc11"
385c9217
SC
2793 [(set (match_operand:HI 0 "register_operand" "=d")
2794 (mult:HI (match_operand:HI 1 "register_operand" "%0")
3d0746ba
SC
2795 (match_operand:HI 2 "register_operand" "x")))
2796 (clobber (match_scratch:HI 3 "=X"))]
2797 "TARGET_M6811"
385c9217
SC
2798 "*
2799{
2800 CC_STATUS_INIT;
2801 /* D * X -> D (X and Y are preserved by this function call). */
2802 return \"jsr\\t___mulhi3\";
2803}")
2804
3d0746ba
SC
2805(define_insn "mulhi3_m68hc12"
2806 [(set (match_operand:HI 0 "register_operand" "=d,d")
2807 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2808 (match_operand:HI 2 "register_operand" "y,x")))
2809 (clobber (match_scratch:HI 3 "=2,2"))]
2810 "TARGET_M6812"
2811 "*
2812{
2813 CC_STATUS_INIT;
2814 if (X_REG_P (operands[2]))
2815 return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
2816 else
2817 return \"emul\";
2818}")
2819
2820(define_insn "umulhisi3"
2821 [(set (match_operand:SI 0 "register_operand" "=D,D")
2822 (mult:SI (zero_extend:SI
2823 (match_operand:HI 1 "register_operand" "%d,d"))
2824 (zero_extend:SI
2825 (match_operand:HI 2 "register_operand" "y,x"))))
2826 (clobber (match_scratch:HI 3 "=2,X"))]
2827 "TARGET_M6812"
2828 "*
2829{
2830 if (X_REG_P (operands [2]))
2831 output_asm_insn (\"exg\\tx,y\", operands);
2832
2833 /* Can't use the carry after that; other flags are ok when testing
2834 the 32-bit result. */
2835 cc_status.flags |= CC_NO_OVERFLOW;
2836 return \"emul\\n\\texg\\tx,y\";
2837}")
2838
2839(define_insn "mulhisi3"
2840 [(set (match_operand:SI 0 "register_operand" "=D,D")
2841 (mult:SI (sign_extend:SI
2842 (match_operand:HI 1 "register_operand" "%d,d"))
2843 (sign_extend:SI
2844 (match_operand:HI 2 "register_operand" "y,x"))))
2845 (clobber (match_scratch:HI 3 "=2,X"))]
2846 "TARGET_M6812"
2847 "*
2848{
2849 if (X_REG_P (operands [2]))
2850 output_asm_insn (\"exg\\tx,y\", operands);
2851
2852 /* Can't use the carry after that; other flags are ok when testing
2853 the 32-bit result. */
2854 cc_status.flags |= CC_NO_OVERFLOW;
2855 return \"emuls\\n\\texg\\tx,y\";
2856}")
2857
385c9217
SC
2858(define_insn "umulqihi3"
2859 [(set (match_operand:HI 0 "register_operand" "=d")
2860 (mult:HI (zero_extend:HI
2861 (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
2862 (zero_extend:HI
2863 (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
2864 ""
2865 "*
2866{
2867 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2868 {
2869 output_asm_insn (\"tba\", operands);
2870 }
2871 else
2872 {
2873 rtx ops[2];
2874
2875 if (D_REG_P (operands[2]))
2876 {
2877 rtx temp = operands[2];
2878 operands[2] = operands[1];
2879 operands[1] = temp;
2880 }
2881
2882 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
2883 ops[1] = operands[2];
2884 m68hc11_gen_movqi (insn, ops);
2885
2886 if (!D_REG_P (operands[1]))
2887 {
2888 output_asm_insn (\"ldab\\t%b1\", operands);
2889 }
2890 }
2891
2892 CC_STATUS_INIT;
2893 return \"mul\";
2894}")
2895
2896(define_insn "mulqi3"
2897 [(set (match_operand:QI 0 "register_operand" "=d")
2898 (mult:QI (match_operand:QI 1 "nonimmediate_operand" "dum")
2899 (match_operand:QI 2 "nonimmediate_operand" "dum")))]
2900 ""
2901 "*
2902{
2903 if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
2904 {
2905 output_asm_insn (\"tba\", operands);
2906 }
2907 else
2908 {
2909 if (D_REG_P (operands[2]))
2910 {
2911 rtx temp = operands[2];
2912 operands[2] = operands[1];
2913 operands[1] = temp;
2914 }
2915
2916 output_asm_insn (\"ldaa\\t%b2\", operands);
2917
2918 if (!D_REG_P (operands[1]))
2919 {
2920 output_asm_insn (\"ldab\\t%b1\", operands);
2921 }
2922 }
2923
2924 CC_STATUS_INIT;
2925 return \"mul\";
2926}")
2927
2928(define_insn "mulqihi3"
2929 [(set (match_operand:HI 0 "register_operand" "=d,d")
2930 (mult:HI (sign_extend:HI
2931 (match_operand:QI 1 "register_operand" "%0,0"))
2932 (sign_extend:HI
2933 (match_operand:QI 2 "nonimmediate_operand" "dm,*A"))))]
2934 ""
2935 "*
2936{
2937 CC_STATUS_INIT;
2938
2939 /* Special case when multiplying the register with itself. */
2940 if (D_REG_P (operands[2]))
2941 {
2942 output_asm_insn (\"tba\", operands);
2943 return \"mul\";
2944 }
2945
2946 if (!H_REG_P (operands[2]))
2947 {
2948 output_asm_insn (\"ldaa\\t%b2\", operands);
2949 }
2950 else
2951 {
2952 rtx ops[2];
2953
2954 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
2955 ops[1] = operands[2];
2956 m68hc11_gen_movqi (insn, ops);
2957 }
2958 return \"jsr\\t___mulqi3\";
2959}")
2960
2961;;--------------------------------------------------------------------
2962;;- Divide instructions.
2963;;--------------------------------------------------------------------
2964
2965(define_insn "divmodhi4"
2966 [(set (match_operand:HI 0 "register_operand" "=d,d")
2967 (div:HI (match_operand:HI 1 "register_operand" "0,0")
2968 (match_operand:HI 2 "general_operand" "A,ium")))
3d0746ba 2969 (set (match_operand:HI 3 "register_operand" "=&x,&x")
385c9217
SC
2970 (mod:HI (match_dup 1) (match_dup 2)))]
2971 ""
2972 "*
2973{
2974 if (!X_REG_P (operands[2]))
2975 {
2976 if (Y_REG_P (operands[2]))
2977 {
2978 output_asm_insn (\"sty\\t%t1\", operands);
2979 output_asm_insn (\"ldx\\t%t1\", operands);
2980 }
2981 else
2982 {
2983 output_asm_insn (\"ldx\\t%2\", operands);
2984 }
2985 }
3d0746ba
SC
2986 if (TARGET_M6812)
2987 {
2988 /* Flags are ok after that. */
2989 return \"idivs\\n\\txgdx\";
2990 }
2991 else
2992 {
2993 CC_STATUS_INIT;
2994 return \"bsr\\t__divmodhi4\";
2995 }
385c9217
SC
2996}")
2997
2998(define_insn "udivmodhi4"
2999 [(set (match_operand:HI 0 "register_operand" "=d,d")
3000 (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
3001 (match_operand:HI 2 "general_operand" "A,ium")))
3002 (set (match_operand:HI 3 "register_operand" "=x,x")
3003 (umod:HI (match_dup 1) (match_dup 2)))]
3004 ""
3005 "*
3006{
3007 if (!X_REG_P (operands[2]))
3008 {
3009 if (Y_REG_P (operands[2]))
3010 {
3011 output_asm_insn (\"sty\\t%t1\", operands);
3012 output_asm_insn (\"ldx\\t%t1\", operands);
3013 }
3014 else
3015 {
3016 output_asm_insn (\"ldx\\t%2\", operands);
3017 }
3018 }
3019
3020 /* Z V and C flags are set but N is unchanged.
3021 Since this is an unsigned divide, we can probably keep the flags
3022 and indicate this. */
3023 cc_status.flags |= CC_NOT_NEGATIVE;
3024 return \"idiv\\n\\txgdx\";
3025}")
3026
3027;;--------------------------------------------------------------------
3028;;- and instructions.
3029;;--------------------------------------------------------------------
3030
3031(define_insn "anddi3"
76028b1f
SC
3032 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3033 (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3034 (match_operand:DI 2 "general_operand" "imu,imu")))
3035 (clobber (match_scratch:HI 3 "=d,d"))]
385c9217
SC
3036 ""
3037 "#")
3038
3039(define_insn "andsi3"
932657df
SC
3040 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3041 (and:SI (match_operand:SI 1 "register_operand" "%0,0")
3042 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3043 (clobber (match_scratch:HI 3 "=X,d"))]
385c9217
SC
3044 ""
3045 "#")
3046
932657df
SC
3047(define_expand "andhi3"
3048 [(set (match_operand:HI 0 "register_operand" "")
3049 (and:HI (match_operand:HI 1 "register_operand" "")
3050 (match_operand:HI 2 "general_operand" "")))]
385c9217 3051 ""
932657df
SC
3052 "")
3053
3054(define_insn "*andhi3_mem"
3055 [(set (match_operand:HI 0 "memory_operand" "=Q,R")
3056 (and:HI (match_dup 0)
3057 (match_operand:HI 1 "immediate_operand" "i,i")))
3058 (clobber (match_scratch:HI 2 "=xy,X"))]
3059 "TARGET_RELAX && !TARGET_M6812"
385c9217
SC
3060 "*
3061{
932657df 3062 int val = INTVAL (operands[1]) & 0x0FFFF;
385c9217 3063
932657df 3064 if (val == 0x0ffff)
385c9217 3065 {
932657df
SC
3066 cc_status = cc_prev_status;
3067 return \"\";
3068 }
385c9217 3069
932657df 3070 CC_STATUS_INIT;
385c9217 3071
932657df 3072 /* The bclr instruction uses an inverted mask. */
65e6c005 3073 operands[1] = GEN_INT ((~val) & 0x0FFFF);
385c9217 3074
932657df
SC
3075 /* When destination is a global variable, generate a .relax instruction
3076 and load the address in the clobber register. That load can be
3077 eliminated by the linker if the address is in page0. */
3078 if (which_alternative == 0)
3079 {
3080 rtx ops[3];
385c9217 3081
932657df
SC
3082 ops[0] = operands[2];
3083 ops[1] = XEXP (operands[0], 0);
3084 ops[2] = gen_label_rtx ();
3085 output_asm_insn (\".relax\\t%l2\", ops);
3086 m68hc11_gen_movhi (insn, ops);
3087 if ((val & 0x0FF) != 0x0FF)
3088 output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
385c9217 3089
932657df
SC
3090 if ((val & 0x0FF00) != 0x0FF00)
3091 output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
385c9217 3092
932657df
SC
3093 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3094 CODE_LABEL_NUMBER (ops[2]));
3095 return \"\";
3096 }
3097
3098 if ((val & 0x0FF) != 0x0FF)
3099 output_asm_insn (\"bclr\\t%b0, %b1\", operands);
385c9217 3100
932657df
SC
3101 if ((val & 0x0FF00) != 0x0FF00)
3102 output_asm_insn (\"bclr\\t%h0, %h1\", operands);
385c9217 3103
932657df
SC
3104 return \"\";
3105}")
3106
3107(define_insn "*andhi3_const"
3108 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3109 (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3110 (match_operand:HI 2 "const_int_operand" "")))]
3111 ""
3112 "*
3113{
3114 int val = INTVAL (operands[2]) & 0x0FFFF;
3115 int lowpart_zero = 0;
3116 int highpart_zero = 0;
3117 int lowpart_unknown = 0;
3118 int highpart_unknown = 0;
3119
3120 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3121 return \"#\";
3122
3123 if (val == 0x0ffff)
3124 {
3125 cc_status = cc_prev_status;
385c9217
SC
3126 return \"\";
3127 }
3128
932657df
SC
3129 /* First, try to clear the low and high part.
3130 If that's possible, the second 'and' will give
3131 the good status flags and we can avoid a tsthi. */
3132 if ((val & 0x0FF) == 0)
3133 {
3134 if (D_REG_P (operands[0]))
3135 output_asm_insn (\"clrb\", operands);
3136 else
3137 output_asm_insn (\"clr\\t%b0\", operands);
3138 lowpart_zero = 1;
3139 }
3140 if ((val & 0x0FF00) == 0)
3141 {
3142 if (D_REG_P (operands[0]))
3143 output_asm_insn (\"clra\", operands);
3144 else
3145 output_asm_insn (\"clr\\t%h0\", operands);
3146 highpart_zero = 1;
3147 }
3148
3149 if ((val & 0x0FF) == 0x0FF)
3150 {
3151 lowpart_unknown = 1;
3152 }
3153 else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
3154 {
3155 rtx ops[2];
3156
3157 ops[0] = operands[0];
65e6c005 3158 ops[1] = GEN_INT ((~val) & 0x0FF);
932657df
SC
3159 output_asm_insn (\"bclr\\t%b0, %1\", ops);
3160 }
3161 else if ((val & 0x0FF) != 0)
3162 {
3163 output_asm_insn (\"andb\\t%b2\", operands);
3164 }
3165
3166 if ((val & 0x0FF00) == 0x0FF00)
3167 {
3168 highpart_unknown = 1;
3169 }
3170 else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
3171 {
3172 rtx ops[2];
3173
3174 ops[0] = operands[0];
65e6c005 3175 ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
932657df
SC
3176 output_asm_insn (\"bclr\\t%h0, %1\", ops);
3177 }
3178 else if ((val & 0x0FF00) != 0)
3179 {
3180 output_asm_insn (\"anda\\t%h2\", operands);
3181 }
3182
3183 if (highpart_unknown || lowpart_unknown)
3184 CC_STATUS_INIT;
3185 else if (highpart_zero == 0 && lowpart_zero == 0)
3186 CC_STATUS_INIT;
3187
3188 return \"\";
3189}")
3190
3191(define_insn "*andhi3_gen"
3192 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3193 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
3194 (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))]
3195 ""
3196 "*
3197{
3198 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3199 return \"#\";
3200
385c9217 3201 CC_STATUS_INIT;
2e3d3481 3202 return \"anda\\t%h2\\n\\tandb\\t%b2\";
385c9217
SC
3203}")
3204
932657df
SC
3205(define_expand "andqi3"
3206 [(set (match_operand:QI 0 "register_operand" "")
3207 (and:QI (match_operand:QI 1 "register_operand" "")
3208 (match_operand:QI 2 "general_operand" "")))]
385c9217 3209 ""
932657df
SC
3210 "")
3211
3212(define_insn "*andqi3_mem"
3213 [(set (match_operand:QI 0 "memory_operand" "=Q,R")
3214 (and:QI (match_dup 0)
3215 (match_operand:QI 1 "const_int_operand" "i,i")))
3216 (clobber (match_scratch:HI 2 "=xy,X"))]
3217 "TARGET_RELAX && !TARGET_M6812"
385c9217
SC
3218 "*
3219{
932657df
SC
3220 int val = INTVAL (operands[1]) & 0x0FF;
3221
3222 if (val == 0x0ff)
3223 {
3224 cc_status = cc_prev_status;
3225 return \"\";
3226 }
3227
3228 /* The bclr instruction uses an inverted mask. */
65e6c005 3229 operands[1] = GEN_INT ((~val) & 0x0FF);
932657df
SC
3230
3231 /* When destination is a global variable, generate a .relax instruction
3232 and load the address in the clobber register. That load can be
3233 eliminated by the linker if the address is in page0. */
3234 if (which_alternative == 0)
3235 {
3236 rtx ops[3];
3237
3238 ops[0] = operands[2];
3239 ops[1] = XEXP (operands[0], 0);
3240 ops[2] = gen_label_rtx ();
3241 output_asm_insn (\".relax\\t%l2\", ops);
3242 m68hc11_gen_movhi (insn, ops);
3243 output_asm_insn (\"bclr\\t0,%2, %1\", operands);
3244 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3245 CODE_LABEL_NUMBER (ops[2]));
3246 return \"\";
3247 }
3248 return \"bclr\\t%b0, %1\";
3249}")
3250
3251(define_insn "*andqi3_const"
3252 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3253 (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3254 (match_operand:QI 2 "const_int_operand" "")))]
3255 ""
3256 "*
3257{
3258 int val = INTVAL (operands[2]) & 0x0FF;
3259
385c9217
SC
3260 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3261 return \"#\";
3262
932657df 3263 if (val == 0x0ff)
385c9217 3264 {
932657df
SC
3265 cc_status = cc_prev_status;
3266 return \"\";
3267 }
3268 if (!H_REG_P (operands[0]))
3269 {
3270 rtx ops[2];
385c9217 3271
932657df 3272 ops[0] = operands[0];
65e6c005 3273 ops[1] = GEN_INT ((~val) & 0x0FF);
932657df
SC
3274 output_asm_insn (\"bclr\\t%b0, %b1\", ops);
3275 return \"\";
385c9217
SC
3276 }
3277 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3278 return \"andb\\t%b2\";
3279 else if (DA_REG_P (operands[0]))
3280 return \"anda\\t%b2\";
3281 else
3282 fatal_insn (\"Invalid operand in the instruction\", insn);
3283}")
3284
932657df
SC
3285(define_insn "*andqi3_gen"
3286 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3287 (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
3288 (match_operand:QI 2 "general_operand" "mi,!u,?*A,!um,?*A*d,!um*A")))]
3289 ""
3290 "*
3291{
3292 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3293 return \"#\";
3294
3295 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3296 return \"andb\\t%b2\";
3297 else if (DA_REG_P (operands[0]))
3298 return \"anda\\t%b2\";
3299 else
3300 fatal_insn (\"Invalid operand in the instruction\", insn);
3301}")
3302
385c9217
SC
3303;;--------------------------------------------------------------------
3304;;- Bit set or instructions.
3305;;--------------------------------------------------------------------
3306
3307(define_insn "iordi3"
76028b1f
SC
3308 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3309 (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3310 (match_operand:DI 2 "general_operand" "imu,imu")))
3311 (clobber (match_scratch:HI 3 "=d,d"))]
385c9217
SC
3312 ""
3313 "#")
3314
3315(define_insn "iorsi3"
932657df
SC
3316 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3317 (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
3318 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3319 (clobber (match_scratch:HI 3 "=X,d"))]
385c9217
SC
3320 ""
3321 "#")
3322
932657df
SC
3323(define_expand "iorhi3"
3324 [(set (match_operand:HI 0 "register_operand" "")
3325 (ior:HI (match_operand:HI 1 "register_operand" "")
3326 (match_operand:HI 2 "general_operand" "")))]
385c9217 3327 ""
932657df
SC
3328 "")
3329
3330(define_insn "*iorhi3_mem"
3331 [(set (match_operand:HI 0 "memory_operand" "=Q,R")
3332 (ior:HI (match_dup 0)
3333 (match_operand:HI 1 "const_int_operand" "")))
3334 (clobber (match_scratch:HI 2 "=xy,X"))]
3335 "TARGET_RELAX && !TARGET_M6812"
385c9217
SC
3336 "*
3337{
932657df 3338 int val = INTVAL (operands[1]) & 0x0FFFF;
385c9217 3339
932657df 3340 if (val == 0)
385c9217 3341 {
932657df
SC
3342 cc_status = cc_prev_status;
3343 return \"\";
3344 }
3345 CC_STATUS_INIT;
3346 if (which_alternative == 0)
3347 {
3348 rtx ops[3];
385c9217 3349
932657df
SC
3350 ops[0] = operands[2];
3351 ops[1] = XEXP (operands[0], 0);
3352 ops[2] = gen_label_rtx ();
3353 output_asm_insn (\".relax\\t%l2\", ops);
3354 m68hc11_gen_movhi (insn, ops);
385c9217 3355 if ((val & 0x0FF) != 0)
932657df 3356 output_asm_insn (\"bset\\t1,%2, %b1\", operands);
385c9217
SC
3357
3358 if ((val & 0x0FF00) != 0)
932657df
SC
3359 output_asm_insn (\"bset\\t0,%2, %h1\", operands);
3360 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3361 CODE_LABEL_NUMBER (ops[2]));
3362 return \"\";
3363 }
385c9217 3364
932657df
SC
3365 if ((val & 0x0FF) != 0)
3366 output_asm_insn (\"bset\\t%b0, %b1\", operands);
3367
3368 if ((val & 0x0FF00) != 0)
3369 output_asm_insn (\"bset\\t%h0, %h1\", operands);
3370
3371 return \"\";
3372}")
3373
3374(define_insn "*iorhi3_const"
3375 [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
3376 (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
3377 (match_operand:HI 2 "const_int_operand" "")))]
3378 ""
3379 "*
3380{
3381 int val = INTVAL (operands[2]) & 0x0FFFF;
3382
3383 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3384 return \"#\";
3385
3386 if (val == 0)
3387 {
3388 cc_status = cc_prev_status;
385c9217
SC
3389 return \"\";
3390 }
3391
932657df
SC
3392 if ((val & 0x0FF) != 0)
3393 {
3394 if (!H_REG_P (operands[0]))
3395 output_asm_insn (\"bset\\t%b0, %b2\", operands);
3396 else
3397 output_asm_insn (\"orab\\t%b2\", operands);
3398 }
3399
3400 if ((val & 0x0FF00) != 0)
3401 {
3402 if (!H_REG_P (operands[0]))
3403 output_asm_insn (\"bset\\t%h0, %h2\", operands);
3404 else
3405 output_asm_insn (\"oraa\\t%h2\", operands);
3406 }
3407
385c9217 3408 CC_STATUS_INIT;
932657df 3409 return \"\";
385c9217
SC
3410}")
3411
932657df
SC
3412(define_insn "*iorhi3_gen"
3413 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3414 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0")
3415 (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))]
385c9217
SC
3416 ""
3417 "*
3418{
3419 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3420 return \"#\";
3421
932657df 3422 CC_STATUS_INIT;
2e3d3481 3423 return \"oraa\\t%h2\\n\\torab\\t%b2\";
932657df
SC
3424}")
3425
3426(define_expand "iorqi3"
3427 [(set (match_operand:QI 0 "register_operand" "")
3428 (ior:QI (match_operand:QI 1 "register_operand" "")
3429 (match_operand:QI 2 "general_operand" "")))]
3430 ""
3431 "")
3432
3433(define_insn "*iorqi3_mem"
3434 [(set (match_operand:QI 0 "memory_operand" "=Q,R")
3435 (ior:QI (match_dup 0)
3436 (match_operand:QI 1 "const_int_operand" "")))
3437 (clobber (match_scratch:HI 2 "=xy,X"))]
3438 "TARGET_RELAX && !TARGET_M6812"
3439 "*
3440{
3441 int val = INTVAL (operands[1]) & 0x0FF;
3442
3443 if (val == 0)
385c9217 3444 {
932657df
SC
3445 cc_status = cc_prev_status;
3446 return \"\";
3447 }
3448 if (which_alternative == 0)
3449 {
3450 rtx ops[3];
385c9217 3451
932657df
SC
3452 ops[0] = operands[2];
3453 ops[1] = XEXP (operands[0], 0);
3454 ops[2] = gen_label_rtx ();
3455 output_asm_insn (\".relax\\t%l2\", ops);
3456 m68hc11_gen_movhi (insn, ops);
3457 output_asm_insn (\"bset\\t0,%2, %1\", operands);
3458 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3459 CODE_LABEL_NUMBER (ops[2]));
3460 return \"\";
385c9217 3461 }
932657df
SC
3462 return \"bset\\t%b0, %1\";
3463}")
3464
3465(define_insn "*iorqi3_const"
3466 [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
3467 (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
3468 (match_operand:QI 2 "const_int_operand" "")))]
3469 ""
3470 "*
3471{
3472 int val = INTVAL (operands[2]) & 0x0FF;
3473
3474 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3475 return \"#\";
3476
3477 if (val == 0)
3478 {
3479 cc_status = cc_prev_status;
3480 return \"\";
3481 }
3482 if (!H_REG_P (operands[0]))
3483 {
3484 return \"bset\\t%b0, %2\";
3485 }
3486
385c9217
SC
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\";
3491 else
3492 fatal_insn (\"Invalid operand in the instruction\", insn);
3493}")
3494
932657df
SC
3495(define_insn "*iorqi3_gen"
3496 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3497 (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
3498 (match_operand:QI 2 "general_operand" "mi,!u,!*A,!um,?*A*d,!um*A")))]
3499 ""
3500 "*
3501{
3502 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3503 return \"#\";
3504
3505 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3506 return \"orab\\t%b2\";
3507 else if (DA_REG_P (operands[0]))
3508 return \"oraa\\t%b2\";
3509 else
3510 fatal_insn (\"Invalid operand in the instruction\", insn);
3511}")
3512
3513
385c9217
SC
3514;;--------------------------------------------------------------------
3515;;- xor instructions.
3516;;--------------------------------------------------------------------
3517
3518(define_insn "xordi3"
76028b1f
SC
3519 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
3520 (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
3521 (match_operand:DI 2 "general_operand" "imu,imu")))
3522 (clobber (match_scratch:HI 3 "=d,d"))]
385c9217
SC
3523 ""
3524 "#")
3525
3526(define_insn "xorsi3"
932657df
SC
3527 [(set (match_operand:SI 0 "register_operand" "=D,!u")
3528 (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
3529 (match_operand:SI 2 "general_operand" "Dimu,imu")))
3530 (clobber (match_scratch:HI 3 "=X,d"))]
385c9217
SC
3531 ""
3532 "#")
3533
3534(define_insn "xorhi3"
3535 [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
3536 (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
3537 (match_operand:HI 2 "general_operand" "im,!u*A,!ium*A")))]
3538 ""
3539 "*
3540{
3541 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3542 return \"#\";
3543
3544 if (GET_CODE (operands[2]) == CONST_INT)
3545 {
3546 int val = INTVAL (operands[2]) & 0x0FFFF;
3547
3548 if (val == 0)
3549 {
3550 cc_status = cc_prev_status;
3551 return \"\";
3552 }
3553 if ((val & 0x0FF) != 0)
3554 {
3555 output_asm_insn (\"eorb\\t%b2\", operands);
3556 }
3557 else if ((val & 0x0FF) == 0x0FF)
3558 {
3559 output_asm_insn (\"comb\", operands);
3560 }
3561
3562 if ((val & 0x0FF00) != 0)
3563 {
3564 output_asm_insn (\"eora\\t%h2\", operands);
3565 }
3566 else if ((val & 0x0FF00) == 0x0FF00)
3567 {
3568 output_asm_insn (\"coma\", operands);
3569 }
3570
3571 CC_STATUS_INIT;
3572 return \"\";
3573 }
3574
3575 CC_STATUS_INIT;
2e3d3481 3576 return \"eora\\t%h2\\n\\teorb\\t%b2\";
385c9217
SC
3577}")
3578
3579(define_insn "xorqi3"
0477256c
SC
3580 [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
3581 (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
932657df 3582 (match_operand:QI 2 "general_operand" "im,!u,!*A,!ium,?*A*d,!ium*A")))]
385c9217
SC
3583 ""
3584 "*
3585{
3586 if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
3587 return \"#\";
3588
3589 if (GET_CODE (operands[2]) == CONST_INT)
3590 {
3591 int val = INTVAL (operands[2]) & 0x0FF;
3592
3593 if (val == 0)
3594 {
3595 cc_status = cc_prev_status;
3596 return \"\";
3597 }
3598 if (val == 0x0FF)
3599 {
3600 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3601 return \"comb\";
3602 else
3603 return \"coma\";
3604 }
3605 }
3606 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
3607 return \"eorb\\t%b2\";
3608 else if (DA_REG_P (operands[0]))
3609 return \"eora\\t%b2\";
3610 else
3611 fatal_insn (\"Invalid operand in the instruction\", insn);
3612}")
3613
3614;;--------------------------------------------------------------------
3615;;- Bit set or instructions.
3616;;--------------------------------------------------------------------
3617
3618(define_insn "*logicalsi3_zexthi"
cd28557c 3619 [(set (match_operand:SI 0 "register_operand" "=D")
385c9217
SC
3620 (match_operator:SI 3 "m68hc11_logical_operator"
3621 [(zero_extend:SI
cd28557c
SC
3622 (match_operand:HI 1 "general_operand" "imudA"))
3623 (match_operand:SI 2 "general_operand" "Dimu")]))]
385c9217
SC
3624 ""
3625 "#")
3626
3627(define_insn "*logicalsi3_zextqi"
3628 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
3629 (match_operator:SI 3 "m68hc11_logical_operator"
3630 [(zero_extend:SI
3631 (match_operand:QI 1 "general_operand" "d,*A,imu"))
3632 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
3633 ""
3634 "#")
3635
cd28557c
SC
3636(define_split /* logicalsi3_zextqi */
3637 [(set (match_operand:SI 0 "register_operand" "")
385c9217
SC
3638 (match_operator:SI 3 "m68hc11_logical_operator"
3639 [(zero_extend:SI
cd28557c
SC
3640 (match_operand:QI 1 "general_operand" ""))
3641 (match_operand:SI 2 "general_operand" "")]))]
385c9217 3642 "z_replacement_completed == 2"
01beec65
SC
3643 [(set (reg:QI A_REGNUM) (match_dup 4))
3644 (set (reg:QI D_REGNUM) (match_dup 7))
3645 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
3646 (set (reg:HI X_REGNUM) (match_dup 6))]
385c9217
SC
3647 "PUT_MODE (operands[3], QImode);
3648 if (X_REG_P (operands[2]))
3649 {
3650 operands[5] = operands[1];
3651 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3652 operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM);
3653 operands[7] = gen_rtx (REG, QImode, HARD_D_REGNUM);
3654 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3655 }
3656 else
3657 {
3658 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3659 operands[7] = operands[1];
3660 operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
3661 operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
3662 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
cd28557c
SC
3663 }
3664 /* For an AND, make sure the high 24-bit part is cleared. */
3665 if (GET_CODE (operands[3]) == AND)
3666 {
3667 operands[4] = const0_rtx;
3668 operands[6] = const0_rtx;
3669 }
385c9217
SC
3670 ")
3671
cd28557c
SC
3672(define_split /* logicalsi3_zexthi */
3673 [(set (match_operand:SI 0 "register_operand" "")
385c9217
SC
3674 (match_operator:SI 3 "m68hc11_logical_operator"
3675 [(zero_extend:SI
cd28557c
SC
3676 (match_operand:HI 1 "general_operand" ""))
3677 (match_operand:SI 2 "general_operand" "")]))]
385c9217 3678 "reload_completed"
01beec65
SC
3679 [(set (reg:HI D_REGNUM) (match_dup 4))
3680 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3681 (set (reg:HI X_REGNUM) (match_dup 6))]
385c9217
SC
3682 "PUT_MODE (operands[3], HImode);
3683 if (X_REG_P (operands[2]))
3684 {
3685 operands[5] = operands[1];
3686 /* Make all the (set (REG:x) (REG:y)) a nop set. */
3687 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3688 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3689 }
3690 else
3691 {
3692 operands[4] = operands[1];
3693 operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
3694 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
cd28557c
SC
3695 }
3696 /* For an AND, make sure the high 16-bit part is cleared. */
3697 if (GET_CODE (operands[3]) == AND)
3698 {
3699 operands[6] = const0_rtx;
3700 }
385c9217
SC
3701 ")
3702
cd28557c 3703(define_insn "*logicalhi3_zexthi_ashift8"
385c9217
SC
3704 [(set (match_operand:HI 0 "register_operand" "=d")
3705 (match_operator:HI 3 "m68hc11_logical_operator"
3706 [(zero_extend:HI
3707 (match_operand:QI 1 "general_operand" "imud"))
3708 (ashift:HI
3709 (match_operand:HI 2 "general_operand" "dimu")
3710 (const_int 8))]))]
3711 ""
3712 "#")
3713
3714(define_insn "*logicalhi3_zexthi"
c9b9c05c 3715 [(set (match_operand:HI 0 "register_operand" "=d,d")
385c9217
SC
3716 (match_operator:HI 3 "m68hc11_logical_operator"
3717 [(zero_extend:HI
c9b9c05c
SC
3718 (match_operand:QI 1 "general_operand" "imd*A,?u"))
3719 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
385c9217
SC
3720 ""
3721 "#")
3722
cd28557c
SC
3723(define_split /* logicalhi3_zexthi */
3724 [(set (match_operand:HI 0 "register_operand" "")
385c9217
SC
3725 (match_operator:HI 3 "m68hc11_logical_operator"
3726 [(zero_extend:HI
cd28557c
SC
3727 (match_operand:QI 1 "general_operand" ""))
3728 (match_operand:HI 2 "general_operand" "")]))]
385c9217 3729 "z_replacement_completed == 2"
01beec65
SC
3730 [(set (reg:QI B_REGNUM) (match_dup 6))
3731 (set (reg:QI A_REGNUM) (match_dup 4))
3732 (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
385c9217
SC
3733 "
3734 PUT_MODE (operands[3], QImode);
3735 if (D_REG_P (operands[2]))
3736 {
3737 operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM);
3738 operands[5] = operands[1];
3739 operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3740 }
3741 else
3742 {
3743 operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
3744 operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
3745 if (D_REG_P (operands[1]))
3746 operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3747 else
3748 operands[6] = operands[1];
3749 }
cd28557c
SC
3750 /* For an AND, make sure the high 8-bit part is cleared. */
3751 if (GET_CODE (operands[3]) == AND)
3752 {
3753 operands[4] = const0_rtx;
3754 }
385c9217
SC
3755 ")
3756
cd28557c
SC
3757(define_split /* logicalhi3_zexthi_ashift8 */
3758 [(set (match_operand:HI 0 "register_operand" "")
385c9217
SC
3759 (match_operator:HI 3 "m68hc11_logical_operator"
3760 [(zero_extend:HI
cd28557c 3761 (match_operand:QI 1 "general_operand" ""))
385c9217 3762 (ashift:HI
cd28557c 3763 (match_operand:HI 2 "general_operand" "")
385c9217
SC
3764 (const_int 8))]))]
3765 "z_replacement_completed == 2"
01beec65
SC
3766 [(set (reg:QI A_REGNUM) (match_dup 4))
3767 (set (reg:QI B_REGNUM) (match_dup 5))]
385c9217
SC
3768 "
3769 if (GET_CODE (operands[3]) == AND)
3770 {
3771 emit_insn (gen_movhi (operands[0], const0_rtx));
3772 DONE;
3773 }
3774 else
3775 {
3776 operands[5] = operands[1];
3777 if (D_REG_P (operands[2]))
3778 {
3779 operands[4] = gen_rtx (REG, QImode, HARD_B_REGNUM);
3780 }
3781 else
3782 {
3783 operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
3784 }
3785 }
3786 ")
3787
3788(define_insn "*logicalsi3_silshr16"
cd28557c 3789 [(set (match_operand:SI 0 "register_operand" "=D,D,D")
385c9217
SC
3790 (match_operator:SI 3 "m68hc11_logical_operator"
3791 [(lshiftrt:SI
cd28557c 3792 (match_operand:SI 1 "general_operand" "uim,uim,?D")
385c9217 3793 (const_int 16))
cd28557c 3794 (match_operand:SI 2 "general_operand" "uim,0,0")]))]
385c9217
SC
3795 ""
3796 "#")
3797
cd28557c
SC
3798(define_split /* logicalsi3_silshr16 */
3799 [(set (match_operand:SI 0 "register_operand" "")
385c9217
SC
3800 (match_operator:SI 3 "m68hc11_logical_operator"
3801 [(lshiftrt:SI
cd28557c 3802 (match_operand:SI 1 "general_operand" "")
385c9217 3803 (const_int 16))
cd28557c 3804 (match_operand:SI 2 "general_operand" "")]))]
385c9217 3805 "reload_completed"
01beec65
SC
3806 [(set (reg:HI D_REGNUM) (match_dup 4))
3807 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
3808 (set (reg:HI X_REGNUM) (match_dup 6))]
385c9217
SC
3809 "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
3810 if (X_REG_P (operands[2]))
3811 {
3812 operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3813 operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM);
3814 }
3815 else
3816 {
3817 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
3818 operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
3819 }
3820 PUT_MODE (operands[3], HImode);
3821
cd28557c
SC
3822 /* For an AND, make sure the high 16-bit part is cleared. */
3823 if (GET_CODE (operands[3]) == AND)
3824 {
3825 operands[6] = const0_rtx;
3826 }
385c9217
SC
3827")
3828
3829(define_insn "*logicalsi3_silshl16"
3830 [(set (match_operand:SI 0 "register_operand" "=D,D")
3831 (match_operator:SI 3 "m68hc11_logical_operator"
3832 [(ashift:SI
a1fdc802 3833 (match_operand:SI 1 "general_operand" "uim,?D")
385c9217
SC
3834 (const_int 16))
3835 (match_operand:SI 2 "general_operand" "0,0")]))]
3836 ""
3837 "#")
3838
cd28557c
SC
3839(define_split /* logicalsi3_silshl16 */
3840 [(set (match_operand:SI 0 "register_operand" "")
385c9217
SC
3841 (match_operator:SI 3 "m68hc11_logical_operator"
3842 [(ashift:SI
cd28557c 3843 (match_operand:SI 1 "general_operand" "")
385c9217 3844 (const_int 16))
cd28557c 3845 (match_operand:SI 2 "general_operand" "")]))]
385c9217 3846 "z_replacement_completed == 2"
cd28557c
SC
3847 [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
3848 (set (reg:HI D_REGNUM) (match_dup 5))]
385c9217 3849 "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
cd28557c
SC
3850 PUT_MODE (operands[3], HImode);
3851
3852 if (GET_CODE (operands[3]) == AND)
3853 operands[5] = const0_rtx;
3854 else
3855 operands[5] = gen_rtx (REG, HImode, HARD_D_REGNUM);
3856 ")
385c9217
SC
3857
3858
3859;;--------------------------------------------------------------------
3860;;- 64/32-bit Logical Operations. Patterns are defined so that GCC
3861;; can optimize correctly. These insns are split by the `final'
3862;; pass (# pattern). They are split to fall in the corresponding
3863;; 16-bit logical patterns.
3864;;--------------------------------------------------------------------
3865
cd28557c 3866;; Split 64-bit logical operations: anddi3, iordi3, xordi3
385c9217 3867(define_split
cd28557c 3868 [(set (match_operand:DI 0 "reg_or_some_mem_operand" "")
385c9217 3869 (match_operator:DI 4 "m68hc11_logical_operator"
cd28557c
SC
3870 [(match_operand:DI 1 "reg_or_some_mem_operand" "")
3871 (match_operand:DI 2 "general_operand" "")]))
3872 (clobber (match_scratch:HI 3 ""))]
385c9217
SC
3873 "reload_completed"
3874 [(const_int 0)]
3875 "m68hc11_split_logical (SImode, GET_CODE (operands[4]), operands);
3876 DONE;")
3877
cd28557c 3878;; Split 32-bit logical operations: andsi3, iorsi3, xorsi3
385c9217 3879(define_split
cd28557c 3880 [(set (match_operand:SI 0 "register_operand" "")
385c9217 3881 (match_operator:SI 3 "m68hc11_logical_operator"
cd28557c
SC
3882 [(match_operand:SI 1 "register_operand" "")
3883 (match_operand:SI 2 "general_operand" "")]))]
3884 "0 && reload_completed"
385c9217
SC
3885 [(const_int 0)]
3886 "m68hc11_split_logical (HImode, GET_CODE (operands[3]), operands);
3887 DONE;")
3888
cd28557c
SC
3889;; Split 32-bit logical operations: andsi3, iorsi3, xorsi3
3890(define_split
3891 [(set (match_operand:SI 0 "reg_or_some_mem_operand" "")
3892 (match_operator:SI 4 "m68hc11_logical_operator"
3893 [(match_operand:SI 1 "reg_or_some_mem_operand" "")
3894 (match_operand:SI 2 "general_operand" "")]))
3895 (clobber (match_scratch:HI 3 ""))]
3896 "reload_completed"
3897 [(const_int 0)]
3898 "m68hc11_split_logical (HImode, GET_CODE (operands[4]), operands);
3899 DONE;")
3900
385c9217
SC
3901;;--------------------------------------------------------------------
3902;; 16-bit Arithmetic and logical operations on X and Y:
3903;;
3904;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
3905;;
3906;; Operations on X or Y registers are split here. Instructions are
3907;; changed into:
3908;; - xgdx/xgdy instruction pattern,
3909;; - The same operation on register D,
3910;; - xgdx/xgdy instruction pattern.
3911;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
3912;; We also handle the case were the address register is used in both source
3913;; operands, such as:
3914;;
3915;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
3916;; or
3917;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
3918;;
3919;;
3920(define_split
65e6c005 3921 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
385c9217 3922 (match_operator:HI 3 "m68hc11_arith_operator"
65e6c005
JJ
3923 [(match_operand:HI 1 "hard_addr_reg_operand" "")
3924 (match_operand:HI 2 "general_operand" "")]))]
385c9217
SC
3925 "z_replacement_completed == 2
3926 /* If we are adding a small constant to X or Y, it's
9caea35c 3927 better to use one or several inx/iny instructions. */
385c9217 3928 && !(GET_CODE (operands[3]) == PLUS
01beec65
SC
3929 && ((TARGET_M6812
3930 && (immediate_operand (operands[2], HImode)
3931 || hard_reg_operand (operands[2], HImode)))
385c9217
SC
3932 || (GET_CODE (operands[2]) == CONST_INT
3933 && INTVAL (operands[2]) >= -4
3934 && INTVAL (operands[2]) <= 4)))"
ae9bd481
SC
3935 [(set (match_dup 9) (match_dup 0))
3936 (set (match_dup 4) (match_dup 5))
385c9217 3937 (set (match_dup 8) (match_dup 7))
ae9bd481 3938 (set (match_dup 0) (match_dup 1))
01beec65
SC
3939 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3940 (set (match_dup 0) (reg:HI D_REGNUM))])
3941 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
3942 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
3943 (set (match_dup 0) (reg:HI D_REGNUM))])]
385c9217 3944 "
ae9bd481
SC
3945 operands[9] = operands[0];
3946 /* For 68HC12, push the value on the stack and do the operation
3947 with a pop. */
3948 if (TARGET_M6812
3949 && m68hc11_non_shift_operator (operands[3], HImode)
3950 && (H_REG_P (operands[2])
3951 || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
3952 && reg_mentioned_p (operands[0], operands[2]))))
3953 {
3954 operands[4] = gen_rtx (MEM, HImode,
3955 gen_rtx (PRE_DEC, HImode,
3956 gen_rtx (REG, HImode, HARD_SP_REGNUM)));
3957 operands[6] = gen_rtx (MEM, HImode,
3958 gen_rtx (POST_INC, HImode,
3959 gen_rtx (REG, HImode, HARD_SP_REGNUM)));
3960 operands[5] = operands[2];
3961 operands[8] = operands[7] = operands[0];
3962 }
9caea35c 3963 /* Save the operand2 in a temporary location and use it. */
ae9bd481
SC
3964 else if ((H_REG_P (operands[2])
3965 || reg_mentioned_p (operands[0], operands[2]))
3966 && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
385c9217 3967 {
ae9bd481
SC
3968 if (GET_CODE (operands[3]) == MINUS
3969 && reg_mentioned_p (operands[0], operands[2]))
3970 {
3971 operands[9] = gen_rtx (MEM, HImode,
3972 gen_rtx (PRE_DEC, HImode,
3973 gen_rtx (REG, HImode, HARD_SP_REGNUM)));
3974 operands[1] = gen_rtx (MEM, HImode,
3975 gen_rtx (POST_INC, HImode,
3976 gen_rtx (REG, HImode, HARD_SP_REGNUM)));
3977 operands[8] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
3978 operands[4] = operands[7] = operands[0];
3979 operands[6] = operands[8];
3980 operands[5] = operands[2];
3981 }
3982 else
3983 {
385c9217
SC
3984 operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
3985 operands[6] = operands[4];
3986 if (!H_REG_P (operands[2]))
3987 {
3988 operands[5] = operands[0];
3989 operands[7] = operands[2];
3990 operands[8] = operands[0];
3991 }
3992 else
3993 {
3994 operands[5] = operands[2];
3995 operands[8] = operands[7] = operands[0];
3996 }
ae9bd481 3997 }
385c9217
SC
3998 }
3999 else
4000 {
4001 operands[4] = operands[5] = operands[0];
4002 operands[6] = operands[2];
4003 operands[8] = operands[7] = operands[0];
4004 }
4005 ")
4006
4007(define_split
65e6c005 4008 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
385c9217 4009 (match_operator:HI 3 "m68hc11_arith_operator"
65e6c005
JJ
4010 [(match_operand:HI 1 "general_operand" "")
4011 (match_operand:HI 2 "general_operand" "")]))]
385c9217
SC
4012 "z_replacement_completed == 2
4013 /* If we are adding a small constant to X or Y, it's
9caea35c 4014 better to use one or several inx/iny instructions. */
385c9217 4015 && !(GET_CODE (operands[3]) == PLUS
01beec65
SC
4016 && ((TARGET_M6812
4017 && (immediate_operand (operands[2], HImode)
4018 || hard_reg_operand (operands[2], HImode)))
385c9217
SC
4019 || (GET_CODE (operands[2]) == CONST_INT
4020 && INTVAL (operands[2]) >= -4
4021 && INTVAL (operands[2]) <= 4)))"
4022 [(set (match_dup 0) (match_dup 1))
01beec65
SC
4023 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4024 (set (match_dup 0) (reg:HI D_REGNUM))])
4025 (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
4026 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4027 (set (match_dup 0) (reg:HI D_REGNUM))])]
385c9217
SC
4028 "
4029 ")
4030
4031;;
4032;; Next split handles the logical operations on D register with
4033;; another hard register for the second operand. For this, we
4034;; have to save the second operand in a scratch location and use
4035;; it instead. This must be supported because in some (rare) cases
4036;; the second operand can come in a hard register and the reload
4037;; pass doesn't know how to reload it in a memory location.
4038;;
4039;; PLUS MINUS AND IOR XOR
4040;;
4041;; The shift operators are special and must not appear here.
4042;;
4043(define_split
65e6c005 4044 [(set (match_operand:HI 0 "d_register_operand" "")
385c9217 4045 (match_operator:HI 3 "m68hc11_non_shift_operator"
65e6c005
JJ
4046 [(match_operand:HI 1 "d_register_operand" "")
4047 (match_operand:HI 2 "hard_reg_operand" "")]))]
840e2ff1
SC
4048 "TARGET_M6811
4049 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
385c9217
SC
4050 [(set (match_dup 4) (match_dup 2))
4051 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4052 "operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);")
4053
840e2ff1
SC
4054;;
4055;; For 68HC12, push the operand[2] value on the stack and do the
4056;; logical/arithmetic operation with a pop.
4057;;
4058(define_split
65e6c005 4059 [(set (match_operand:HI 0 "d_register_operand" "")
840e2ff1 4060 (match_operator:HI 3 "m68hc11_non_shift_operator"
65e6c005
JJ
4061 [(match_operand:HI 1 "d_register_operand" "")
4062 (match_operand:HI 2 "hard_reg_operand" "")]))]
840e2ff1
SC
4063 "TARGET_M6812
4064 && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
4065 [(set (match_dup 4) (match_dup 2))
4066 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
4067 "operands[4] = gen_rtx (MEM, HImode,
4068 gen_rtx (PRE_DEC, HImode,
4069 gen_rtx (REG, HImode, HARD_SP_REGNUM)));
4070 operands[5] = gen_rtx (MEM, HImode,
4071 gen_rtx (POST_INC, HImode,
4072 gen_rtx (REG, HImode, HARD_SP_REGNUM)));
4073 ")
4074
385c9217
SC
4075;;--------------------------------------------------------------------
4076;; 16-bit Unary operations on X and Y:
4077;;
4078;; NOT NEG
4079;;
840e2ff1 4080;; Operations on X or Y registers are split here. Instructions are
385c9217
SC
4081;; changed into:
4082;; - xgdx/xgdy instruction pattern,
4083;; - The same operation on register D,
4084;; - xgdx/xgdy instruction pattern.
4085;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4086;; We also handle the case were the address register is used in both source
4087;; operands, such as:
4088;;
4089;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4090;; or
4091;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4092;;
4093(define_split
840e2ff1 4094 [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
385c9217 4095 (match_operator:HI 2 "m68hc11_unary_operator"
840e2ff1 4096 [(match_operand 1 "general_operand" "")]))]
385c9217
SC
4097 "z_replacement_completed == 2"
4098 [(set (match_dup 4) (match_dup 5))
01beec65
SC
4099 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4100 (set (match_dup 0) (reg:HI D_REGNUM))])
4101 (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
4102 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
4103 (set (match_dup 0) (reg:HI D_REGNUM))])]
385c9217
SC
4104 "
4105{
4106 if ((H_REG_P (operands[1])
4107 && !rtx_equal_p (operands[0], operands[1]))
4108 || reg_mentioned_p (operands[0], operands[1]))
4109 {
9caea35c 4110 /* Move to the destination register, before the xgdx. */
385c9217
SC
4111 operands[4] = gen_rtx (REG, GET_MODE (operands[1]),
4112 REGNO (operands[0]));
4113 operands[5] = operands[1];
4114
9caea35c 4115 /* Apply the operation on D. */
385c9217
SC
4116 operands[3] = gen_rtx (REG, GET_MODE (operands[1]), HARD_D_REGNUM);
4117 }
4118 else
4119 {
9caea35c 4120 /* Generate a copy to same register (nop). */
385c9217
SC
4121 operands[4] = operands[5] = operands[0];
4122 operands[3] = operands[1];
4123 }
4124}")
4125
4126;;
4127;; 8-bit operations on address registers.
4128;;
4129;; We have to take care that the address register is not used for the
4130;; source of operand2. If operand2 is the D register, we have to save
4131;; that register in a temporary location.
4132;;
4133;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
4134;;
4135(define_split
65e6c005 4136 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
385c9217 4137 (match_operator:QI 3 "m68hc11_arith_operator"
65e6c005
JJ
4138 [(match_operand:QI 1 "hard_addr_reg_operand" "")
4139 (match_operand:QI 2 "general_operand" "")]))]
385c9217
SC
4140 "z_replacement_completed == 2
4141 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
9caea35c 4142 incqi pattern generates a better code. */
385c9217
SC
4143 && !(GET_CODE (operands[3]) == PLUS
4144 && GET_CODE (operands[2]) == CONST_INT
4145 && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
4146 [(set (match_dup 5) (match_dup 6))
01beec65
SC
4147 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4148 (set (match_dup 4) (reg:HI D_REGNUM))])
4149 (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
4150 (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
4151 (set (match_dup 4) (reg:HI D_REGNUM))])]
385c9217
SC
4152 "operands[4] = gen_rtx (REG, HImode, REGNO (operands[0]));
4153
4154 /* For the second operand is a hard register or if the address
4155 register appears in the source, we have to save the operand[2]
4156 value in a temporary location and then use that temp.
4157 Otherwise, it's ok and we generate a (set (D) (D)) that
9caea35c 4158 will result in a nop. */
385c9217
SC
4159 if (H_REG_P (operands[2]))
4160 {
4161 operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
4162 operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));
4163 operands[7] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
4164 }
4165 else if (reg_mentioned_p (operands[0], operands[2]))
4166 {
4167 operands[5] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
4168 operands[6] = operands[2];
4169 operands[7] = operands[5];
4170 }
4171 else
4172 {
4173 operands[5] = operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM);
4174 operands[7] = operands[2];
4175 }
4176 ")
4177
4178;;
4179;; Next split handles the logical operations on D register with
4180;; another hard register for the second operand. For this, we
4181;; have to save the second operand in a scratch location and use
4182;; it instead. This must be supported because in some (rare) cases
4183;; the second operand can come in a hard register and the reload
4184;; pass doesn't know how to reload it in a memory location.
4185;;
4186;; PLUS MINUS AND IOR XOR
4187;;
4188;; The shift operators are special and must not appear here.
4189;;
4190(define_split
840e2ff1 4191 [(set (match_operand:QI 0 "d_register_operand" "")
385c9217 4192 (match_operator:QI 3 "m68hc11_non_shift_operator"
840e2ff1
SC
4193 [(match_operand:QI 1 "d_register_operand" "")
4194 (match_operand:QI 2 "hard_reg_operand" "")]))]
385c9217
SC
4195 "reload_completed"
4196 [(set (match_dup 5) (match_dup 6))
4197 (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
4198 "operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);
4199 operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);
4200 operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));")
4201
4202;;--------------------------------------------------------------------
4203;; 8-bit Unary operations on X and Y:
4204;;
4205;; NOT NEG
4206;;
840e2ff1 4207;; Operations on X or Y registers are split here. Instructions are
385c9217
SC
4208;; changed into:
4209;; - xgdx/xgdy instruction pattern,
4210;; - The same operation on register D,
4211;; - xgdx/xgdy instruction pattern.
4212;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
4213;; We also handle the case were the address register is used in both source
4214;; operands, such as:
4215;;
4216;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
4217;; or
4218;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
4219;;
4220(define_split
840e2ff1 4221 [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
385c9217 4222 (match_operator:QI 2 "m68hc11_unary_operator"
840e2ff1 4223 [(match_operand:QI 1 "general_operand" "")]))]
385c9217
SC
4224 "z_replacement_completed == 2"
4225 [(set (match_dup 4) (match_dup 5))
01beec65
SC
4226 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4227 (set (match_dup 3) (reg:HI D_REGNUM))])
4228 (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
4229 (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
4230 (set (match_dup 3) (reg:HI D_REGNUM))])]
385c9217
SC
4231 "
4232{
4233 operands[3] = gen_rtx (REG, HImode, REGNO (operands[0]));
4234 if ((H_REG_P (operands[1])
4235 && !rtx_equal_p (operands[0], operands[1]))
4236 || reg_mentioned_p (operands[0], operands[1]))
4237 {
9caea35c 4238 /* Move to the destination register, before the xgdx. */
385c9217
SC
4239 operands[4] = operands[0];
4240 operands[5] = operands[1];
4241
9caea35c 4242 /* Apply the operation on D. */
385c9217
SC
4243 operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM);
4244 }
4245 else
4246 {
4247 operands[4] = operands[5] = operands[0];
4248 operands[6] = operands[1];
4249 }
4250}")
4251
4252
4253;;--------------------------------------------------------------------
4254;;- Complements
4255;;--------------------------------------------------------------------
4256
4257(define_expand "negdi2"
4258 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4259 (neg:DI (match_operand:DI 1 "general_operand" "")))]
4260 ""
4261 "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
4262 DONE;")
4263
4264
4265(define_insn "negsi2"
4266 [(set (match_operand:SI 0 "register_operand" "=D")
015a2e59 4267 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
385c9217
SC
4268 ""
4269 "*
4270{
015a2e59
SC
4271 rtx ops[1];
4272
385c9217
SC
4273 CC_STATUS_INIT;
4274
4275 /* With -Os or without -O, use a special library call. */
4276 if (optimize_size || optimize == 0)
4277 return \"bsr\\t___negsi2\";
4278
015a2e59
SC
4279 ops[0] = gen_label_rtx ();
4280
4281 /* 32-bit complement and add 1. */
4282 output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
4283 output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
4284 output_asm_insn (\"bne\\t%l0\", ops);
4285 output_asm_insn (\"inx\", operands);
4286 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
4287 return \"\";
385c9217
SC
4288}")
4289
4290(define_insn "neghi2"
015a2e59 4291 [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
385c9217
SC
4292 (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
4293 ""
4294 "@
4295 coma\\n\\tcomb\\n\\taddd\\t#1
4296 clra\\n\\tclrb\\n\\tsubd\\t%1
4297 xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
4298
4299(define_insn "negqi2"
76028b1f
SC
4300 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
4301 (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
385c9217
SC
4302 ""
4303 "@
4304 negb
4305 neg\\t%b0
76028b1f 4306 neg\\t%b0
385c9217
SC
4307 #")
4308
4309;;
4310;; - 32-bit complement. GCC knows how to translate them but providing a
4311;; pattern generates better/smaller code.
4312;;
4313(define_expand "one_cmpldi2"
4314 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4315 (not:DI (match_operand:DI 1 "general_operand" "")))]
4316 ""
4317 "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
4318 DONE;")
4319
4320(define_insn "one_cmplsi2"
015a2e59
SC
4321 [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
4322 (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
4323 (clobber (match_scratch:HI 2 "=X,d,X"))]
385c9217 4324 ""
015a2e59
SC
4325 "@
4326 bsr\\t___one_cmplsi2
4327 #
4328 #")
385c9217
SC
4329
4330(define_insn "one_cmplhi2"
015a2e59 4331 [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
76028b1f 4332 (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
385c9217
SC
4333 ""
4334 "@
4335 comb\\n\\tcoma
4336 com\\t%b0\\n\\tcom\\t%h0
015a2e59
SC
4337 #
4338 com\\t%b0\\n\\tcom\\t%h0")
385c9217
SC
4339
4340(define_insn "one_cmplqi2"
015a2e59 4341 [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
76028b1f 4342 (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
385c9217
SC
4343 ""
4344 "@
4345 comb
4346 com\\t%b0
015a2e59
SC
4347 #
4348 com\\t%b0")
385c9217
SC
4349
4350(define_split /* "*one_cmplsi2" */
015a2e59
SC
4351 [(set (match_operand:SI 0 "non_push_operand" "")
4352 (not:SI (match_dup 0)))
4353 (clobber (match_scratch:HI 1 ""))]
385c9217 4354 "z_replacement_completed == 2
015a2e59
SC
4355 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4356 [(set (match_dup 2) (not:HI (match_dup 2)))
4357 (set (match_dup 3) (not:HI (match_dup 3)))]
4358 "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
4359 operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
385c9217 4360
015a2e59
SC
4361(define_split /* "*one_cmplsi2" */
4362 [(set (match_operand:SI 0 "non_push_operand" "")
4363 (not:SI (match_operand:SI 1 "non_push_operand" "")))
4364 (clobber (match_operand:HI 2 "d_register_operand" ""))]
4365 "z_replacement_completed == 2
4366 && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
4367 [(set (match_dup 2) (match_dup 3))
4368 (set (match_dup 2) (not:HI (match_dup 2)))
4369 (set (match_dup 4) (match_dup 2))
4370 (set (match_dup 2) (match_dup 5))
4371 (set (match_dup 2) (not:HI (match_dup 2)))
4372 (set (match_dup 6) (match_dup 2))]
4373 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
4374 operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
4375 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4376 operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
385c9217
SC
4377
4378;;--------------------------------------------------------------------
4379;;- arithmetic shifts
4380;;--------------------------------------------------------------------
4381;;
4382;; Provide some 64-bit shift patterns.
4383(define_expand "ashldi3"
4384 [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
4385 (ashift:DI (match_operand:DI 1 "general_operand" "")
4386 (match_operand:HI 2 "general_operand" "")))
4387 (clobber (match_scratch:HI 3 ""))])]
4388 ""
4389 "
4390{
4391 if (GET_CODE (operands[2]) != CONST_INT
4392 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
4393 {
4394 FAIL;
4395 }
4396}")
4397
4398(define_insn "*ashldi3_const32"
76028b1f
SC
4399 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
4400 (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
385c9217 4401 (const_int 32)))
a1fdc802 4402 (clobber (match_scratch:HI 2 "=&A,d,d"))]
385c9217
SC
4403 ""
4404 "#")
4405
4406(define_split
65e6c005
JJ
4407 [(set (match_operand:DI 0 "nonimmediate_operand" "")
4408 (ashift:DI (match_operand:DI 1 "general_operand" "")
385c9217 4409 (const_int 32)))
65e6c005 4410 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
4411 "reload_completed"
4412 [(const_int 0)]
4413 "/* Move the lowpart in the highpart first in case the shift
4414 is applied on the source. */
4415 if (IS_STACK_PUSH (operands[0]))
4416 {
4417 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4418 const0_rtx, operands[2]);
4419 }
4420 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
4421 m68hc11_gen_lowpart (SImode, operands[1]),
4422 operands[2]);
4423 if (!IS_STACK_PUSH (operands[0]))
4424 {
4425 m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
4426 const0_rtx, operands[2]);
4427 }
4428 DONE;")
4429
4430(define_insn "*ashldi3_const1"
76028b1f
SC
4431 [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
4432 (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
385c9217 4433 (const_int 1)))
76028b1f 4434 (clobber (match_scratch:HI 2 "=d,d,d"))]
385c9217
SC
4435 ""
4436 "#")
4437
4438(define_split
65e6c005
JJ
4439 [(set (match_operand:DI 0 "non_push_operand" "")
4440 (ashift:DI (match_operand:DI 1 "general_operand" "")
385c9217 4441 (const_int 1)))
65e6c005 4442 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
4443 "z_replacement_completed == 2"
4444 [(set (match_dup 2) (match_dup 3))
4445 (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
4446 (set (match_dup 4) (match_dup 2))
4447
4448 (set (match_dup 2) (match_dup 5))
01beec65 4449 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
385c9217
SC
4450 (set (match_dup 6) (match_dup 2))
4451
4452 (set (match_dup 2) (match_dup 7))
01beec65 4453 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
385c9217
SC
4454 (set (match_dup 8) (match_dup 2))
4455
4456 (set (match_dup 2) (match_dup 9))
01beec65 4457 (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM)))
385c9217
SC
4458 (set (match_dup 10) (match_dup 2))]
4459 "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
4460 operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
4461 operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
4462
4463 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
4464 operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
4465 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
4466
4467 operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
4468 operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
4469 operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
4470
4471 operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
4472 operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
4473 operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
4474
4475(define_insn "addsi_silshr16"
840e2ff1
SC
4476 [(set (match_operand:SI 0 "register_operand" "=D,D")
4477 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0")
385c9217 4478 (const_int 16))
840e2ff1 4479 (match_operand:SI 2 "general_operand" "0,m!*u")))]
385c9217
SC
4480 ""
4481 "#")
4482
4483(define_split
840e2ff1
SC
4484 [(set (match_operand:SI 0 "register_operand" "")
4485 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
385c9217 4486 (const_int 16))
840e2ff1
SC
4487 (match_operand:SI 2 "general_operand" "")))]
4488 "z_replacement_completed == 2 && !X_REG_P (operands[1])"
01beec65 4489 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
840e2ff1
SC
4490 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4491 (const_int 0))
4492 (reg:HI CC_REGNUM)))]
385c9217
SC
4493 "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
4494
840e2ff1
SC
4495(define_split
4496 [(set (match_operand:SI 0 "register_operand" "")
4497 (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
4498 (const_int 16))
4499 (match_operand:SI 2 "general_operand" "")))]
4500 "z_replacement_completed == 2 && X_REG_P (operands[1])"
4501 [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
4502 (set (reg:HI X_REGNUM) (match_dup 3))
4503 (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
4504 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
4505 (const_int 0))
4506 (reg:HI CC_REGNUM)))]
4507 "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
4508 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);")
4509
385c9217
SC
4510(define_insn "addsi_ashift16"
4511 [(set (match_operand:SI 0 "register_operand" "=D")
4512 (plus:SI
4513 (mult:SI (match_operand:SI 2 "general_operand" "uim")
4514 (const_int 65536))
4515 (match_operand:SI 1 "general_operand" "0")))
4516 (clobber (match_scratch:HI 3 "=X"))]
4517 "0"
4518 "#")
4519
4520(define_split
65e6c005 4521 [(set (match_operand:SI 0 "register_operand" "")
385c9217 4522 (plus:SI
65e6c005 4523 (mult:SI (match_operand:SI 2 "general_operand" "")
385c9217 4524 (const_int 65536))
65e6c005 4525 (match_operand:SI 1 "general_operand" "")))
385c9217
SC
4526 (clobber (match_scratch:HI 3 "=X"))]
4527 "0 && reload_completed && z_replacement_completed == 2"
01beec65 4528 [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
385c9217
SC
4529 "
4530{
4531 operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
4532}")
4533
4534(define_insn "addsi_andshr16"
4535 [(set (match_operand:SI 0 "register_operand" "=D")
4536 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
4537 (const_int 65535))
4538 (match_operand:SI 2 "general_operand" "0")))]
4539 ""
4540 "#")
4541
4542(define_split
65e6c005
JJ
4543 [(set (match_operand:SI 0 "register_operand" "")
4544 (plus:SI (and:SI (match_operand:SI 1 "general_operand" "")
385c9217 4545 (const_int 65535))
65e6c005 4546 (match_operand:SI 2 "general_operand" "")))]
385c9217 4547 "z_replacement_completed == 2"
01beec65
SC
4548 [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
4549 (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
385c9217
SC
4550 "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4551
4552;;
4553;; 32-bit shifts are made by a small library routine that uses
4554;; a specific passing convention for parameters (for efficiency reasons).
4555;;
4556;; [D + X] -> Value to be shifted
4557;; Y -> Shift count
4558;;
4559;; The shift count is clobbered by the routine.
4560;;
4561(define_expand "ashlsi3"
4562 [(parallel
4563 [(set (match_operand:SI 0 "register_operand" "")
4564 (match_operand:SI 1 "general_operand" ""))
4565 (clobber (scratch:HI))])
4566 (parallel
4567 [(set (match_dup 0) (ashift:SI (match_dup 0)
4568 (match_operand:HI 2 "nonmemory_operand" "")))
4569 (clobber (scratch:HI))])]
4570 ""
4571 "")
4572
4573(define_split
65e6c005
JJ
4574 [(set (match_operand:SI 0 "nonimmediate_operand" "")
4575 (ashift:SI (match_operand:SI 1 "general_operand" "")
385c9217 4576 (const_int 16)))
65e6c005 4577 (clobber (match_scratch:HI 3 ""))]
385c9217
SC
4578 ""
4579 [(set (match_dup 2) (match_dup 3))
4580 (set (match_dup 4) (const_int 0))]
4581 "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
4582 operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
4583 operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
4584
4585(define_insn "*ashlsi3_const16"
76028b1f
SC
4586 [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
4587 (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
385c9217 4588 (const_int 16)))
76028b1f 4589 (clobber (match_scratch:HI 2 "=X,X,X"))]
385c9217
SC
4590 ""
4591 "#")
4592
4593(define_insn "*ashlsi3_const16_zexthi"
4594 [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
4595 (ashift:SI (zero_extend:HI
4596 (match_operand:HI 1 "general_operand" "duim*A"))
4597 (const_int 16)))
76d06edc 4598 (clobber (match_scratch:HI 2 "=X"))]
385c9217
SC
4599 ""
4600 "#")
4601
4602(define_split /* "*ashlsi3_const16_zexthi"*/
65e6c005 4603 [(set (match_operand:SI 0 "nonimmediate_operand" "")
385c9217 4604 (ashift:SI (zero_extend:HI
65e6c005 4605 (match_operand:HI 1 "general_operand" ""))
385c9217 4606 (const_int 16)))
76d06edc 4607 (clobber (match_scratch:HI 2 "=X"))]
385c9217 4608 "reload_completed"
01beec65
SC
4609 [(set (reg:HI X_REGNUM) (match_dup 1))
4610 (set (reg:HI D_REGNUM) (const_int 0))]
385c9217
SC
4611 "")
4612
4613(define_insn "*ashlsi3_const1"
76028b1f
SC
4614 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,!*u,?*um")
4615 (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,*um,0,0,*um")
385c9217 4616 (const_int 1)))
76028b1f 4617 (clobber (match_scratch:HI 2 "=X,X,&d,&d,&d"))]
385c9217
SC
4618 ""
4619 "*
4620{
4621 CC_STATUS_INIT;
4622 if (X_REG_P (operands[1]))
4623 {
4624 return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
4625 }
4626 else
4627 {
4628 rtx ops[2];
4629
4630 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
4631 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
4632 m68hc11_gen_movhi (insn, ops);
4633 output_asm_insn (\"lsld\", ops);
4634 if (!X_REG_P (operands[0]))
4635 {
4636 ops[1] = ops[0];
4637 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
4638 m68hc11_gen_movhi (insn, ops);
4639 ops[0] = ops[1];
4640 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4641 m68hc11_gen_movhi (insn, ops);
4642 }
4643 else
4644 {
4645 /* Load the high part in X in case the source operand
4646 uses X as a memory pointer. */
4647 ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM);
4648 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
4649 m68hc11_gen_movhi (insn, ops);
4650 output_asm_insn (\"xgdx\", ops);
4651 }
4652 output_asm_insn (\"rolb\", ops);
4653 output_asm_insn (\"rola\", ops);
4654 if (!X_REG_P (operands[0]))
4655 {
4656 ops[1] = ops[0];
4657 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
4658 m68hc11_gen_movhi (insn, ops);
4659 }
4660 else
4661 {
4662 output_asm_insn (\"xgdx\", ops);
4663 }
4664 return \"\";
4665 }
4666}")
4667
4668(define_insn "*ashlsi3_const"
4669 [(set (match_operand:SI 0 "register_operand" "+D")
4670 (ashift:SI (match_dup 0)
76d06edc
SC
4671 (match_operand:HI 1 "const_int_operand" "")))
4672 (clobber (match_scratch:HI 2 "=y"))]
385c9217
SC
4673 ""
4674 "*
4675{
4676 CC_STATUS_INIT;
76d06edc 4677 return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
385c9217
SC
4678}")
4679
4680(define_insn "*ashlsi3"
4681 [(set (match_operand:SI 0 "register_operand" "+D,D")
4682 (ashift:SI (match_dup 0)
76d06edc
SC
4683 (match_operand:HI 1 "general_operand" "y,m")))
4684 (clobber (match_scratch:HI 2 "=1,X"))]
385c9217
SC
4685 ""
4686 "*
4687{
4688 CC_STATUS_INIT;
4689
4690 /* There is a reload problem if we don't accept 'm' for the shift value.
4691 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
4692 and this conflicts with all reloads. Since X, Y, Z are used there
4693 is not enough register in class A_REGS.
4694
76d06edc 4695 Assuming that 'operands[1]' does not refer to the stack (which
385c9217 4696 is true for 68hc11 only, we save temporary the value of Y. */
76d06edc 4697 if (!Y_REG_P (operands[2]))
385c9217 4698 {
43a72755 4699 rtx ops[1];
4c8aed14 4700 int y_dead = dead_register_here (insn, iy_reg);
43a72755
SC
4701
4702 ops[0] = operands[1];
4c8aed14 4703 if (y_dead == 0)
43a72755 4704 {
4c8aed14
SC
4705 output_asm_insn (\"pshy\", operands);
4706 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
4707 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
43a72755
SC
4708 }
4709 output_asm_insn (\"ldy\\t%0\", ops);
385c9217 4710 output_asm_insn (\"bsr\\t___ashlsi3\", operands);
4c8aed14 4711 return y_dead == 0 ? \"puly\" : \"\";
385c9217
SC
4712 }
4713 return \"bsr\\t___ashlsi3\";
4714}")
4715
4716(define_expand "ashlhi3"
4717 [(set (match_operand:HI 0 "register_operand" "")
4718 (ashift:HI (match_operand:HI 1 "register_operand" "")
4719 (match_operand:HI 2 "general_operand" "")))]
4720 ""
4721 "
4722{
4723 if (GET_CODE (operands[2]) != CONST_INT)
4724 {
4725 rtx scratch = gen_reg_rtx (HImode);
4726 emit_move_insn (scratch, operands[2]);
4727 emit_insn (gen_rtx (PARALLEL, VOIDmode,
4728 gen_rtvec (2, gen_rtx (SET, VOIDmode,
4729 operand0,
4730 gen_rtx_ASHIFT (HImode,
4731 operand1, scratch)),
4732 gen_rtx (CLOBBER, VOIDmode, scratch))));
4733 DONE;
4734 }
4735}")
4736
4737(define_insn "*ashlhi3_const1"
4738 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4739 (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
4740 (const_int 1)))]
4741 ""
4742 "*
4743{
4744 if (A_REG_P (operands[0]))
4745 return \"#\";
4746
4747 if (D_REG_P (operands[0]))
4748 {
4749 return \"asld\";
4750 }
4751
4752 output_asm_insn (\"asl\\t%b0\", operands);
4753 output_asm_insn (\"rol\\t%h0\", operands);
4754 CC_STATUS_INIT;
4755 return \"\";
4756}")
4757
4758
4759(define_insn "*ashlhi3_2"
4760 [(set (match_operand:HI 0 "register_operand" "=d")
4761 (ashift:HI (match_operand:HI 1 "register_operand" "0")
01beec65 4762 (match_operand:HI 2 "register_operand" "+x")))
385c9217
SC
4763 (clobber (match_dup 2))]
4764 ""
4765 "*
4766{
4767 CC_STATUS_INIT;
4768 return \"bsr\\t___lshlhi3\";
4769}")
4770
01beec65 4771(define_insn "*ashlhi3"
385c9217
SC
4772 [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
4773 (ashift:HI (match_dup 0)
01beec65 4774 (match_operand:HI 1 "register_operand" "+x")))
385c9217
SC
4775 (clobber (match_dup 1))]
4776 ""
4777 "*
4778{
4779 CC_STATUS_INIT;
4780 return \"bsr\\t___lshlhi3\";
4781}")
4782
4783(define_insn "*ashlhi3"
4784 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4785 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
4786 (match_operand:HI 2 "const_int_operand" "")))]
4787 ""
4788 "*
4789{
4790 int i;
4791
4792 if (A_REG_P (operands[0]))
4793 return \"#\";
4794
4795 i = INTVAL (operands[2]);
4796 if (i >= 8)
4797 {
4798 CC_STATUS_INIT;
4799 output_asm_insn (\"tba\", operands);
4800 if (i == 15)
4801 {
4802 output_asm_insn (\"rora\", operands);
4803 output_asm_insn (\"anda\\t#0\", operands);
4804 output_asm_insn (\"rora\", operands);
4805 }
4806 else
4807 while (i != 8 )
4808 {
4809 output_asm_insn (\"asla\", operands);
4810 i--;
4811 }
4812 return \"clrb\";
4813 }
4814 for (i = 0; i < INTVAL (operands[2]) - 1; i++)
4815 {
4816 output_asm_insn (\"asld\", operands);
4817 }
4818 return \"asld\";
4819}")
4820
4821(define_expand "ashlqi3"
4822 [(set (match_operand:QI 0 "register_operand" "")
4823 (ashift:QI (match_operand:QI 1 "register_operand" "")
4824 (match_operand:QI 2 "general_operand" "")))]
4825 ""
4826 "")
4827
4828(define_insn "*ashlqi3_const1"
76028b1f
SC
4829 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
4830 (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
385c9217
SC
4831 (const_int 1)))]
4832 ""
4833 "@
4834 aslb
4835 asl\\t%b0
76028b1f 4836 asl\\t%b0
385c9217
SC
4837 asl%0
4838 #")
4839
4840(define_insn "*ashlqi3_const"
4841 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4842 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4843 (match_operand:QI 2 "const_int_operand" "")))]
4844 ""
4845 "*
4846{
4847 int i;
4848 const char* insn_code;
4849
4850 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
4851 insn_code = \"aslb\";
4852 else if (DA_REG_P (operands[0]))
4853 insn_code = \"asla\";
4854 else
4855 return \"#\";
4856
4857 i = INTVAL (operands[2]);
4858 if (i >= 8)
4859 {
4860 if (DA_REG_P (operands[0]))
4861 return \"clra\";
4862 else
4863 return \"clrb\";
4864 }
4865 else if (i == 7)
4866 {
4867 if (DA_REG_P (operands[0]))
4868 {
4869 output_asm_insn (\"rora\", operands);
4870 output_asm_insn (\"ldaa\\t#0\", operands);
4871 return \"rora\";
4872 }
4873 else
4874 {
4875 output_asm_insn (\"rorb\", operands);
4876 output_asm_insn (\"ldab\\t#0\", operands);
4877 return \"rorb\";
4878 }
4879 }
4880 else if (i == 6)
4881 {
4882 if (DA_REG_P (operands[0]))
4883 {
4884 output_asm_insn (\"rora\", operands);
4885 output_asm_insn (\"rora\", operands);
4886 output_asm_insn (\"rora\", operands);
4887 return \"anda\\t#0xC0\";
4888 }
4889 else
4890 {
4891 output_asm_insn (\"rorb\", operands);
4892 output_asm_insn (\"rorb\", operands);
4893 output_asm_insn (\"rorb\", operands);
4894 return \"andb\\t#0xC0\";
4895 }
4896 }
4897 while (--i >= 0)
4898 {
4899 output_asm_insn (insn_code, operands);
4900 }
4901 return \"\";
4902}")
4903
4904(define_insn "*ashlqi3"
4905 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
4906 (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
4907 (match_operand:QI 2 "nonimmediate_operand"
4908 "m*u*d*A,m*u*d*A,m*u")))]
4909 ""
4910 "*
4911{
4912 rtx ops[2];
4913
4914 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
4915 return \"#\";
4916
4917 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
4918 ops[1] = operands[2];
4919 m68hc11_gen_movqi (insn, ops);
4920
4921 CC_STATUS_INIT;
4922 return \"bsr\\t___lshlqi3\";
4923}")
4924
4925(define_expand "ashrhi3"
4926 [(set (match_operand:HI 0 "register_operand" "")
4927 (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
4928 (match_operand:HI 2 "general_operand" "")))]
4929 ""
4930 "
4931{
4932 if (GET_CODE (operands[2]) != CONST_INT)
4933 {
4934 rtx scratch = gen_reg_rtx (HImode);
4935
4936 emit_move_insn (scratch, operands[2]);
4937 emit_insn (gen_rtx (PARALLEL, VOIDmode,
4938 gen_rtvec (2, gen_rtx (SET, VOIDmode,
4939 operand0,
4940 gen_rtx_ASHIFTRT (HImode,
4941 operand1, scratch)),
4942 gen_rtx (CLOBBER, VOIDmode, scratch))));
4943 DONE;
4944 }
4945}")
4946
4947(define_insn "*ashrhi3_const1"
4948 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
4949 (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
4950 (const_int 1)))]
4951 ""
4952 "*
4953{
4954 if (A_REG_P (operands[0]))
4955 return \"#\";
4956
4957 CC_STATUS_INIT;
4958 if (D_REG_P (operands[0]))
4959 {
4960 return \"asra\\n\\trorb\";
4961 }
4962
4963 output_asm_insn (\"asr\\t%h0\", operands);
4964 output_asm_insn (\"ror\\t%b0\", operands);
4965 return \"\";
4966}")
4967
4968
4969(define_insn "*ashrhi3_const"
4970 [(set (match_operand:HI 0 "register_operand" "=d,!*A")
4971 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
4972 (match_operand:HI 2 "const_int_operand" "")))]
4973 ""
4974 "*
4975{
4976 rtx ops[2];
4977 int val = INTVAL (operands[2]);
4978
4979 if (A_REG_P (operands[0]))
4980 return \"#\";
4981
4982 if (val >= 15)
4983 {
4984 ops[0] = gen_label_rtx ();
4985
4986 output_asm_insn (\"clrb\", operands);
4987 output_asm_insn (\"rola\", operands);
4988
9caea35c 4989 /* Clear A without clearing the carry flag. */
385c9217
SC
4990 output_asm_insn (\"tba\", operands);
4991 output_asm_insn (\"bcc\\t%l0\", ops);
4992 output_asm_insn (\"coma\", operands);
4993 output_asm_insn (\"comb\", operands);
4994
4995 CC_STATUS_INIT;
4996 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4997 CODE_LABEL_NUMBER (ops[0]));
4998 return \"\";
4999 }
5000 if (val >= 8)
5001 {
5002 ops[0] = gen_label_rtx ();
5003
5004 output_asm_insn (\"tab\", operands);
5005 output_asm_insn (\"clra\", operands);
5006 output_asm_insn (\"tstb\", operands);
5007 output_asm_insn (\"bge\\t%l0\", ops);
5008 output_asm_insn (\"deca\", operands);
5009
5010 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
5011 CODE_LABEL_NUMBER (ops[0]));
5012
5013 val -= 8;
5014
5015 while (val > 0)
5016 {
5017 output_asm_insn (\"asrb\", operands);
5018 val--;
5019 }
9caea35c 5020 /* Status is ok. */
385c9217
SC
5021 return \"\";
5022 }
5023 if (val == 7)
5024 {
5025 ops[0] = gen_label_rtx ();
5026 output_asm_insn (\"rolb\", operands);
5027 output_asm_insn (\"rola\", operands);
5028 output_asm_insn (\"tab\", operands);
01beec65 5029 output_asm_insn (\"anda\\t#0\", operands);
385c9217 5030 output_asm_insn (\"bcc\\t%l0\", ops);
01beec65 5031 output_asm_insn (\"coma\", ops);
385c9217
SC
5032
5033 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
5034 CODE_LABEL_NUMBER (ops[0]));
5035 return \"\";
5036 }
5037 while (val > 0)
5038 {
5039 output_asm_insn (\"asra\", operands);
5040 output_asm_insn (\"rorb\", operands);
5041 val--;
5042 }
5043 CC_STATUS_INIT;
5044
5045 return \"\";
5046}")
5047
5048(define_insn "*ashrhi3"
5049 [(set (match_operand:HI 0 "register_operand" "=d,x")
5050 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
01beec65 5051 (match_operand:HI 2 "register_operand" "+x,+d")))
385c9217
SC
5052 (clobber (match_dup 2))]
5053 ""
5054 "*
5055{
5056 CC_STATUS_INIT;
5057 if (D_REG_P (operands[2]))
5058 output_asm_insn (\"xgd%0\", operands);
5059
5060 output_asm_insn (\"bsr\\t___ashrhi3\", operands);
5061 if (D_REG_P (operands[2]))
5062 output_asm_insn (\"xgd%0\", operands);
5063
5064 return \"\";
5065}")
5066
5067(define_expand "ashrsi3"
5068 [(parallel
5069 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5070 (clobber (scratch:HI))])
5071 (parallel
5072 [(set (match_operand:SI 0 "register_operand" "")
5073 (ashiftrt:SI (match_dup 0)
5074 (match_operand:HI 2 "general_operand" "")))
5075 (clobber (scratch:HI))])]
5076 ""
5077 "")
5078
5079(define_insn "*ashrsi3_const"
5080 [(set (match_operand:SI 0 "register_operand" "+D")
5081 (ashiftrt:SI (match_dup 0)
76d06edc
SC
5082 (match_operand:HI 1 "const_int_operand" "")))
5083 (clobber (match_scratch:HI 2 "=y"))]
385c9217
SC
5084 ""
5085 "*
5086{
5087 CC_STATUS_INIT;
76d06edc 5088 return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
385c9217
SC
5089}")
5090
5091(define_insn "*ashrsi3"
5092 [(set (match_operand:SI 0 "register_operand" "+D,D")
5093 (ashiftrt:SI (match_dup 0)
76d06edc
SC
5094 (match_operand:HI 1 "general_operand" "y,m")))
5095 (clobber (match_scratch:HI 2 "=1,X"))]
385c9217
SC
5096 ""
5097 "*
5098{
5099 CC_STATUS_INIT;
5100 /* There is a reload problem if we don't accept 'm' for the shift value.
5101 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5102 and this conflicts with all reloads. Since X, Y, Z are used there
5103 is not enough register in class A_REGS.
5104
76d06edc 5105 Assuming that 'operands[1]' does not refer to the stack (which
385c9217 5106 is true for 68hc11 only, we save temporary the value of Y. */
76d06edc 5107 if (!Y_REG_P (operands[2]))
385c9217 5108 {
43a72755 5109 rtx ops[1];
4c8aed14 5110 int y_dead = dead_register_here (insn, iy_reg);
43a72755
SC
5111
5112 ops[0] = operands[1];
4c8aed14 5113 if (y_dead == 0)
43a72755 5114 {
4c8aed14
SC
5115 output_asm_insn (\"pshy\", operands);
5116 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5117 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
43a72755
SC
5118 }
5119 output_asm_insn (\"ldy\\t%0\", ops);
385c9217 5120 output_asm_insn (\"bsr\\t___ashrsi3\", operands);
4c8aed14 5121 return y_dead == 0 ? \"puly\" : \"\";
385c9217
SC
5122 }
5123 return \"bsr\\t___ashrsi3\";
5124}")
5125
5126(define_expand "ashrqi3"
5127 [(set (match_operand:QI 0 "register_operand" "")
5128 (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
5129 (match_operand:QI 2 "general_operand" "")))]
5130 ""
5131 "")
5132
5133(define_insn "*ashrqi3_const1"
76028b1f
SC
5134 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
5135 (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
385c9217
SC
5136 (const_int 1)))]
5137 ""
5138 "@
5139 asrb
5140 asr\\t%b0
76028b1f 5141 asr\\t%b0
385c9217
SC
5142 asr%0
5143 #")
5144
5145(define_insn "*ashrqi3_const"
5146 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5147 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5148 (match_operand:QI 2 "const_int_operand" "")))]
5149 ""
5150 "*
5151{
5152 int i;
5153 const char* insn_code;
5154
5155 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5156 insn_code = \"asrb\";
5157 else if (DA_REG_P (operands[0]))
5158 insn_code = \"asra\";
5159 else
5160 return \"#\";
5161
5162 i = INTVAL (operands[2]);
5163 if (i > 8)
5164 i = 8;
5165 while (--i >= 0)
5166 {
5167 output_asm_insn (insn_code, operands);
5168 }
5169 return \"\";
5170}")
5171
5172(define_insn "*ashrqi3"
5173 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5174 (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5175 (match_operand:QI 2 "nonimmediate_operand"
5176 "m*u*d*A,m*u*d*A,m*u")))]
5177 ""
5178 "*
5179{
5180 rtx ops[2];
5181
5182 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5183 return \"#\";
5184
5185 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
5186 ops[1] = operands[2];
5187 m68hc11_gen_movqi (insn, ops);
5188
5189 CC_STATUS_INIT;
5190 return \"bsr\\t___ashrqi3\";
5191}")
5192
5193;;--------------------------------------------------------------------
5194;; logical shift instructions
5195;;--------------------------------------------------------------------
5196(define_expand "lshrdi3"
5197 [(parallel [(set (match_operand:DI 0 "general_operand" "")
5198 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
5199 (match_operand:HI 2 "general_operand" "")))
5200 (clobber (match_scratch:HI 3 ""))])]
5201 ""
5202 "
5203{
5204 if (GET_CODE (operands[2]) != CONST_INT
5205 || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
5206 && INTVAL (operands[2]) != 1))
5207 {
5208 FAIL;
5209 }
5210}")
5211
5212(define_insn "*lshrdi3_const32"
76028b1f
SC
5213 [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
5214 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
385c9217 5215 (const_int 32)))
c6af4c2e 5216 (clobber (match_scratch:HI 2 "=&A,d,d"))]
385c9217
SC
5217 ""
5218 "#")
5219
5220(define_split
65e6c005
JJ
5221 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5222 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
385c9217 5223 (const_int 32)))
c6af4c2e 5224 (clobber (match_scratch:HI 2 "=&A,d"))]
385c9217
SC
5225 "reload_completed"
5226 [(const_int 0)]
5227 "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
5228 m68hc11_gen_highpart (SImode, operands[1]),
5229 operands[2]);
5230 m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
5231 const0_rtx, operands[2]);
5232 DONE;")
5233
5234(define_insn "*lshrdi3_const63"
76028b1f
SC
5235 [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
5236 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
385c9217 5237 (match_operand:DI 2 "const_int_operand" "")))
76028b1f 5238 (clobber (match_scratch:HI 3 "=d,d"))]
385c9217
SC
5239 "INTVAL (operands[2]) >= 48"
5240 "#")
5241
5242(define_split
65e6c005
JJ
5243 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5244 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
385c9217
SC
5245 (match_operand:DI 2 "const_int_operand" "")))
5246 (clobber (match_scratch:HI 3 "=d"))]
5247 "z_replacement_completed && INTVAL (operands[2]) >= 56"
01beec65
SC
5248 [(set (reg:QI D_REGNUM) (match_dup 9))
5249 (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
5250 (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
5251 (set (match_dup 4) (reg:HI D_REGNUM))
5252 (set (reg:QI D_REGNUM) (const_int 0))
5253 (set (match_dup 5) (reg:HI D_REGNUM))
5254 (set (match_dup 6) (reg:HI D_REGNUM))
5255 (set (match_dup 7) (reg:HI D_REGNUM))]
65e6c005 5256 "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
385c9217
SC
5257 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5258 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5259 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5260
5261 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5262 operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
5263 operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
5264
5265 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5266 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5267 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5268
5269(define_split
65e6c005
JJ
5270 [(set (match_operand:DI 0 "nonimmediate_operand" "")
5271 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
385c9217
SC
5272 (match_operand:DI 2 "const_int_operand" "")))
5273 (clobber (match_scratch:HI 3 "=d"))]
5274 "z_replacement_completed && INTVAL (operands[2]) >= 48
5275 && INTVAL (operands[2]) < 56"
01beec65
SC
5276 [(set (reg:HI D_REGNUM) (match_dup 9))
5277 (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
5278 (set (match_dup 4) (reg:HI D_REGNUM))
5279 (set (reg:HI D_REGNUM) (const_int 0))
5280 (set (match_dup 5) (reg:HI D_REGNUM))
5281 (set (match_dup 6) (reg:HI D_REGNUM))
5282 (set (match_dup 7) (reg:HI D_REGNUM))]
65e6c005 5283 "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
385c9217
SC
5284 operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
5285 operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
5286 operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
5287
5288 operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
5289 operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
5290 operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
5291 operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
5292 operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
5293
5294(define_insn "*lshrdi_const1"
76028b1f
SC
5295 [(set (match_operand:DI 0 "non_push_operand" "=m,u")
5296 (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
385c9217 5297 (const_int 1)))
76028b1f 5298 (clobber (match_scratch:HI 2 "=d,d"))]
385c9217
SC
5299 ""
5300 "#")
5301
5302(define_split
65e6c005
JJ
5303 [(set (match_operand:DI 0 "non_push_operand" "")
5304 (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
385c9217 5305 (const_int 1)))
65e6c005 5306 (clobber (match_scratch:HI 2 ""))]
385c9217
SC
5307 "z_replacement_completed == 2"
5308 [(set (match_dup 2) (match_dup 3))
5309 (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
5310 (set (match_dup 4) (match_dup 2))
5311
5312 (set (match_dup 2) (match_dup 5))
01beec65 5313 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
385c9217
SC
5314 (set (match_dup 6) (match_dup 2))
5315
5316 (set (match_dup 2) (match_dup 7))
01beec65 5317 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
385c9217
SC
5318 (set (match_dup 8) (match_dup 2))
5319
5320 (set (match_dup 2) (match_dup 9))
01beec65 5321 (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM)))
385c9217
SC
5322 (set (match_dup 10) (match_dup 2))]
5323 "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
5324 operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
5325 operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
5326
5327 operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
5328 operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
5329 operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
5330
5331 operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
5332 operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
5333 operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
5334
5335 operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
5336 operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
5337 operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
5338
5339(define_expand "lshrsi3"
5340 [(parallel
5341 [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
5342 (clobber (scratch:HI))])
5343 (parallel
5344 [(set (match_operand:SI 0 "register_operand" "")
5345 (lshiftrt:SI (match_dup 0)
5346 (match_operand:HI 2 "general_operand" "")))
5347 (clobber (scratch:HI))])]
5348 ""
5349 "")
5350
5351(define_split
65e6c005
JJ
5352 [(set (match_operand:SI 0 "non_push_operand" "")
5353 (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
385c9217 5354 (const_int 16)))
65e6c005 5355 (clobber (match_scratch:HI 3 ""))]
385c9217
SC
5356 "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
5357 [(set (match_dup 2) (match_dup 3))
5358 (set (match_dup 4) (const_int 0))]
5359 "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
5360 operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
5361 operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
5362
5363(define_insn "*lshrsi3_const16"
76028b1f
SC
5364 [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
5365 (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
385c9217 5366 (const_int 16)))
76028b1f 5367 (clobber (match_scratch:HI 2 "=X,X,X,X"))]
385c9217 5368 ""
01beec65
SC
5369 "@
5370 #
385c9217 5371 xgdx\\n\\tldx\\t#0
01beec65 5372 #
385c9217
SC
5373 #")
5374
5375(define_insn "*lshrsi3_const1"
76028b1f
SC
5376 [(set (match_operand:SI 0 "non_push_operand" "=D,m,*u")
5377 (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "D*um,*um,*um")
385c9217 5378 (const_int 1)))
76028b1f 5379 (clobber (match_scratch:HI 2 "=X,&d,&d"))]
385c9217
SC
5380 ""
5381 "*
5382{
5383 CC_STATUS_INIT;
5384 if (X_REG_P (operands[1]))
5385 {
5386 return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
5387 }
5388 else
5389 {
5390 rtx ops[2];
5391
5392 ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
5393 ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM);
5394 m68hc11_gen_movhi (insn, ops);
5395 output_asm_insn (\"lsrd\", ops);
5396 if (!X_REG_P (operands[0]))
5397 {
5398 ops[1] = ops[0];
5399 ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
5400 m68hc11_gen_movhi (insn, ops);
5401 ops[0] = ops[1];
5402 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5403 m68hc11_gen_movhi (insn, ops);
5404 }
5405 else
5406 {
5407 /* Load the lowpart in X in case the operands is some N,x. */
5408 ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM);
5409 ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
5410 m68hc11_gen_movhi (insn, ops);
5411 output_asm_insn (\"xgdx\", ops);
5412 }
5413 output_asm_insn (\"rora\", ops);
5414 output_asm_insn (\"rorb\", ops);
5415 if (!X_REG_P (operands[0]))
5416 {
5417 ops[1] = ops[0];
5418 ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
5419 m68hc11_gen_movhi (insn, ops);
5420 }
5421 return \"\";
5422 }
5423}")
5424
5425(define_insn "*lshrsi3_const"
5426 [(set (match_operand:SI 0 "register_operand" "+D")
5427 (lshiftrt:SI (match_dup 0)
76d06edc
SC
5428 (match_operand:HI 1 "const_int_operand" "")))
5429 (clobber (match_scratch:HI 2 "=y"))]
385c9217
SC
5430 ""
5431 "*
5432{
5433 CC_STATUS_INIT;
76d06edc 5434 return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
385c9217
SC
5435}")
5436
5437(define_insn "*lshrsi3"
5438 [(set (match_operand:SI 0 "register_operand" "+D,D")
5439 (lshiftrt:SI (match_dup 0)
76d06edc
SC
5440 (match_operand:HI 1 "general_operand" "y,m")))
5441 (clobber (match_scratch:HI 2 "=1,X"))]
385c9217
SC
5442 ""
5443 "*
5444{
5445 CC_STATUS_INIT;
5446 /* There is a reload problem if we don't accept 'm' for the shift value.
5447 A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
5448 and this conflicts with all reloads. Since X, Y, Z are used there
5449 is not enough register in class A_REGS.
5450
76d06edc 5451 Assuming that 'operands[1]' does not refer to the stack (which
385c9217 5452 is true for 68hc11 only, we save temporary the value of Y. */
76d06edc 5453 if (!Y_REG_P (operands[2]))
385c9217 5454 {
43a72755 5455 rtx ops[1];
4c8aed14 5456 int y_dead = dead_register_here (insn, iy_reg);
43a72755
SC
5457
5458 ops[0] = operands[1];
4c8aed14 5459 if (y_dead == 0)
43a72755 5460 {
4c8aed14
SC
5461 output_asm_insn (\"pshy\", operands);
5462 if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
5463 ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
43a72755
SC
5464 }
5465 output_asm_insn (\"ldy\\t%0\", ops);
385c9217 5466 output_asm_insn (\"bsr\\t___lshrsi3\", operands);
4c8aed14 5467 return y_dead == 0 ? \"puly\" : \"\";
385c9217
SC
5468 }
5469 return \"bsr\\t___lshrsi3\";
5470}")
5471
5472(define_expand "lshrhi3"
5473 [(set (match_operand:HI 0 "register_operand" "")
5474 (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
5475 (match_operand:HI 2 "general_operand" "")))]
5476 ""
5477 "
5478{
5479 if (GET_CODE (operands[2]) != CONST_INT)
5480 {
5481 rtx scratch = gen_reg_rtx (HImode);
5482 operand1 = force_reg (HImode, operand1);
5483
5484 emit_move_insn (scratch, operands[2]);
5485 emit_insn (gen_rtx (PARALLEL, VOIDmode,
5486 gen_rtvec (2, gen_rtx (SET, VOIDmode,
5487 operand0,
5488 gen_rtx_LSHIFTRT (HImode,
5489 operand1, scratch)),
5490 gen_rtx (CLOBBER, VOIDmode, scratch))));
5491 DONE;
5492 }
5493}")
5494
5495(define_insn "lshrhi3_const1"
5496 [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
5497 (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
5498 (const_int 1)))]
5499 ""
5500 "*
5501{
5502 if (A_REG_P (operands[0]))
5503 return \"#\";
5504
5505 if (D_REG_P (operands[0]))
5506 return \"lsrd\";
5507
5508 CC_STATUS_INIT;
39cc8df7 5509 return \"lsr\\t%h0\\n\\tror\\t%b0\";
385c9217
SC
5510}")
5511
5512(define_insn "lshrhi3_const"
5513 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
5514 (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
5515 (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
5516 ""
5517 "*
5518{
5519 int val = INTVAL (operands[2]);
5520
5521 if (A_REG_P (operands[0]))
5522 return \"#\";
5523
5524 if (val >= 8)
5525 {
5526 if (val == 8)
5527 CC_STATUS_INIT;
5528
5529 if (!H_REG_P (operands[1]))
5530 {
5531 output_asm_insn (\"clra\", operands);
5532 output_asm_insn (\"ldab\\t%h1\", operands);
5533 }
5534 else if (A_REG_P (operands[1]))
5535 {
5536 output_asm_insn (\"st%1\\t%t0\", operands);
5537 output_asm_insn (\"ldab\\t%t0\", operands);
5538 output_asm_insn (\"clra\", operands);
5539 }
5540 else
5541 {
5542 output_asm_insn (\"tab\", operands);
5543 output_asm_insn (\"clra\", operands);
5544 }
5545 val -= 8;
5546 switch (val)
5547 {
5548 case 7:
5549 output_asm_insn (\"rolb\", operands);
5550 output_asm_insn (\"tab\", operands);
5551 output_asm_insn (\"rolb\", operands);
5552 break;
5553
5554 case 6:
5555 output_asm_insn (\"rolb\", operands);
5556 output_asm_insn (\"rolb\", operands);
5557 output_asm_insn (\"rolb\", operands);
5558 output_asm_insn (\"andb\\t#3\", operands);
5559 break;
5560
5561 default:
5562 while (val > 0)
5563 {
5564 val --;
5565 output_asm_insn (\"lsrb\", operands);
5566 }
5567 break;
5568 }
5569 return \"\";
5570 }
5571
5572 if (!D_REG_P (operands[1]))
5573 m68hc11_gen_movhi (insn, operands);
5574 switch (val)
5575 {
5576 case 7:
5577 output_asm_insn (\"rolb\", operands);
5578 output_asm_insn (\"tab\", operands);
5579 output_asm_insn (\"rolb\", operands);
5580 output_asm_insn (\"rola\", operands);
5581 output_asm_insn (\"rola\", operands);
5582 output_asm_insn (\"anda\\t#1\", operands);
5583 CC_STATUS_INIT;
5584 break;
5585
5586 default:
5587 while (val > 0)
5588 {
5589 val --;
5590 output_asm_insn (\"lsrd\", operands);
5591 }
5592 }
5593 return \"\";
5594}")
5595
5596(define_insn "*lshrhi3"
5597 [(set (match_operand:HI 0 "register_operand" "=d,x")
5598 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
01beec65 5599 (match_operand:HI 2 "register_operand" "+x,+d")))
385c9217
SC
5600 (clobber (match_dup 2))]
5601 ""
5602 "*
5603{
5604 CC_STATUS_INIT;
5605 if (D_REG_P (operands[2]))
5606 output_asm_insn (\"xgd%0\", operands);
5607
5608 output_asm_insn (\"bsr\\t___lshrhi3\", operands);
5609 if (D_REG_P (operands[2]))
5610 output_asm_insn (\"xgd%0\", operands);
5611
5612 return \"\";
5613}")
5614
5615(define_expand "lshrqi3"
5616 [(set (match_operand:QI 0 "register_operand" "")
5617 (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
5618 (match_operand:QI 2 "general_operand" "")))]
5619 ""
5620 "")
5621
5622(define_insn "*lshrqi3_const1"
a1fdc802 5623 [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
76028b1f 5624 (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
385c9217
SC
5625 (const_int 1)))]
5626 ""
5627 "@
385c9217 5628 lsr\\t%b0
a1fdc802 5629 lsrb
76028b1f 5630 lsr\\t%b0
385c9217
SC
5631 lsr%0
5632 #")
5633
5634(define_insn "*lshrqi3_const"
5635 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5636 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5637 (match_operand:QI 2 "const_int_operand" "")))]
5638 ""
5639 "*
5640{
5641 int i;
5642 const char* insn_code;
5643
5644 if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
5645 insn_code = \"lsrb\";
5646 else if (DA_REG_P (operands[0]))
5647 insn_code = \"lsra\";
5648 else
5649 return \"#\";
5650
5651 i = INTVAL (operands[2]);
5652 if (i >= 8)
5653 {
5654 if (DA_REG_P (operands[0]))
5655 return \"clra\";
5656 else
5657 return \"clrb\";
5658 }
5659 else if (i == 7)
5660 {
5661 if (DA_REG_P (operands[0]))
5662 {
5663 output_asm_insn (\"rola\", operands);
5664 output_asm_insn (\"ldaa\\t#0\", operands);
5665 return \"rola\";
5666 }
5667 else
5668 {
5669 output_asm_insn (\"rolb\", operands);
5670 output_asm_insn (\"ldab\\t#0\", operands);
5671 return \"rolb\";
5672 }
5673 }
5674 else if (i == 6)
5675 {
5676 if (DA_REG_P (operands[0]))
5677 {
5678 output_asm_insn (\"rola\", operands);
5679 output_asm_insn (\"rola\", operands);
5680 output_asm_insn (\"rola\", operands);
5681 return \"anda\\t#3\";
5682 }
5683 else
5684 {
5685 output_asm_insn (\"rolb\", operands);
5686 output_asm_insn (\"rolb\", operands);
5687 output_asm_insn (\"rolb\", operands);
5688 return \"andb\\t#3\";
5689 }
5690 }
5691 while (--i >= 0)
5692 {
5693 output_asm_insn (insn_code, operands);
5694 }
5695 return \"\";
5696}")
5697
5698(define_insn "*lshrqi3"
5699 [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
5700 (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
5701 (match_operand:QI 2 "nonimmediate_operand"
5702 "m*u*d*A,m*u*d*A,m*u")))]
5703 ""
5704 "*
5705{
5706 rtx ops[2];
5707
5708 if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
5709 return \"#\";
5710
5711 CC_STATUS_INIT;
5712 ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM);
5713 ops[1] = operands[2];
5714 m68hc11_gen_movqi (insn, ops);
5715
5716 if (!optimize || optimize_size)
5717 {
5718 return \"bsr\\t___lshrqi3\";
5719 }
5720
5721 ops[0] = gen_label_rtx ();
5722 ops[1] = gen_label_rtx ();
5723 output_asm_insn (\"ble\\t%l1\", ops);
5724
5725 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
5726 CODE_LABEL_NUMBER (ops[0]));
5727
5728 output_asm_insn (\"lsrb\", operands);
5729 output_asm_insn (\"deca\", operands);
5730 output_asm_insn (\"bne\\t%l0\", ops);
5731
5732 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
5733 CODE_LABEL_NUMBER (ops[1]));
5734 return \"\";
5735}")
5736
5737(define_insn "*rotlqi3_with_carry"
5738 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5739 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
01beec65 5740 (reg:QI CC_REGNUM)))]
385c9217
SC
5741 ""
5742 "*
5743{
5744 if (DA_REG_P (operands[0]))
5745 return \"rola\";
5746 else
5747 return \"rolb\";
5748}")
5749
5750(define_insn "*rotlhi3_with_carry"
5751 [(set (match_operand:HI 0 "register_operand" "=d")
5752 (rotate:HI (match_operand:HI 1 "register_operand" "0")
01beec65 5753 (reg:HI CC_REGNUM)))]
385c9217
SC
5754 ""
5755 "*
5756{
5757 CC_STATUS_INIT;
5758 return \"rolb\\n\\trola\";
5759}")
5760
5761(define_insn "*rotrhi3_with_carry"
5762 [(set (match_operand:HI 0 "register_operand" "=d")
5763 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
01beec65 5764 (reg:HI CC_REGNUM)))]
385c9217
SC
5765 ""
5766 "*
5767{
5768 CC_STATUS_INIT;
5769 return \"rora\\n\\trorb\";
5770}")
5771
5772(define_insn "rotlqi3"
5773 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5774 (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
5775 (match_operand:QI 2 "const_int_operand" "i,i")))]
5776 ""
5777 "*
5778{
5779 m68hc11_gen_rotate (ROTATE, insn, operands);
5780 return \"\";
5781}")
5782
5783(define_insn "rotlhi3"
5784 [(set (match_operand:HI 0 "register_operand" "=d")
5785 (rotate:HI (match_operand:HI 1 "register_operand" "0")
5786 (match_operand:HI 2 "const_int_operand" "i")))]
5787 ""
5788 "*
5789{
5790 m68hc11_gen_rotate (ROTATE, insn, operands);
5791 return \"\";
5792}")
5793
5794(define_insn "rotrqi3"
5795 [(set (match_operand:QI 0 "register_operand" "=d,!q")
5796 (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
5797 (match_operand:QI 2 "const_int_operand" "i,i")))]
5798 ""
5799 "*
5800{
5801 m68hc11_gen_rotate (ROTATERT, insn, operands);
5802 return \"\";
5803}")
5804
5805(define_insn "rotrhi3"
5806 [(set (match_operand:HI 0 "register_operand" "=d")
5807 (rotatert:HI (match_operand:HI 1 "register_operand" "0")
5808 (match_operand:HI 2 "const_int_operand" "i")))]
5809 ""
5810 "*
5811{
5812 m68hc11_gen_rotate (ROTATERT, insn, operands);
5813 return \"\";
5814}")
5815
5816;;--------------------------------------------------------------------
5817;;- Jumps and transfers
5818;;--------------------------------------------------------------------
5819(define_insn "jump"
5820 [(set (pc)
5821 (label_ref (match_operand 0 "" "")))]
5822 ""
5823 "bra\\t%l0")
5824
5825(define_expand "beq"
5826 [(set (pc)
5827 (if_then_else (eq (cc0)
5828 (const_int 0))
5829 (label_ref (match_operand 0 "" ""))
5830 (pc)))]
5831 ""
5832 "
5833{
5834 m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
5835 m68hc11_compare_op1,
5836 operands[0]);
5837 DONE;
5838}")
5839
5840(define_expand "bne"
5841 [(set (pc)
5842 (if_then_else (ne (cc0)
5843 (const_int 0))
5844 (label_ref (match_operand 0 "" ""))
5845 (pc)))]
5846 ""
5847 "
5848{
5849 m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
5850 m68hc11_compare_op1,
5851 operands[0]);
5852 DONE;
5853}")
5854
5855(define_expand "bgt"
5856 [(set (pc)
5857 (if_then_else (gt (cc0)
5858 (const_int 0))
5859 (label_ref (match_operand 0 "" ""))
5860 (pc)))]
5861 ""
5862 "
5863{
5864 m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
5865 m68hc11_compare_op1,
5866 operands[0]);
5867 DONE;
5868}")
5869
5870(define_expand "bgtu"
5871 [(set (pc)
5872 (if_then_else (gtu (cc0)
5873 (const_int 0))
5874 (label_ref (match_operand 0 "" ""))
5875 (pc)))]
5876 ""
5877 "
5878{
5879 m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
5880 m68hc11_compare_op1,
5881 operands[0]);
5882 DONE;
5883}")
5884
5885(define_expand "blt"
5886 [(set (pc)
5887 (if_then_else (lt (cc0)
5888 (const_int 0))
5889 (label_ref (match_operand 0 "" ""))
5890 (pc)))]
5891 ""
5892 "
5893{
5894 m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
5895 m68hc11_compare_op1,
5896 operands[0]);
5897 DONE;
5898}")
5899
5900(define_expand "bltu"
5901 [(set (pc)
5902 (if_then_else (ltu (cc0)
5903 (const_int 0))
5904 (label_ref (match_operand 0 "" ""))
5905 (pc)))]
5906 ""
5907 "
5908{
5909 m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
5910 m68hc11_compare_op1,
5911 operands[0]);
5912 DONE;
5913}")
5914
5915(define_expand "bge"
5916 [(set (pc)
5917 (if_then_else (ge (cc0)
5918 (const_int 0))
5919 (label_ref (match_operand 0 "" ""))
5920 (pc)))]
5921 ""
5922 "
5923{
5924 m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
5925 m68hc11_compare_op1,
5926 operands[0]);
5927 DONE;
5928}")
5929
5930(define_expand "bgeu"
5931 [(set (pc)
5932 (if_then_else (geu (cc0)
5933 (const_int 0))
5934 (label_ref (match_operand 0 "" ""))
5935 (pc)))]
5936 ""
5937 "
5938{
5939 m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
5940 m68hc11_compare_op1,
5941 operands[0]);
5942 DONE;
5943}")
5944
5945(define_expand "ble"
5946 [(set (pc)
5947 (if_then_else (le (cc0)
5948 (const_int 0))
5949 (label_ref (match_operand 0 "" ""))
5950 (pc)))]
5951 ""
5952 "
5953{
5954 m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
5955 m68hc11_compare_op1,
5956 operands[0]);
5957 DONE;
5958}")
5959
5960(define_expand "bleu"
5961 [(set (pc)
5962 (if_then_else (leu (cc0)
5963 (const_int 0))
5964 (label_ref (match_operand 0 "" ""))
5965 (pc)))]
5966 ""
5967 "
5968{
5969 m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
5970 m68hc11_compare_op1,
5971 operands[0]);
5972 DONE;
5973}")
5974
dc3c6806
SC
5975;;
5976;; Test and branch instructions for 68HC12 for EQ and NE.
5977;; 'z' must not appear in the constraints because the z replacement
5978;; pass does not know how to restore the replacement register.
5979;;
5980(define_insn "*tbeq"
5981 [(set (pc)
5982 (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
5983 (const_int 0))
5984 (label_ref (match_operand 1 "" ""))
5985 (pc)))]
5986 "TARGET_M6812"
5987 "*
5988{
5989 /* If the flags are already set correctly, use 'bne/beq' which are
5990 smaller and a little bit faster. This happens quite often due
5991 to reloading of operands[0]. In that case, flags are set correctly
5992 due to the load instruction. */
a0df6910
SC
5993 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
5994 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
dc3c6806
SC
5995 return \"beq\\t%l1\";
5996 else
5997 return \"tbeq\\t%0,%l1\";
5998}")
5999
6000(define_insn "*tbne"
6001 [(set (pc)
6002 (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
6003 (const_int 0))
6004 (label_ref (match_operand 1 "" ""))
6005 (pc)))]
6006 "TARGET_M6812"
6007 "*
6008{
a0df6910
SC
6009 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6010 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
dc3c6806
SC
6011 return \"bne\\t%l1\";
6012 else
6013 return \"tbne\\t%0,%l1\";
6014}")
6015
6016;;
6017;; Test and branch with 8-bit register. Register must be B (or A).
6018;;
6019(define_insn "*tbeq8"
6020 [(set (pc)
6021 (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
6022 (const_int 0))
6023 (label_ref (match_operand 1 "" ""))
6024 (pc)))]
6025 "TARGET_M6812"
6026 "*
6027{
a0df6910
SC
6028 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6029 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
dc3c6806
SC
6030 return \"beq\\t%l1\";
6031 else
6032 return \"tbeq\\tb,%l1\";
6033}")
6034
6035(define_insn "*tbne8"
6036 [(set (pc)
6037 (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
6038 (const_int 0))
6039 (label_ref (match_operand 1 "" ""))
6040 (pc)))]
6041 "TARGET_M6812"
6042 "*
6043{
a0df6910
SC
6044 if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
6045 || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
dc3c6806
SC
6046 return \"bne\\t%l1\";
6047 else
6048 return \"tbne\\tb,%l1\";
6049}")
6050
385c9217
SC
6051(define_insn "*beq"
6052 [(set (pc)
6053 (if_then_else (eq (cc0)
6054 (const_int 0))
6055 (label_ref (match_operand 0 "" ""))
6056 (pc)))]
6057 ""
6058 "beq\\t%l0")
6059
6060(define_insn "*bne"
6061 [(set (pc)
6062 (if_then_else (ne (cc0)
6063 (const_int 0))
6064 (label_ref (match_operand 0 "" ""))
6065 (pc)))]
6066 ""
6067 "bne\\t%l0")
6068
6069(define_insn "*bgt"
6070 [(set (pc)
6071 (if_then_else (gt (cc0)
6072 (const_int 0))
6073 (label_ref (match_operand 0 "" ""))
6074 (pc)))]
6075 ""
6076 "bgt\\t%l0")
6077
6078(define_insn "*bgtu"
6079 [(set (pc)
6080 (if_then_else (gtu (cc0)
6081 (const_int 0))
6082 (label_ref (match_operand 0 "" ""))
6083 (pc)))]
6084 ""
6085 "bhi\\t%l0")
6086
6087(define_insn "*blt"
6088 [(set (pc)
6089 (if_then_else (lt (cc0)
6090 (const_int 0))
6091 (label_ref (match_operand 0 "" ""))
6092 (pc)))]
6093 ""
6094 "*
6095{
6096 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6097 return \"bmi\\t%l0\";
6098 else
6099 return \"blt\\t%l0\";
6100}")
6101
6102(define_insn "*bltu"
6103 [(set (pc)
6104 (if_then_else (ltu (cc0)
6105 (const_int 0))
6106 (label_ref (match_operand 0 "" ""))
6107 (pc)))]
6108 ""
6109 "blo\\t%l0")
6110
6111(define_insn "*bge"
6112 [(set (pc)
6113 (if_then_else (ge (cc0)
6114 (const_int 0))
6115 (label_ref (match_operand 0 "" ""))
6116 (pc)))]
6117 ""
6118 "*
6119{
6120 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6121 return \"bpl\\t%l0\";
6122 else
6123 return \"bge\\t%l0\";
6124}")
6125
6126(define_insn "*bgeu"
6127 [(set (pc)
6128 (if_then_else (geu (cc0)
6129 (const_int 0))
6130 (label_ref (match_operand 0 "" ""))
6131 (pc)))]
6132 ""
6133 "bhs\\t%l0")
6134
6135(define_insn "*ble"
6136 [(set (pc)
6137 (if_then_else (le (cc0)
6138 (const_int 0))
6139 (label_ref (match_operand 0 "" ""))
6140 (pc)))]
6141 ""
6142 "*
6143{
6144 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6145 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6146 else
6147 return \"ble\\t%l0\";
6148}")
6149
6150(define_insn "*bleu"
6151 [(set (pc)
6152 (if_then_else (leu (cc0)
6153 (const_int 0))
6154 (label_ref (match_operand 0 "" ""))
6155 (pc)))]
6156 ""
6157 "bls\\t%l0")
6158
6159;;--------------------------------------------------------------------
6160;;- Negative test and branch
6161;;--------------------------------------------------------------------
6162(define_insn ""
6163 [(set (pc)
6164 (if_then_else (eq (cc0)
6165 (const_int 0))
6166 (pc)
6167 (label_ref (match_operand 0 "" ""))))]
6168 ""
6169 "bne\\t%l0")
6170
6171(define_insn ""
6172 [(set (pc)
6173 (if_then_else (ne (cc0)
6174 (const_int 0))
6175 (pc)
6176 (label_ref (match_operand 0 "" ""))))]
6177 ""
6178 "beq\\t%l0")
6179
6180(define_insn ""
6181 [(set (pc)
6182 (if_then_else (gt (cc0)
6183 (const_int 0))
6184 (pc)
6185 (label_ref (match_operand 0 "" ""))))]
6186 ""
6187 "*
6188{
6189 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6190 return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
6191 else
6192 return \"ble\\t%l0\";
6193}")
6194
6195(define_insn ""
6196 [(set (pc)
6197 (if_then_else (gtu (cc0)
6198 (const_int 0))
6199 (pc)
6200 (label_ref (match_operand 0 "" ""))))]
6201 ""
6202 "bls\\t%l0")
6203
6204(define_insn ""
6205 [(set (pc)
6206 (if_then_else (lt (cc0)
6207 (const_int 0))
6208 (pc)
6209 (label_ref (match_operand 0 "" ""))))]
6210 ""
6211 "*
6212{
6213 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6214 return \"bpl\\t%l0\";
6215 else
6216 return \"bge\\t%l0\";
6217}")
6218
6219(define_insn ""
6220 [(set (pc)
6221 (if_then_else (ltu (cc0)
6222 (const_int 0))
6223 (pc)
6224 (label_ref (match_operand 0 "" ""))))]
6225 ""
6226 "bhs\\t%l0")
6227
6228(define_insn ""
6229 [(set (pc)
6230 (if_then_else (ge (cc0)
6231 (const_int 0))
6232 (pc)
6233 (label_ref (match_operand 0 "" ""))))]
6234 ""
6235 "*
6236{
6237 if (cc_prev_status.flags & CC_NO_OVERFLOW)
6238 return \"bmi\\t%l0\";
6239 else
6240 return \"blt\\t%l0\";
6241}")
6242
6243(define_insn ""
6244 [(set (pc)
6245 (if_then_else (geu (cc0)
6246 (const_int 0))
6247 (pc)
6248 (label_ref (match_operand 0 "" ""))))]
6249 ""
6250 "blo\\t%l0")
6251
6252(define_insn ""
6253 [(set (pc)
6254 (if_then_else (le (cc0)
6255 (const_int 0))
6256 (pc)
6257 (label_ref (match_operand 0 "" ""))))]
6258 ""
6259 "bgt\\t%l0")
6260
6261(define_insn ""
6262 [(set (pc)
6263 (if_then_else (leu (cc0)
6264 (const_int 0))
6265 (pc)
6266 (label_ref (match_operand 0 "" ""))))]
6267 ""
6268 "bhi\\t%l0")
6269
6270;;--------------------------------------------------------------------
6271;;- Calls
6272;;--------------------------------------------------------------------
6273;;
6274;;- Call a function that returns no value.
6275(define_insn "call"
01beec65 6276 [(call (match_operand:QI 0 "memory_operand" "m")
385c9217
SC
6277 (match_operand:SI 1 "general_operand" "g"))]
6278 ;; Operand 1 not really used on the m68hc11.
6279 ""
6280 "*
6281{
6282 if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
6283 {
6284 if (SYMBOL_REF_FLAG (XEXP (operands[0], 0)) == 1)
6285 return \"swi\";
6286 else
6287 return \"bsr\\t%0\";
6288 }
6289 else
6290 {
6291 return \"jsr\\t%0\";
6292 }
6293}")
6294
6295(define_insn "call_value"
6296 [(set (match_operand 0 "" "=g")
01beec65 6297 (call (match_operand:QI 1 "memory_operand" "m")
385c9217
SC
6298 (match_operand:SI 2 "general_operand" "g")))]
6299 ""
6300 "*
6301{
6302 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
6303 {
6304 if (SYMBOL_REF_FLAG (XEXP (operands[1], 0)) == 1)
6305 return \"swi\";
6306 else
6307 return \"bsr\\t%1\";
6308 }
6309 else
6310 {
6311 return \"jsr\\t%1\";
6312 }
6313}")
6314
6315;; Call subroutine returning any type.
6316
6317(define_expand "untyped_call"
6318 [(parallel [(call (match_operand 0 "" "")
6319 (const_int 0))
6320 (match_operand 1 "" "")
6321 (match_operand 2 "" "")])]
6322 ""
6323 "
6324{
6325 int i;
6326
6327 emit_call_insn (gen_call (operands[0], const0_rtx));
6328
6329 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6330 {
6331 rtx set = XVECEXP (operands[2], 0, i);
6332 emit_move_insn (SET_DEST (set), SET_SRC (set));
6333 }
6334
6335 /* The optimizer does not know that the call sets the function value
6336 registers we stored in the result block. We avoid problems by
6337 claiming that all hard registers are used and clobbered at this
6338 point. */
6339 emit_insn (gen_blockage ());
6340
6341 DONE;
6342}")
6343
6344;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6345;; all of memory. This blocks insns from being moved across this point.
6346
6347(define_insn "blockage"
6348 [(unspec_volatile [(const_int 0)] 0)]
6349 ""
6350 "")
6351
6352(define_insn "nop"
6353 [(const_int 0)]
6354 ""
6355 "nop")
6356
6357(define_expand "prologue"
6358 [(const_int 0)]
6359 ""
6360 "
6361{
6362 expand_prologue ();
6363 DONE;
6364}")
6365
6366(define_expand "epilogue"
6367 [(return)]
6368 ""
6369 "
6370{
6371 expand_epilogue ();
6372 DONE;
6373}")
6374
6375;; Used for frameless functions which save no regs and allocate no locals.
6376(define_expand "return"
6377 [(return)]
6378 "reload_completed && m68hc11_total_frame_size () == 0"
6379 "
6380{
6381 int ret_size = 0;
6382
6383 if (current_function_return_rtx)
6384 ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
6385
6386 /* Emit use notes only when HAVE_return is true. */
6387 if (m68hc11_total_frame_size () != 0)
6388 ret_size = 0;
6389
6390 if (ret_size && ret_size <= 2)
6391 {
6392 emit_insn (gen_rtx (PARALLEL, VOIDmode,
6393 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6394 gen_rtx_USE (VOIDmode,
6395 gen_rtx_REG (HImode, 1)))));
6396 DONE;
6397 }
6398 if (ret_size)
6399 {
6400 emit_insn (gen_rtx (PARALLEL, VOIDmode,
6401 gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
6402 gen_rtx_USE (VOIDmode,
6403 gen_rtx_REG (SImode, 0)))));
6404 DONE;
6405 }
6406}")
6407
6408(define_insn "*return_void"
6409 [(return)]
6410 "reload_completed"
6411 "*
6412{
6413 rtx next = next_active_insn (insn);
6414
6415 if (next
6416 && GET_CODE (next) == JUMP_INSN
6417 && GET_CODE (PATTERN (next)) == RETURN)
6418 return \"\";
6419 if (current_function_interrupt || current_function_trap)
6420 return \"rti\";
6421 return \"rts\";
6422}")
6423
6424(define_insn "*return_16bit"
6425 [(return)
01beec65 6426 (use (reg:HI D_REGNUM))]
385c9217
SC
6427 "reload_completed && m68hc11_total_frame_size () == 0"
6428 "*
6429{
6430 rtx next = next_active_insn (insn);
6431
6432 if (next
6433 && GET_CODE (next) == JUMP_INSN
6434 && GET_CODE (PATTERN (next)) == RETURN)
6435 return \"\";
6436 if (current_function_interrupt || current_function_trap)
6437 return \"rti\";
6438 return \"rts\";
6439}")
6440
6441(define_insn "*return_32bit"
6442 [(return)
6443 (use (reg:SI 0))]
6444 "reload_completed && m68hc11_total_frame_size () == 0"
6445 "*
6446{
6447 rtx next = next_active_insn (insn);
6448
6449 if (next
6450 && GET_CODE (next) == JUMP_INSN
6451 && GET_CODE (PATTERN (next)) == RETURN)
6452 return \"\";
6453 if (current_function_interrupt || current_function_trap)
6454 return \"rti\";
6455 return \"rts\";
6456}")
6457
6458(define_insn "indirect_jump"
6459 [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
6460 ""
6461 "jmp\\t0,%0")
6462
6463;;--------------------------------------------------------------------
6464;;- Table jump
6465;;--------------------------------------------------------------------
6466;;
6467;; Operand 0 is the address of the table element to use
6468;; operand 1 is the CODE_LABEL for the table
6469;;--------------------------------------------------------------------
6470(define_expand "tablejump"
6471 [(parallel [(set (pc) (match_operand 0 "" ""))
6472 (use (label_ref (match_operand 1 "" "")))])]
6473 ""
6474 "")
6475
6476(define_insn "*jump_indirect"
6477 [(parallel [
6478 (set (pc) (match_operand:HI 0 "register_operand" "xy"))
6479 (use (label_ref (match_operand 1 "" "")))])]
6480 ""
6481 "jmp\\t0,%0")
6482
6483;;--------------------------------------------------------------------
6484;;- Peepholes
6485;;--------------------------------------------------------------------
6486
4f81fba1 6487;;
581fd392
SC
6488;; Replace "leas 2,sp" with a "pulx" or a "puly".
6489;; On 68HC12, this is one cycle slower but one byte smaller.
6490;; pr target/6899: This peephole is not valid because a register CSE
6491;; pass removes the pulx/puly.
4f81fba1
SC
6492;;
6493(define_peephole2
581fd392
SC
6494 [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
6495 (match_scratch:HI 0 "xy")]
6496 "0 && TARGET_M6812 && optimize_size"
6497 [(set (match_dup 0) (match_dup 1))]
6498 "operands[1] = gen_rtx (MEM, HImode,
6499 gen_rtx (POST_INC, HImode,
6500 gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
4f81fba1
SC
6501
6502;;
581fd392
SC
6503;; Optimize memory<->memory moves when the value is also loaded in
6504;; a register.
4f81fba1
SC
6505;;
6506(define_peephole2
581fd392
SC
6507 [(set (match_operand:QI 0 "memory_operand" "")
6508 (match_operand:QI 1 "memory_operand" ""))
6509 (set (reg:QI D_REGNUM)
6510 (match_operand:QI 2 "memory_operand" ""))]
6511 "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
6512 || (GET_CODE (XEXP (operands[0], 0)) == REG
6513 && GET_CODE (XEXP (operands[2], 0)) == POST_INC
6514 && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
6515 [(set (reg:QI D_REGNUM) (match_dup 1))
6516 (set (match_dup 2) (reg:QI D_REGNUM))]
4f81fba1
SC
6517 "")
6518
a0df6910
SC
6519;;
6520;; Remove a possible move before a compare instruction when that
6521;; move will go in a dead register. Compare with the source then.
6522;;
6523(define_peephole2
6524 [(set (match_operand:HI 0 "hard_reg_operand" "")
6525 (match_operand:HI 1 "hard_reg_operand" ""))
6526 (set (cc0)
6527 (compare (match_dup 0)
6528 (match_operand:HI 2 "cmp_operand" "")))]
6529 "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
6530 && peep2_reg_dead_p (2, operands[0])
6531 && !reg_mentioned_p (operands[0], operands[2])"
6532 [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
6533 "")
6534
581fd392
SC
6535;;
6536;; Optimize loading a constant to memory when that same constant
6537;; is loaded to a hard register. Switch the two to use the register
6538;; for memory initialization. In most cases, the constant is 0.
6539;;
6540(define_peephole2
6541 [(set (match_operand:HI 0 "memory_operand" "")
6542 (match_operand:HI 1 "immediate_operand" ""))
6543 (set (match_operand:HI 2 "hard_reg_operand" "")
6544 (match_dup 1))]
6545 "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
6546 && !reg_mentioned_p (operands[2], operands[0])
6547 && GET_MODE (operands[2]) == HImode"
6548 [(set (match_dup 2) (match_dup 1))
6549 (set (match_dup 0) (match_dup 2))]
6550 "")
6551
6552;;
6553;; Reorganize to optimize address computations.
6554;;
6555(define_peephole2
6556 [(set (match_operand:HI 0 "hard_reg_operand" "")
6557 (match_operand:HI 1 "const_int_operand" ""))
6558 (set (match_dup 0)
6559 (plus:HI (match_dup 0)
6560 (match_operand:HI 2 "general_operand" "")))]
6561 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
6562 [(set (match_dup 0) (match_dup 2))
6563 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
6564 "")
6565
a0df6910
SC
6566;;
6567;; Optimize an address register increment and a compare to use
581fd392 6568;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
a0df6910
SC
6569;; before reload, but can be enabled after).
6570;;
581fd392
SC
6571(define_peephole2
6572 [(set (match_operand:HI 0 "hard_reg_operand" "")
6573 (plus:HI (match_dup 0)
6574 (match_operand:HI 1 "const_int_operand" "")))
6575 (set (cc0)
6576 (match_operand:QI 2 "memory_operand" ""))]
6577 "TARGET_AUTO_INC_DEC
6578 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6579 && reg_mentioned_p (operands[0], operands[2])"
6580 [(set (cc0) (match_dup 3))]
6581 "if (INTVAL (operands[1]) == 1)
6582 operands[3] = gen_rtx (MEM, QImode,
6583 gen_rtx (PRE_INC, HImode, operands[0]));
6584 else
6585 operands[3] = gen_rtx (MEM, QImode,
6586 gen_rtx (PRE_DEC, HImode, operands[0]));
6587 ")
6588
6589;;
6590;; Likewise for compare.
6591;;
a0df6910
SC
6592(define_peephole2
6593 [(set (match_operand:HI 0 "hard_reg_operand" "")
6594 (plus:HI (match_dup 0)
6595 (match_operand:HI 1 "const_int_operand" "")))
6596 (set (cc0)
6597 (compare (match_operand:QI 2 "hard_reg_operand" "")
6598 (match_operand:QI 3 "memory_operand" "")))]
6599 "TARGET_AUTO_INC_DEC
6600 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6601 && reg_mentioned_p (operands[0], operands[3])"
6602 [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
6603 "if (INTVAL (operands[1]) == 1)
6604 operands[4] = gen_rtx (MEM, QImode,
6605 gen_rtx (PRE_INC, HImode, operands[0]));
6606 else
6607 operands[4] = gen_rtx (MEM, QImode,
6608 gen_rtx (PRE_DEC, HImode, operands[0]));
6609 ")
6610
6611(define_peephole2
6612 [(set (match_operand:HI 0 "hard_reg_operand" "")
6613 (plus:HI (match_dup 0)
6614 (match_operand:HI 1 "const_int_operand" "")))
6615 (set (cc0)
6616 (compare (match_operand:QI 2 "memory_operand" "")
6617 (match_operand:QI 3 "hard_reg_operand" "")))]
6618 "TARGET_AUTO_INC_DEC
6619 && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
6620 && reg_mentioned_p (operands[0], operands[2])"
6621 [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
6622 "if (INTVAL (operands[1]) == 1)
6623 operands[4] = gen_rtx (MEM, QImode,
6624 gen_rtx (PRE_INC, HImode, operands[0]));
6625 else
6626 operands[4] = gen_rtx (MEM, QImode,
6627 gen_rtx (PRE_DEC, HImode, operands[0]));
6628 ")
6629
581fd392
SC
6630;;
6631;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
6632;; (avoids many temporary moves because we can't add sp to another reg easily)
6633;;
6634(define_peephole2
6635 [(set (match_operand:HI 0 "hard_reg_operand" "")
6636 (match_operand:HI 1 "const_int_operand" ""))
6637 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
6638 ""
6639 [(set (match_dup 0) (reg:HI SP_REGNUM))
6640 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
6641 "")
6642
6643;;
6644;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
6645;;
6646(define_peephole2
6647 [(set (match_operand:HI 0 "hard_reg_operand" "")
6648 (match_operand:HI 1 "const_int_operand" ""))
6649 (set (match_dup 0)
6650 (plus:HI (match_dup 0)
6651 (match_operand:HI 2 "general_operand" "")))]
6652 "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
6653 [(set (match_dup 0) (match_dup 2))
6654 (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
6655 "")
6656
6657;;
6658;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
6659;;
6660(define_peephole2
6661 [(set (match_operand:HI 0 "hard_reg_operand" "")
6662 (match_operand:HI 1 "memory_operand" ""))
6663 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
6664 (match_dup 0))
6665 (match_scratch:HI 2 "x")]
6666 "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
6667 [(set (match_dup 2) (match_dup 1))
6668 (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
6669 "")
6670
385c9217
SC
6671;;
6672;; This peephole catches the address computations generated by the reload
6673;; pass.
6674(define_peephole
6675 [(set (match_operand:HI 0 "hard_reg_operand" "xy")
6676 (match_operand:HI 1 "const_int_operand" ""))
01beec65
SC
6677 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6678 (set (match_dup 0) (reg:HI D_REGNUM))])
6679 (set (reg:HI D_REGNUM)
6680 (plus (reg:HI D_REGNUM)
385c9217 6681 (match_operand:HI 2 "general_operand" "")))
01beec65
SC
6682 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6683 (set (match_dup 0) (reg:HI D_REGNUM))])]
385c9217
SC
6684 "(INTVAL (operands[1]) & 0x0FF) == 0"
6685 "*
6686{
6687 int value_loaded = 1;
6688
d5d5ec45 6689 if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
385c9217 6690 {
d5d5ec45
SC
6691 rtx ops[2];
6692
6693 ops[0] = operands[0];
6694 ops[1] = operands[2];
6695 m68hc11_gen_movhi (insn, ops);
6696 output_asm_insn (\"xgd%0\", operands);
385c9217
SC
6697 }
6698 else if (Y_REG_P (operands[0]))
6699 {
6700 if (reg_mentioned_p (iy_reg, operands[2]))
6701 output_asm_insn (\"ldy\\t%2\", operands);
6702 else
6703 value_loaded = 0;
6704 output_asm_insn (\"xgdy\", operands);
6705 }
6706 else
6707 {
6708 output_asm_insn (\"ldd\\t%2\", operands);
6709 }
6710
6711 if (value_loaded == 0)
6712 output_asm_insn (\"ldd\\t%2\", operands);
6713 if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
6714 output_asm_insn (\"inca\", operands);
1943c2c1 6715 else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
385c9217
SC
6716 output_asm_insn (\"deca\", operands);
6717 else if (INTVAL (operands[1]) != 0)
6718 output_asm_insn (\"adda\\t%h1\", operands);
6719
6720 if (X_REG_P (operands[0]))
6721 return \"xgdx\";
6722 else if (Y_REG_P (operands[0]))
6723 return \"xgdy\";
6724 else
6725 return \"\";
6726}
6727")
6728
6729(define_peephole
6730 [(set (match_operand:HI 0 "hard_reg_operand" "h")
6731 (match_operand:HI 1 "non_push_operand" "g"))
6732 (set (match_operand:HI 2 "hard_reg_operand" "h")
6733 (match_dup 0))]
6734 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
6735 && !S_REG_P (operands[2])"
6736 "*
6737{
6738 rtx ops[2];
6739
6740 ops[0] = operands[2];
6741 ops[1] = operands[1];
6742 m68hc11_gen_movhi (insn, ops);
6743 return \"\";
6744}
6745")
6746
6747(define_peephole
6748 [(set (match_operand:HI 0 "hard_reg_operand" "h")
6749 (match_operand:HI 1 "hard_reg_operand" "h"))
6750 (set (match_operand:HI 2 "non_push_operand" "g")
6751 (match_dup 0))]
6752 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
6753 && !S_REG_P (operands[2])"
6754 "*
6755{
6756 rtx ops[2];
6757
6758 ops[0] = operands[2];
6759 ops[1] = operands[1];
6760 m68hc11_gen_movhi (insn, ops);
6761 return \"\";
6762}
6763")
6764
6765;;
6766;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
6767;; the set, so we don't need to emit anything. 'ins1' refers to the
6768;; (set ...) insn.
6769;;
6770(define_peephole
01beec65
SC
6771 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
6772 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6773 (set (match_dup 0) (reg:HI D_REGNUM))])]
385c9217
SC
6774 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
6775 "*
6776{
6777 cc_status = cc_prev_status;
6778 return \"\";
6779}
6780")
6781
6782;; Same as above but due to some split, there may be a noop set
6783;; between the two.
6784(define_peephole
01beec65 6785 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
385c9217 6786 (set (match_dup 0) (match_dup 0))
01beec65
SC
6787 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6788 (set (match_dup 0) (reg:HI D_REGNUM))])]
385c9217
SC
6789 "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
6790 "*
6791{
6792 cc_status = cc_prev_status;
6793 return \"\";
6794}
6795")
6796
6797;;
6798;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
6799;; and we must, at least, setup X/Y with value of D.
6800;;
6801(define_peephole
01beec65
SC
6802 [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
6803 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6804 (set (match_dup 0) (reg:HI D_REGNUM))])]
385c9217
SC
6805 ""
6806 "*
6807{
6808 rtx ops[2];
6809
6810 ops[0] = operands[0];
6811 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6812 m68hc11_gen_movhi (insn, ops);
6813 return \"\";
6814}
6815")
6816
6817;;;
6818;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6819;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
6820;;;
6821(define_peephole
01beec65
SC
6822 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6823 (set (match_dup 0) (reg:HI D_REGNUM))])
6824 (set (reg:HI D_REGNUM) (match_dup 0))]
385c9217
SC
6825 "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
6826 "*
6827{
6828 cc_status = cc_prev_status;
6829 return \"\";
6830}
6831")
6832
6833;;;
6834;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6835;;; need to emit anything. Otherwise, we just need an copy of D to X/Y.
6836;;;
6837(define_peephole
01beec65
SC
6838 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6839 (set (match_dup 0) (reg:HI D_REGNUM))])
6840 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
385c9217
SC
6841 "REGNO (operands[0]) == REGNO (operands[1])
6842 && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
6843 "*
6844{
6845 cc_status = cc_prev_status;
6846 return \"\";
6847}
6848")
6849
6850;;;
6851;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
6852;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
6853;;;
6854(define_peephole
01beec65
SC
6855 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6856 (set (match_dup 0) (reg:HI D_REGNUM))])
6857 (set (reg:HI D_REGNUM) (match_dup 0))]
385c9217
SC
6858 ""
6859 "*
6860{
6861 rtx ops[2];
6862
6863 ops[0] = operands[0];
6864 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6865 m68hc11_gen_movhi (insn, ops);
6866 return \"\";
6867}
6868")
6869
6870;;;
6871;;; Same peephole with a QI set. The copy is made as 16-bit to comply
6872;;; with the xgdx.
6873;;;
6874(define_peephole
01beec65
SC
6875 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6876 (set (match_dup 0) (reg:HI D_REGNUM))])
6877 (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
385c9217
SC
6878 "REGNO (operands[0]) == REGNO (operands[1])"
6879 "*
6880{
6881 rtx ops[2];
6882
6883 ops[0] = operands[0];
6884 ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM);
6885 m68hc11_gen_movhi (insn, ops);
6886 return \"\";
6887}
6888")
6889
6890;;;
6891;;; Catch two consecutive xgdx or xgdy, emit nothing.
6892;;;
6893(define_peephole
01beec65
SC
6894 [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
6895 (set (match_dup 0) (reg:HI D_REGNUM))])
6896 (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
6897 (set (match_dup 0) (reg:HI D_REGNUM))])]
385c9217
SC
6898 ""
6899 "*
6900{
6901 cc_status = cc_prev_status;
6902 return \"\";
6903}
6904")
6905
385c9217
SC
6906(define_peephole
6907 [(set (match_operand:HI 0 "hard_reg_operand" "")
6908 (match_operand:HI 1 "stack_register_operand" ""))
6909 (set (match_operand:HI 2 "hard_reg_operand" "")
6910 (match_operand:HI 3 "memory_operand" "m"))
6911 (set (match_dup 0)
6912 (match_operand:HI 4 "memory_operand" "m"))]
6913 "IS_STACK_POP (operands[4])
6914 && (GET_CODE (operands[3]) == MEM &&
6915 rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
6916 "*
6917{
6918 rtx ops[2];
6919
6920 ops[0] = operands[2];
6921 ops[1] = gen_rtx (MEM, HImode,
6922 gen_rtx (POST_INC, HImode, stack_pointer_rtx));
6923 m68hc11_gen_movhi (insn, ops);
6924 return \"\";
6925}
6926")
6927
6928;;
6929;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
6930;;
6931(define_peephole
6932 [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
01beec65 6933 (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
385c9217
SC
6934 "TARGET_M6811"
6935 "*
6936{
6937 return \"sts\\t%t0\\n\\tld%0\\t%t0\";
6938}
6939")
This page took 1.258652 seconds and 5 git commands to generate.