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