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