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"
36 (HARD_FRAME_POINTER_REGNUM 5)
37 (STACK_POINTER_REGNUM 6)
43 ;; The next two are not physical registers but are used for addressing
45 (FRAME_POINTER_REGNUM 14)
46 (ARG_POINTER_REGNUM 15)
47 ;; Condition code registers
50 ;; End of hard registers
51 (FIRST_PSEUDO_REGISTER 18)
53 ;; Branch offset limits, as byte offsets from instruction address
65 ;; Integer modes supported on the PDP11, with a mapping from machine mode
66 ;; to mnemonic suffix. SImode and DImode are usually special cases.
67 (define_mode_iterator PDPint [QI HI])
68 (define_mode_attr isfx [(QI "b") (HI "")])
69 (define_mode_attr mname [(QI "QImode") (HI "HImode") (SI "SImode") (DI "DImode")])
70 (define_mode_attr e_mname [(QI "E_QImode") (HI "E_HImode") (SI "E_SImode") (DI "E_DImode")])
71 (define_mode_attr hmode [(QI "hi") (HI "hi") (SI "si") (DI "di")])
73 ;; These are analogous for use in splitters and expanders.
74 (define_mode_iterator HSint [HI SI])
75 (define_mode_iterator QHSint [QI HI SI])
76 (define_mode_iterator QHSDint [QI HI SI DI])
78 (define_code_iterator SHF [ashift ashiftrt lshiftrt])
80 ;; Substitution to turn a CC clobber into a CC setter. We have four of
81 ;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
83 [(set (match_operand 0 "") (match_operand 1 ""))
84 (clobber (reg CC_REGNUM))]
86 [(set (reg:CC CC_REGNUM)
87 (compare:CC (match_dup 1) (const_int 0)))
88 (set (match_dup 0) (match_dup 1))])
90 (define_subst "cc_ccnz"
91 [(set (match_operand 0 "") (match_operand 1 ""))
92 (clobber (reg CC_REGNUM))]
94 [(set (reg:CCNZ CC_REGNUM)
95 (compare:CCNZ (match_dup 1) (const_int 0)))
96 (set (match_dup 0) (match_dup 1))])
98 (define_subst "fcc_cc"
99 [(set (match_operand 0 "") (match_operand 1 ""))
100 (clobber (reg FCC_REGNUM))]
102 [(set (reg:CC FCC_REGNUM)
103 (compare:CC (match_dup 1) (const_int 0)))
104 (set (match_dup 0) (match_dup 1))])
106 (define_subst "fcc_ccnz"
107 [(set (match_operand 0 "") (match_operand 1 ""))
108 (clobber (reg FCC_REGNUM))]
110 [(set (reg:CCNZ FCC_REGNUM)
111 (compare:CCNZ (match_dup 1) (const_int 0)))
112 (set (match_dup 0) (match_dup 1))])
114 (define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
115 (define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc")
116 (define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc")
117 (define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc")
119 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
121 ;; Compare instructions.
123 ;; currently we only support df floats, which saves us quite some
124 ;; hassle switching the FP mode!
125 ;; we assume that CPU is always in long float mode, and
126 ;; 16 bit integer mode - currently, the prologue for main does this,
127 ;; but maybe we should just set up a NEW crt0 properly,
128 ;; -- and what about signal handling code?
129 ;; (we don't even let sf floats in the register file, so
130 ;; we only should have to worry about truncating and widening
131 ;; when going to memory)
133 ;; abort() call by g++ - must define libfunc for cmp_optab
134 ;; and ucmp_optab for mode SImode, because we don't have that!!!
135 ;; - yet since no libfunc is there, we abort ()
138 ;; currently type is only fpu or arith or unknown, maybe branch later ?
140 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
142 ;; length default is 2 bytes each
143 (define_attr "length" "" (const_int 2))
145 ;; a user's asm statement
146 (define_asm_attributes
147 [(set_attr "type" "unknown")
148 ; length for asm is the max length per statement. That would be
149 ; 3 words, for a two-operand instruction with extra word addressing
150 ; modes for both operands.
151 (set_attr "length" "6")])
153 ;; define function units
155 ;; Prologue and epilogue support.
157 (define_expand "prologue"
161 pdp11_expand_prologue ();
165 (define_expand "epilogue"
169 pdp11_expand_epilogue ();
173 (define_expand "return"
175 "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
183 (define_insn "blockage"
184 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
187 [(set_attr "length" "0")])
190 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
195 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
199 ;; arithmetic - values here immediately when next insn issued
200 ;; or does it mean the number of cycles after this insn was issued?
201 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
203 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
204 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
207 (define_insn "*cmpdf"
208 [(set (reg:CC FCC_REGNUM)
209 (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
210 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
211 "TARGET_FPU && reload_completed"
214 if (which_alternative == 0 || which_alternative == 2)
215 return \"{tstd|tstf}\t%0\";
217 return \"{cmpd|cmpf}\t%0,%1\";
219 [(set_attr "length" "2,2,4,4")
220 (set_attr "type" "fp")])
222 ;; Copy floating point processor condition code register to main CPU
223 ;; condition code register.
225 [(set (reg CC_REGNUM) (reg FCC_REGNUM))]
226 "TARGET_FPU && reload_completed"
229 (define_insn "cmp<mode>"
230 [(set (reg:CC CC_REGNUM)
231 (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
232 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
236 cmp<PDPint:isfx>\t%0,%1
237 cmp<PDPint:isfx>\t%0,%1
239 cmp<PDPint:isfx>\t%0,%1
240 cmp<PDPint:isfx>\t%0,%1"
241 [(set_attr "length" "2,2,4,4,4,6")])
243 ;; sob instruction - FIXME: this doesn't do anything, need to use doloop_end.
248 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
251 (label_ref (match_operand 1 "" ""))
254 (plus:HI (match_dup 0)
259 if (get_attr_length (insn) == 2)
260 return \"sob\t%0,%l1\";
263 operands[2] = gen_label_rtx ();
264 output_asm_insn (\"dec\t%0\", operands);
265 output_asm_insn (\"beq\t%l2\", operands);
266 output_asm_insn (\"jmp\t%l1\", operands);
268 output_asm_label (operands[2]);
269 fputs (\":\\n\", asm_out_file);
273 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
276 (gt (minus (match_dup 0)
278 (const_int MAX_SOB)))
282 ;; These control RTL generation for conditional jump insns
283 ;; and match them for register allocation.
284 ;; Post reload these get expanded into insns that actually
285 ;; manipulate the condition code registers. We can't do that before
286 ;; because instructions generated by reload clobber condition codes (new
287 ;; CC design, type #2).
288 (define_insn_and_split "cbranchdf4"
290 (if_then_else (match_operator 0 "ordered_comparison_operator"
291 [(match_operand:DF 1 "general_operand" "fg")
292 (match_operand:DF 2 "general_operand" "a")])
293 (label_ref (match_operand 3 "" ""))
297 "&& reload_completed"
298 [(set (reg:CC FCC_REGNUM)
299 (compare:CC (match_dup 1) (match_dup 2)))
301 (if_then_else (match_op_dup 0
302 [(reg:CC FCC_REGNUM) (const_int 0)])
303 (label_ref (match_dup 3))
307 (define_insn_and_split "cbranch<mode>4"
309 (if_then_else (match_operator 0 "ordered_comparison_operator"
310 [(match_operand:PDPint 1 "general_operand" "g")
311 (match_operand:PDPint 2 "general_operand" "g")])
312 (label_ref (match_operand 3 "" ""))
317 [(set (reg:CC CC_REGNUM)
318 (compare:CC (match_dup 1) (match_dup 2)))
320 (if_then_else (match_op_dup 0
321 [(reg:CC CC_REGNUM) (const_int 0)])
322 (label_ref (match_dup 3))
326 ;; This splitter turns a branch on float condition into a branch on
327 ;; CPU condition, by adding a CFCC.
330 (if_then_else (match_operator 0 "ordered_comparison_operator"
331 [(reg:CC FCC_REGNUM) (const_int 0)])
332 (label_ref (match_operand 1 "" ""))
334 "TARGET_FPU && reload_completed"
335 [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM))
337 (if_then_else (match_op_dup 0
338 [(reg:CC CC_REGNUM) (const_int 0)])
339 (label_ref (match_dup 1))
343 (define_insn "cond_branch"
345 (if_then_else (match_operator 0 "ordered_comparison_operator"
346 [(reg:CC CC_REGNUM) (const_int 0)])
347 (label_ref (match_operand 1 "" ""))
350 "* return output_jump (operands, 0, get_attr_length (insn));"
351 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
353 (const_int MIN_BRANCH))
354 (gt (minus (match_dup 1)
356 (const_int MAX_BRANCH)))
360 (define_insn "*branch"
362 (if_then_else (match_operator 0 "ccnz_operator"
363 [(reg:CCNZ CC_REGNUM) (const_int 0)])
364 (label_ref (match_operand 1 "" ""))
367 "* return output_jump (operands, 1, get_attr_length (insn));"
368 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
370 (const_int MIN_BRANCH))
371 (gt (minus (match_dup 1)
373 (const_int MAX_BRANCH)))
381 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
382 (match_operand:DI 1 "general_operand" "rN,g"))]
387 (define_insn "*movdi_nocc"
388 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
389 (match_operand:DI 1 "general_operand" "rN,g"))
390 (clobber (reg:CC CC_REGNUM))]
392 "* return output_move_multiple (operands);"
393 [(set_attr "length" "16,32")])
396 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
397 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
401 (define_insn "*movsi_nocc"
402 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
403 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))
404 (clobber (reg:CC CC_REGNUM))]
406 "* return output_move_multiple (operands);"
407 [(set_attr "length" "4,6,8,16")])
409 (define_insn "mov<mode>"
410 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
411 (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
415 ;; This splits all the integer moves: DI and SI modes as well as
416 ;; the simple machine operations.
418 [(set (match_operand:QHSDint 0 "nonimmediate_operand" "")
419 (match_operand:QHSDint 1 "general_operand" ""))]
421 [(parallel [(set (match_dup 0)
423 (clobber (reg:CC CC_REGNUM))])]
427 (define_insn "*mov<mode>_<cc_cc>"
428 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
429 (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))
430 (clobber (reg:CC CC_REGNUM))]
434 if (operands[1] == const0_rtx)
435 return \"clr<PDPint:isfx>\t%0\";
437 return \"mov<PDPint:isfx>\t%1,%0\";
439 [(set_attr "length" "2,4,4,6")])
441 ;; movdf has unusually complicated condition code handling, because
442 ;; load (into float register) updates the FCC, while store (from
443 ;; float register) leaves it untouched.
445 ;; 1. Loads are: ac4, ac5, or non-register into load-register
446 ;; 2. Stores are: load-register to non-register, ac4, or ac5
447 ;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled
448 ;; either as loads or as stores.
450 (define_expand "movdf"
451 [(set (match_operand:DF 0 "float_nonimm_operand" "")
452 (match_operand:DF 1 "float_operand" ""))]
456 ;; Splitter for all these cases. Store is the first two
457 ;; alternatives, which are not split. Note that case 3
458 ;; is treated as a store, i.e., not split.
459 (define_insn_and_split "movdf_split"
460 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,FQ,a,a,a")
461 (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))]
464 gcc_assert (which_alternative < 2);
465 return \"std\t%1,%0\";
467 "&& reload_completed"
468 [(parallel [(set (match_dup 0)
470 (clobber (reg:CC FCC_REGNUM))])]
472 if (GET_CODE (operands[1]) == REG &&
473 REGNO_REG_CLASS (REGNO (operands[1])) == LOAD_FPU_REGS)
476 [(set_attr "length" "2,4,0,0,0")])
479 (define_insn "*ldd<fcc_cc>"
480 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,a,a")
481 (match_operand:DF 1 "float_operand" "hR,FQ,G"))
482 (clobber (reg:CC FCC_REGNUM))]
483 "TARGET_FPU && reload_completed"
488 [(set_attr "length" "2,4,2")])
490 ;; SFmode is easier because that uses convert load/store, which
491 ;; always change condition codes.
492 ;; Note that these insns are cheating a bit. We actually have
493 ;; DFmode operands in the FPU registers, which is why the
494 ;; ldcfd and stcdf instructions appear. But GCC likes to think
495 ;; of these as SFmode loads and does the conversion once in the
496 ;; register, at least in many cases. So we pretend to do this,
497 ;; but then extend and truncate register-to-register are NOP and
499 (define_insn_and_split "movsf"
500 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q")
501 (match_operand:SF 1 "float_operand" "fRG,a,FQ,a"))]
504 "&& reload_completed"
505 [(parallel [(set (match_dup 0)
507 (clobber (reg:CC FCC_REGNUM))])]
510 (define_insn "*movsf<fcc_ccnz>"
511 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
512 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G"))
513 (clobber (reg:CC FCC_REGNUM))]
514 "TARGET_FPU && reload_completed"
521 [(set_attr "length" "2,2,4,4,2")])
523 ;; maybe fiddle a bit with move_ratio, then
524 ;; let constraints only accept a register ...
526 (define_expand "movmemhi"
527 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
528 (match_operand:BLK 1 "general_operand" "g,g"))
529 (use (match_operand:HI 2 "general_operand" "n,mr"))
530 (use (match_operand:HI 3 "immediate_operand" "i,i"))
531 (clobber (match_scratch:HI 6 "=&r,X"))
532 (clobber (match_dup 4))
533 (clobber (match_dup 5))
534 (clobber (match_dup 2))])]
539 = replace_equiv_address (operands[0],
540 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
542 = replace_equiv_address (operands[1],
543 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
545 operands[4] = XEXP (operands[0], 0);
546 operands[5] = XEXP (operands[1], 0);
550 (define_insn "*movmemhi1"
551 [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
552 (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
553 (use (match_operand:HI 2 "general_operand" "n,r"))
554 (use (match_operand:HI 3 "immediate_operand" "i,i"))
555 (clobber (match_scratch:HI 4 "=&r,X"))
556 (clobber (match_dup 0))
557 (clobber (match_dup 1))
558 (clobber (match_dup 2))]
560 "* return output_block_move (operands);"
562 [(set_attr "length" "80")])
566 ;;- truncation instructions
568 ;; We sometimes end up doing a register to register truncate,
569 ;; which isn't right because we actually load registers always
570 ;; with a DFmode value. But even with PROMOTE the compiler
571 ;; doesn't always get that (so we don't use it). That means
572 ;; a register to register truncate is a NOP.
573 (define_insn_and_split "truncdfsf2"
574 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
575 (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))]
578 gcc_assert (which_alternative == 0);
581 "&& reload_completed"
582 [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1)))
583 (clobber (reg:CC FCC_REGNUM))])]
585 if (GET_CODE (operands[0]) == REG &&
586 GET_CODE (operands[1]) == REG &&
587 REGNO (operands[0]) == REGNO (operands[1]))
590 [(set_attr "length" "0,0,0")])
592 (define_insn "*truncdfsf2_<fcc_cc>"
593 [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q")
594 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a")))
595 (clobber (reg:CC FCC_REGNUM))]
596 "TARGET_FPU && reload_completed"
597 "{stcdf|movfo}\t%1,%0"
598 [(set_attr "length" "2,4")])
601 ;;- zero extension instructions
603 (define_insn_and_split "zero_extendqihi2"
604 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
605 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
609 [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
610 (clobber (reg:CC CC_REGNUM))])]
613 (define_insn "*zero_extendqihi2<cc_cc>"
614 [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
615 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))
616 (clobber (reg:CC CC_REGNUM))])]
619 [(set_attr "length" "4,6")])
621 (define_expand "zero_extendhisi2"
625 (match_operand:HI 1 "register_operand" "r"))
627 (match_operand:SI 0 "register_operand" "=r")
631 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
634 ;;- sign extension instructions
636 ;; We sometimes end up doing a register to register extend,
637 ;; which isn't right because we actually load registers always
638 ;; with a DFmode value. But even with PROMOTE the compiler
639 ;; doesn't always get that (so we don't use it). That means
640 ;; a register to register truncate is a NOP.
641 (define_insn_and_split "extendsfdf2"
642 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
643 (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))]
646 gcc_assert (which_alternative == 0);
649 "&& reload_completed"
650 [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1)))
651 (clobber (reg:CC FCC_REGNUM))])]
653 if (GET_CODE (operands[0]) == REG &&
654 GET_CODE (operands[1]) == REG &&
655 REGNO (operands[0]) == REGNO (operands[1]))
658 [(set_attr "length" "0,0,0")])
660 (define_insn "*extendsfdf2_<fcc_cc>"
661 [(set (match_operand:DF 0 "register_operand" "=a,a")
662 (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q")))
663 (clobber (reg:CC FCC_REGNUM))]
664 "TARGET_FPU && reload_completed"
665 "{ldcfd|movof}\t%1,%0"
666 [(set_attr "length" "2,4")])
668 ;; movb sign extends if destination is a register
669 (define_insn_and_split "extendqihi2"
670 [(set (match_operand:HI 0 "register_operand" "=r,r")
671 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
675 [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
676 (clobber (reg:CC CC_REGNUM))])]
680 (define_insn "*extendqihi2<cc_cc>"
681 [(set (match_operand:HI 0 "register_operand" "=r,r")
682 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))
683 (clobber (reg:CC CC_REGNUM))]
686 [(set_attr "length" "2,4")])
688 (define_insn_and_split "extendhisi2"
689 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
690 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
693 "&& reload_completed"
694 [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
695 (clobber (reg:CC CC_REGNUM))])]
698 (define_insn "*extendhisi2_nocc"
699 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
700 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))
701 (clobber (reg:CC CC_REGNUM))]
702 "TARGET_40_PLUS && reload_completed"
707 /* we don't want to mess with auto increment */
709 switch (which_alternative)
713 latehalf[0] = operands[0];
714 operands[0] = adjust_address(operands[0], HImode, 2);
716 output_asm_insn(\"mov\t%1,%0\", operands);
717 output_asm_insn(\"sxt\t%0\", latehalf);
723 /* - auto-decrement - right direction ;-) */
724 output_asm_insn(\"mov\t%1,%0\", operands);
725 output_asm_insn(\"sxt\t%0\", operands);
731 /* make register pair available */
732 latehalf[0] = operands[0];
733 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
735 output_asm_insn(\"mov\t%1,%0\", operands);
736 output_asm_insn(\"sxt\t%0\", latehalf);
745 [(set_attr "length" "10,6,6")])
747 ;; make float to int and vice versa
748 ;; assume that we are normally in double and integer mode -
749 ;; what do pdp library routines do to fpu mode ?
751 ;; Note: the hardware treats register source as
752 ;; a 16-bit (high order only) source, which isn't
753 ;; what we want. But we do need to support register
754 ;; dest because gcc asks for it.
755 (define_insn_and_split "floatsidf2"
756 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
757 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
760 "&& reload_completed"
761 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
762 (clobber (reg:CC FCC_REGNUM))])]
765 (define_insn "*floatsidf2<fcc_cc>"
766 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
767 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))
768 (clobber (reg:CC FCC_REGNUM))]
769 "TARGET_FPU && reload_completed"
770 "* if (which_alternative ==0)
775 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
776 output_asm_insn(\"mov\t%1,-(sp)\", latehalf);
777 output_asm_insn(\"mov\t%1,-(sp)\", operands);
779 output_asm_insn(\"setl\", operands);
780 output_asm_insn(\"{ldcld|movif}\t(sp)+,%0\", operands);
781 output_asm_insn(\"seti\", operands);
785 return \"setl\;{ldcld|movif}\t%1,%0\;seti\";
787 [(set_attr "length" "10,6,8")])
789 (define_insn_and_split "floathidf2"
790 [(set (match_operand:DF 0 "register_operand" "=a,a")
791 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
794 "&& reload_completed"
795 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
796 (clobber (reg:CC FCC_REGNUM))])]
799 (define_insn "*floathidf2<fcc_cc>"
800 [(set (match_operand:DF 0 "register_operand" "=a,a")
801 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))
802 (clobber (reg:CC FCC_REGNUM))]
803 "TARGET_FPU && reload_completed"
804 "{ldcid|movif}\t%1,%0"
805 [(set_attr "length" "2,4")])
809 ;; Note: the hardware treats register destination as
810 ;; a 16-bit (high order only) destination, which isn't
811 ;; what we want. But we do need to support register
812 ;; dest because gcc asks for it.
813 (define_insn_and_split "fix_truncdfsi2"
814 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
815 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
818 "&& reload_completed"
819 [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1))))
820 (clobber (reg:CC CC_REGNUM))
821 (clobber (reg:CC FCC_REGNUM))])]
824 ;; Note: this clobbers both sets of condition codes!
825 (define_insn "*fix_truncdfsi2_nocc"
826 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
827 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))
828 (clobber (reg:CC CC_REGNUM))
829 (clobber (reg:CC FCC_REGNUM))]
830 "TARGET_FPU && reload_completed"
831 "* if (which_alternative ==0)
833 output_asm_insn(\"setl\", operands);
834 output_asm_insn(\"{stcdl|movfi}\t%1,-(sp)\", operands);
835 output_asm_insn(\"seti\", operands);
836 output_asm_insn(\"mov\t(sp)+,%0\", operands);
837 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
838 output_asm_insn(\"mov\t(sp)+,%0\", operands);
842 return \"setl\;{stcdl|movfi}\t%1,%0\;seti\";
844 [(set_attr "length" "10,6,8")])
846 (define_insn_and_split "fix_truncdfhi2"
847 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
848 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
851 "&& reload_completed"
852 [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1))))
853 (clobber (reg:CC CC_REGNUM))
854 (clobber (reg:CC FCC_REGNUM))])]
857 ;; Note: this clobbers both sets of condition codes!
858 (define_insn "*fix_truncdfhi2_nocc"
859 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
860 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))
861 (clobber (reg:CC CC_REGNUM))
862 (clobber (reg:CC FCC_REGNUM))]
863 "TARGET_FPU && reload_completed"
864 "{stcdi|movfi}\t%1,%0"
865 [(set_attr "length" "2,4")])
868 ;;- arithmetic instructions
871 (define_insn_and_split "adddf3"
872 [(set (match_operand:DF 0 "register_operand" "=a,a")
873 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
874 (match_operand:DF 2 "general_operand" "fR,QF")))]
877 "&& reload_completed"
878 [(parallel [(set (match_dup 0)
879 (plus:DF (match_dup 1) (match_dup 2)))
880 (clobber (reg:CC FCC_REGNUM))])]
883 ;; Float add sets V if overflow from add
884 (define_insn "*adddf3<fcc_ccnz>"
885 [(set (match_operand:DF 0 "register_operand" "=a,a")
886 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
887 (match_operand:DF 2 "general_operand" "fR,QF")))
888 (clobber (reg:CC FCC_REGNUM))]
889 "TARGET_FPU && reload_completed"
891 [(set_attr "length" "2,4")])
893 (define_insn_and_split "adddi3"
894 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
895 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
896 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
900 [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
901 (clobber (reg:CC CC_REGNUM))])]
904 (define_insn "*adddi3_nocc"
905 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
906 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
907 (match_operand:DI 2 "general_operand" "r,on,r,on")))
908 (clobber (reg:CC CC_REGNUM))]
915 inops[0] = operands[0];
916 inops[1] = operands[2];
917 pdp11_expand_operands (inops, exops, 2, NULL, either);
919 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
920 output_asm_insn (\"add\t%1,%0\", exops[0]);
921 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
923 output_asm_insn (\"add\t%1,%0\", exops[1]);
924 output_asm_insn (\"adc\t%0\", exops[0]);
926 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
928 output_asm_insn (\"add\t%1,%0\", exops[2]);
929 output_asm_insn (\"adc\t%0\", exops[1]);
930 output_asm_insn (\"adc\t%0\", exops[0]);
932 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
934 output_asm_insn (\"add\t%1,%0\", exops[3]);
935 output_asm_insn (\"adc\t%0\", exops[2]);
936 output_asm_insn (\"adc\t%0\", exops[1]);
937 output_asm_insn (\"adc\t%0\", exops[0]);
942 [(set_attr "length" "20,28,40,48")])
944 ;; Note that the register operand is not marked earlyclobber.
945 ;; The reason is that SI values go in register pairs, so they
946 ;; can't partially overlap. They can be either disjoint, or
947 ;; source and destination can be equal. The latter case is
948 ;; handled properly because of the ordering of the individual
949 ;; instructions used. Specifically, carry from the low to the
950 ;; high word is added at the end, so the adding of the high parts
951 ;; will always used the original high part and not a high part
952 ;; modified by carry (which would amount to double carry).
953 (define_insn_and_split "addsi3"
954 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
955 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
956 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
960 [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
961 (clobber (reg:CC CC_REGNUM))])]
964 (define_insn "*addsi3_nocc"
965 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
966 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
967 (match_operand:SI 2 "general_operand" "r,on,r,on")))
968 (clobber (reg:CC CC_REGNUM))]
975 inops[0] = operands[0];
976 inops[1] = operands[2];
977 pdp11_expand_operands (inops, exops, 2, NULL, either);
979 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
980 output_asm_insn (\"add\t%1,%0\", exops[0]);
981 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
983 output_asm_insn (\"add\t%1,%0\", exops[1]);
984 output_asm_insn (\"adc\t%0\", exops[0]);
989 [(set_attr "length" "6,10,12,16")])
991 (define_insn_and_split "addhi3"
992 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
993 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
994 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
998 [(parallel [(set (match_dup 0)
999 (plus:HI (match_dup 1) (match_dup 2)))
1000 (clobber (reg:CC CC_REGNUM))])]
1003 ;; Add sets V if overflow from the add
1004 (define_insn "*addhi3<cc_ccnz>"
1005 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1006 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1007 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1008 (clobber (reg:CC CC_REGNUM))]
1012 if (GET_CODE (operands[2]) == CONST_INT)
1014 if (INTVAL(operands[2]) == 1)
1016 else if (INTVAL(operands[2]) == -1)
1020 return \"add\t%2,%0\";
1022 [(set_attr "length" "2,4,4,6")])
1025 ;;- subtract instructions
1026 ;; we don't have to care for constant second
1027 ;; args, since they are canonical plus:xx now!
1028 ;; also for minus:DF ??
1030 (define_insn_and_split "subdf3"
1031 [(set (match_operand:DF 0 "register_operand" "=a,a")
1032 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1033 (match_operand:DF 2 "general_operand" "fR,Q")))]
1036 "&& reload_completed"
1037 [(parallel [(set (match_dup 0)
1038 (minus:DF (match_dup 1) (match_dup 2)))
1039 (clobber (reg:CC FCC_REGNUM))])]
1042 (define_insn "*subdf3<fcc_ccnz>"
1043 [(set (match_operand:DF 0 "register_operand" "=a,a")
1044 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1045 (match_operand:DF 2 "general_operand" "fR,QF")))
1046 (clobber (reg:CC FCC_REGNUM))]
1047 "TARGET_FPU && reload_completed"
1048 "{subd|subf}\t%2,%0"
1049 [(set_attr "length" "2,4")])
1051 (define_insn_and_split "subdi3"
1052 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1053 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1054 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1058 [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
1059 (clobber (reg:CC CC_REGNUM))])]
1062 (define_insn "*subdi3_nocc"
1063 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1064 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1065 (match_operand:DI 2 "general_operand" "r,on,r,on")))
1066 (clobber (reg:CC CC_REGNUM))]
1073 inops[0] = operands[0];
1074 inops[1] = operands[2];
1075 pdp11_expand_operands (inops, exops, 2, NULL, either);
1077 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1078 output_asm_insn (\"sub\t%1,%0\", exops[0]);
1079 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1081 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1082 output_asm_insn (\"sbc\t%0\", exops[0]);
1084 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1086 output_asm_insn (\"sub\t%1,%0\", exops[2]);
1087 output_asm_insn (\"sbc\t%0\", exops[1]);
1088 output_asm_insn (\"sbc\t%0\", exops[0]);
1090 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1092 output_asm_insn (\"sub\t%1,%0\", exops[3]);
1093 output_asm_insn (\"sbc\t%0\", exops[2]);
1094 output_asm_insn (\"sbc\t%0\", exops[1]);
1095 output_asm_insn (\"sbc\t%0\", exops[0]);
1100 [(set_attr "length" "20,28,40,48")])
1102 (define_insn_and_split "subsi3"
1103 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1104 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1105 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1109 [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1110 (clobber (reg:CC CC_REGNUM))])]
1113 (define_insn "*subsi3_nocc"
1114 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1115 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1116 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1117 (clobber (reg:CC CC_REGNUM))]
1124 inops[0] = operands[0];
1125 inops[1] = operands[2];
1126 pdp11_expand_operands (inops, exops, 2, NULL, either);
1128 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1129 output_asm_insn (\"sub\t%1,%0\", exops[0]);
1130 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1132 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1133 output_asm_insn (\"sbc\t%0\", exops[0]);
1138 [(set_attr "length" "6,10,12,16")])
1140 (define_insn_and_split "subhi3"
1141 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1142 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1143 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1147 [(parallel [(set (match_dup 0)
1148 (minus:HI (match_dup 1) (match_dup 2)))
1149 (clobber (reg:CC CC_REGNUM))])]
1152 ;; Note: the manual says that (minus m (const_int n)) is converted
1153 ;; to (plus m (const_int -n)) but that does not appear to be
1154 ;; the case when it's wrapped in a PARALLEL. So instead we handle
1155 ;; that case here, which is easy enough.
1156 (define_insn "*subhi3<cc_ccnz>"
1157 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1158 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1159 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1160 (clobber (reg:CC CC_REGNUM))]
1164 if (GET_CODE (operands[2]) == CONST_INT)
1166 if (INTVAL(operands[2]) == 1)
1168 else if (INTVAL(operands[2]) == -1)
1172 return \"sub\t%2,%0\";
1174 [(set_attr "length" "2,4,4,6")])
1176 ;;;;- and instructions
1177 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1179 (define_expand "and<mode>3"
1180 [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
1181 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
1182 (match_operand:PDPint 2 "general_operand" "")))]
1186 rtx op1 = operands[1];
1188 /* If there is a constant argument, complement that one.
1189 Similarly, if one of the inputs is the same as the output,
1190 complement the other input. */
1191 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
1192 rtx_equal_p (operands[0], operands[1]))
1194 operands[1] = operands[2];
1199 if (CONST_INT_P (op1))
1200 operands[1] = GEN_INT (~INTVAL (op1));
1202 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
1205 (define_insn_and_split "*bic<mode>"
1206 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1208 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1209 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
1213 [(parallel [(set (match_dup 0)
1214 (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2)))
1215 (clobber (reg:CC CC_REGNUM))])]
1218 (define_insn "*bic<mode><cc_cc>"
1219 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1221 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1222 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))
1223 (clobber (reg:CC CC_REGNUM))]
1225 "bic<PDPint:isfx>\t%1,%0"
1226 [(set_attr "length" "2,4,4,6")])
1228 ;;- Bit set (inclusive or) instructions
1229 (define_insn_and_split "ior<mode>3"
1230 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1231 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1232 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
1236 [(parallel [(set (match_dup 0)
1237 (ior:PDPint (match_dup 1) (match_dup 2)))
1238 (clobber (reg:CC CC_REGNUM))])]
1241 (define_insn "ior<mode>3<cc_cc>"
1242 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1243 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1244 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))
1245 (clobber (reg:CC CC_REGNUM))]
1247 "bis<PDPint:isfx>\t%2,%0"
1248 [(set_attr "length" "2,4,4,6")])
1250 ;;- xor instructions
1251 (define_insn_and_split "xorhi3"
1252 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1253 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1254 (match_operand:HI 2 "register_operand" "r,r")))]
1257 "&& reload_completed"
1258 [(parallel [(set (match_dup 0)
1259 (xor:HI (match_dup 1) (match_dup 2)))
1260 (clobber (reg:CC CC_REGNUM))])]
1263 (define_insn "*xorhi3<cc_cc>"
1264 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1265 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1266 (match_operand:HI 2 "register_operand" "r,r")))
1267 (clobber (reg:CC CC_REGNUM))]
1268 "TARGET_40_PLUS && reload_completed"
1270 [(set_attr "length" "2,4")])
1272 ;;- one complement instructions
1274 (define_insn_and_split "one_cmpl<mode>2"
1275 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1276 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1280 [(parallel [(set (match_dup 0)
1281 (not:PDPint (match_dup 1)))
1282 (clobber (reg:CC CC_REGNUM))])]
1285 (define_insn "*one_cmpl<mode>2<cc_cc>"
1286 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1287 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1288 (clobber (reg:CC CC_REGNUM))]
1290 "com<PDPint:isfx>\t%0"
1291 [(set_attr "length" "2,4")])
1293 ;;- arithmetic shift instructions
1295 ;; There is a fair amount of complexity here because with -m10
1296 ;; (pdp-11/10, /20) we only have shift by one bit. Iterators are
1297 ;; used to reduce the amount of very similar code.
1299 ;; First the insns used for small constant shifts.
1300 (define_insn "<code><mode>_sc"
1301 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1302 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1303 (match_operand:HI 2 "expand_shift_operand" "O,O")))]
1305 "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1306 [(set (attr "length")
1307 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1308 <CODE>, which_alternative == 0)"))])
1310 ;; Next, shifts that are done as a loop on base (11/10 class) machines.
1311 ;; This applies to shift counts too large to unroll, or variable shift
1312 ;; counts. The check for count <= 0 is done before we get here.
1313 (define_insn "<code><mode>_base"
1314 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1315 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1316 (match_operand:HI 2 "register_operand" "r,r")))
1317 (clobber (match_dup 2))]
1319 "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1320 [(set (attr "length")
1321 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1322 <CODE>, which_alternative == 0)"))])
1324 ;; Next the insns that use the extended instructions ash and ashc.
1325 ;; Note that these are just left shifts, and HI/SI only. (Right shifts
1326 ;; are done by shifting by a negative amount.)
1327 (define_insn "aslhi_op"
1328 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1329 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1330 (match_operand:HI 2 "general_operand" "rR,Q")))]
1333 [(set_attr "length" "2,4")])
1335 (define_insn "aslsi_op"
1336 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1337 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1338 (match_operand:HI 2 "general_operand" "rR,Q")))]
1341 [(set_attr "length" "2,4")])
1343 ;; Now the expanders that produce the insns defined above.
1344 (define_expand "ashl<mode>3"
1345 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1346 (match_operand:QHSint 1 "general_operand" "")
1347 (match_operand:HI 2 "general_operand" "")]
1353 if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base))
1355 if (<QHSint:e_mname> == E_QImode)
1357 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1358 emit_insn (gen_aslhi_op (r, r, operands[2]));
1359 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1363 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1369 (define_expand "ashr<mode>3"
1370 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1371 (match_operand:QHSint 1 "general_operand" "")
1372 (match_operand:HI 2 "general_operand" "")]
1378 if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base))
1380 operands[2] = negate_rtx (HImode, operands[2]);
1381 if (<QHSint:e_mname> == E_QImode)
1383 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1384 emit_insn (gen_aslhi_op (r, r, operands[2]));
1385 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1389 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1395 (define_expand "lshr<mode>3"
1396 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1397 (match_operand:QHSint 1 "general_operand" "")
1398 (match_operand:HI 2 "general_operand" "")]
1404 if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base))
1406 if (<QHSint:e_mname> == E_QImode)
1408 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1409 emit_insn (gen_aslhi_op (r, r, operands[2]));
1410 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1414 r = gen_reg_rtx (<QHSint:mname>);
1415 emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx));
1416 if (GET_CODE (operands[2]) != CONST_INT)
1418 n = gen_reg_rtx (HImode);
1419 emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1)));
1420 emit_insn (gen_ashr<mode>3 (operands[0], r, n));
1423 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r,
1424 GEN_INT (1 - INTVAL (operands[2]))));
1432 (define_insn_and_split "absdf2"
1433 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1434 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1437 "&& reload_completed"
1438 [(parallel [(set (match_dup 0) (abs:DF (match_dup 1)))
1439 (clobber (reg:CC FCC_REGNUM))])]
1442 (define_insn "absdf2<fcc_cc>"
1443 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1444 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))
1445 (clobber (reg:CC FCC_REGNUM))]
1446 "TARGET_FPU && reload_completed"
1448 [(set_attr "length" "2,4")])
1452 (define_insn_and_split "negdf2"
1453 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1454 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
1457 "&& reload_completed"
1458 [(parallel [(set (match_dup 0) (neg:DF (match_dup 1)))
1459 (clobber (reg:CC FCC_REGNUM))])]
1462 (define_insn "negdf2<fcc_cc>"
1463 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1464 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))
1465 (clobber (reg:CC FCC_REGNUM))]
1466 "TARGET_FPU && reload_completed"
1468 [(set_attr "length" "2,4")])
1470 (define_insn_and_split "negdi2"
1471 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1472 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1476 [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
1477 (clobber (reg:CC CC_REGNUM))])]
1480 ;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1481 (define_insn "negdi2_nocc"
1482 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1483 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))
1484 (clobber (reg:CC CC_REGNUM))]
1489 pdp11_expand_operands (operands, exops, 1, NULL, either);
1491 output_asm_insn (\"com\t%0\", exops[3]);
1492 output_asm_insn (\"com\t%0\", exops[2]);
1493 output_asm_insn (\"com\t%0\", exops[1]);
1494 output_asm_insn (\"com\t%0\", exops[0]);
1495 output_asm_insn (\"add\t%#1,%0\", exops[3]);
1496 output_asm_insn (\"adc\t%0\", exops[2]);
1497 output_asm_insn (\"adc\t%0\", exops[1]);
1498 output_asm_insn (\"adc\t%0\", exops[0]);
1502 [(set_attr "length" "18,34")])
1504 (define_insn_and_split "negsi2"
1505 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1506 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1510 [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
1511 (clobber (reg:CC CC_REGNUM))])]
1514 ;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1515 (define_insn "negsi2_nocc"
1516 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1517 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))
1518 (clobber (reg:CC CC_REGNUM))]
1523 pdp11_expand_operands (operands, exops, 1, NULL, either);
1525 output_asm_insn (\"com\t%0\", exops[1]);
1526 output_asm_insn (\"com\t%0\", exops[0]);
1527 output_asm_insn (\"add\t%#1,%0\", exops[1]);
1528 output_asm_insn (\"adc\t%0\", exops[0]);
1532 [(set_attr "length" "10,18")])
1534 (define_insn_and_split "neg<mode>2"
1535 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1536 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1540 [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1)))
1541 (clobber (reg:CC CC_REGNUM))])]
1544 (define_insn "neg<mode>2<cc_ccnz>"
1545 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1546 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1547 (clobber (reg:CC CC_REGNUM))]
1549 "neg<PDPint:isfx>\t%0"
1550 [(set_attr "length" "2,4")])
1553 ;; Unconditional and other jump instructions
1556 (label_ref (match_operand 0 "" "")))]
1560 if (get_attr_length (insn) == 2)
1562 return \"jmp\t%l0\";
1564 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1566 (const_int MIN_BRANCH))
1567 (gt (minus (match_dup 0)
1569 (const_int MAX_BRANCH)))
1573 (define_insn "tablejump"
1574 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1575 (use (label_ref (match_operand 1 "" "")))]
1581 [(set_attr "length" "2,2,4")])
1583 ;; indirect jump. TODO: this needs a constraint that allows memory
1584 ;; references but not indirection, since we add a level of indirection
1585 ;; in the generated code.
1586 (define_insn "indirect_jump"
1587 [(set (pc) (match_operand:HI 0 "general_operand" "r"))]
1590 [(set_attr "length" "2")])
1592 ;;- jump to subroutine
1595 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1596 (match_operand:HI 1 "general_operand" "g,g"))]
1597 ;;- Don't use operand 1 for most machines.
1600 [(set_attr "length" "2,4")])
1602 ;;- jump to subroutine
1603 (define_insn "call_value"
1604 [(set (match_operand 0 "" "")
1605 (call (match_operand:HI 1 "general_operand" "rR,Q")
1606 (match_operand:HI 2 "general_operand" "g,g")))]
1607 ;;- Don't use operand 2 for most machines.
1610 [(set_attr "length" "2,4")])
1612 (define_expand "untyped_call"
1613 [(parallel [(call (match_operand 0 "" "")
1615 (match_operand 1 "" "")
1616 (match_operand 2 "" "")])]
1621 emit_call_insn (gen_call (operands[0], const0_rtx));
1623 for (i = 0; i < XVECLEN (operands[2], 0); i++)
1625 rtx set = XVECEXP (operands[2], 0, i);
1626 emit_move_insn (SET_DEST (set), SET_SRC (set));
1629 /* The optimizer does not know that the call sets the function value
1630 registers we stored in the result block. We avoid problems by
1631 claiming that all hard registers are used and clobbered at this
1633 emit_insn (gen_blockage ());
1647 (define_insn_and_split "muldf3"
1648 [(set (match_operand:DF 0 "register_operand" "=a,a")
1649 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1650 (match_operand:DF 2 "float_operand" "fR,QF")))]
1653 "&& reload_completed"
1654 [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2)))
1655 (clobber (reg:CC FCC_REGNUM))])]
1658 (define_insn "muldf3<fcc_ccnz>"
1659 [(set (match_operand:DF 0 "register_operand" "=a,a")
1660 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1661 (match_operand:DF 2 "float_operand" "fR,QF")))
1662 (clobber (reg:CC FCC_REGNUM))]
1663 "TARGET_FPU && reload_completed"
1664 "{muld|mulf}\t%2,%0"
1665 [(set_attr "length" "2,4")])
1667 ;; 16 bit result multiply. This uses odd numbered registers.
1669 (define_insn_and_split "mulhi3"
1670 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1671 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1672 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1675 "&& reload_completed"
1676 [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2)))
1677 (clobber (reg:CC CC_REGNUM))])]
1680 (define_insn "mulhi3<cc_cc>"
1681 [(set (match_operand:HI 0 "register_operand" "=d,d")
1682 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1683 (match_operand:HI 2 "general_operand" "rR,Qi")))
1684 (clobber (reg:CC CC_REGNUM))]
1685 "TARGET_40_PLUS && reload_completed"
1687 [(set_attr "length" "2,4")])
1689 ;; 32 bit result from 16 bit operands
1690 (define_insn_and_split "mulhisi3"
1691 [(set (match_operand:SI 0 "register_operand" "=r,r")
1692 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
1693 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))]
1696 "&& reload_completed"
1697 [(parallel [(set (match_dup 0)
1698 (mult:SI (sign_extend:SI (match_dup 1))
1699 (sign_extend:SI (match_dup 2))))
1700 (clobber (reg:CC CC_REGNUM))])]
1703 (define_insn "mulhisi3<cc_cc>"
1704 [(set (match_operand:SI 0 "register_operand" "=r,r")
1705 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
1706 (sign_extend:SI (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")])
1713 (define_insn_and_split "divdf3"
1714 [(set (match_operand:DF 0 "register_operand" "=a,a")
1715 (div:DF (match_operand:DF 1 "register_operand" "0,0")
1716 (match_operand:DF 2 "general_operand" "fR,QF")))]
1719 "&& reload_completed"
1720 [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2)))
1721 (clobber (reg:CC FCC_REGNUM))])]
1724 (define_insn "divdf3<fcc_ccnz>"
1725 [(set (match_operand:DF 0 "register_operand" "=a,a")
1726 (div:DF (match_operand:DF 1 "register_operand" "0,0")
1727 (match_operand:DF 2 "general_operand" "fR,QF")))
1728 (clobber (reg:CC FCC_REGNUM))]
1729 "TARGET_FPU && reload_completed"
1730 "{divd|divf}\t%2,%0"
1731 [(set_attr "length" "2,4")])
1733 (define_expand "divmodhi4"
1735 [(set (subreg:HI (match_dup 1) 0)
1736 (div:HI (match_operand:SI 1 "register_operand" "0")
1737 (match_operand:HI 2 "general_operand" "g")))
1738 (set (subreg:HI (match_dup 1) 2)
1739 (mod:HI (match_dup 1) (match_dup 2)))])
1740 (set (match_operand:HI 0 "register_operand" "=r")
1741 (subreg:HI (match_dup 1) 0))
1742 (set (match_operand:HI 3 "register_operand" "=r")
1743 (subreg:HI (match_dup 1) 2))]
1747 (define_insn_and_split "*divmodhi4"
1748 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
1749 (div:HI (match_operand:SI 1 "register_operand" "0,0")
1750 (match_operand:HI 2 "general_operand" "rR,Qi")))
1751 (set (subreg:HI (match_dup 1) 2)
1752 (mod:HI (match_dup 1) (match_dup 2)))]
1755 "&& reload_completed"
1756 [(parallel [(set (subreg:HI (match_dup 0) 0)
1757 (div:HI (match_dup 1) (match_dup 2)))
1758 (set (subreg:HI (match_dup 1) 2)
1759 (mod:HI (match_dup 1) (match_dup 2)))
1760 (clobber (reg:CC CC_REGNUM))])]
1763 ;; Note that there is no corresponding CC setter pattern.
1764 ;; The reason is that it won't be generated, because
1765 ;; compare-elim.c only does the transformation on input
1766 ;; insns that have a two-element PARALLEL, as opposed to
1767 ;; the three-element one we have here.
1768 (define_insn "divmodhi4_nocc"
1769 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
1770 (div:HI (match_operand:SI 1 "register_operand" "0,0")
1771 (match_operand:HI 2 "general_operand" "rR,Qi")))
1772 (set (subreg:HI (match_dup 1) 2)
1773 (mod:HI (match_dup 1) (match_dup 2)))
1774 (clobber (reg:CC CC_REGNUM))]
1777 [(set_attr "length" "2,4")])