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