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