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