1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994-2018 Free Software Foundation, Inc.
3 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
5 ;; This file is part of GCC.
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)
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.
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/>.
21 (include "predicates.md")
22 (include "constraints.md")
24 (define_c_enum "unspecv"
37 (FRAME_POINTER_REGNUM 5)
38 (STACK_POINTER_REGNUM 6)
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
50 ;; End of hard registers
51 (FIRST_PSEUDO_REGISTER 17)
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.
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")])
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])
83 (define_code_iterator SHF [ashift ashiftrt lshiftrt])
85 ;; Substitution to turn a CC clobber into a CC setter. We have four of
86 ;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
88 [(set (match_operand 0 "") (match_operand 1 ""))
89 (clobber (reg CC_REGNUM))]
91 [(set (reg:CC CC_REGNUM)
92 (compare:CC (match_dup 1) (const_int 0)))
93 (set (match_dup 0) (match_dup 1))])
95 (define_subst "cc_ccnz"
96 [(set (match_operand 0 "") (match_operand 1 ""))
97 (clobber (reg CC_REGNUM))]
99 [(set (reg:CCNZ CC_REGNUM)
100 (compare:CCNZ (match_dup 1) (const_int 0)))
101 (set (match_dup 0) (match_dup 1))])
103 (define_subst "fcc_cc"
104 [(set (match_operand 0 "") (match_operand 1 ""))
105 (clobber (reg FCC_REGNUM))]
107 [(set (reg:CC FCC_REGNUM)
108 (compare:CC (match_dup 1) (const_int 0)))
109 (set (match_dup 0) (match_dup 1))])
111 (define_subst "fcc_ccnz"
112 [(set (match_operand 0 "") (match_operand 1 ""))
113 (clobber (reg FCC_REGNUM))]
115 [(set (reg:CCNZ FCC_REGNUM)
116 (compare:CCNZ (match_dup 1) (const_int 0)))
117 (set (match_dup 0) (match_dup 1))])
119 (define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
120 (define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc")
121 (define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc")
122 (define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc")
124 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
126 ;; Compare instructions.
128 ;; currently we only support df floats, which saves us quite some
129 ;; hassle switching the FP mode!
130 ;; we assume that CPU is always in long float mode, and
131 ;; 16 bit integer mode - currently, the prologue for main does this,
132 ;; but maybe we should just set up a NEW crt0 properly,
133 ;; -- and what about signal handling code?
134 ;; (we don't even let sf floats in the register file, so
135 ;; we only should have to worry about truncating and widening
136 ;; when going to memory)
138 ;; abort() call by g++ - must define libfunc for cmp_optab
139 ;; and ucmp_optab for mode SImode, because we don't have that!!!
140 ;; - yet since no libfunc is there, we abort ()
143 ;; currently type is only fpu or arith or unknown, maybe branch later ?
145 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
147 ;; length default is 2 bytes each
148 (define_attr "length" "" (const_int 2))
150 ;; instruction base cost (not counting operands)
151 (define_attr "base_cost" "" (const_int 2))
153 ;; a user's asm statement
154 (define_asm_attributes
155 [(set_attr "type" "unknown")
156 ; length for asm is the max length per statement. That would be
157 ; 3 words, for a two-operand instruction with extra word addressing
158 ; modes for both operands.
159 (set_attr "length" "6")])
161 ;; define function units
163 ;; Prologue and epilogue support.
165 (define_expand "prologue"
169 pdp11_expand_prologue ();
173 (define_expand "epilogue"
177 pdp11_expand_epilogue ();
186 (define_insn "blockage"
187 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
190 [(set_attr "length" "0")])
193 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
198 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
202 ;; arithmetic - values here immediately when next insn issued
203 ;; or does it mean the number of cycles after this insn was issued?
204 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
206 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
207 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
210 (define_insn "*cmpdf"
211 [(set (reg:CC FCC_REGNUM)
212 (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
213 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
214 "TARGET_FPU && reload_completed"
217 if (which_alternative == 0 || which_alternative == 2)
218 return \"{tstd|tstf}\t%0\";
220 return \"{cmpd|cmpf}\t%0,%1\";
222 [(set_attr "length" "2,2,4,4")
223 (set_attr "base_cost" "4")
224 (set_attr "type" "fp")])
226 ;; Copy floating point processor condition code register to main CPU
227 ;; condition code register.
229 [(set (reg CC_REGNUM) (reg FCC_REGNUM))]
230 "TARGET_FPU && reload_completed"
233 (define_insn "cmp<mode>"
234 [(set (reg:CC CC_REGNUM)
235 (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
236 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
240 cmp<PDPint:isfx>\t%0,%1
241 cmp<PDPint:isfx>\t%0,%1
243 cmp<PDPint:isfx>\t%0,%1
244 cmp<PDPint:isfx>\t%0,%1"
245 [(set_attr "length" "2,2,4,4,4,6")])
249 [(set (reg:CC CC_REGNUM)
250 (compare:CC (match_operand:SI 0 "general_operand" "rDQi")
251 (match_operand:SI 1 "general_operand" "rDQi")))]
258 inops[0] = operands[0];
259 inops[1] = operands[1];
260 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
261 lb[0] = gen_label_rtx ();
263 if (CONST_INT_P (exops[0][1]) && INTVAL (exops[0][1]) == 0)
264 output_asm_insn ("tst\t%0", exops[0]);
266 output_asm_insn ("cmp\t%0,%1", exops[0]);
267 output_asm_insn ("bne\t%l0", lb);
268 if (CONST_INT_P (exops[1][1]) && INTVAL (exops[1][1]) == 0)
269 output_asm_insn ("tst\t%0", exops[1]);
271 output_asm_insn ("cmp\t%0,%1", exops[1]);
272 output_asm_label (lb[0]);
273 fputs (":\n", asm_out_file);
277 [(set (attr "length")
278 (symbol_ref "pdp11_cmp_length (operands, 2)"))
279 (set_attr "base_cost" "0")])
283 [(set (reg:CC CC_REGNUM)
284 (compare:CC (match_operand:DI 0 "general_operand" "rDQi")
285 (match_operand:DI 1 "general_operand" "rDQi")))]
293 inops[0] = operands[0];
294 inops[1] = operands[1];
295 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
296 lb[0] = gen_label_rtx ();
298 for (i = 0; i < 3; i++)
300 if (CONST_INT_P (exops[i][1]) && INTVAL (exops[i][1]) == 0)
301 output_asm_insn ("tst\t%0", exops[i]);
303 output_asm_insn ("cmp\t%0,%1", exops[i]);
304 output_asm_insn ("bne\t%l0", lb);
306 if (CONST_INT_P (exops[3][1]) && INTVAL (exops[3][1]) == 0)
307 output_asm_insn ("tst\t%0", exops[3]);
309 output_asm_insn ("cmp\t%0,%1", exops[3]);
310 output_asm_label (lb[0]);
311 fputs (":\n", asm_out_file);
315 [(set (attr "length")
316 (symbol_ref "pdp11_cmp_length (operands, 2)"))
317 (set_attr "base_cost" "0")])
321 ;; This expander has to check for mode match because the doloop pass
322 ;; in gcc that invokes it does not do so, i.e., it may attempt to apply
323 ;; this pattern even if the count operand is QI or SI mode.
324 (define_expand "doloop_end"
325 [(parallel [(set (pc)
327 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
329 (label_ref (match_operand 1 "" ""))
332 (plus:HI (match_dup 0)
336 if (GET_MODE (operands[0]) != HImode)
340 ;; Do a define_split because some alternatives clobber CC.
341 ;; Some don't, but it isn't all that interesting to cover that case.
342 (define_insn_and_split "doloop_end_insn"
345 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
347 (label_ref (match_operand 1 "" ""))
350 (plus:HI (match_dup 0)
354 "&& reload_completed"
355 [(parallel [(set (pc)
357 (ne (match_dup 0) (const_int 1))
358 (label_ref (match_dup 1))
361 (plus:HI (match_dup 0)
363 (clobber (reg:CC CC_REGNUM))])]
366 ;; Note that there is a memory alternative here. This is as documented
367 ;; in gccint, which says that doloop_end, since it has both a jump and
368 ;; an output interrupt "must handle its own reloads". That translates
369 ;; to: must accept memory operands as valid though they may be deprecated.
370 (define_insn "doloop_end_nocc"
373 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
375 (label_ref (match_operand 1 "" ""))
378 (plus:HI (match_dup 0)
380 (clobber (reg:CC CC_REGNUM))]
381 "TARGET_40_PLUS && reload_completed"
386 if (get_attr_length (insn) == 2)
387 return \"sob\t%0,%l1\";
390 lb[0] = gen_label_rtx ();
391 output_asm_insn (\"dec\t%0\", operands);
392 output_asm_insn (\"beq\t%l0\", lb);
393 output_asm_insn (\"jmp\t%l1\", operands);
395 output_asm_label (lb[0]);
396 fputs (\":\\n\", asm_out_file);
400 [(set (attr "length")
401 (if_then_else (eq (symbol_ref ("which_alternative")) (const_int 1))
403 (if_then_else (ior (lt (minus (match_dup 1) (pc))
405 (gt (minus (match_dup 1) (pc))
406 (const_int MAX_SOB)))
410 ;; These control RTL generation for conditional jump insns
411 ;; and match them for register allocation.
412 ;; Post reload these get expanded into insns that actually
413 ;; manipulate the condition code registers. We can't do that before
414 ;; because instructions generated by reload clobber condition codes (new
415 ;; CC design, type #2).
416 (define_insn_and_split "cbranchdf4"
418 (if_then_else (match_operator 0 "ordered_comparison_operator"
419 [(match_operand:DF 1 "general_operand" "fg")
420 (match_operand:DF 2 "general_operand" "a")])
421 (label_ref (match_operand 3 "" ""))
425 "&& reload_completed"
426 [(set (reg:CC FCC_REGNUM)
427 (compare:CC (match_dup 1) (match_dup 2)))
429 (if_then_else (match_op_dup 0
430 [(reg:CC FCC_REGNUM) (const_int 0)])
431 (label_ref (match_dup 3))
435 (define_insn_and_split "cbranch<mode>4"
437 (if_then_else (match_operator 0 "ordered_comparison_operator"
438 [(match_operand:QHSDint 1 "general_operand" "g")
439 (match_operand:QHSDint 2 "general_operand" "g")])
440 (label_ref (match_operand 3 "" ""))
445 [(set (reg:CC CC_REGNUM)
446 (compare:CC (match_dup 1) (match_dup 2)))
448 (if_then_else (match_op_dup 0
449 [(reg:CC CC_REGNUM) (const_int 0)])
450 (label_ref (match_dup 3))
454 ;; This splitter turns a branch on float condition into a branch on
455 ;; CPU condition, by adding a CFCC.
458 (if_then_else (match_operator 0 "ordered_comparison_operator"
459 [(reg:CC FCC_REGNUM) (const_int 0)])
460 (label_ref (match_operand 1 "" ""))
462 "TARGET_FPU && reload_completed"
463 [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM))
465 (if_then_else (match_op_dup 0
466 [(reg:CC CC_REGNUM) (const_int 0)])
467 (label_ref (match_dup 1))
471 (define_insn "cond_branch"
473 (if_then_else (match_operator 0 "ordered_comparison_operator"
474 [(reg:CC CC_REGNUM) (const_int 0)])
475 (label_ref (match_operand 1 "" ""))
478 "* return output_jump (operands, 0, get_attr_length (insn));"
479 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
481 (const_int MIN_BRANCH))
482 (gt (minus (match_dup 1)
484 (const_int MAX_BRANCH)))
488 (define_insn "*branch"
490 (if_then_else (match_operator 0 "ccnz_operator"
491 [(reg:CCNZ CC_REGNUM) (const_int 0)])
492 (label_ref (match_operand 1 "" ""))
495 "* return output_jump (operands, 1, get_attr_length (insn));"
496 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
498 (const_int MIN_BRANCH))
499 (gt (minus (match_dup 1)
501 (const_int MAX_BRANCH)))
508 ;; "length" is defined even though this pattern won't appear at
509 ;; assembly language output time. But the length is used by
510 ;; pdp11_insn_cost, before the post-reload splitter adds the
511 ;; CC clobber to the insn.
513 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
514 (match_operand:DI 1 "general_operand" "rN,g"))]
517 [(set_attr "length" "16,32")])
520 (define_insn "*movdi_nocc"
521 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
522 (match_operand:DI 1 "general_operand" "rN,g"))
523 (clobber (reg:CC CC_REGNUM))]
525 "* return output_move_multiple (operands);"
526 [(set_attr "length" "16,32")])
529 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
530 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
533 [(set_attr "length" "4,6,8,16")])
535 (define_insn "*movsi_nocc"
536 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
537 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))
538 (clobber (reg:CC CC_REGNUM))]
540 "* return output_move_multiple (operands);"
541 [(set_attr "length" "4,6,8,16")])
543 ;; That long string of "Z" constraints enforces the restriction that
544 ;; a register source and auto increment or decrement destination must
545 ;; not use the same register, because that case is not consistently
546 ;; implemented across the PDP11 models.
547 ;; TODO: the same should be applied to insn like add, but this is not
548 ;; necessary yet because the incdec optimization pass does not apply
549 ;; that optimization to 3-operand insns at the moment.
550 (define_insn "mov<mode>"
551 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
552 (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))]
555 [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
557 ;; This splits all the integer moves: DI and SI modes as well as
558 ;; the simple machine operations.
560 [(set (match_operand:QHSDint 0 "nonimmediate_operand" "")
561 (match_operand:QHSDint 1 "general_operand" ""))]
563 [(parallel [(set (match_dup 0)
565 (clobber (reg:CC CC_REGNUM))])]
569 (define_insn "*mov<mode>_<cc_cc>"
570 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
571 (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))
572 (clobber (reg:CC CC_REGNUM))]
576 if (operands[1] == const0_rtx)
577 return \"clr<PDPint:isfx>\t%0\";
579 return \"mov<PDPint:isfx>\t%1,%0\";
581 [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
583 ;; movdf has unusually complicated condition code handling, because
584 ;; load (into float register) updates the FCC, while store (from
585 ;; float register) leaves it untouched.
587 ;; 1. Loads are: ac4, ac5, or non-register into load-register
588 ;; 2. Stores are: load-register to non-register, ac4, or ac5
589 ;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled
590 ;; either as loads or as stores.
592 (define_expand "movdf"
593 [(set (match_operand:DF 0 "float_nonimm_operand" "")
594 (match_operand:DF 1 "float_operand" ""))]
598 ;; Splitter for all these cases. Store is the first two
599 ;; alternatives, which are not split. Note that case 3
600 ;; is treated as a store, i.e., not split.
601 (define_insn_and_split "movdf_split"
602 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,FQ,a,a,a")
603 (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))]
606 gcc_assert (which_alternative < 2);
607 return \"std\t%1,%0\";
609 "&& reload_completed"
610 [(parallel [(set (match_dup 0)
612 (clobber (reg:CC FCC_REGNUM))])]
614 if (GET_CODE (operands[1]) == REG &&
615 REGNO_REG_CLASS (REGNO (operands[1])) == LOAD_FPU_REGS)
618 [(set_attr "length" "2,4,0,0,0")])
621 (define_insn "*ldd<fcc_cc>"
622 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,a,a")
623 (match_operand:DF 1 "float_operand" "hR,FQ,G"))
624 (clobber (reg:CC FCC_REGNUM))]
625 "TARGET_FPU && reload_completed"
630 [(set_attr "length" "2,4,2")])
632 ;; SFmode is easier because that uses convert load/store, which
633 ;; always change condition codes.
634 ;; Note that these insns are cheating a bit. We actually have
635 ;; DFmode operands in the FPU registers, which is why the
636 ;; ldcfd and stcdf instructions appear. But GCC likes to think
637 ;; of these as SFmode loads and does the conversion once in the
638 ;; register, at least in many cases. So we pretend to do this,
639 ;; but then extend and truncate register-to-register are NOP and
641 (define_insn_and_split "movsf"
642 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
643 (match_operand:SF 1 "float_operand" "fRG,a,FQ,a,G"))]
646 "&& reload_completed"
647 [(parallel [(set (match_dup 0)
649 (clobber (reg:CC FCC_REGNUM))])]
651 [(set_attr "length" "2,2,4,4,2")])
653 (define_insn "*movsf<fcc_ccnz>"
654 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
655 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G"))
656 (clobber (reg:CC FCC_REGNUM))]
657 "TARGET_FPU && reload_completed"
664 [(set_attr "length" "2,2,4,4,2")])
666 ;; Expand a block move. We turn this into a move loop.
667 (define_expand "movmemhi"
668 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
669 (match_operand:BLK 0 "general_operand" "=g")
670 (match_operand:BLK 1 "general_operand" "g")
671 (match_operand:HI 2 "immediate_operand" "i")
672 (match_operand:HI 3 "immediate_operand" "i")
673 (clobber (mem:BLK (scratch)))
674 (clobber (match_dup 0))
675 (clobber (match_dup 1))
676 (clobber (match_dup 2))])]
681 count = INTVAL (operands[2]);
684 if (INTVAL (operands [3]) >= 2 && (count & 1) == 0)
687 operands[3] = const1_rtx;
688 operands[2] = copy_to_mode_reg (HImode,
689 gen_rtx_CONST_INT (HImode, count));
691 /* Load BLKmode MEM addresses into scratch registers. */
692 operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
693 operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
696 ;; Expand a block move. We turn this into a move loop.
697 (define_insn_and_split "movmemhi1"
698 [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
699 (match_operand:HI 0 "register_operand" "+r")
700 (match_operand:HI 1 "register_operand" "+r")
701 (match_operand:HI 2 "register_operand" "+r")
702 (match_operand:HI 3 "immediate_operand" "i")
703 (clobber (mem:BLK (scratch)))
704 (clobber (match_dup 0))
705 (clobber (match_dup 1))
706 (clobber (match_dup 2))]
710 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
715 (clobber (mem:BLK (scratch)))
716 (clobber (match_dup 0))
717 (clobber (match_dup 1))
718 (clobber (match_dup 2))
719 (clobber (reg:CC CC_REGNUM))])]
722 (define_insn "movmemhi_nocc"
723 [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
724 (match_operand:HI 0 "register_operand" "+r")
725 (match_operand:HI 1 "register_operand" "+r")
726 (match_operand:HI 2 "register_operand" "+r")
727 (match_operand:HI 3 "immediate_operand" "i")
728 (clobber (mem:BLK (scratch)))
729 (clobber (match_dup 0))
730 (clobber (match_dup 1))
731 (clobber (match_dup 2))
732 (clobber (reg:CC CC_REGNUM))]
739 lb[1] = gen_label_rtx ();
741 output_asm_label (lb[1]);
742 fputs (\":\n\", asm_out_file);
743 if (INTVAL (operands[3]) > 1)
744 output_asm_insn (\"mov\t(%1)+,(%0)+\", operands);
746 output_asm_insn (\"movb\t(%1)+,(%0)+\", operands);
748 output_asm_insn (\"sob\t%0,%l1\", lb);
751 output_asm_insn (\"dec\t%0\", lb);
752 output_asm_insn (\"bne\t%l1\", lb);
756 [(set (attr "length")
757 (if_then_else (match_test "TARGET_40_PLUS")
761 ;;- truncation instructions
763 ;; We sometimes end up doing a register to register truncate,
764 ;; which isn't right because we actually load registers always
765 ;; with a DFmode value. But even with PROMOTE the compiler
766 ;; doesn't always get that (so we don't use it). That means
767 ;; a register to register truncate is a NOP.
768 (define_insn_and_split "truncdfsf2"
769 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
770 (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))]
773 gcc_assert (which_alternative == 0);
776 "&& reload_completed"
777 [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1)))
778 (clobber (reg:CC FCC_REGNUM))])]
780 if (GET_CODE (operands[0]) == REG &&
781 GET_CODE (operands[1]) == REG &&
782 REGNO (operands[0]) == REGNO (operands[1]))
785 [(set_attr "length" "0,0,0")])
787 (define_insn "*truncdfsf2_<fcc_cc>"
788 [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q")
789 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a")))
790 (clobber (reg:CC FCC_REGNUM))]
791 "TARGET_FPU && reload_completed"
792 "{stcdf|movfo}\t%1,%0"
793 [(set_attr "length" "2,4")])
796 ;;- zero extension instruction
798 (define_insn_and_split "zero_extendqihi2"
799 [(set (match_operand:HI 0 "nonimmediate_operand" "=rD,Q,&r,&r")
800 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0,rR,Q")))]
804 [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
805 (clobber (reg:CC CC_REGNUM))])]
809 if (!REG_P (operands[0]))
811 r = gen_rtx_MEM (QImode, operands[0]);
812 adjust_address (r, QImode, 1);
813 emit_move_insn (r, const0_rtx);
816 else if (!REG_P (operands[1]) ||
817 REGNO (operands[0]) != REGNO (operands[1]))
819 /* Alternatives 2 and 3 */
820 emit_move_insn (operands[0], const0_rtx);
821 r = gen_rtx_REG (QImode, REGNO (operands[0]));
822 emit_insn (gen_iorqi3_nocc (r, r, operands[1]));
826 [(set_attr "length" "4,4,4,6")])
828 (define_insn "*zero_extendqihi2<cc_cc>"
829 [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
830 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))
831 (clobber (reg:CC CC_REGNUM))])]
834 [(set_attr "length" "4,6")])
836 ;;- sign extension instructions
838 ;; We sometimes end up doing a register to register extend,
839 ;; which isn't right because we actually load registers always
840 ;; with a DFmode value. But even with PROMOTE the compiler
841 ;; doesn't always get that (so we don't use it). That means
842 ;; a register to register truncate is a NOP.
843 (define_insn_and_split "extendsfdf2"
844 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
845 (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))]
848 gcc_assert (which_alternative == 0);
851 "&& reload_completed"
852 [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1)))
853 (clobber (reg:CC FCC_REGNUM))])]
855 if (GET_CODE (operands[0]) == REG &&
856 GET_CODE (operands[1]) == REG &&
857 REGNO (operands[0]) == REGNO (operands[1]))
860 [(set_attr "length" "0,0,0")])
862 (define_insn "*extendsfdf2_<fcc_cc>"
863 [(set (match_operand:DF 0 "register_operand" "=a,a")
864 (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q")))
865 (clobber (reg:CC FCC_REGNUM))]
866 "TARGET_FPU && reload_completed"
867 "{ldcfd|movof}\t%1,%0"
868 [(set_attr "length" "2,4")
869 (set_attr "base_cost" "6")])
871 ;; movb sign extends if destination is a register
872 (define_insn_and_split "extendqihi2"
873 [(set (match_operand:HI 0 "register_operand" "=r,r")
874 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
878 [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
879 (clobber (reg:CC CC_REGNUM))])]
881 [(set_attr "length" "2,4")])
884 (define_insn "*extendqihi2<cc_cc>"
885 [(set (match_operand:HI 0 "register_operand" "=r,r")
886 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))
887 (clobber (reg:CC CC_REGNUM))]
890 [(set_attr "length" "2,4")])
892 (define_insn_and_split "extendhisi2"
893 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
894 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
897 "&& reload_completed"
898 [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
899 (clobber (reg:CC CC_REGNUM))])]
901 [(set_attr "length" "10,6,6")])
903 (define_insn "*extendhisi2_nocc"
904 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
905 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))
906 (clobber (reg:CC CC_REGNUM))]
907 "TARGET_40_PLUS && reload_completed"
912 /* we don't want to mess with auto increment */
914 switch (which_alternative)
918 latehalf[0] = operands[0];
919 operands[0] = adjust_address(operands[0], HImode, 2);
921 output_asm_insn(\"mov\t%1,%0\", operands);
922 output_asm_insn(\"sxt\t%0\", latehalf);
928 /* - auto-decrement - right direction ;-) */
929 output_asm_insn(\"mov\t%1,%0\", operands);
930 output_asm_insn(\"sxt\t%0\", operands);
936 /* make register pair available */
937 latehalf[0] = operands[0];
938 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
940 output_asm_insn(\"mov\t%1,%0\", operands);
941 output_asm_insn(\"sxt\t%0\", latehalf);
950 [(set_attr "length" "10,6,6")])
952 ;; make float to int and vice versa
953 ;; assume that we are normally in double and integer mode -
954 ;; what do pdp library routines do to fpu mode ?
956 ;; Note: the hardware treats register source as
957 ;; a 16-bit (high order only) source, which isn't
958 ;; what we want. But we do need to support register
959 ;; dest because gcc asks for it.
960 (define_insn_and_split "floatsidf2"
961 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
962 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
965 "&& reload_completed"
966 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
967 (clobber (reg:CC FCC_REGNUM))])]
969 [(set_attr "length" "10,6,8")])
971 (define_insn "*floatsidf2<fcc_cc>"
972 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
973 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))
974 (clobber (reg:CC FCC_REGNUM))]
975 "TARGET_FPU && reload_completed"
976 "* if (which_alternative ==0)
981 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
982 output_asm_insn(\"mov\t%1,-(sp)\", latehalf);
983 output_asm_insn(\"mov\t%1,-(sp)\", operands);
985 output_asm_insn(\"setl\", operands);
986 output_asm_insn(\"{ldcld|movif}\t(sp)+,%0\", operands);
987 output_asm_insn(\"seti\", operands);
991 return \"setl\;{ldcld|movif}\t%1,%0\;seti\";
993 [(set_attr "length" "10,6,8")
994 (set_attr "base_cost" "12")])
996 (define_insn_and_split "floathidf2"
997 [(set (match_operand:DF 0 "register_operand" "=a,a")
998 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
1001 "&& reload_completed"
1002 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
1003 (clobber (reg:CC FCC_REGNUM))])]
1005 [(set_attr "length" "2,4")])
1007 (define_insn "*floathidf2<fcc_cc>"
1008 [(set (match_operand:DF 0 "register_operand" "=a,a")
1009 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))
1010 (clobber (reg:CC FCC_REGNUM))]
1011 "TARGET_FPU && reload_completed"
1012 "{ldcid|movif}\t%1,%0"
1013 [(set_attr "length" "2,4")
1014 (set_attr "base_cost" "12")])
1018 ;; Note: the hardware treats register destination as
1019 ;; a 16-bit (high order only) destination, which isn't
1020 ;; what we want. But we do need to support register
1021 ;; dest because gcc asks for it.
1022 (define_insn_and_split "fix_truncdfsi2"
1023 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
1024 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
1027 "&& reload_completed"
1028 [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1))))
1029 (clobber (reg:CC CC_REGNUM))
1030 (clobber (reg:CC FCC_REGNUM))])]
1032 [(set_attr "length" "10,6,8")])
1034 ;; Note: this clobbers both sets of condition codes!
1035 (define_insn "*fix_truncdfsi2_nocc"
1036 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
1037 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))
1038 (clobber (reg:CC CC_REGNUM))
1039 (clobber (reg:CC FCC_REGNUM))]
1040 "TARGET_FPU && reload_completed"
1041 "* if (which_alternative ==0)
1043 output_asm_insn(\"setl\", operands);
1044 output_asm_insn(\"{stcdl|movfi}\t%1,-(sp)\", operands);
1045 output_asm_insn(\"seti\", operands);
1046 output_asm_insn(\"mov\t(sp)+,%0\", operands);
1047 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1048 output_asm_insn(\"mov\t(sp)+,%0\", operands);
1052 return \"setl\;{stcdl|movfi}\t%1,%0\;seti\";
1054 [(set_attr "length" "10,6,8")
1055 (set_attr "base_cost" "12")])
1057 (define_insn_and_split "fix_truncdfhi2"
1058 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1059 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
1062 "&& reload_completed"
1063 [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1))))
1064 (clobber (reg:CC CC_REGNUM))
1065 (clobber (reg:CC FCC_REGNUM))])]
1067 [(set_attr "length" "2,4")])
1069 ;; Note: this clobbers both sets of condition codes!
1070 (define_insn "*fix_truncdfhi2_nocc"
1071 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1072 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))
1073 (clobber (reg:CC CC_REGNUM))
1074 (clobber (reg:CC FCC_REGNUM))]
1075 "TARGET_FPU && reload_completed"
1076 "{stcdi|movfi}\t%1,%0"
1077 [(set_attr "length" "2,4")
1078 (set_attr "base_cost" "12")])
1081 ;;- arithmetic instructions
1082 ;;- add instructions
1084 (define_insn_and_split "adddf3"
1085 [(set (match_operand:DF 0 "register_operand" "=a,a")
1086 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
1087 (match_operand:DF 2 "general_operand" "fR,QF")))]
1090 "&& reload_completed"
1091 [(parallel [(set (match_dup 0)
1092 (plus:DF (match_dup 1) (match_dup 2)))
1093 (clobber (reg:CC FCC_REGNUM))])]
1095 [(set_attr "length" "2,4")])
1097 ;; Float add sets V if overflow from add
1098 (define_insn "*adddf3<fcc_ccnz>"
1099 [(set (match_operand:DF 0 "register_operand" "=a,a")
1100 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
1101 (match_operand:DF 2 "general_operand" "fR,QF")))
1102 (clobber (reg:CC FCC_REGNUM))]
1103 "TARGET_FPU && reload_completed"
1104 "{addd|addf}\t%2,%0"
1105 [(set_attr "length" "2,4")
1106 (set_attr "base_cost" "6")])
1108 (define_insn_and_split "adddi3"
1109 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1110 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
1111 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1115 [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
1116 (clobber (reg:CC CC_REGNUM))])]
1118 [(set_attr "length" "20,28,40,48")])
1120 (define_insn "*adddi3_nocc"
1121 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1122 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
1123 (match_operand:DI 2 "general_operand" "r,on,r,on")))
1124 (clobber (reg:CC CC_REGNUM))]
1131 inops[0] = operands[0];
1132 inops[1] = operands[2];
1133 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
1135 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1136 output_asm_insn (\"add\t%1,%0\", exops[0]);
1137 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1139 output_asm_insn (\"add\t%1,%0\", exops[1]);
1140 output_asm_insn (\"adc\t%0\", exops[0]);
1142 if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1144 output_asm_insn (\"add\t%1,%0\", exops[2]);
1145 output_asm_insn (\"adc\t%0\", exops[1]);
1146 output_asm_insn (\"adc\t%0\", exops[0]);
1148 if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1150 output_asm_insn (\"add\t%1,%0\", exops[3]);
1151 output_asm_insn (\"adc\t%0\", exops[2]);
1152 output_asm_insn (\"adc\t%0\", exops[1]);
1153 output_asm_insn (\"adc\t%0\", exops[0]);
1158 [(set_attr "length" "20,28,40,48")
1159 (set_attr "base_cost" "0")])
1161 ;; Note that the register operand is not marked earlyclobber.
1162 ;; The reason is that SI values go in register pairs, so they
1163 ;; can't partially overlap. They can be either disjoint, or
1164 ;; source and destination can be equal. The latter case is
1165 ;; handled properly because of the ordering of the individual
1166 ;; instructions used. Specifically, carry from the low to the
1167 ;; high word is added at the end, so the adding of the high parts
1168 ;; will always used the original high part and not a high part
1169 ;; modified by carry (which would amount to double carry).
1170 (define_insn_and_split "addsi3"
1171 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1172 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1173 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1177 [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
1178 (clobber (reg:CC CC_REGNUM))])]
1180 [(set_attr "length" "6,10,12,16")])
1182 (define_insn "*addsi3_nocc"
1183 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1184 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1185 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1186 (clobber (reg:CC CC_REGNUM))]
1193 inops[0] = operands[0];
1194 inops[1] = operands[2];
1195 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
1197 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1198 output_asm_insn (\"add\t%1,%0\", exops[0]);
1199 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1201 output_asm_insn (\"add\t%1,%0\", exops[1]);
1202 output_asm_insn (\"adc\t%0\", exops[0]);
1207 [(set_attr "length" "6,10,12,16")
1208 (set_attr "base_cost" "0")])
1210 (define_insn_and_split "addhi3"
1211 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1212 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1213 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1217 [(parallel [(set (match_dup 0)
1218 (plus:HI (match_dup 1) (match_dup 2)))
1219 (clobber (reg:CC CC_REGNUM))])]
1221 [(set_attr "length" "2,4,4,6")])
1223 ;; Add sets V if overflow from the add
1224 (define_insn "*addhi3<cc_ccnz>"
1225 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1226 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1227 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1228 (clobber (reg:CC CC_REGNUM))]
1232 if (GET_CODE (operands[2]) == CONST_INT)
1234 if (INTVAL(operands[2]) == 1)
1236 else if (INTVAL(operands[2]) == -1)
1240 return \"add\t%2,%0\";
1242 [(set_attr "length" "2,4,4,6")])
1244 (define_insn_and_split "addqi3"
1245 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1246 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1247 (match_operand:QI 2 "incdec_operand" "LM,LM")))]
1251 [(parallel [(set (match_dup 0)
1252 (plus:QI (match_dup 1) (match_dup 2)))
1253 (clobber (reg:CC CC_REGNUM))])]
1255 [(set_attr "length" "2,4")])
1257 ;; Inc/dec sets V if overflow from the operation
1258 (define_insn "*addqi3<cc_ccnz>"
1259 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1260 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1261 (match_operand:QI 2 "incdec_operand" "LM,LM")))
1262 (clobber (reg:CC CC_REGNUM))]
1266 if (INTVAL(operands[2]) == 1)
1267 return \"incb\t%0\";
1269 return \"decb\t%0\";
1271 [(set_attr "length" "2,4")])
1274 ;;- subtract instructions
1275 ;; we don't have to care for constant second
1276 ;; args, since they are canonical plus:xx now!
1277 ;; also for minus:DF ??
1279 (define_insn_and_split "subdf3"
1280 [(set (match_operand:DF 0 "register_operand" "=a,a")
1281 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1282 (match_operand:DF 2 "general_operand" "fR,Q")))]
1285 "&& reload_completed"
1286 [(parallel [(set (match_dup 0)
1287 (minus:DF (match_dup 1) (match_dup 2)))
1288 (clobber (reg:CC FCC_REGNUM))])]
1290 [(set_attr "length" "2,4")])
1292 (define_insn "*subdf3<fcc_ccnz>"
1293 [(set (match_operand:DF 0 "register_operand" "=a,a")
1294 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1295 (match_operand:DF 2 "general_operand" "fR,QF")))
1296 (clobber (reg:CC FCC_REGNUM))]
1297 "TARGET_FPU && reload_completed"
1298 "{subd|subf}\t%2,%0"
1299 [(set_attr "length" "2,4")
1300 (set_attr "base_cost" "6")])
1302 (define_insn_and_split "subdi3"
1303 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1304 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1305 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1309 [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
1310 (clobber (reg:CC CC_REGNUM))])]
1312 [(set_attr "length" "20,28,40,48")])
1314 (define_insn "*subdi3_nocc"
1315 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1316 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1317 (match_operand:DI 2 "general_operand" "r,on,r,on")))
1318 (clobber (reg:CC CC_REGNUM))]
1325 inops[0] = operands[0];
1326 inops[1] = operands[2];
1327 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
1329 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1330 output_asm_insn (\"sub\t%1,%0\", exops[0]);
1331 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1333 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1334 output_asm_insn (\"sbc\t%0\", exops[0]);
1336 if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1338 output_asm_insn (\"sub\t%1,%0\", exops[2]);
1339 output_asm_insn (\"sbc\t%0\", exops[1]);
1340 output_asm_insn (\"sbc\t%0\", exops[0]);
1342 if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1344 output_asm_insn (\"sub\t%1,%0\", exops[3]);
1345 output_asm_insn (\"sbc\t%0\", exops[2]);
1346 output_asm_insn (\"sbc\t%0\", exops[1]);
1347 output_asm_insn (\"sbc\t%0\", exops[0]);
1352 [(set_attr "length" "20,28,40,48")
1353 (set_attr "base_cost" "0")])
1355 (define_insn_and_split "subsi3"
1356 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1357 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1358 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1362 [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1363 (clobber (reg:CC CC_REGNUM))])]
1365 [(set_attr "length" "6,10,12,16")])
1367 (define_insn "*subsi3_nocc"
1368 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1369 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1370 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1371 (clobber (reg:CC CC_REGNUM))]
1378 inops[0] = operands[0];
1379 inops[1] = operands[2];
1380 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
1382 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1383 output_asm_insn (\"sub\t%1,%0\", exops[0]);
1384 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1386 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1387 output_asm_insn (\"sbc\t%0\", exops[0]);
1392 [(set_attr "length" "6,10,12,16")
1393 (set_attr "base_cost" "0")])
1395 (define_insn_and_split "subhi3"
1396 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1397 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1398 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1402 [(parallel [(set (match_dup 0)
1403 (minus:HI (match_dup 1) (match_dup 2)))
1404 (clobber (reg:CC CC_REGNUM))])]
1406 [(set_attr "length" "2,4,4,6")])
1408 ;; Note: the manual says that (minus m (const_int n)) is converted
1409 ;; to (plus m (const_int -n)) but that does not appear to be
1410 ;; the case when it's wrapped in a PARALLEL. So instead we handle
1411 ;; that case here, which is easy enough.
1412 (define_insn "*subhi3<cc_ccnz>"
1413 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1414 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1415 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1416 (clobber (reg:CC CC_REGNUM))]
1420 if (GET_CODE (operands[2]) == CONST_INT)
1422 if (INTVAL(operands[2]) == 1)
1424 else if (INTVAL(operands[2]) == -1)
1428 return \"sub\t%2,%0\";
1430 [(set_attr "length" "2,4,4,6")])
1432 (define_insn_and_split "subqi3"
1433 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1434 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1435 (match_operand:QI 2 "incdec_operand" "LM,LM")))]
1439 [(parallel [(set (match_dup 0)
1440 (plus:QI (match_dup 1) (match_dup 2)))
1441 (clobber (reg:CC CC_REGNUM))])]
1443 [(set_attr "length" "2,4")])
1445 ;; Inc/dec sets V if overflow from the operation
1446 (define_insn "*subqi3<cc_ccnz>"
1447 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1448 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1449 (match_operand:QI 2 "incdec_operand" "LM,LM")))
1450 (clobber (reg:CC CC_REGNUM))]
1454 if (INTVAL(operands[2]) == -1)
1455 return \"incb\t%0\";
1457 return \"decb\t%0\";
1459 [(set_attr "length" "2,4")])
1461 ;;;;- and instructions
1462 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1464 (define_expand "and<mode>3"
1465 [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
1466 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
1467 (match_operand:PDPint 2 "general_operand" "")))]
1471 rtx op1 = operands[1];
1473 /* If there is a constant argument, complement that one.
1474 Similarly, if one of the inputs is the same as the output,
1475 complement the other input. */
1476 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
1477 rtx_equal_p (operands[0], operands[1]))
1479 operands[1] = operands[2];
1484 if (CONST_INT_P (op1))
1485 operands[1] = GEN_INT (~INTVAL (op1));
1487 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
1489 [(set_attr "length" "2,4,4,6")])
1491 (define_insn_and_split "*bic<mode>"
1492 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1494 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1495 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
1499 [(parallel [(set (match_dup 0)
1500 (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2)))
1501 (clobber (reg:CC CC_REGNUM))])]
1504 (define_insn "*bic<mode><cc_cc>"
1505 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1507 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1508 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))
1509 (clobber (reg:CC CC_REGNUM))]
1511 "bic<PDPint:isfx>\t%1,%0"
1512 [(set_attr "length" "2,4,4,6")])
1514 ;;- Bit set (inclusive or) instructions
1515 (define_insn_and_split "ior<mode>3"
1516 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1517 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1518 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
1522 [(parallel [(set (match_dup 0)
1523 (ior:PDPint (match_dup 1) (match_dup 2)))
1524 (clobber (reg:CC CC_REGNUM))])]
1526 [(set_attr "length" "2,4,4,6")])
1528 (define_insn "ior<mode>3<cc_cc>"
1529 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1530 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1531 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))
1532 (clobber (reg:CC CC_REGNUM))]
1534 "bis<PDPint:isfx>\t%2,%0"
1535 [(set_attr "length" "2,4,4,6")])
1537 ;;- xor instructions
1538 (define_insn_and_split "xorhi3"
1539 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1540 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1541 (match_operand:HI 2 "register_operand" "r,r")))]
1544 "&& reload_completed"
1545 [(parallel [(set (match_dup 0)
1546 (xor:HI (match_dup 1) (match_dup 2)))
1547 (clobber (reg:CC CC_REGNUM))])]
1549 [(set_attr "length" "2,4")])
1551 (define_insn "*xorhi3<cc_cc>"
1552 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1553 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1554 (match_operand:HI 2 "register_operand" "r,r")))
1555 (clobber (reg:CC CC_REGNUM))]
1556 "TARGET_40_PLUS && reload_completed"
1558 [(set_attr "length" "2,4")])
1560 ;;- one complement instructions
1562 (define_insn_and_split "one_cmpl<mode>2"
1563 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1564 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1568 [(parallel [(set (match_dup 0)
1569 (not:PDPint (match_dup 1)))
1570 (clobber (reg:CC CC_REGNUM))])]
1572 [(set_attr "length" "2,4")])
1574 (define_insn "*one_cmpl<mode>2<cc_cc>"
1575 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1576 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1577 (clobber (reg:CC CC_REGNUM))]
1579 "com<PDPint:isfx>\t%0"
1580 [(set_attr "length" "2,4")])
1582 ;;- arithmetic shift instructions
1584 ;; There is a fair amount of complexity here because with -m10
1585 ;; (pdp-11/10, /20) we only have shift by one bit. Iterators are
1586 ;; used to reduce the amount of very similar code.
1588 ;; First the insns used for small constant shifts.
1589 (define_insn_and_split "<code><mode>_sc"
1590 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1591 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1592 (match_operand:HI 2 "expand_shift_operand" "O,O")))]
1596 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1597 (clobber (reg:CC CC_REGNUM))])]
1599 [(set (attr "length")
1600 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1601 <CODE>, which_alternative == 0)"))
1602 (set_attr "base_cost" "0")])
1604 (define_insn "<code><mode>_sc<cc_ccnz>"
1605 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rD,Q")
1606 (SHF:PDPint (match_operand:PDPint 1 "general_operand" "0,0")
1607 (match_operand:HI 2 "expand_shift_operand" "O,O")))
1608 (clobber (reg:CC CC_REGNUM))]
1610 "* return pdp11_assemble_shift (operands, <PDPint:mname>, <CODE>);"
1611 [(set (attr "length")
1612 (symbol_ref "pdp11_shift_length (operands, <PDPint:mname>,
1613 <CODE>, which_alternative == 0)"))
1614 (set_attr "base_cost" "0")])
1616 ;; This one comes only in clobber flavor.
1617 (define_insn "<code>si_sc_nocc"
1618 [(set (match_operand:SI 0 "nonimmediate_operand" "=rD,Q")
1619 (SHF:SI (match_operand:SI 1 "general_operand" "0,0")
1620 (match_operand:HI 2 "expand_shift_operand" "O,O")))
1621 (clobber (reg:CC CC_REGNUM))]
1623 "* return pdp11_assemble_shift (operands, SImode, <CODE>);"
1624 [(set (attr "length")
1625 (symbol_ref "pdp11_shift_length (operands, SImode,
1626 <CODE>, which_alternative == 0)"))
1627 (set_attr "base_cost" "0")])
1629 ;; Next, shifts that are done as a loop on base (11/10 class) machines.
1630 ;; This applies to shift counts too large to unroll, or variable shift
1631 ;; counts. The check for count <= 0 is done before we get here.
1632 (define_insn_and_split "<code><mode>_base"
1633 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1634 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1635 (match_operand:HI 2 "register_operand" "r,r")))
1636 (clobber (match_dup 2))]
1640 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1641 (clobber (match_dup 2))
1642 (clobber (reg:CC CC_REGNUM))])]
1644 [(set (attr "length")
1645 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1646 <CODE>, which_alternative == 0)"))
1647 (set_attr "base_cost" "0")])
1649 (define_insn "<code><mode>_base_nocc"
1650 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1651 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1652 (match_operand:HI 2 "register_operand" "r,r")))
1653 (clobber (match_dup 2))
1654 (clobber (reg:CC CC_REGNUM))]
1656 "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1657 [(set (attr "length")
1658 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1659 <CODE>, which_alternative == 0)"))
1660 (set_attr "base_cost" "0")])
1662 ;; Next the insns that use the extended instructions ash and ashc.
1663 ;; Note that these are just left shifts, and HI/SI only. (Right shifts
1664 ;; are done by shifting by a negative amount.)
1665 (define_insn_and_split "aslhi_op"
1666 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1667 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1668 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1671 "&& reload_completed"
1672 [(parallel [(set (match_dup 0)
1673 (ashift:HI (match_dup 1) (match_dup 2)))
1674 (clobber (reg:CC CC_REGNUM))])]
1676 [(set_attr "length" "2,4")
1677 (set_attr "base_cost" "8")])
1679 (define_insn "aslhi_op<cc_ccnz>"
1680 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1681 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1682 (match_operand:HI 2 "general_operand" "rR,Qi")))
1683 (clobber (reg:CC CC_REGNUM))]
1684 "TARGET_40_PLUS && reload_completed"
1686 [(set_attr "length" "2,4")
1687 (set_attr "base_cost" "8")])
1689 (define_insn_and_split "aslsi_op"
1690 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1691 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1692 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1695 "&& reload_completed"
1696 [(parallel [(set (match_dup 0)
1697 (ashift:SI (match_dup 1) (match_dup 2)))
1698 (clobber (reg:CC CC_REGNUM))])]
1700 [(set_attr "length" "2,4")
1701 (set_attr "base_cost" "8")])
1703 (define_insn "aslsi_op_<cc_ccnz>"
1704 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1705 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1706 (match_operand:HI 2 "general_operand" "rR,Qi")))
1707 (clobber (reg:CC CC_REGNUM))]
1708 "TARGET_40_PLUS && reload_completed"
1710 [(set_attr "length" "2,4")
1711 (set_attr "base_cost" "8")])
1713 ;; Now the expanders that produce the insns defined above.
1714 (define_expand "ashl<mode>3"
1715 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1716 (match_operand:QHSint 1 "general_operand" "")
1717 (match_operand:HI 2 "general_operand" "")]
1723 if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base))
1725 if (<QHSint:e_mname> == E_QImode)
1727 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1728 emit_insn (gen_aslhi_op (r, r, operands[2]));
1729 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1733 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1739 (define_expand "ashr<mode>3"
1740 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1741 (match_operand:QHSint 1 "general_operand" "")
1742 (match_operand:HI 2 "general_operand" "")]
1748 if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base))
1750 operands[2] = negate_rtx (HImode, operands[2]);
1751 if (<QHSint:e_mname> == E_QImode)
1753 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1754 emit_insn (gen_aslhi_op (r, r, operands[2]));
1755 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1759 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1765 (define_expand "lshr<mode>3"
1766 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1767 (match_operand:QHSint 1 "general_operand" "")
1768 (match_operand:HI 2 "general_operand" "")]
1774 if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base))
1776 if (<QHSint:e_mname> == E_QImode)
1778 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1779 emit_insn (gen_aslhi_op (r, r, operands[2]));
1780 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1784 r = gen_reg_rtx (<QHSint:mname>);
1785 emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx));
1786 if (GET_CODE (operands[2]) != CONST_INT)
1788 n = gen_reg_rtx (HImode);
1789 emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1)));
1790 emit_insn (gen_ashr<mode>3 (operands[0], r, n));
1793 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r,
1794 GEN_INT (1 - INTVAL (operands[2]))));
1802 (define_insn_and_split "absdf2"
1803 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1804 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1807 "&& reload_completed"
1808 [(parallel [(set (match_dup 0) (abs:DF (match_dup 1)))
1809 (clobber (reg:CC FCC_REGNUM))])]
1811 [(set_attr "length" "2,4")])
1813 (define_insn "absdf2<fcc_cc>"
1814 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1815 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))
1816 (clobber (reg:CC FCC_REGNUM))]
1817 "TARGET_FPU && reload_completed"
1819 [(set_attr "length" "2,4")])
1823 (define_insn_and_split "negdf2"
1824 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1825 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
1828 "&& reload_completed"
1829 [(parallel [(set (match_dup 0) (neg:DF (match_dup 1)))
1830 (clobber (reg:CC FCC_REGNUM))])]
1832 [(set_attr "length" "2,4")])
1834 (define_insn "negdf2<fcc_cc>"
1835 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1836 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))
1837 (clobber (reg:CC FCC_REGNUM))]
1838 "TARGET_FPU && reload_completed"
1840 [(set_attr "length" "2,4")])
1842 (define_insn_and_split "negdi2"
1843 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1844 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1848 [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
1849 (clobber (reg:CC CC_REGNUM))])]
1851 [(set_attr "length" "18,34")])
1853 ;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1854 (define_insn "negdi2_nocc"
1855 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1856 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))
1857 (clobber (reg:CC CC_REGNUM))]
1863 inops[0] = operands[0];
1864 pdp11_expand_operands (inops, exops, 1, 4, NULL, big);
1866 output_asm_insn (\"com\t%0\", exops[3]);
1867 output_asm_insn (\"com\t%0\", exops[2]);
1868 output_asm_insn (\"com\t%0\", exops[1]);
1869 output_asm_insn (\"com\t%0\", exops[0]);
1870 output_asm_insn (\"add\t%#1,%0\", exops[3]);
1871 output_asm_insn (\"adc\t%0\", exops[2]);
1872 output_asm_insn (\"adc\t%0\", exops[1]);
1873 output_asm_insn (\"adc\t%0\", exops[0]);
1877 [(set_attr "length" "18,34")
1878 (set_attr "base_cost" "0")])
1880 (define_insn_and_split "negsi2"
1881 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1882 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1886 [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
1887 (clobber (reg:CC CC_REGNUM))])]
1889 [(set_attr "length" "10,18")])
1891 ;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1892 (define_insn "negsi2_nocc"
1893 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1894 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))
1895 (clobber (reg:CC CC_REGNUM))]
1901 inops[0] = operands[0];
1902 pdp11_expand_operands (inops, exops, 1, 2, NULL, big);
1904 output_asm_insn (\"com\t%0\", exops[1]);
1905 output_asm_insn (\"com\t%0\", exops[0]);
1906 output_asm_insn (\"add\t%#1,%0\", exops[1]);
1907 output_asm_insn (\"adc\t%0\", exops[0]);
1911 [(set_attr "length" "10,18")
1912 (set_attr "base_cost" "0")])
1914 (define_insn_and_split "neg<mode>2"
1915 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1916 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1920 [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1)))
1921 (clobber (reg:CC CC_REGNUM))])]
1923 [(set_attr "length" "2,4")])
1925 (define_insn "neg<mode>2<cc_ccnz>"
1926 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1927 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1928 (clobber (reg:CC CC_REGNUM))]
1930 "neg<PDPint:isfx>\t%0"
1931 [(set_attr "length" "2,4")])
1934 ;; Unconditional and other jump instructions
1937 (label_ref (match_operand 0 "" "")))]
1941 if (get_attr_length (insn) == 2)
1943 return \"jmp\t%l0\";
1945 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1947 (const_int MIN_BRANCH))
1948 (gt (minus (match_dup 0)
1950 (const_int MAX_BRANCH)))
1954 (define_insn "tablejump"
1955 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1956 (use (label_ref (match_operand 1 "" "")))]
1962 [(set_attr "length" "2,2,4")])
1964 ;; indirect jump. TODO: this needs a constraint that allows memory
1965 ;; references but not indirection, since we add a level of indirection
1966 ;; in the generated code.
1967 (define_insn "indirect_jump"
1968 [(set (pc) (match_operand:HI 0 "general_operand" "r"))]
1971 [(set_attr "length" "2")])
1973 ;;- jump to subroutine
1976 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1977 (match_operand:HI 1 "general_operand" "g,g"))]
1978 ;;- Don't use operand 1 for most machines.
1981 [(set_attr "length" "2,4")])
1983 ;;- jump to subroutine
1984 (define_insn "call_value"
1985 [(set (match_operand 0 "" "")
1986 (call (match_operand:HI 1 "general_operand" "rR,Q")
1987 (match_operand:HI 2 "general_operand" "g,g")))]
1988 ;;- Don't use operand 2 for most machines.
1991 [(set_attr "length" "2,4")])
1993 (define_expand "untyped_call"
1994 [(parallel [(call (match_operand 0 "" "")
1996 (match_operand 1 "" "")
1997 (match_operand 2 "" "")])]
2002 emit_call_insn (gen_call (operands[0], const0_rtx));
2004 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2006 rtx set = XVECEXP (operands[2], 0, i);
2007 emit_move_insn (SET_DEST (set), SET_SRC (set));
2010 /* The optimizer does not know that the call sets the function value
2011 registers we stored in the result block. We avoid problems by
2012 claiming that all hard registers are used and clobbered at this
2014 emit_insn (gen_blockage ());
2028 (define_insn_and_split "muldf3"
2029 [(set (match_operand:DF 0 "register_operand" "=a,a")
2030 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
2031 (match_operand:DF 2 "float_operand" "fR,QF")))]
2034 "&& reload_completed"
2035 [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2)))
2036 (clobber (reg:CC FCC_REGNUM))])]
2038 [(set_attr "length" "2,4")])
2040 (define_insn "muldf3<fcc_ccnz>"
2041 [(set (match_operand:DF 0 "register_operand" "=a,a")
2042 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
2043 (match_operand:DF 2 "float_operand" "fR,QF")))
2044 (clobber (reg:CC FCC_REGNUM))]
2045 "TARGET_FPU && reload_completed"
2046 "{muld|mulf}\t%2,%0"
2047 [(set_attr "length" "2,4")
2048 (set_attr "base_cost" "20")])
2050 ;; 16 bit result multiply. This uses odd numbered registers.
2052 (define_insn_and_split "mulhi3"
2053 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
2054 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2055 (match_operand:HI 2 "general_operand" "rR,Qi")))]
2058 "&& reload_completed"
2059 [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2)))
2060 (clobber (reg:CC CC_REGNUM))])]
2062 [(set_attr "length" "2,4")])
2064 (define_insn "mulhi3<cc_cc>"
2065 [(set (match_operand:HI 0 "register_operand" "=d,d")
2066 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2067 (match_operand:HI 2 "general_operand" "rR,Qi")))
2068 (clobber (reg:CC CC_REGNUM))]
2069 "TARGET_40_PLUS && reload_completed"
2071 [(set_attr "length" "2,4")
2072 (set_attr "base_cost" "20")])
2074 ;; 32 bit result from 16 bit operands
2075 (define_insn_and_split "mulhisi3"
2076 [(set (match_operand:SI 0 "register_operand" "=r,r")
2077 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
2078 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))]
2081 "&& reload_completed"
2082 [(parallel [(set (match_dup 0)
2083 (mult:SI (sign_extend:SI (match_dup 1))
2084 (sign_extend:SI (match_dup 2))))
2085 (clobber (reg:CC CC_REGNUM))])]
2087 [(set_attr "length" "2,4")])
2089 (define_insn "mulhisi3<cc_cc>"
2090 [(set (match_operand:SI 0 "register_operand" "=r,r")
2091 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
2092 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))
2093 (clobber (reg:CC CC_REGNUM))]
2094 "TARGET_40_PLUS && reload_completed"
2096 [(set_attr "length" "2,4")
2097 (set_attr "base_cost" "20")])
2100 (define_insn_and_split "divdf3"
2101 [(set (match_operand:DF 0 "register_operand" "=a,a")
2102 (div:DF (match_operand:DF 1 "register_operand" "0,0")
2103 (match_operand:DF 2 "general_operand" "fR,QF")))]
2106 "&& reload_completed"
2107 [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2)))
2108 (clobber (reg:CC FCC_REGNUM))])]
2110 [(set_attr "length" "2,4")])
2112 (define_insn "divdf3<fcc_ccnz>"
2113 [(set (match_operand:DF 0 "register_operand" "=a,a")
2114 (div:DF (match_operand:DF 1 "register_operand" "0,0")
2115 (match_operand:DF 2 "general_operand" "fR,QF")))
2116 (clobber (reg:CC FCC_REGNUM))]
2117 "TARGET_FPU && reload_completed"
2118 "{divd|divf}\t%2,%0"
2119 [(set_attr "length" "2,4")
2120 (set_attr "base_cost" "20")])
2122 (define_expand "divmodhi4"
2124 [(set (subreg:HI (match_dup 1) 0)
2125 (div:HI (match_operand:SI 1 "register_operand" "0")
2126 (match_operand:HI 2 "general_operand" "g")))
2127 (set (subreg:HI (match_dup 1) 2)
2128 (mod:HI (match_dup 1) (match_dup 2)))])
2129 (set (match_operand:HI 0 "register_operand" "=r")
2130 (subreg:HI (match_dup 1) 0))
2131 (set (match_operand:HI 3 "register_operand" "=r")
2132 (subreg:HI (match_dup 1) 2))]
2136 (define_insn_and_split "*divmodhi4"
2137 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
2138 (div:HI (match_operand:SI 1 "register_operand" "0,0")
2139 (match_operand:HI 2 "general_operand" "rR,Qi")))
2140 (set (subreg:HI (match_dup 1) 2)
2141 (mod:HI (match_dup 1) (match_dup 2)))]
2144 "&& reload_completed"
2145 [(parallel [(set (subreg:HI (match_dup 0) 0)
2146 (div:HI (match_dup 1) (match_dup 2)))
2147 (set (subreg:HI (match_dup 1) 2)
2148 (mod:HI (match_dup 1) (match_dup 2)))
2149 (clobber (reg:CC CC_REGNUM))])]
2151 [(set_attr "length" "2,4")])
2153 ;; Note that there is no corresponding CC setter pattern.
2154 ;; The reason is that it won't be generated, because
2155 ;; compare-elim.c only does the transformation on input
2156 ;; insns that have a two-element PARALLEL, as opposed to
2157 ;; the three-element one we have here.
2158 (define_insn "divmodhi4_nocc"
2159 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
2160 (div:HI (match_operand:SI 1 "register_operand" "0,0")
2161 (match_operand:HI 2 "general_operand" "rR,Qi")))
2162 (set (subreg:HI (match_dup 1) 2)
2163 (mod:HI (match_dup 1) (match_dup 2)))
2164 (clobber (reg:CC CC_REGNUM))]
2167 [(set_attr "length" "2,4")
2168 (set_attr "base_cost" "40")])
2171 (define_insn_and_split "bswaphi2"
2172 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2173 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))]
2177 [(parallel [(set (match_dup 0) (bswap:HI (match_dup 1)))
2178 (clobber (reg:CC CC_REGNUM))])]
2180 [(set_attr "length" "2,4")])
2182 (define_insn "bswaphi2<cc_ccnz>"
2183 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2184 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))
2185 (clobber (reg:CC CC_REGNUM))]
2188 [(set_attr "length" "2,4")])
2190 (define_insn_and_split "bswapsi2"
2191 [(set (match_operand:SI 0 "register_operand" "=&r")
2192 (bswap:SI (match_operand:SI 1 "general_operand" "g")))]
2196 [(parallel [(set (match_dup 0)
2197 (bswap:SI (match_dup 1)))
2198 (clobber (reg:CC CC_REGNUM))])]
2200 [(set_attr "length" "10")])
2202 (define_insn "bswapsi2_nocc"
2203 [(set (match_operand:SI 0 "register_operand" "=&r,&r,&r")
2204 (bswap:SI (match_operand:SI 1 "general_operand" "r,D,Q")))
2205 (clobber (reg:CC CC_REGNUM))]
2212 inops[0] = operands[0];
2213 inops[1] = operands[1];
2214 pdp11_expand_operands (inops, exops, 2, 2, NULL, either);
2217 exops[0][0] = exops[1][0];
2220 output_asm_insn ("mov\t%0,%1", exops[0]);
2221 output_asm_insn ("mov\t%0,%1", exops[1]);
2222 output_asm_insn ("swab\t%0", exops[0]);
2223 output_asm_insn ("swab\t%0", exops[1]);
2226 [(set_attr "length" "8,10,12")])
2228 (define_expand "rotrhi3"
2229 [(match_operand:HI 0 "register_operand" "")
2230 (match_operand:HI 1 "register_operand" "")
2231 (match_operand:HI 2 "general_operand" "")]
2235 operands[2] = negate_rtx (HImode, operands[2]);
2236 emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2]));
2240 (define_insn_and_split "rotlhi3"
2241 [(set (match_operand:HI 0 "register_operand" "=d,d")
2242 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2243 (match_operand:HI 2 "general_operand" "rR,Qi")))]
2246 "&& reload_completed"
2247 [(parallel [(set (match_dup 0)
2248 (rotate:HI (match_dup 1) (match_dup 2)))
2249 (clobber (reg:CC CC_REGNUM))])]
2251 [(set_attr "length" "2,4")
2252 (set_attr "base_cost" "8")])
2254 (define_insn "rotlhi3<cc_ccnz>"
2255 [(set (match_operand:HI 0 "register_operand" "=d,d")
2256 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2257 (match_operand:HI 2 "general_operand" "rR,Qi")))
2258 (clobber (reg:CC CC_REGNUM))]
2259 "TARGET_40_PLUS && reload_completed"
2261 [(set_attr "length" "2,4")
2262 (set_attr "base_cost" "8")])
2266 ;; Some peephole optimizations
2268 ;; Move then conditional branch on the result of the move is handled
2269 ;; by compare elimination, but an earlier pass sometimes changes the
2270 ;; compare operand to the move input, and then the compare is not
2271 ;; eliminated. Do so here.
2273 [(parallel [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
2274 (match_operand:PDPint 1 "general_operand" ""))
2275 (clobber (reg:CC CC_REGNUM))])
2276 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))]
2278 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
2279 (set (match_dup 0) (match_dup 1))])]