]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/pdp11/pdp11.md
Change references of .c files to .cc files
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.md
1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994-2022 Free Software Foundation, Inc.
3 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
4
5 ;; This file is part of GCC.
6
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
20
21 (include "predicates.md")
22 (include "constraints.md")
23
24 (define_c_enum "unspecv"
25 [
26 UNSPECV_BLOCKAGE
27 UNSPECV_SETD
28 UNSPECV_SETI
29 UNSPECV_CPYMEM
30 ])
31
32 (define_constants
33 [
34 ;; Register numbers
35 (R0_REGNUM 0)
36 (RETVAL_REGNUM 0)
37 (FRAME_POINTER_REGNUM 5)
38 (STACK_POINTER_REGNUM 6)
39 (PC_REGNUM 7)
40 (AC0_REGNUM 8)
41 (AC3_REGNUM 11)
42 (AC4_REGNUM 12)
43 (AC5_REGNUM 13)
44 ;; The next one is not a physical register but is used for
45 ;; addressing arguments.
46 (ARG_POINTER_REGNUM 14)
47 ;; Condition code registers
48 (CC_REGNUM 15)
49 (FCC_REGNUM 16)
50 ;; End of hard registers
51 (FIRST_PSEUDO_REGISTER 17)
52
53 ;; Branch offset limits, as byte offsets from (pc). That is NOT
54 ;; the same thing as "instruction address" -- it is for backward
55 ;; branches, but for forward branches it refers to the address
56 ;; following the instruction. So the max forward distance
57 ;; matches what the processor handbook says, while the max
58 ;; backward branch is 2 less than the book.
59 (MIN_BRANCH -254)
60 (MAX_BRANCH 254)
61 (MIN_SOB -124)
62 (MAX_SOB 0)])
63
64 ;; DF is 64 bit
65 ;; SF is 32 bit
66 ;; SI is 32 bit
67 ;; HI is 16 bit
68 ;; QI is 8 bit
69
70 ;; Integer modes supported on the PDP11, with a mapping from machine mode
71 ;; to mnemonic suffix. SImode and DImode are usually special cases.
72 (define_mode_iterator PDPint [QI HI])
73 (define_mode_attr isfx [(QI "b") (HI "")])
74 (define_mode_attr mname [(QI "QImode") (HI "HImode") (SI "SImode") (DI "DImode")])
75 (define_mode_attr e_mname [(QI "E_QImode") (HI "E_HImode") (SI "E_SImode") (DI "E_DImode")])
76 (define_mode_attr hmode [(QI "hi") (HI "hi") (SI "si") (DI "di")])
77
78 ;; These are analogous for use in splitters and expanders.
79 (define_mode_iterator HSint [HI SI])
80 (define_mode_iterator QHSint [QI HI SI])
81 (define_mode_iterator QHSDint [QI HI SI DI])
82
83 (define_code_iterator SHF [ashift ashiftrt lshiftrt])
84
85 (define_mode_iterator PDPfp [SF DF])
86
87 ;; Substitution to turn a CC clobber into a CC setter. We have four of
88 ;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
89 (define_subst "cc_cc"
90 [(set (match_operand 0 "") (match_operand 1 ""))
91 (clobber (reg CC_REGNUM))]
92 ""
93 [(set (reg:CC CC_REGNUM)
94 (compare:CC (match_dup 1) (const_int 0)))
95 (set (match_dup 0) (match_dup 1))])
96
97 (define_subst "cc_ccnz"
98 [(set (match_operand 0 "") (match_operand 1 ""))
99 (clobber (reg CC_REGNUM))]
100 ""
101 [(set (reg:CCNZ CC_REGNUM)
102 (compare:CCNZ (match_dup 1) (const_int 0)))
103 (set (match_dup 0) (match_dup 1))])
104
105 (define_subst "fcc_cc"
106 [(set (match_operand:PDPfp 0 "") (match_operand:PDPfp 1 ""))
107 (clobber (reg FCC_REGNUM))]
108 ""
109 [(set (reg:CC FCC_REGNUM)
110 (compare:CC (match_dup 1) (const_double_zero:PDPfp)))
111 (set (match_dup 0) (match_dup 1))])
112
113 (define_subst "fcc_ccnz"
114 [(set (match_operand:PDPfp 0 "") (match_operand:PDPfp 1 ""))
115 (clobber (reg FCC_REGNUM))]
116 ""
117 [(set (reg:CCNZ FCC_REGNUM)
118 (compare:CCNZ (match_dup 1) (const_double_zero:PDPfp)))
119 (set (match_dup 0) (match_dup 1))])
120
121 (define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
122 (define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc")
123 (define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc")
124 (define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc")
125
126 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
127
128 ;; Compare instructions.
129
130 ;; currently we only support df floats, which saves us quite some
131 ;; hassle switching the FP mode!
132 ;; we assume that CPU is always in long float mode, and
133 ;; 16 bit integer mode - currently, the prologue for main does this,
134 ;; but maybe we should just set up a NEW crt0 properly,
135 ;; -- and what about signal handling code?
136 ;; (we don't even let sf floats in the register file, so
137 ;; we only should have to worry about truncating and widening
138 ;; when going to memory)
139
140 ;; abort() call by g++ - must define libfunc for cmp_optab
141 ;; and ucmp_optab for mode SImode, because we don't have that!!!
142 ;; - yet since no libfunc is there, we abort ()
143
144 ;; define attributes
145 ;; currently type is only fpu or arith or unknown, maybe branch later ?
146 ;; default is arith
147 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
148
149 ;; length default is 2 bytes each
150 (define_attr "length" "" (const_int 2))
151
152 ;; instruction base cost (not counting operands)
153 (define_attr "base_cost" "" (const_int 2))
154
155 ;; a user's asm statement
156 (define_asm_attributes
157 [(set_attr "type" "unknown")
158 ; length for asm is the max length per statement. That would be
159 ; 3 words, for a two-operand instruction with extra word addressing
160 ; modes for both operands.
161 (set_attr "length" "6")])
162
163 ;; define function units
164
165 ;; Prologue and epilogue support.
166
167 (define_expand "prologue"
168 [(const_int 0)]
169 ""
170 {
171 pdp11_expand_prologue ();
172 DONE;
173 })
174
175 (define_expand "epilogue"
176 [(const_int 0)]
177 ""
178 {
179 pdp11_expand_epilogue ();
180 DONE;
181 })
182
183 (define_insn "rtspc"
184 [(return)]
185 ""
186 "rts\tpc")
187
188 (define_insn "blockage"
189 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
190 ""
191 ""
192 [(set_attr "length" "0")])
193
194 (define_insn "setd"
195 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
196 ""
197 "setd")
198
199 (define_insn "seti"
200 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
201 ""
202 "seti")
203
204 ;; arithmetic - values here immediately when next insn issued
205 ;; or does it mean the number of cycles after this insn was issued?
206 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
207
208 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
209 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
210
211 ;; compare
212 (define_insn "*cmpdf"
213 [(set (reg:CC FCC_REGNUM)
214 (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
215 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
216 "TARGET_FPU && reload_completed"
217 "*
218 {
219 if (which_alternative == 0 || which_alternative == 2)
220 return \"{tstd|tstf}\t%0\";
221 else
222 return \"{cmpd|cmpf}\t%0,%1\";
223 }"
224 [(set_attr "length" "2,2,4,4")
225 (set_attr "base_cost" "4")
226 (set_attr "type" "fp")])
227
228 ;; Copy floating point processor condition code register to main CPU
229 ;; condition code register.
230 (define_insn "*cfcc"
231 [(set (reg CC_REGNUM) (reg FCC_REGNUM))]
232 "TARGET_FPU && reload_completed"
233 "cfcc")
234
235 (define_insn "cmp<mode>"
236 [(set (reg:CC CC_REGNUM)
237 (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
238 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
239 ""
240 "@
241 tst<PDPint:isfx>\t%0
242 cmp<PDPint:isfx>\t%0,%1
243 cmp<PDPint:isfx>\t%0,%1
244 tst<PDPint:isfx>\t%0
245 cmp<PDPint:isfx>\t%0,%1
246 cmp<PDPint:isfx>\t%0,%1"
247 [(set_attr "length" "2,2,4,4,4,6")])
248
249 ;; Two word compare
250 (define_insn "cmpsi"
251 [(set (reg:CC CC_REGNUM)
252 (compare:CC (match_operand:SI 0 "general_operand" "rDQi")
253 (match_operand:SI 1 "general_operand" "rDQi")))]
254 ""
255 {
256 rtx inops[2];
257 rtx exops[2][2];
258 rtx lb[1];
259
260 inops[0] = operands[0];
261 inops[1] = operands[1];
262 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
263 lb[0] = gen_label_rtx ();
264
265 if (CONST_INT_P (exops[0][1]) && INTVAL (exops[0][1]) == 0)
266 output_asm_insn ("tst\t%0", exops[0]);
267 else
268 output_asm_insn ("cmp\t%0,%1", exops[0]);
269 output_asm_insn ("bne\t%l0", lb);
270 if (CONST_INT_P (exops[1][1]) && INTVAL (exops[1][1]) == 0)
271 output_asm_insn ("tst\t%0", exops[1]);
272 else
273 output_asm_insn ("cmp\t%0,%1", exops[1]);
274 output_asm_label (lb[0]);
275 fputs (":\n", asm_out_file);
276
277 return "";
278 }
279 [(set (attr "length")
280 (symbol_ref "pdp11_cmp_length (operands, 2)"))
281 (set_attr "base_cost" "0")])
282
283 ;; Four word compare
284 (define_insn "cmpdi"
285 [(set (reg:CC CC_REGNUM)
286 (compare:CC (match_operand:DI 0 "general_operand" "rDQi")
287 (match_operand:DI 1 "general_operand" "rDQi")))]
288 ""
289 {
290 rtx inops[4];
291 rtx exops[4][2];
292 rtx lb[1];
293 int i;
294
295 inops[0] = operands[0];
296 inops[1] = operands[1];
297 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
298 lb[0] = gen_label_rtx ();
299
300 for (i = 0; i < 3; i++)
301 {
302 if (CONST_INT_P (exops[i][1]) && INTVAL (exops[i][1]) == 0)
303 output_asm_insn ("tst\t%0", exops[i]);
304 else
305 output_asm_insn ("cmp\t%0,%1", exops[i]);
306 output_asm_insn ("bne\t%l0", lb);
307 }
308 if (CONST_INT_P (exops[3][1]) && INTVAL (exops[3][1]) == 0)
309 output_asm_insn ("tst\t%0", exops[3]);
310 else
311 output_asm_insn ("cmp\t%0,%1", exops[3]);
312 output_asm_label (lb[0]);
313 fputs (":\n", asm_out_file);
314
315 return "";
316 }
317 [(set (attr "length")
318 (symbol_ref "pdp11_cmp_length (operands, 2)"))
319 (set_attr "base_cost" "0")])
320
321 ;; sob instruction
322 ;;
323 ;; This expander has to check for mode match because the doloop pass
324 ;; in gcc that invokes it does not do so, i.e., it may attempt to apply
325 ;; this pattern even if the count operand is QI or SI mode.
326 (define_expand "doloop_end"
327 [(parallel [(set (pc)
328 (if_then_else
329 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
330 (const_int 1))
331 (label_ref (match_operand 1 "" ""))
332 (pc)))
333 (set (match_dup 0)
334 (plus:HI (match_dup 0)
335 (const_int -1)))])]
336 "TARGET_40_PLUS"
337 "{
338 if (GET_MODE (operands[0]) != HImode)
339 FAIL;
340 }")
341
342 ;; Do a define_split because some alternatives clobber CC.
343 ;; Some don't, but it isn't all that interesting to cover that case.
344 (define_insn_and_split "doloop_end_insn"
345 [(set (pc)
346 (if_then_else
347 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
348 (const_int 1))
349 (label_ref (match_operand 1 "" ""))
350 (pc)))
351 (set (match_dup 0)
352 (plus:HI (match_dup 0)
353 (const_int -1)))]
354 "TARGET_40_PLUS"
355 "#"
356 "&& reload_completed"
357 [(parallel [(set (pc)
358 (if_then_else
359 (ne (match_dup 0) (const_int 1))
360 (label_ref (match_dup 1))
361 (pc)))
362 (set (match_dup 0)
363 (plus:HI (match_dup 0)
364 (const_int -1)))
365 (clobber (reg:CC CC_REGNUM))])]
366 "")
367
368 ;; Note that there is a memory alternative here. This is as documented
369 ;; in gccint, which says that doloop_end, since it has both a jump and
370 ;; an output interrupt "must handle its own reloads". That translates
371 ;; to: must accept memory operands as valid though they may be deprecated.
372 (define_insn "doloop_end_nocc"
373 [(set (pc)
374 (if_then_else
375 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
376 (const_int 1))
377 (label_ref (match_operand 1 "" ""))
378 (pc)))
379 (set (match_dup 0)
380 (plus:HI (match_dup 0)
381 (const_int -1)))
382 (clobber (reg:CC CC_REGNUM))]
383 "TARGET_40_PLUS && reload_completed"
384 "*
385 {
386 rtx lb[1];
387
388 if (get_attr_length (insn) == 2)
389 return \"sob\t%0,%l1\";
390
391 /* emulate sob */
392 lb[0] = gen_label_rtx ();
393 output_asm_insn (\"dec\t%0\", operands);
394 output_asm_insn (\"beq\t%l0\", lb);
395 output_asm_insn (\"jmp\t%l1\", operands);
396
397 output_asm_label (lb[0]);
398 fputs (\":\\n\", asm_out_file);
399
400 return \"\";
401 }"
402 [(set (attr "length")
403 (if_then_else (eq (symbol_ref ("which_alternative")) (const_int 1))
404 (const_int 10)
405 (if_then_else (ior (lt (minus (match_dup 1) (pc))
406 (const_int MIN_SOB))
407 (gt (minus (match_dup 1) (pc))
408 (const_int MAX_SOB)))
409 (const_int 8)
410 (const_int 2))))])
411
412 ;; These control RTL generation for conditional jump insns
413 ;; and match them for register allocation.
414 ;; Post reload these get expanded into insns that actually
415 ;; manipulate the condition code registers. We can't do that before
416 ;; because instructions generated by reload clobber condition codes (new
417 ;; CC design, type #2).
418 (define_insn_and_split "cbranchdf4"
419 [(set (pc)
420 (if_then_else (match_operator 0 "ordered_comparison_operator"
421 [(match_operand:DF 1 "general_operand" "fg")
422 (match_operand:DF 2 "general_operand" "a")])
423 (label_ref (match_operand 3 "" ""))
424 (pc)))]
425 "TARGET_FPU"
426 "#"
427 "&& reload_completed"
428 [(set (reg:CC FCC_REGNUM)
429 (compare:CC (match_dup 1) (match_dup 2)))
430 (set (pc)
431 (if_then_else (match_op_dup 0
432 [(reg:CC FCC_REGNUM) (const_int 0)])
433 (label_ref (match_dup 3))
434 (pc)))]
435 "")
436
437 (define_insn_and_split "cbranch<mode>4"
438 [(set (pc)
439 (if_then_else (match_operator 0 "ordered_comparison_operator"
440 [(match_operand:QHSDint 1 "general_operand" "g")
441 (match_operand:QHSDint 2 "general_operand" "g")])
442 (label_ref (match_operand 3 "" ""))
443 (pc)))]
444 ""
445 "#"
446 "reload_completed"
447 [(set (reg:CC CC_REGNUM)
448 (compare:CC (match_dup 1) (match_dup 2)))
449 (set (pc)
450 (if_then_else (match_op_dup 0
451 [(reg:CC CC_REGNUM) (const_int 0)])
452 (label_ref (match_dup 3))
453 (pc)))]
454 "")
455
456 ;; This splitter turns a branch on float condition into a branch on
457 ;; CPU condition, by adding a CFCC.
458 (define_split
459 [(set (pc)
460 (if_then_else (match_operator 0 "ordered_comparison_operator"
461 [(reg:CC FCC_REGNUM) (const_int 0)])
462 (label_ref (match_operand 1 "" ""))
463 (pc)))]
464 "TARGET_FPU && reload_completed"
465 [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM))
466 (set (pc)
467 (if_then_else (match_op_dup 0
468 [(reg:CC CC_REGNUM) (const_int 0)])
469 (label_ref (match_dup 1))
470 (pc)))]
471 "")
472
473 (define_insn "cond_branch"
474 [(set (pc)
475 (if_then_else (match_operator 0 "ordered_comparison_operator"
476 [(reg:CC CC_REGNUM) (const_int 0)])
477 (label_ref (match_operand 1 "" ""))
478 (pc)))]
479 "reload_completed"
480 "* return output_jump (operands, 0, get_attr_length (insn));"
481 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
482 (pc))
483 (const_int MIN_BRANCH))
484 (gt (minus (match_dup 1)
485 (pc))
486 (const_int MAX_BRANCH)))
487 (const_int 6)
488 (const_int 2)))])
489
490 (define_insn "*branch"
491 [(set (pc)
492 (if_then_else (match_operator 0 "ccnz_operator"
493 [(reg:CCNZ CC_REGNUM) (const_int 0)])
494 (label_ref (match_operand 1 "" ""))
495 (pc)))]
496 "reload_completed"
497 "* return output_jump (operands, 1, get_attr_length (insn));"
498 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
499 (pc))
500 (const_int MIN_BRANCH))
501 (gt (minus (match_dup 1)
502 (pc))
503 (const_int MAX_BRANCH)))
504 (const_int 6)
505 (const_int 2)))])
506
507 \f
508 ;; Move instructions
509
510 ;; "length" is defined even though this pattern won't appear at
511 ;; assembly language output time. But the length is used by
512 ;; pdp11_insn_cost, before the post-reload splitter adds the
513 ;; CC clobber to the insn.
514 (define_insn "movdi"
515 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
516 (match_operand:DI 1 "general_operand" "rN,g"))]
517 ""
518 ""
519 [(set_attr "length" "16,32")])
520
521
522 (define_insn "*movdi_nocc"
523 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
524 (match_operand:DI 1 "general_operand" "rN,g"))
525 (clobber (reg:CC CC_REGNUM))]
526 ""
527 "* return output_move_multiple (operands);"
528 [(set_attr "length" "16,32")])
529
530 (define_insn "movsi"
531 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
532 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
533 ""
534 ""
535 [(set_attr "length" "4,6,8,16")])
536
537 (define_insn "*movsi_nocc"
538 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
539 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))
540 (clobber (reg:CC CC_REGNUM))]
541 ""
542 "* return output_move_multiple (operands);"
543 [(set_attr "length" "4,6,8,16")])
544
545 ;; That long string of "Z" constraints enforces the restriction that
546 ;; a register source and auto increment or decrement destination must
547 ;; not use the same register, because that case is not consistently
548 ;; implemented across the PDP11 models.
549 ;; TODO: the same should be applied to insn like add, but this is not
550 ;; necessary yet because the incdec optimization pass does not apply
551 ;; that optimization to 3-operand insns at the moment.
552 (define_insn "mov<mode>"
553 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
554 (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))]
555 ""
556 ""
557 [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
558
559 ;; This splits all the integer moves: DI and SI modes as well as
560 ;; the simple machine operations.
561 (define_split
562 [(set (match_operand:QHSDint 0 "nonimmediate_operand" "")
563 (match_operand:QHSDint 1 "general_operand" ""))]
564 "reload_completed"
565 [(parallel [(set (match_dup 0)
566 (match_dup 1))
567 (clobber (reg:CC CC_REGNUM))])]
568 "")
569
570 ;; MOV clears V
571 (define_insn "*mov<mode>_<cc_cc>"
572 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
573 (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))
574 (clobber (reg:CC CC_REGNUM))]
575 "reload_completed"
576 "*
577 {
578 if (operands[1] == const0_rtx)
579 return \"clr<PDPint:isfx>\t%0\";
580
581 return \"mov<PDPint:isfx>\t%1,%0\";
582 }"
583 [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
584
585 ;; movdf has unusually complicated condition code handling, because
586 ;; load (into float register) updates the FCC, while store (from
587 ;; float register) leaves it untouched.
588 ;;
589 ;; 1. Loads are: ac4, ac5, or non-register into load-register
590 ;; 2. Stores are: load-register to non-register, ac4, or ac5
591 ;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled
592 ;; either as loads or as stores.
593
594 (define_expand "movdf"
595 [(set (match_operand:DF 0 "float_nonimm_operand" "")
596 (match_operand:DF 1 "float_operand" ""))]
597 "TARGET_FPU"
598 "")
599
600 ;; Splitter for all these cases. Store is the first two
601 ;; alternatives, which are not split. Note that case 3
602 ;; is treated as a store, i.e., not split.
603 (define_insn_and_split "movdf_split"
604 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,FQ,a,a,a")
605 (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))]
606 "TARGET_FPU"
607 "*
608 gcc_assert (which_alternative < 2);
609 return \"std\t%1,%0\";
610 "
611 "&& reload_completed"
612 [(parallel [(set (match_dup 0)
613 (match_dup 1))
614 (clobber (reg:CC FCC_REGNUM))])]
615 "{
616 if (GET_CODE (operands[1]) == REG &&
617 REGNO_REG_CLASS (REGNO (operands[1])) == LOAD_FPU_REGS)
618 FAIL;
619 }"
620 [(set_attr "length" "2,4,0,0,0")])
621
622 ;; Loads (case 1).
623 (define_insn "*ldd<fcc_cc>"
624 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,a,a")
625 (match_operand:DF 1 "float_operand" "hR,FQ,G"))
626 (clobber (reg:CC FCC_REGNUM))]
627 "TARGET_FPU && reload_completed"
628 "@
629 ldd\t%1,%0
630 ldd\t%1,%0
631 clrd\t%0"
632 [(set_attr "length" "2,4,2")])
633
634 ;; SFmode is easier because that uses convert load/store, which
635 ;; always change condition codes.
636 ;; Note that these insns are cheating a bit. We actually have
637 ;; DFmode operands in the FPU registers, which is why the
638 ;; ldcfd and stcdf instructions appear. But GCC likes to think
639 ;; of these as SFmode loads and does the conversion once in the
640 ;; register, at least in many cases. So we pretend to do this,
641 ;; but then extend and truncate register-to-register are NOP and
642 ;; generate no code.
643 (define_insn_and_split "movsf"
644 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
645 (match_operand:SF 1 "float_operand" "fRG,a,FQ,a,G"))]
646 "TARGET_FPU"
647 "#"
648 "&& reload_completed"
649 [(parallel [(set (match_dup 0)
650 (match_dup 1))
651 (clobber (reg:CC FCC_REGNUM))])]
652 ""
653 [(set_attr "length" "2,2,4,4,2")])
654
655 (define_insn "*movsf<fcc_ccnz>"
656 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
657 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G"))
658 (clobber (reg:CC FCC_REGNUM))]
659 "TARGET_FPU && reload_completed"
660 "@
661 {ldcfd|movof}\t%1,%0
662 {stcdf|movfo}\t%1,%0
663 {ldcfd|movof}\t%1,%0
664 {stcdf|movfo}\t%1,%0
665 clrf\t%0"
666 [(set_attr "length" "2,2,4,4,2")])
667
668 ;; Expand a block move. We turn this into a move loop.
669 (define_expand "cpymemhi"
670 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
671 (match_operand:BLK 0 "general_operand" "=g")
672 (match_operand:BLK 1 "general_operand" "g")
673 (match_operand:HI 2 "immediate_operand" "i")
674 (match_operand:HI 3 "immediate_operand" "i")
675 (clobber (mem:BLK (scratch)))
676 (clobber (match_dup 0))
677 (clobber (match_dup 1))
678 (clobber (match_dup 2))])]
679 ""
680 "
681 {
682 int count;
683 count = INTVAL (operands[2]);
684 if (count == 0)
685 DONE;
686 if (INTVAL (operands [3]) >= 2 && (count & 1) == 0)
687 count >>= 1;
688 else
689 operands[3] = const1_rtx;
690 operands[2] = copy_to_mode_reg (HImode,
691 gen_rtx_CONST_INT (HImode, count));
692
693 /* Load BLKmode MEM addresses into scratch registers. */
694 operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
695 operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
696 }")
697
698 ;; Expand a block move. We turn this into a move loop.
699 (define_insn_and_split "cpymemhi1"
700 [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
701 (match_operand:HI 0 "register_operand" "+r")
702 (match_operand:HI 1 "register_operand" "+r")
703 (match_operand:HI 2 "register_operand" "+r")
704 (match_operand:HI 3 "immediate_operand" "i")
705 (clobber (mem:BLK (scratch)))
706 (clobber (match_dup 0))
707 (clobber (match_dup 1))
708 (clobber (match_dup 2))]
709 ""
710 "#"
711 "reload_completed"
712 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
713 (match_dup 0)
714 (match_dup 1)
715 (match_dup 2)
716 (match_dup 3)
717 (clobber (mem:BLK (scratch)))
718 (clobber (match_dup 0))
719 (clobber (match_dup 1))
720 (clobber (match_dup 2))
721 (clobber (reg:CC CC_REGNUM))])]
722 "")
723
724 (define_insn "cpymemhi_nocc"
725 [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
726 (match_operand:HI 0 "register_operand" "+r")
727 (match_operand:HI 1 "register_operand" "+r")
728 (match_operand:HI 2 "register_operand" "+r")
729 (match_operand:HI 3 "immediate_operand" "i")
730 (clobber (mem:BLK (scratch)))
731 (clobber (match_dup 0))
732 (clobber (match_dup 1))
733 (clobber (match_dup 2))
734 (clobber (reg:CC CC_REGNUM))]
735 "reload_completed"
736 "*
737 {
738 rtx lb[2];
739
740 lb[0] = operands[2];
741 lb[1] = gen_label_rtx ();
742
743 output_asm_label (lb[1]);
744 fputs (\":\n\", asm_out_file);
745 if (INTVAL (operands[3]) > 1)
746 output_asm_insn (\"mov\t(%1)+,(%0)+\", operands);
747 else
748 output_asm_insn (\"movb\t(%1)+,(%0)+\", operands);
749 if (TARGET_40_PLUS)
750 output_asm_insn (\"sob\t%0,%l1\", lb);
751 else
752 {
753 output_asm_insn (\"dec\t%0\", lb);
754 output_asm_insn (\"bne\t%l1\", lb);
755 }
756 return \"\";
757 }"
758 [(set (attr "length")
759 (if_then_else (match_test "TARGET_40_PLUS")
760 (const_int 4)
761 (const_int 6)))])
762 \f
763 ;;- truncation instructions
764
765 ;; We sometimes end up doing a register to register truncate,
766 ;; which isn't right because we actually load registers always
767 ;; with a DFmode value. But even with PROMOTE the compiler
768 ;; doesn't always get that (so we don't use it). That means
769 ;; a register to register truncate is a NOP.
770 (define_insn_and_split "truncdfsf2"
771 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
772 (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))]
773 "TARGET_FPU"
774 {
775 gcc_assert (which_alternative == 0);
776 return "";
777 }
778 "&& reload_completed"
779 [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1)))
780 (clobber (reg:CC FCC_REGNUM))])]
781 "{
782 if (GET_CODE (operands[0]) == REG &&
783 GET_CODE (operands[1]) == REG &&
784 REGNO (operands[0]) == REGNO (operands[1]))
785 FAIL;
786 }"
787 [(set_attr "length" "0,0,0")])
788
789 (define_insn "*truncdfsf2_<fcc_cc>"
790 [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q")
791 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a")))
792 (clobber (reg:CC FCC_REGNUM))]
793 "TARGET_FPU && reload_completed"
794 "{stcdf|movfo}\t%1,%0"
795 [(set_attr "length" "2,4")])
796
797 \f
798 ;;- zero extension instruction
799
800 (define_insn_and_split "zero_extendqihi2"
801 [(set (match_operand:HI 0 "nonimmediate_operand" "=rD,Q,&r,&r")
802 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0,rR,Q")))]
803 ""
804 "#"
805 "reload_completed"
806 [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
807 (clobber (reg:CC CC_REGNUM))])]
808 "{
809 rtx r;
810
811 if (!REG_P (operands[0]))
812 {
813 r = gen_rtx_MEM (QImode, operands[0]);
814 adjust_address (r, QImode, 1);
815 emit_move_insn (r, const0_rtx);
816 DONE;
817 }
818 else if (!REG_P (operands[1]) ||
819 REGNO (operands[0]) != REGNO (operands[1]))
820 {
821 /* Alternatives 2 and 3 */
822 emit_move_insn (operands[0], const0_rtx);
823 r = gen_rtx_REG (QImode, REGNO (operands[0]));
824 emit_insn (gen_iorqi3_nocc (r, r, operands[1]));
825 DONE;
826 }
827 }"
828 [(set_attr "length" "4,4,4,6")])
829
830 (define_insn "*zero_extendqihi2<cc_cc>"
831 [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
832 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))
833 (clobber (reg:CC CC_REGNUM))])]
834 "reload_completed"
835 "bic\t%#0177400,%0"
836 [(set_attr "length" "4,6")])
837
838 ;;- sign extension instructions
839
840 ;; We sometimes end up doing a register to register extend,
841 ;; which isn't right because we actually load registers always
842 ;; with a DFmode value. But even with PROMOTE the compiler
843 ;; doesn't always get that (so we don't use it). That means
844 ;; a register to register truncate is a NOP.
845 (define_insn_and_split "extendsfdf2"
846 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
847 (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))]
848 "TARGET_FPU"
849 {
850 gcc_assert (which_alternative == 0);
851 return "";
852 }
853 "&& reload_completed"
854 [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1)))
855 (clobber (reg:CC FCC_REGNUM))])]
856 "{
857 if (GET_CODE (operands[0]) == REG &&
858 GET_CODE (operands[1]) == REG &&
859 REGNO (operands[0]) == REGNO (operands[1]))
860 FAIL;
861 }"
862 [(set_attr "length" "0,0,0")])
863
864 (define_insn "*extendsfdf2_<fcc_cc>"
865 [(set (match_operand:DF 0 "register_operand" "=a,a")
866 (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q")))
867 (clobber (reg:CC FCC_REGNUM))]
868 "TARGET_FPU && reload_completed"
869 "{ldcfd|movof}\t%1,%0"
870 [(set_attr "length" "2,4")
871 (set_attr "base_cost" "6")])
872
873 ;; movb sign extends if destination is a register
874 (define_insn_and_split "extendqihi2"
875 [(set (match_operand:HI 0 "register_operand" "=r,r")
876 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
877 ""
878 "#"
879 "reload_completed"
880 [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
881 (clobber (reg:CC CC_REGNUM))])]
882 ""
883 [(set_attr "length" "2,4")])
884
885 ;; MOVB clears V
886 (define_insn "*extendqihi2<cc_cc>"
887 [(set (match_operand:HI 0 "register_operand" "=r,r")
888 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))
889 (clobber (reg:CC CC_REGNUM))]
890 "reload_completed"
891 "movb\t%1,%0"
892 [(set_attr "length" "2,4")])
893
894 (define_insn_and_split "extendhisi2"
895 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
896 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
897 "TARGET_40_PLUS"
898 "#"
899 "&& reload_completed"
900 [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
901 (clobber (reg:CC CC_REGNUM))])]
902 ""
903 [(set_attr "length" "10,6,6")])
904
905 (define_insn "*extendhisi2_nocc"
906 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
907 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))
908 (clobber (reg:CC CC_REGNUM))]
909 "TARGET_40_PLUS && reload_completed"
910 "*
911 {
912 rtx latehalf[2];
913
914 /* we don't want to mess with auto increment */
915
916 switch (which_alternative)
917 {
918 case 0:
919
920 latehalf[0] = operands[0];
921 operands[0] = adjust_address(operands[0], HImode, 2);
922
923 output_asm_insn(\"mov\t%1,%0\", operands);
924 output_asm_insn(\"sxt\t%0\", latehalf);
925
926 return \"\";
927
928 case 1:
929
930 /* - auto-decrement - right direction ;-) */
931 output_asm_insn(\"mov\t%1,%0\", operands);
932 output_asm_insn(\"sxt\t%0\", operands);
933
934 return \"\";
935
936 case 2:
937
938 /* make register pair available */
939 latehalf[0] = operands[0];
940 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
941
942 output_asm_insn(\"mov\t%1,%0\", operands);
943 output_asm_insn(\"sxt\t%0\", latehalf);
944
945 return \"\";
946
947 default:
948
949 gcc_unreachable ();
950 }
951 }"
952 [(set_attr "length" "10,6,6")])
953
954 ;; make float to int and vice versa
955 ;; assume that we are normally in double and integer mode -
956 ;; what do pdp library routines do to fpu mode ?
957
958 ;; Note: the hardware treats register source as
959 ;; a 16-bit (high order only) source, which isn't
960 ;; what we want. But we do need to support register
961 ;; dest because gcc asks for it.
962 (define_insn_and_split "floatsidf2"
963 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
964 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
965 "TARGET_FPU"
966 "#"
967 "&& reload_completed"
968 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
969 (clobber (reg:CC FCC_REGNUM))])]
970 ""
971 [(set_attr "length" "10,6,8")])
972
973 (define_insn "*floatsidf2<fcc_cc>"
974 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
975 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))
976 (clobber (reg:CC FCC_REGNUM))]
977 "TARGET_FPU && reload_completed"
978 "* if (which_alternative ==0)
979 {
980 rtx latehalf[2];
981
982 latehalf[0] = NULL;
983 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
984 output_asm_insn(\"mov\t%1,-(sp)\", latehalf);
985 output_asm_insn(\"mov\t%1,-(sp)\", operands);
986
987 output_asm_insn(\"setl\", operands);
988 output_asm_insn(\"{ldcld|movif}\t(sp)+,%0\", operands);
989 output_asm_insn(\"seti\", operands);
990 return \"\";
991 }
992 else
993 return \"setl\;{ldcld|movif}\t%1,%0\;seti\";
994 "
995 [(set_attr "length" "10,6,8")
996 (set_attr "base_cost" "12")])
997
998 (define_insn_and_split "floathidf2"
999 [(set (match_operand:DF 0 "register_operand" "=a,a")
1000 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
1001 "TARGET_FPU"
1002 "#"
1003 "&& reload_completed"
1004 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
1005 (clobber (reg:CC FCC_REGNUM))])]
1006 ""
1007 [(set_attr "length" "2,4")])
1008
1009 (define_insn "*floathidf2<fcc_cc>"
1010 [(set (match_operand:DF 0 "register_operand" "=a,a")
1011 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))
1012 (clobber (reg:CC FCC_REGNUM))]
1013 "TARGET_FPU && reload_completed"
1014 "{ldcid|movif}\t%1,%0"
1015 [(set_attr "length" "2,4")
1016 (set_attr "base_cost" "12")])
1017
1018 ;; cut float to int
1019
1020 ;; Note: the hardware treats register destination as
1021 ;; a 16-bit (high order only) destination, which isn't
1022 ;; what we want. But we do need to support register
1023 ;; dest because gcc asks for it.
1024 (define_insn_and_split "fix_truncdfsi2"
1025 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
1026 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
1027 "TARGET_FPU"
1028 "#"
1029 "&& reload_completed"
1030 [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1))))
1031 (clobber (reg:CC CC_REGNUM))
1032 (clobber (reg:CC FCC_REGNUM))])]
1033 ""
1034 [(set_attr "length" "10,6,8")])
1035
1036 ;; Note: this clobbers both sets of condition codes!
1037 (define_insn "*fix_truncdfsi2_nocc"
1038 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
1039 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))
1040 (clobber (reg:CC CC_REGNUM))
1041 (clobber (reg:CC FCC_REGNUM))]
1042 "TARGET_FPU && reload_completed"
1043 "* if (which_alternative ==0)
1044 {
1045 output_asm_insn(\"setl\", operands);
1046 output_asm_insn(\"{stcdl|movfi}\t%1,-(sp)\", operands);
1047 output_asm_insn(\"seti\", operands);
1048 output_asm_insn(\"mov\t(sp)+,%0\", operands);
1049 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1050 output_asm_insn(\"mov\t(sp)+,%0\", operands);
1051 return \"\";
1052 }
1053 else
1054 return \"setl\;{stcdl|movfi}\t%1,%0\;seti\";
1055 "
1056 [(set_attr "length" "10,6,8")
1057 (set_attr "base_cost" "12")])
1058
1059 (define_insn_and_split "fix_truncdfhi2"
1060 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1061 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
1062 "TARGET_FPU"
1063 "#"
1064 "&& reload_completed"
1065 [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1))))
1066 (clobber (reg:CC CC_REGNUM))
1067 (clobber (reg:CC FCC_REGNUM))])]
1068 ""
1069 [(set_attr "length" "2,4")])
1070
1071 ;; Note: this clobbers both sets of condition codes!
1072 (define_insn "*fix_truncdfhi2_nocc"
1073 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1074 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))
1075 (clobber (reg:CC CC_REGNUM))
1076 (clobber (reg:CC FCC_REGNUM))]
1077 "TARGET_FPU && reload_completed"
1078 "{stcdi|movfi}\t%1,%0"
1079 [(set_attr "length" "2,4")
1080 (set_attr "base_cost" "12")])
1081
1082 \f
1083 ;;- arithmetic instructions
1084 ;;- add instructions
1085
1086 (define_insn_and_split "adddf3"
1087 [(set (match_operand:DF 0 "register_operand" "=a,a")
1088 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
1089 (match_operand:DF 2 "general_operand" "fR,QF")))]
1090 "TARGET_FPU"
1091 "#"
1092 "&& reload_completed"
1093 [(parallel [(set (match_dup 0)
1094 (plus:DF (match_dup 1) (match_dup 2)))
1095 (clobber (reg:CC FCC_REGNUM))])]
1096 ""
1097 [(set_attr "length" "2,4")])
1098
1099 ;; Float add sets V if overflow from add
1100 (define_insn "*adddf3<fcc_ccnz>"
1101 [(set (match_operand:DF 0 "register_operand" "=a,a")
1102 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
1103 (match_operand:DF 2 "general_operand" "fR,QF")))
1104 (clobber (reg:CC FCC_REGNUM))]
1105 "TARGET_FPU && reload_completed"
1106 "{addd|addf}\t%2,%0"
1107 [(set_attr "length" "2,4")
1108 (set_attr "base_cost" "6")])
1109
1110 (define_insn_and_split "adddi3"
1111 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1112 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
1113 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1114 ""
1115 "#"
1116 "reload_completed"
1117 [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
1118 (clobber (reg:CC CC_REGNUM))])]
1119 ""
1120 [(set_attr "length" "20,28,40,48")])
1121
1122 (define_insn "*adddi3_nocc"
1123 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1124 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
1125 (match_operand:DI 2 "general_operand" "r,on,r,on")))
1126 (clobber (reg:CC CC_REGNUM))]
1127 "reload_completed"
1128 "*
1129 {
1130 rtx inops[2];
1131 rtx exops[4][2];
1132
1133 inops[0] = operands[0];
1134 inops[1] = operands[2];
1135 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
1136
1137 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1138 output_asm_insn (\"add\t%1,%0\", exops[0]);
1139 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1140 {
1141 output_asm_insn (\"add\t%1,%0\", exops[1]);
1142 output_asm_insn (\"adc\t%0\", exops[0]);
1143 }
1144 if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1145 {
1146 output_asm_insn (\"add\t%1,%0\", exops[2]);
1147 output_asm_insn (\"adc\t%0\", exops[1]);
1148 output_asm_insn (\"adc\t%0\", exops[0]);
1149 }
1150 if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1151 {
1152 output_asm_insn (\"add\t%1,%0\", exops[3]);
1153 output_asm_insn (\"adc\t%0\", exops[2]);
1154 output_asm_insn (\"adc\t%0\", exops[1]);
1155 output_asm_insn (\"adc\t%0\", exops[0]);
1156 }
1157
1158 return \"\";
1159 }"
1160 [(set_attr "length" "20,28,40,48")
1161 (set_attr "base_cost" "0")])
1162
1163 ;; Note that the register operand is not marked earlyclobber.
1164 ;; The reason is that SI values go in register pairs, so they
1165 ;; can't partially overlap. They can be either disjoint, or
1166 ;; source and destination can be equal. The latter case is
1167 ;; handled properly because of the ordering of the individual
1168 ;; instructions used. Specifically, carry from the low to the
1169 ;; high word is added at the end, so the adding of the high parts
1170 ;; will always used the original high part and not a high part
1171 ;; modified by carry (which would amount to double carry).
1172 (define_insn_and_split "addsi3"
1173 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1174 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1175 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1176 ""
1177 "#"
1178 "reload_completed"
1179 [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
1180 (clobber (reg:CC CC_REGNUM))])]
1181 ""
1182 [(set_attr "length" "6,10,12,16")])
1183
1184 (define_insn "*addsi3_nocc"
1185 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1186 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1187 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1188 (clobber (reg:CC CC_REGNUM))]
1189 "reload_completed"
1190 "*
1191 {
1192 rtx inops[2];
1193 rtx exops[2][2];
1194
1195 inops[0] = operands[0];
1196 inops[1] = operands[2];
1197 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
1198
1199 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1200 output_asm_insn (\"add\t%1,%0\", exops[0]);
1201 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1202 {
1203 output_asm_insn (\"add\t%1,%0\", exops[1]);
1204 output_asm_insn (\"adc\t%0\", exops[0]);
1205 }
1206
1207 return \"\";
1208 }"
1209 [(set_attr "length" "6,10,12,16")
1210 (set_attr "base_cost" "0")])
1211
1212 (define_insn_and_split "addhi3"
1213 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1214 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1215 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1216 ""
1217 "#"
1218 "reload_completed"
1219 [(parallel [(set (match_dup 0)
1220 (plus:HI (match_dup 1) (match_dup 2)))
1221 (clobber (reg:CC CC_REGNUM))])]
1222 ""
1223 [(set_attr "length" "2,4,4,6")])
1224
1225 ;; Add sets V if overflow from the add
1226 (define_insn "*addhi3<cc_ccnz>"
1227 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1228 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1229 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1230 (clobber (reg:CC CC_REGNUM))]
1231 "reload_completed"
1232 "*
1233 {
1234 if (GET_CODE (operands[2]) == CONST_INT)
1235 {
1236 if (INTVAL(operands[2]) == 1)
1237 return \"inc\t%0\";
1238 else if (INTVAL(operands[2]) == -1)
1239 return \"dec\t%0\";
1240 }
1241
1242 return \"add\t%2,%0\";
1243 }"
1244 [(set_attr "length" "2,4,4,6")])
1245
1246 (define_insn_and_split "addqi3"
1247 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1248 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1249 (match_operand:QI 2 "incdec_operand" "LM,LM")))]
1250 ""
1251 "#"
1252 "reload_completed"
1253 [(parallel [(set (match_dup 0)
1254 (plus:QI (match_dup 1) (match_dup 2)))
1255 (clobber (reg:CC CC_REGNUM))])]
1256 ""
1257 [(set_attr "length" "2,4")])
1258
1259 ;; Inc/dec sets V if overflow from the operation
1260 (define_insn "*addqi3<cc_ccnz>"
1261 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1262 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1263 (match_operand:QI 2 "incdec_operand" "LM,LM")))
1264 (clobber (reg:CC CC_REGNUM))]
1265 "reload_completed"
1266 "*
1267 {
1268 if (INTVAL(operands[2]) == 1)
1269 return \"incb\t%0\";
1270 else
1271 return \"decb\t%0\";
1272 }"
1273 [(set_attr "length" "2,4")])
1274
1275 \f
1276 ;;- subtract instructions
1277 ;; we don't have to care for constant second
1278 ;; args, since they are canonical plus:xx now!
1279 ;; also for minus:DF ??
1280
1281 (define_insn_and_split "subdf3"
1282 [(set (match_operand:DF 0 "register_operand" "=a,a")
1283 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1284 (match_operand:DF 2 "general_operand" "fR,Q")))]
1285 "TARGET_FPU"
1286 "#"
1287 "&& reload_completed"
1288 [(parallel [(set (match_dup 0)
1289 (minus:DF (match_dup 1) (match_dup 2)))
1290 (clobber (reg:CC FCC_REGNUM))])]
1291 ""
1292 [(set_attr "length" "2,4")])
1293
1294 (define_insn "*subdf3<fcc_ccnz>"
1295 [(set (match_operand:DF 0 "register_operand" "=a,a")
1296 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1297 (match_operand:DF 2 "general_operand" "fR,QF")))
1298 (clobber (reg:CC FCC_REGNUM))]
1299 "TARGET_FPU && reload_completed"
1300 "{subd|subf}\t%2,%0"
1301 [(set_attr "length" "2,4")
1302 (set_attr "base_cost" "6")])
1303
1304 (define_insn_and_split "subdi3"
1305 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1306 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1307 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1308 ""
1309 "#"
1310 "reload_completed"
1311 [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
1312 (clobber (reg:CC CC_REGNUM))])]
1313 ""
1314 [(set_attr "length" "20,28,40,48")])
1315
1316 (define_insn "*subdi3_nocc"
1317 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1318 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1319 (match_operand:DI 2 "general_operand" "r,on,r,on")))
1320 (clobber (reg:CC CC_REGNUM))]
1321 "reload_completed"
1322 "*
1323 {
1324 rtx inops[2];
1325 rtx exops[4][2];
1326
1327 inops[0] = operands[0];
1328 inops[1] = operands[2];
1329 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
1330
1331 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1332 output_asm_insn (\"sub\t%1,%0\", exops[0]);
1333 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1334 {
1335 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1336 output_asm_insn (\"sbc\t%0\", exops[0]);
1337 }
1338 if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1339 {
1340 output_asm_insn (\"sub\t%1,%0\", exops[2]);
1341 output_asm_insn (\"sbc\t%0\", exops[1]);
1342 output_asm_insn (\"sbc\t%0\", exops[0]);
1343 }
1344 if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1345 {
1346 output_asm_insn (\"sub\t%1,%0\", exops[3]);
1347 output_asm_insn (\"sbc\t%0\", exops[2]);
1348 output_asm_insn (\"sbc\t%0\", exops[1]);
1349 output_asm_insn (\"sbc\t%0\", exops[0]);
1350 }
1351
1352 return \"\";
1353 }"
1354 [(set_attr "length" "20,28,40,48")
1355 (set_attr "base_cost" "0")])
1356
1357 (define_insn_and_split "subsi3"
1358 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1359 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1360 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1361 ""
1362 "#"
1363 "reload_completed"
1364 [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1365 (clobber (reg:CC CC_REGNUM))])]
1366 ""
1367 [(set_attr "length" "6,10,12,16")])
1368
1369 (define_insn "*subsi3_nocc"
1370 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1371 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1372 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1373 (clobber (reg:CC CC_REGNUM))]
1374 "reload_completed"
1375 "*
1376 {
1377 rtx inops[2];
1378 rtx exops[2][2];
1379
1380 inops[0] = operands[0];
1381 inops[1] = operands[2];
1382 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
1383
1384 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1385 output_asm_insn (\"sub\t%1,%0\", exops[0]);
1386 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1387 {
1388 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1389 output_asm_insn (\"sbc\t%0\", exops[0]);
1390 }
1391
1392 return \"\";
1393 }"
1394 [(set_attr "length" "6,10,12,16")
1395 (set_attr "base_cost" "0")])
1396
1397 (define_insn_and_split "subhi3"
1398 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1399 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1400 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1401 ""
1402 "#"
1403 "reload_completed"
1404 [(parallel [(set (match_dup 0)
1405 (minus:HI (match_dup 1) (match_dup 2)))
1406 (clobber (reg:CC CC_REGNUM))])]
1407 ""
1408 [(set_attr "length" "2,4,4,6")])
1409
1410 ;; Note: the manual says that (minus m (const_int n)) is converted
1411 ;; to (plus m (const_int -n)) but that does not appear to be
1412 ;; the case when it's wrapped in a PARALLEL. So instead we handle
1413 ;; that case here, which is easy enough.
1414 (define_insn "*subhi3<cc_ccnz>"
1415 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1416 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1417 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1418 (clobber (reg:CC CC_REGNUM))]
1419 "reload_completed"
1420 "*
1421 {
1422 if (GET_CODE (operands[2]) == CONST_INT)
1423 {
1424 if (INTVAL(operands[2]) == 1)
1425 return \"dec\t%0\";
1426 else if (INTVAL(operands[2]) == -1)
1427 return \"inc\t%0\";
1428 }
1429
1430 return \"sub\t%2,%0\";
1431 }"
1432 [(set_attr "length" "2,4,4,6")])
1433
1434 (define_insn_and_split "subqi3"
1435 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1436 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1437 (match_operand:QI 2 "incdec_operand" "LM,LM")))]
1438 ""
1439 "#"
1440 "reload_completed"
1441 [(parallel [(set (match_dup 0)
1442 (plus:QI (match_dup 1) (match_dup 2)))
1443 (clobber (reg:CC CC_REGNUM))])]
1444 ""
1445 [(set_attr "length" "2,4")])
1446
1447 ;; Inc/dec sets V if overflow from the operation
1448 (define_insn "*subqi3<cc_ccnz>"
1449 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1450 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1451 (match_operand:QI 2 "incdec_operand" "LM,LM")))
1452 (clobber (reg:CC CC_REGNUM))]
1453 "reload_completed"
1454 "*
1455 {
1456 if (INTVAL(operands[2]) == -1)
1457 return \"incb\t%0\";
1458 else
1459 return \"decb\t%0\";
1460 }"
1461 [(set_attr "length" "2,4")])
1462
1463 ;;;;- and instructions
1464 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1465
1466 (define_expand "and<mode>3"
1467 [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
1468 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
1469 (match_operand:PDPint 2 "general_operand" "")))]
1470 ""
1471 "
1472 {
1473 rtx op1 = operands[1];
1474
1475 /* If there is a constant argument, complement that one.
1476 Similarly, if one of the inputs is the same as the output,
1477 complement the other input. */
1478 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
1479 rtx_equal_p (operands[0], operands[1]))
1480 {
1481 operands[1] = operands[2];
1482 operands[2] = op1;
1483 op1 = operands[1];
1484 }
1485
1486 if (CONST_INT_P (op1))
1487 operands[1] = GEN_INT (~INTVAL (op1));
1488 else
1489 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
1490 }"
1491 [(set_attr "length" "2,4,4,6")])
1492
1493 (define_insn_and_split "*bic<mode>"
1494 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1495 (and:PDPint
1496 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1497 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
1498 ""
1499 "#"
1500 "reload_completed"
1501 [(parallel [(set (match_dup 0)
1502 (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2)))
1503 (clobber (reg:CC CC_REGNUM))])]
1504 "")
1505
1506 (define_insn "*bic<mode><cc_cc>"
1507 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1508 (and:PDPint
1509 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1510 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))
1511 (clobber (reg:CC CC_REGNUM))]
1512 "reload_completed"
1513 "bic<PDPint:isfx>\t%1,%0"
1514 [(set_attr "length" "2,4,4,6")])
1515
1516 ;;- Bit set (inclusive or) instructions
1517 (define_insn_and_split "ior<mode>3"
1518 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1519 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1520 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
1521 ""
1522 "#"
1523 "reload_completed"
1524 [(parallel [(set (match_dup 0)
1525 (ior:PDPint (match_dup 1) (match_dup 2)))
1526 (clobber (reg:CC CC_REGNUM))])]
1527 ""
1528 [(set_attr "length" "2,4,4,6")])
1529
1530 (define_insn "ior<mode>3<cc_cc>"
1531 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1532 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1533 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))
1534 (clobber (reg:CC CC_REGNUM))]
1535 "reload_completed"
1536 "bis<PDPint:isfx>\t%2,%0"
1537 [(set_attr "length" "2,4,4,6")])
1538
1539 ;;- xor instructions
1540 (define_insn_and_split "xorhi3"
1541 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1542 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1543 (match_operand:HI 2 "register_operand" "r,r")))]
1544 "TARGET_40_PLUS"
1545 "#"
1546 "&& reload_completed"
1547 [(parallel [(set (match_dup 0)
1548 (xor:HI (match_dup 1) (match_dup 2)))
1549 (clobber (reg:CC CC_REGNUM))])]
1550 ""
1551 [(set_attr "length" "2,4")])
1552
1553 (define_insn "*xorhi3<cc_cc>"
1554 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1555 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1556 (match_operand:HI 2 "register_operand" "r,r")))
1557 (clobber (reg:CC CC_REGNUM))]
1558 "TARGET_40_PLUS && reload_completed"
1559 "xor\t%2,%0"
1560 [(set_attr "length" "2,4")])
1561
1562 ;;- one complement instructions
1563
1564 (define_insn_and_split "one_cmpl<mode>2"
1565 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1566 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1567 ""
1568 "#"
1569 "reload_completed"
1570 [(parallel [(set (match_dup 0)
1571 (not:PDPint (match_dup 1)))
1572 (clobber (reg:CC CC_REGNUM))])]
1573 ""
1574 [(set_attr "length" "2,4")])
1575
1576 (define_insn "*one_cmpl<mode>2<cc_cc>"
1577 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1578 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1579 (clobber (reg:CC CC_REGNUM))]
1580 "reload_completed"
1581 "com<PDPint:isfx>\t%0"
1582 [(set_attr "length" "2,4")])
1583
1584 ;;- arithmetic shift instructions
1585 ;;
1586 ;; There is a fair amount of complexity here because with -m10
1587 ;; (pdp-11/10, /20) we only have shift by one bit. Iterators are
1588 ;; used to reduce the amount of very similar code.
1589 ;;
1590 ;; First the insns used for small constant shifts.
1591 (define_insn_and_split "<code><mode>_sc"
1592 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1593 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1594 (match_operand:HI 2 "expand_shift_operand" "O,O")))]
1595 ""
1596 "#"
1597 "reload_completed"
1598 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1599 (clobber (reg:CC CC_REGNUM))])]
1600 ""
1601 [(set (attr "length")
1602 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1603 <CODE>, which_alternative == 0)"))
1604 (set_attr "base_cost" "0")])
1605
1606 (define_insn "<code><mode>_sc<cc_ccnz>"
1607 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rD,Q")
1608 (SHF:PDPint (match_operand:PDPint 1 "general_operand" "0,0")
1609 (match_operand:HI 2 "expand_shift_operand" "O,O")))
1610 (clobber (reg:CC CC_REGNUM))]
1611 "reload_completed"
1612 "* return pdp11_assemble_shift (operands, <PDPint:mname>, <CODE>);"
1613 [(set (attr "length")
1614 (symbol_ref "pdp11_shift_length (operands, <PDPint:mname>,
1615 <CODE>, which_alternative == 0)"))
1616 (set_attr "base_cost" "0")])
1617
1618 ;; This one comes only in clobber flavor.
1619 (define_insn "<code>si_sc_nocc"
1620 [(set (match_operand:SI 0 "nonimmediate_operand" "=rD,Q")
1621 (SHF:SI (match_operand:SI 1 "general_operand" "0,0")
1622 (match_operand:HI 2 "expand_shift_operand" "O,O")))
1623 (clobber (reg:CC CC_REGNUM))]
1624 "reload_completed"
1625 "* return pdp11_assemble_shift (operands, SImode, <CODE>);"
1626 [(set (attr "length")
1627 (symbol_ref "pdp11_shift_length (operands, SImode,
1628 <CODE>, which_alternative == 0)"))
1629 (set_attr "base_cost" "0")])
1630
1631 ;; Next, shifts that are done as a loop on base (11/10 class) machines.
1632 ;; This applies to shift counts too large to unroll, or variable shift
1633 ;; counts. The check for count <= 0 is done before we get here.
1634 (define_insn_and_split "<code><mode>_base"
1635 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1636 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1637 (match_operand:HI 2 "register_operand" "r,r")))
1638 (clobber (match_dup 2))]
1639 ""
1640 "#"
1641 "reload_completed"
1642 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1643 (clobber (match_dup 2))
1644 (clobber (reg:CC CC_REGNUM))])]
1645 ""
1646 [(set (attr "length")
1647 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1648 <CODE>, which_alternative == 0)"))
1649 (set_attr "base_cost" "0")])
1650
1651 (define_insn "<code><mode>_base_nocc"
1652 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1653 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1654 (match_operand:HI 2 "register_operand" "r,r")))
1655 (clobber (match_dup 2))
1656 (clobber (reg:CC CC_REGNUM))]
1657 "reload_completed"
1658 "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1659 [(set (attr "length")
1660 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1661 <CODE>, which_alternative == 0)"))
1662 (set_attr "base_cost" "0")])
1663
1664 ;; Next the insns that use the extended instructions ash and ashc.
1665 ;; Note that these are just left shifts, and HI/SI only. (Right shifts
1666 ;; are done by shifting by a negative amount.)
1667 (define_insn_and_split "aslhi_op"
1668 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1669 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1670 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1671 "TARGET_40_PLUS"
1672 "#"
1673 "&& reload_completed"
1674 [(parallel [(set (match_dup 0)
1675 (ashift:HI (match_dup 1) (match_dup 2)))
1676 (clobber (reg:CC CC_REGNUM))])]
1677 ""
1678 [(set_attr "length" "2,4")
1679 (set_attr "base_cost" "8")])
1680
1681 (define_insn "aslhi_op<cc_ccnz>"
1682 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1683 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1684 (match_operand:HI 2 "general_operand" "rR,Qi")))
1685 (clobber (reg:CC CC_REGNUM))]
1686 "TARGET_40_PLUS && reload_completed"
1687 "ash\t%2,%0"
1688 [(set_attr "length" "2,4")
1689 (set_attr "base_cost" "8")])
1690
1691 (define_insn_and_split "aslsi_op"
1692 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1693 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1694 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1695 "TARGET_40_PLUS"
1696 "#"
1697 "&& reload_completed"
1698 [(parallel [(set (match_dup 0)
1699 (ashift:SI (match_dup 1) (match_dup 2)))
1700 (clobber (reg:CC CC_REGNUM))])]
1701 ""
1702 [(set_attr "length" "2,4")
1703 (set_attr "base_cost" "8")])
1704
1705 (define_insn "aslsi_op_<cc_ccnz>"
1706 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1707 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1708 (match_operand:HI 2 "general_operand" "rR,Qi")))
1709 (clobber (reg:CC CC_REGNUM))]
1710 "TARGET_40_PLUS && reload_completed"
1711 "ashc\t%2,%0"
1712 [(set_attr "length" "2,4")
1713 (set_attr "base_cost" "8")])
1714
1715 ;; Now the expanders that produce the insns defined above.
1716 (define_expand "ashl<mode>3"
1717 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1718 (match_operand:QHSint 1 "general_operand" "")
1719 (match_operand:HI 2 "general_operand" "")]
1720 ""
1721 "
1722 {
1723 rtx r;
1724
1725 if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base))
1726 {
1727 if (<QHSint:e_mname> == E_QImode)
1728 {
1729 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1730 emit_insn (gen_aslhi_op (r, r, operands[2]));
1731 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1732 }
1733 else
1734 {
1735 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1736 }
1737 }
1738 DONE;
1739 }")
1740
1741 (define_expand "ashr<mode>3"
1742 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1743 (match_operand:QHSint 1 "general_operand" "")
1744 (match_operand:HI 2 "general_operand" "")]
1745 ""
1746 "
1747 {
1748 rtx r;
1749
1750 if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base))
1751 {
1752 operands[2] = negate_rtx (HImode, operands[2]);
1753 if (<QHSint:e_mname> == E_QImode)
1754 {
1755 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1756 emit_insn (gen_aslhi_op (r, r, operands[2]));
1757 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1758 }
1759 else
1760 {
1761 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1762 }
1763 }
1764 DONE;
1765 }")
1766
1767 (define_expand "lshr<mode>3"
1768 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1769 (match_operand:QHSint 1 "general_operand" "")
1770 (match_operand:HI 2 "general_operand" "")]
1771 ""
1772 "
1773 {
1774 rtx r, n;
1775
1776 if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base))
1777 {
1778 if (<QHSint:e_mname> == E_QImode)
1779 {
1780 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1781 emit_insn (gen_aslhi_op (r, r, operands[2]));
1782 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1783 }
1784 else
1785 {
1786 r = gen_reg_rtx (<QHSint:mname>);
1787 emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx));
1788 if (GET_CODE (operands[2]) != CONST_INT)
1789 {
1790 n = gen_reg_rtx (HImode);
1791 emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1)));
1792 emit_insn (gen_ashr<mode>3 (operands[0], r, n));
1793 }
1794 else
1795 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r,
1796 GEN_INT (1 - INTVAL (operands[2]))));
1797 }
1798 }
1799 DONE;
1800 }")
1801
1802 ;; absolute
1803
1804 (define_insn_and_split "absdf2"
1805 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1806 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1807 "TARGET_FPU"
1808 "#"
1809 "&& reload_completed"
1810 [(parallel [(set (match_dup 0) (abs:DF (match_dup 1)))
1811 (clobber (reg:CC FCC_REGNUM))])]
1812 ""
1813 [(set_attr "length" "2,4")])
1814
1815 (define_insn "absdf2<fcc_cc>"
1816 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1817 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))
1818 (clobber (reg:CC FCC_REGNUM))]
1819 "TARGET_FPU && reload_completed"
1820 "{absd|absf}\t%0"
1821 [(set_attr "length" "2,4")])
1822
1823 ;; negate insns
1824
1825 (define_insn_and_split "negdf2"
1826 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1827 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
1828 "TARGET_FPU"
1829 "#"
1830 "&& reload_completed"
1831 [(parallel [(set (match_dup 0) (neg:DF (match_dup 1)))
1832 (clobber (reg:CC FCC_REGNUM))])]
1833 ""
1834 [(set_attr "length" "2,4")])
1835
1836 (define_insn "negdf2<fcc_cc>"
1837 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1838 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))
1839 (clobber (reg:CC FCC_REGNUM))]
1840 "TARGET_FPU && reload_completed"
1841 "{negd|negf}\t%0"
1842 [(set_attr "length" "2,4")])
1843
1844 (define_insn_and_split "negdi2"
1845 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1846 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1847 ""
1848 "#"
1849 "reload_completed"
1850 [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
1851 (clobber (reg:CC CC_REGNUM))])]
1852 ""
1853 [(set_attr "length" "18,34")])
1854
1855 ;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1856 (define_insn "negdi2_nocc"
1857 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1858 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))
1859 (clobber (reg:CC CC_REGNUM))]
1860 "reload_completed"
1861 {
1862 rtx inops[2];
1863 rtx exops[4][2];
1864
1865 inops[0] = operands[0];
1866 pdp11_expand_operands (inops, exops, 1, 4, NULL, big);
1867
1868 output_asm_insn (\"com\t%0\", exops[3]);
1869 output_asm_insn (\"com\t%0\", exops[2]);
1870 output_asm_insn (\"com\t%0\", exops[1]);
1871 output_asm_insn (\"com\t%0\", exops[0]);
1872 output_asm_insn (\"add\t%#1,%0\", exops[3]);
1873 output_asm_insn (\"adc\t%0\", exops[2]);
1874 output_asm_insn (\"adc\t%0\", exops[1]);
1875 output_asm_insn (\"adc\t%0\", exops[0]);
1876
1877 return \"\";
1878 }
1879 [(set_attr "length" "18,34")
1880 (set_attr "base_cost" "0")])
1881
1882 (define_insn_and_split "negsi2"
1883 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1884 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1885 ""
1886 "#"
1887 "reload_completed"
1888 [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
1889 (clobber (reg:CC CC_REGNUM))])]
1890 ""
1891 [(set_attr "length" "10,18")])
1892
1893 ;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1894 (define_insn "negsi2_nocc"
1895 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1896 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))
1897 (clobber (reg:CC CC_REGNUM))]
1898 "reload_completed"
1899 {
1900 rtx inops[2];
1901 rtx exops[4][2];
1902
1903 inops[0] = operands[0];
1904 pdp11_expand_operands (inops, exops, 1, 2, NULL, big);
1905
1906 output_asm_insn (\"com\t%0\", exops[1]);
1907 output_asm_insn (\"com\t%0\", exops[0]);
1908 output_asm_insn (\"add\t%#1,%0\", exops[1]);
1909 output_asm_insn (\"adc\t%0\", exops[0]);
1910
1911 return \"\";
1912 }
1913 [(set_attr "length" "10,18")
1914 (set_attr "base_cost" "0")])
1915
1916 (define_insn_and_split "neg<mode>2"
1917 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1918 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1919 ""
1920 "#"
1921 "reload_completed"
1922 [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1)))
1923 (clobber (reg:CC CC_REGNUM))])]
1924 ""
1925 [(set_attr "length" "2,4")])
1926
1927 (define_insn "neg<mode>2<cc_ccnz>"
1928 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1929 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1930 (clobber (reg:CC CC_REGNUM))]
1931 ""
1932 "neg<PDPint:isfx>\t%0"
1933 [(set_attr "length" "2,4")])
1934
1935
1936 ;; Unconditional and other jump instructions
1937 (define_insn "jump"
1938 [(set (pc)
1939 (label_ref (match_operand 0 "" "")))]
1940 ""
1941 "*
1942 {
1943 if (get_attr_length (insn) == 2)
1944 return \"br\t%l0\";
1945 return \"jmp\t%l0\";
1946 }"
1947 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1948 (pc))
1949 (const_int MIN_BRANCH))
1950 (gt (minus (match_dup 0)
1951 (pc))
1952 (const_int MAX_BRANCH)))
1953 (const_int 4)
1954 (const_int 2)))])
1955
1956 (define_insn "tablejump"
1957 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1958 (use (label_ref (match_operand 1 "" "")))]
1959 ""
1960 "@
1961 jmp\t(%0)
1962 jmp\t%@%0
1963 jmp\t%@%0"
1964 [(set_attr "length" "2,2,4")])
1965
1966 ;; indirect jump. TODO: this needs a constraint that allows memory
1967 ;; references but not indirection, since we add a level of indirection
1968 ;; in the generated code.
1969 (define_insn "indirect_jump"
1970 [(set (pc) (match_operand:HI 0 "general_operand" "r"))]
1971 ""
1972 "jmp\t@%0"
1973 [(set_attr "length" "2")])
1974
1975 ;;- jump to subroutine
1976
1977 (define_insn "call"
1978 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1979 (match_operand:HI 1 "general_operand" "g,g"))]
1980 ;;- Don't use operand 1 for most machines.
1981 ""
1982 "jsr\tpc,%0"
1983 [(set_attr "length" "2,4")])
1984
1985 ;;- jump to subroutine
1986 (define_insn "call_value"
1987 [(set (match_operand 0 "" "")
1988 (call (match_operand:HI 1 "general_operand" "rR,Q")
1989 (match_operand:HI 2 "general_operand" "g,g")))]
1990 ;;- Don't use operand 2 for most machines.
1991 ""
1992 "jsr\tpc,%1"
1993 [(set_attr "length" "2,4")])
1994
1995 (define_expand "untyped_call"
1996 [(parallel [(call (match_operand 0 "" "")
1997 (const_int 0))
1998 (match_operand 1 "" "")
1999 (match_operand 2 "" "")])]
2000 ""
2001 {
2002 int i;
2003
2004 emit_call_insn (gen_call (operands[0], const0_rtx));
2005
2006 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2007 {
2008 rtx set = XVECEXP (operands[2], 0, i);
2009 emit_move_insn (SET_DEST (set), SET_SRC (set));
2010 }
2011
2012 /* The optimizer does not know that the call sets the function value
2013 registers we stored in the result block. We avoid problems by
2014 claiming that all hard registers are used and clobbered at this
2015 point. */
2016 emit_insn (gen_blockage ());
2017
2018 DONE;
2019 })
2020
2021 ;;- nop instruction
2022 (define_insn "nop"
2023 [(const_int 0)]
2024 ""
2025 "nop")
2026 \f
2027
2028 ;;- multiply
2029
2030 (define_insn_and_split "muldf3"
2031 [(set (match_operand:DF 0 "register_operand" "=a,a")
2032 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
2033 (match_operand:DF 2 "float_operand" "fR,QF")))]
2034 "TARGET_FPU"
2035 "#"
2036 "&& reload_completed"
2037 [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2)))
2038 (clobber (reg:CC FCC_REGNUM))])]
2039 ""
2040 [(set_attr "length" "2,4")])
2041
2042 (define_insn "muldf3<fcc_ccnz>"
2043 [(set (match_operand:DF 0 "register_operand" "=a,a")
2044 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
2045 (match_operand:DF 2 "float_operand" "fR,QF")))
2046 (clobber (reg:CC FCC_REGNUM))]
2047 "TARGET_FPU && reload_completed"
2048 "{muld|mulf}\t%2,%0"
2049 [(set_attr "length" "2,4")
2050 (set_attr "base_cost" "20")])
2051
2052 ;; 16 bit result multiply. This uses odd numbered registers.
2053
2054 (define_insn_and_split "mulhi3"
2055 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
2056 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2057 (match_operand:HI 2 "general_operand" "rR,Qi")))]
2058 "TARGET_40_PLUS"
2059 "#"
2060 "&& reload_completed"
2061 [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2)))
2062 (clobber (reg:CC CC_REGNUM))])]
2063 ""
2064 [(set_attr "length" "2,4")])
2065
2066 (define_insn "mulhi3<cc_cc>"
2067 [(set (match_operand:HI 0 "register_operand" "=d,d")
2068 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2069 (match_operand:HI 2 "general_operand" "rR,Qi")))
2070 (clobber (reg:CC CC_REGNUM))]
2071 "TARGET_40_PLUS && reload_completed"
2072 "mul\t%2,%0"
2073 [(set_attr "length" "2,4")
2074 (set_attr "base_cost" "20")])
2075
2076 ;; 32 bit result from 16 bit operands
2077 (define_insn_and_split "mulhisi3"
2078 [(set (match_operand:SI 0 "register_operand" "=r,r")
2079 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
2080 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))]
2081 "TARGET_40_PLUS"
2082 "#"
2083 "&& reload_completed"
2084 [(parallel [(set (match_dup 0)
2085 (mult:SI (sign_extend:SI (match_dup 1))
2086 (sign_extend:SI (match_dup 2))))
2087 (clobber (reg:CC CC_REGNUM))])]
2088 ""
2089 [(set_attr "length" "2,4")])
2090
2091 (define_insn "mulhisi3<cc_cc>"
2092 [(set (match_operand:SI 0 "register_operand" "=r,r")
2093 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
2094 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))
2095 (clobber (reg:CC CC_REGNUM))]
2096 "TARGET_40_PLUS && reload_completed"
2097 "mul\t%2,%0"
2098 [(set_attr "length" "2,4")
2099 (set_attr "base_cost" "20")])
2100
2101 ;;- divide
2102 (define_insn_and_split "divdf3"
2103 [(set (match_operand:DF 0 "register_operand" "=a,a")
2104 (div:DF (match_operand:DF 1 "register_operand" "0,0")
2105 (match_operand:DF 2 "general_operand" "fR,QF")))]
2106 "TARGET_FPU"
2107 "#"
2108 "&& reload_completed"
2109 [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2)))
2110 (clobber (reg:CC FCC_REGNUM))])]
2111 ""
2112 [(set_attr "length" "2,4")])
2113
2114 (define_insn "divdf3<fcc_ccnz>"
2115 [(set (match_operand:DF 0 "register_operand" "=a,a")
2116 (div:DF (match_operand:DF 1 "register_operand" "0,0")
2117 (match_operand:DF 2 "general_operand" "fR,QF")))
2118 (clobber (reg:CC FCC_REGNUM))]
2119 "TARGET_FPU && reload_completed"
2120 "{divd|divf}\t%2,%0"
2121 [(set_attr "length" "2,4")
2122 (set_attr "base_cost" "20")])
2123
2124 (define_expand "divmodhi4"
2125 [(parallel
2126 [(set (subreg:HI (match_dup 1) 0)
2127 (div:HI (match_operand:SI 1 "register_operand" "0")
2128 (match_operand:HI 2 "general_operand" "g")))
2129 (set (subreg:HI (match_dup 1) 2)
2130 (mod:HI (match_dup 1) (match_dup 2)))])
2131 (set (match_operand:HI 0 "register_operand" "=r")
2132 (subreg:HI (match_dup 1) 0))
2133 (set (match_operand:HI 3 "register_operand" "=r")
2134 (subreg:HI (match_dup 1) 2))]
2135 "TARGET_40_PLUS"
2136 "")
2137
2138 (define_insn_and_split "*divmodhi4"
2139 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
2140 (div:HI (match_operand:SI 1 "register_operand" "0,0")
2141 (match_operand:HI 2 "general_operand" "rR,Qi")))
2142 (set (subreg:HI (match_dup 1) 2)
2143 (mod:HI (match_dup 1) (match_dup 2)))]
2144 "TARGET_40_PLUS"
2145 "#"
2146 "&& reload_completed"
2147 [(parallel [(set (subreg:HI (match_dup 0) 0)
2148 (div:HI (match_dup 1) (match_dup 2)))
2149 (set (subreg:HI (match_dup 1) 2)
2150 (mod:HI (match_dup 1) (match_dup 2)))
2151 (clobber (reg:CC CC_REGNUM))])]
2152 ""
2153 [(set_attr "length" "2,4")])
2154
2155 ;; Note that there is no corresponding CC setter pattern.
2156 ;; The reason is that it won't be generated, because
2157 ;; compare-elim.cc only does the transformation on input
2158 ;; insns that have a two-element PARALLEL, as opposed to
2159 ;; the three-element one we have here.
2160 (define_insn "divmodhi4_nocc"
2161 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
2162 (div:HI (match_operand:SI 1 "register_operand" "0,0")
2163 (match_operand:HI 2 "general_operand" "rR,Qi")))
2164 (set (subreg:HI (match_dup 1) 2)
2165 (mod:HI (match_dup 1) (match_dup 2)))
2166 (clobber (reg:CC CC_REGNUM))]
2167 "TARGET_40_PLUS"
2168 "div\t%2,%0"
2169 [(set_attr "length" "2,4")
2170 (set_attr "base_cost" "40")])
2171
2172 ;; Byte swap
2173 (define_insn_and_split "bswaphi2"
2174 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2175 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))]
2176 ""
2177 "#"
2178 "reload_completed"
2179 [(parallel [(set (match_dup 0) (bswap:HI (match_dup 1)))
2180 (clobber (reg:CC CC_REGNUM))])]
2181 ""
2182 [(set_attr "length" "2,4")])
2183
2184 (define_insn "bswaphi2<cc_ccnz>"
2185 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2186 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))
2187 (clobber (reg:CC CC_REGNUM))]
2188 ""
2189 "swab\t%0"
2190 [(set_attr "length" "2,4")])
2191
2192 (define_insn_and_split "bswapsi2"
2193 [(set (match_operand:SI 0 "register_operand" "=&r")
2194 (bswap:SI (match_operand:SI 1 "general_operand" "g")))]
2195 ""
2196 "#"
2197 "reload_completed"
2198 [(parallel [(set (match_dup 0)
2199 (bswap:SI (match_dup 1)))
2200 (clobber (reg:CC CC_REGNUM))])]
2201 ""
2202 [(set_attr "length" "10")])
2203
2204 (define_insn "bswapsi2_nocc"
2205 [(set (match_operand:SI 0 "register_operand" "=&r,&r,&r")
2206 (bswap:SI (match_operand:SI 1 "general_operand" "r,D,Q")))
2207 (clobber (reg:CC CC_REGNUM))]
2208 ""
2209 {
2210 rtx inops[2];
2211 rtx exops[2][2];
2212 rtx t;
2213
2214 inops[0] = operands[0];
2215 inops[1] = operands[1];
2216 pdp11_expand_operands (inops, exops, 2, 2, NULL, either);
2217
2218 t = exops[0][0];
2219 exops[0][0] = exops[1][0];
2220 exops[1][0] = t;
2221
2222 output_asm_insn ("mov\t%0,%1", exops[0]);
2223 output_asm_insn ("mov\t%0,%1", exops[1]);
2224 output_asm_insn ("swab\t%0", exops[0]);
2225 output_asm_insn ("swab\t%0", exops[1]);
2226 return "";
2227 }
2228 [(set_attr "length" "8,10,12")])
2229
2230 (define_expand "rotrhi3"
2231 [(match_operand:HI 0 "register_operand" "")
2232 (match_operand:HI 1 "register_operand" "")
2233 (match_operand:HI 2 "general_operand" "")]
2234 "TARGET_40_PLUS"
2235 "
2236 {
2237 operands[2] = negate_rtx (HImode, operands[2]);
2238 emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2]));
2239 DONE;
2240 }")
2241
2242 (define_insn_and_split "rotlhi3"
2243 [(set (match_operand:HI 0 "register_operand" "=d,d")
2244 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2245 (match_operand:HI 2 "general_operand" "rR,Qi")))]
2246 "TARGET_40_PLUS"
2247 "#"
2248 "&& reload_completed"
2249 [(parallel [(set (match_dup 0)
2250 (rotate:HI (match_dup 1) (match_dup 2)))
2251 (clobber (reg:CC CC_REGNUM))])]
2252 ""
2253 [(set_attr "length" "2,4")
2254 (set_attr "base_cost" "8")])
2255
2256 (define_insn "rotlhi3<cc_ccnz>"
2257 [(set (match_operand:HI 0 "register_operand" "=d,d")
2258 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2259 (match_operand:HI 2 "general_operand" "rR,Qi")))
2260 (clobber (reg:CC CC_REGNUM))]
2261 "TARGET_40_PLUS && reload_completed"
2262 "ashc\t%2,%0"
2263 [(set_attr "length" "2,4")
2264 (set_attr "base_cost" "8")])
2265
2266
2267
2268 ;; Some peephole optimizations
2269
2270 ;; Move then conditional branch on the result of the move is handled
2271 ;; by compare elimination, but an earlier pass sometimes changes the
2272 ;; compare operand to the move input, and then the compare is not
2273 ;; eliminated. Do so here.
2274 (define_peephole2
2275 [(parallel [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
2276 (match_operand:PDPint 1 "general_operand" ""))
2277 (clobber (reg:CC CC_REGNUM))])
2278 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))]
2279 ""
2280 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
2281 (set (match_dup 0) (match_dup 1))])]
2282 "")