1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994-2017 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 (FIRST_PSEUDO_REGISTER 16)
48 ;; Branch offset limits, as byte offsets from instruction address
57 ;; Integer modes supported on the PDP11, with a mapping from machine mode
58 ;; to mnemonic suffix. SImode and DImode always are special cases.
59 (define_mode_iterator PDPint [QI HI])
60 (define_mode_attr isfx [(QI "b") (HI "")])
62 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
64 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
65 ;;- updates for most instructions.
67 ;;- Operand classes for the register allocator:
69 ;; Compare instructions.
71 ;; currently we only support df floats, which saves us quite some
72 ;; hassle switching the FP mode!
73 ;; we assume that CPU is always in long float mode, and
74 ;; 16 bit integer mode - currently, the prologue for main does this,
75 ;; but maybe we should just set up a NEW crt0 properly,
76 ;; -- and what about signal handling code?
77 ;; (we don't even let sf floats in the register file, so
78 ;; we only should have to worry about truncating and widening
79 ;; when going to memory)
81 ;; abort() call by g++ - must define libfunc for cmp_optab
82 ;; and ucmp_optab for mode SImode, because we don't have that!!!
83 ;; - yet since no libfunc is there, we abort ()
85 ;; The only thing that remains to be done then is output
86 ;; the floats in a way the assembler can handle it (and
87 ;; if you're really into it, use a PDP11 float emulation
88 ;; library to do floating point constant folding - but
89 ;; I guess you'll get reasonable results even when not
91 ;; the last thing to do is fix the UPDATE_CC macro to check
92 ;; for floating point condition codes, and set cc_status
93 ;; properly, also setting the CC_IN_FCCR flag.
96 ;; currently type is only fpu or arith or unknown, maybe branch later ?
98 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
100 ;; length default is 2 bytes each
101 (define_attr "length" "" (const_int 2))
103 ;; a user's asm statement
104 (define_asm_attributes
105 [(set_attr "type" "unknown")
106 ; length for asm is the max length per statement. That would be
107 ; 3 words, for a two-operand instruction with extra word addressing
108 ; modes for both operands.
109 (set_attr "length" "6")])
111 ;; define function units
113 ;; Prologue and epilogue support.
115 (define_expand "prologue"
119 pdp11_expand_prologue ();
123 (define_expand "epilogue"
127 pdp11_expand_epilogue ();
131 (define_expand "return"
133 "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
141 (define_insn "blockage"
142 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
145 [(set_attr "length" "0")])
148 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
153 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
157 ;; arithmetic - values here immediately when next insn issued
158 ;; or does it mean the number of cycles after this insn was issued?
159 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
161 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
162 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
165 (define_insn "*cmpdf"
167 (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
168 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
172 cc_status.flags = CC_IN_FPU;
173 if (which_alternative == 0 || which_alternative == 2)
174 return \"{tstd|tstf} %0\;cfcc\";
176 return \"{cmpd|cmpf} %0, %1\;cfcc\";
178 [(set_attr "length" "4,4,6,6")])
180 (define_insn "*cmp<mode>"
182 (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
183 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
187 cmp<PDPint:isfx> %0,%1
188 cmp<PDPint:isfx> %0,%1
190 cmp<PDPint:isfx> %0,%1
191 cmp<PDPint:isfx> %0,%1"
192 [(set_attr "length" "2,2,4,4,4,6")])
194 ;; sob instruction - we need an assembler which can make this instruction
195 ;; valid under _all_ circumstances!
200 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
203 (label_ref (match_operand 1 "" ""))
206 (plus:HI (match_dup 0)
211 static int labelcount = 0;
212 static char buf[1000];
214 if (get_attr_length (insn) == 2)
215 return \"sob %0, %l1\";
218 output_asm_insn (\"dec %0\", operands);
220 sprintf (buf, \"bge LONG_SOB%d\", labelcount);
221 output_asm_insn (buf, NULL);
223 output_asm_insn (\"jmp %l1\", operands);
225 sprintf (buf, \"LONG_SOB%d:\", labelcount++);
226 output_asm_insn (buf, NULL);
230 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
233 (gt (minus (match_dup 0)
235 (const_int MAX_SOB)))
239 ;; These control RTL generation for conditional jump insns
240 ;; and match them for register allocation.
242 (define_expand "cbranchdf4"
244 (compare (match_operand:DF 1 "general_operand")
245 (match_operand:DF 2 "register_or_const0_operand")))
247 (if_then_else (match_operator 0 "ordered_comparison_operator"
248 [(cc0) (const_int 0)])
249 (label_ref (match_operand 3 "" ""))
254 (define_expand "cbranch<mode>4"
256 (compare (match_operand:PDPint 1 "general_operand")
257 (match_operand:PDPint 2 "general_operand")))
259 (if_then_else (match_operator 0 "ordered_comparison_operator"
260 [(cc0) (const_int 0)])
261 (label_ref (match_operand 3 "" ""))
266 ;; problem with too short jump distance! we need an assembler which can
267 ;; make this valid for all jump distances!
270 ;; these must be changed to check for CC_IN_FCCR if float is to be
273 (define_insn "*branch"
275 (if_then_else (match_operator 0 "ordered_comparison_operator"
276 [(cc0) (const_int 0)])
277 (label_ref (match_operand 1 "" ""))
280 "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
281 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
283 (const_int MIN_BRANCH))
284 (gt (minus (match_dup 1)
286 (const_int MAX_BRANCH)))
291 ;; These match inverted jump insns for register allocation.
293 (define_insn "*branch_inverted"
295 (if_then_else (match_operator 0 "ordered_comparison_operator"
296 [(cc0) (const_int 0)])
298 (label_ref (match_operand 1 "" ""))))]
300 "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
301 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
303 (const_int MIN_BRANCH))
304 (gt (minus (match_dup 1)
306 (const_int MAX_BRANCH)))
313 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
314 (match_operand:DI 1 "general_operand" "rN,g"))]
316 "* return output_move_multiple (operands);"
317 ;; what's the mose expensive code - say twice movsi = 16
318 [(set_attr "length" "16,32")])
321 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
322 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
324 "* return output_move_multiple (operands);"
325 ;; what's the most expensive code ? - I think 8!
326 ;; we could split it up and make several sub-cases...
327 [(set_attr "length" "4,6,8,16")])
329 (define_insn "mov<mode>"
330 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
331 (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
335 if (operands[1] == const0_rtx)
336 return \"clr<PDPint:isfx> %0\";
338 return \"mov<PDPint:isfx> %1, %0\";
340 [(set_attr "length" "2,4,4,6")])
343 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
344 (match_operand:DF 1 "float_operand" "fR,a,FQ,a,g"))]
346 "* if (which_alternative ==0 || which_alternative == 2)
347 return \"ldd %1, %0\";
348 else if (which_alternative == 1 || which_alternative == 3)
349 return \"std %1, %0\";
351 return output_move_multiple (operands); "
352 ;; last one is worst-case
353 [(set_attr "length" "2,2,4,4,24")])
356 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
357 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,g"))]
359 "* if (which_alternative ==0 || which_alternative == 2)
360 return \"{ldcfd|movof} %1, %0\";
361 else if (which_alternative == 1 || which_alternative == 3)
362 return \"{stcdf|movfo} %1, %0\";
364 return output_move_multiple (operands); "
365 ;; last one is worst-case
366 [(set_attr "length" "2,2,4,4,12")])
368 ;; maybe fiddle a bit with move_ratio, then
369 ;; let constraints only accept a register ...
371 (define_expand "movmemhi"
372 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
373 (match_operand:BLK 1 "general_operand" "g,g"))
374 (use (match_operand:HI 2 "general_operand" "n,mr"))
375 (use (match_operand:HI 3 "immediate_operand" "i,i"))
376 (clobber (match_scratch:HI 4 "=&r,X"))
377 (clobber (match_dup 5))
378 (clobber (match_dup 6))
379 (clobber (match_dup 2))])]
380 "(TARGET_BCOPY_BUILTIN)"
384 = replace_equiv_address (operands[0],
385 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
387 = replace_equiv_address (operands[1],
388 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
390 operands[5] = XEXP (operands[0], 0);
391 operands[6] = XEXP (operands[1], 0);
395 (define_insn "movmemhi1"
396 [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
397 (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
398 (use (match_operand:HI 2 "general_operand" "n,r"))
399 (use (match_operand:HI 3 "immediate_operand" "i,i"))
400 (clobber (match_scratch:HI 4 "=&r,X"))
401 (clobber (match_dup 0))
402 (clobber (match_dup 1))
403 (clobber (match_dup 2))]
404 "(TARGET_BCOPY_BUILTIN)"
405 "* return output_block_move (operands);"
407 [(set_attr "length" "80")])
411 ;;- truncation instructions
413 (define_insn "truncdfsf2"
414 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
415 (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
417 "* if (which_alternative ==0)
421 else if (which_alternative == 1)
422 return \"{stcdf|movfo} %1, %0\";
424 return \"{stcdf|movfo} %1, %0\";
426 [(set_attr "length" "0,2,4")])
429 (define_expand "truncsihi2"
430 [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
432 (match_operand:SI 1 "general_operand" "or")
438 ;;- zero extension instructions
440 (define_insn "zero_extendqihi2"
441 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
442 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
445 [(set_attr "length" "4,6")])
447 (define_expand "zero_extendhisi2"
451 (match_operand:HI 1 "register_operand" "r"))
453 (match_operand:SI 0 "register_operand" "=r")
457 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
460 ;;- sign extension instructions
462 (define_insn "extendsfdf2"
463 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
464 (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
469 {ldcfd|movof} %1, %0"
470 [(set_attr "length" "0,2,4")])
472 ;; does movb sign extend in register-to-register move?
473 (define_insn "extendqihi2"
474 [(set (match_operand:HI 0 "register_operand" "=r,r")
475 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
478 [(set_attr "length" "2,4")])
480 (define_insn "extendqisi2"
481 [(set (match_operand:SI 0 "register_operand" "=r,r")
482 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
488 /* make register pair available */
489 latehalf[0] = operands[0];
490 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
492 output_asm_insn(\"movb %1, %0\", operands);
493 output_asm_insn(\"sxt %0\", latehalf);
497 [(set_attr "length" "4,6")])
499 ;; maybe we have to use define_expand to say that we have the instruction,
500 ;; unconditionally, and then match dependent on CPU type:
502 (define_expand "extendhisi2"
503 [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
504 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
508 (define_insn "" ; "extendhisi2"
509 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
510 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
516 /* we don't want to mess with auto increment */
518 switch (which_alternative)
522 latehalf[0] = operands[0];
523 operands[0] = adjust_address(operands[0], HImode, 2);
525 output_asm_insn(\"mov %1, %0\", operands);
526 output_asm_insn(\"sxt %0\", latehalf);
532 /* - auto-decrement - right direction ;-) */
533 output_asm_insn(\"mov %1, %0\", operands);
534 output_asm_insn(\"sxt %0\", operands);
540 /* make register pair available */
541 latehalf[0] = operands[0];
542 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
544 output_asm_insn(\"mov %1, %0\", operands);
545 output_asm_insn(\"sxt %0\", latehalf);
554 [(set_attr "length" "10,6,6")])
558 [(set (match_operand:SI 0 "register_operand" "=r")
559 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
563 static int count = 0;
567 lateoperands[0] = operands[0];
568 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
570 output_asm_insn(\"tst %0\", operands);
571 sprintf(buf, \"bge extendhisi%d\", count);
572 output_asm_insn(buf, NULL);
573 output_asm_insn(\"mov -1, %0\", lateoperands);
574 sprintf(buf, \"bne extendhisi%d\", count+1);
575 output_asm_insn(buf, NULL);
576 sprintf(buf, \"\\nextendhisi%d:\", count);
577 output_asm_insn(buf, NULL);
578 output_asm_insn(\"clr %0\", lateoperands);
579 sprintf(buf, \"\\nextendhisi%d:\", count+1);
580 output_asm_insn(buf, NULL);
586 [(set_attr "length" "12")])
588 ;; make float to int and vice versa
589 ;; using the cc_status.flag field we could probably cut down
591 ;; assume that we are normally in double and integer mode -
592 ;; what do pdp library routines do to fpu mode ?
594 (define_insn "floatsidf2"
595 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
596 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
598 "* if (which_alternative ==0)
603 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
604 output_asm_insn(\"mov %1, -(sp)\", latehalf);
605 output_asm_insn(\"mov %1, -(sp)\", operands);
607 output_asm_insn(\"setl\", operands);
608 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
609 output_asm_insn(\"seti\", operands);
612 else if (which_alternative == 1)
613 return \"setl\;{ldcld|movif} %1, %0\;seti\";
615 return \"setl\;{ldcld|movif} %1, %0\;seti\";
617 [(set_attr "length" "10,6,8")])
619 (define_insn "floathidf2"
620 [(set (match_operand:DF 0 "register_operand" "=a,a")
621 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
623 "{ldcid|movif} %1, %0"
624 [(set_attr "length" "2,4")])
627 (define_insn "fix_truncdfsi2"
628 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
629 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
631 "* if (which_alternative ==0)
633 output_asm_insn(\"setl\", operands);
634 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
635 output_asm_insn(\"seti\", operands);
636 output_asm_insn(\"mov (sp)+, %0\", operands);
637 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
638 output_asm_insn(\"mov (sp)+, %0\", operands);
641 else if (which_alternative == 1)
642 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
644 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
646 [(set_attr "length" "10,6,8")])
648 (define_insn "fix_truncdfhi2"
649 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
650 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
652 "{stcdi|movfi} %1, %0"
653 [(set_attr "length" "2,4")])
656 ;;- arithmetic instructions
659 (define_insn "adddf3"
660 [(set (match_operand:DF 0 "register_operand" "=a,a")
661 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
662 (match_operand:DF 2 "general_operand" "fR,QF")))]
665 [(set_attr "length" "2,4")])
667 (define_insn "adddi3"
668 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
669 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
670 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
677 inops[0] = operands[0];
678 inops[1] = operands[2];
679 pdp11_expand_operands (inops, exops, 2, NULL, either);
681 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
682 output_asm_insn (\"add %1, %0\", exops[0]);
683 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
685 output_asm_insn (\"add %1, %0\", exops[1]);
686 output_asm_insn (\"adc %0\", exops[0]);
688 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
690 output_asm_insn (\"add %1, %0\", exops[2]);
691 output_asm_insn (\"adc %0\", exops[1]);
692 output_asm_insn (\"adc %0\", exops[0]);
694 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
696 output_asm_insn (\"add %1, %0\", exops[3]);
697 output_asm_insn (\"adc %0\", exops[2]);
698 output_asm_insn (\"adc %0\", exops[1]);
699 output_asm_insn (\"adc %0\", exops[0]);
704 [(set_attr "length" "20,28,40,48")])
706 ;; Note that the register operand is not marked earlyclobber.
707 ;; The reason is that SI values go in register pairs, so they
708 ;; can't partially overlap. They can be either disjoint, or
709 ;; source and destination can be equal. The latter case is
710 ;; handled properly because of the ordering of the individual
711 ;; instructions used. Specifically, carry from the low to the
712 ;; high word is added at the end, so the adding of the high parts
713 ;; will always used the original high part and not a high part
714 ;; modified by carry (which would amount to double carry).
715 (define_insn "addsi3"
716 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
717 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
718 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
725 inops[0] = operands[0];
726 inops[1] = operands[2];
727 pdp11_expand_operands (inops, exops, 2, NULL, either);
729 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
730 output_asm_insn (\"add %1, %0\", exops[0]);
731 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
733 output_asm_insn (\"add %1, %0\", exops[1]);
734 output_asm_insn (\"adc %0\", exops[0]);
739 [(set_attr "length" "6,10,12,16")])
741 (define_insn "addhi3"
742 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
743 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
744 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
748 if (GET_CODE (operands[2]) == CONST_INT)
750 if (INTVAL(operands[2]) == 1)
752 else if (INTVAL(operands[2]) == -1)
756 return \"add %2, %0\";
758 [(set_attr "length" "2,4,4,6")])
761 ;;- subtract instructions
762 ;; we don't have to care for constant second
763 ;; args, since they are canonical plus:xx now!
764 ;; also for minus:DF ??
766 (define_insn "subdf3"
767 [(set (match_operand:DF 0 "register_operand" "=a,a")
768 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
769 (match_operand:DF 2 "general_operand" "fR,Q")))]
772 [(set_attr "length" "2,4")])
774 (define_insn "subdi3"
775 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
776 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
777 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
784 inops[0] = operands[0];
785 inops[1] = operands[2];
786 pdp11_expand_operands (inops, exops, 2, NULL, either);
788 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
789 output_asm_insn (\"sub %1, %0\", exops[0]);
790 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
792 output_asm_insn (\"sub %1, %0\", exops[1]);
793 output_asm_insn (\"sbc %0\", exops[0]);
795 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
797 output_asm_insn (\"sub %1, %0\", exops[2]);
798 output_asm_insn (\"sbc %0\", exops[1]);
799 output_asm_insn (\"sbc %0\", exops[0]);
801 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
803 output_asm_insn (\"sub %1, %0\", exops[3]);
804 output_asm_insn (\"sbc %0\", exops[2]);
805 output_asm_insn (\"sbc %0\", exops[1]);
806 output_asm_insn (\"sbc %0\", exops[0]);
811 [(set_attr "length" "20,28,40,48")])
813 (define_insn "subsi3"
814 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
815 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
816 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
823 inops[0] = operands[0];
824 inops[1] = operands[2];
825 pdp11_expand_operands (inops, exops, 2, NULL, either);
827 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
828 output_asm_insn (\"sub %1, %0\", exops[0]);
829 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
831 output_asm_insn (\"sub %1, %0\", exops[1]);
832 output_asm_insn (\"sbc %0\", exops[0]);
837 [(set_attr "length" "6,10,12,16")])
839 (define_insn "subhi3"
840 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
841 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
842 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
846 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
848 return \"sub %2, %0\";
850 [(set_attr "length" "2,4,4,6")])
852 ;;;;- and instructions
853 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
855 (define_expand "and<mode>3"
856 [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
857 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
858 (match_operand:PDPint 2 "general_operand" "")))]
862 rtx op1 = operands[1];
864 /* If there is a constant argument, complement that one.
865 Similarly, if one of the inputs is the same as the output,
866 complement the other input. */
867 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
868 rtx_equal_p (operands[0], operands[1]))
870 operands[1] = operands[2];
875 if (CONST_INT_P (op1))
876 operands[1] = GEN_INT (~INTVAL (op1));
878 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
881 (define_insn "*bic<mode>"
882 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
884 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
885 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
887 "bic<PDPint:isfx> %1, %0"
888 [(set_attr "length" "2,4,4,6")])
890 ;;- Bit set (inclusive or) instructions
891 (define_insn "ior<mode>3"
892 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
893 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
894 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
896 "bis<PDPint:isfx> %2, %0"
897 [(set_attr "length" "2,4,4,6")])
900 (define_insn "xorhi3"
901 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
902 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
903 (match_operand:HI 2 "register_operand" "r,r")))]
906 [(set_attr "length" "2,4")])
908 ;;- one complement instructions
910 (define_insn "one_cmpl<mode>2"
911 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
912 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
914 "com<PDPint:isfx> %0"
915 [(set_attr "length" "2,4")])
917 ;;- arithmetic shift instructions
918 (define_insn "ashlsi3"
919 [(set (match_operand:SI 0 "register_operand" "=r,r")
920 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
921 (match_operand:HI 2 "general_operand" "rR,Qi")))]
924 [(set_attr "length" "2,4")])
926 ;; Arithmetic right shift on the pdp works by negating the shift count.
927 (define_expand "ashrsi3"
928 [(set (match_operand:SI 0 "register_operand" "=r")
929 (ashift:SI (match_operand:SI 1 "register_operand" "0")
930 (match_operand:HI 2 "general_operand" "g")))]
934 operands[2] = negate_rtx (HImode, operands[2]);
937 ;; define asl aslb asr asrb - ashc missing!
941 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
942 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
946 [(set_attr "length" "2,4")])
948 ;; and another possibility for asr is << -1
949 ;; might cause problems since -1 can also be encoded as 65535!
954 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
955 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
959 [(set_attr "length" "2,4")])
962 (define_insn "lsrhi1"
963 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
964 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
968 [(set_attr "length" "2,4")])
970 (define_insn "lsrsi1"
971 [(set (match_operand:SI 0 "register_operand" "=r")
972 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
979 lateoperands[0] = operands[0];
980 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
982 lateoperands[1] = operands[1];
983 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
985 output_asm_insn (\"clc\", operands);
986 output_asm_insn (\"ror %0\", lateoperands);
987 output_asm_insn (\"ror %0\", operands);
991 [(set_attr "length" "10")])
993 (define_expand "lshrsi3"
994 [(match_operand:SI 0 "register_operand" "")
995 (match_operand:SI 1 "register_operand" "0")
996 (match_operand:HI 2 "general_operand" "")]
1002 if (!TARGET_40_PLUS &&
1003 (GET_CODE (operands[2]) != CONST_INT ||
1004 (unsigned) INTVAL (operands[2]) > 3))
1006 emit_insn (gen_lsrsi1 (operands[0], operands[1]));
1007 if (GET_CODE (operands[2]) != CONST_INT)
1009 r = gen_reg_rtx (HImode);
1010 emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1011 emit_insn (gen_ashrsi3 (operands[0], operands[0], r));
1013 else if ((unsigned) INTVAL (operands[2]) != 1)
1015 emit_insn (gen_ashlsi3 (operands[0], operands[0],
1016 GEN_INT (1 - INTVAL (operands[2]))));
1023 ;; shift is by arbitrary count is expensive,
1024 ;; shift by one cheap - so let's do that, if
1025 ;; space doesn't matter
1027 [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
1028 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1029 (match_operand:HI 2 "expand_shift_operand" "O")))]
1035 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1036 if (INTVAL(operands[2]) < 0)
1037 output_asm_insn(\"asr %0\", operands);
1039 output_asm_insn(\"asl %0\", operands);
1044 [(set (attr "length") (const_int 8))])
1048 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1049 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1050 (match_operand:HI 2 "const_int_operand" "n,n")))]
1053 { /* allowing predec or post_inc is possible, but hairy! */
1056 cnt = INTVAL(operands[2]) & 0x0007;
1058 for (i=0 ; i < cnt ; i++)
1059 output_asm_insn(\"aslb %0\", operands);
1063 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1064 [(set_attr_alternative "length"
1070 ; [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1071 ; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1075 ; [(set_attr "length" "2,4")])
1079 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1080 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1081 (match_operand:HI 2 "const_int_operand" "n,n")))]
1084 { /* allowing predec or post_inc is possible, but hairy! */
1087 cnt = INTVAL(operands[2]) & 0x0007;
1089 for (i=0 ; i < cnt ; i++)
1090 output_asm_insn(\"asrb %0\", operands);
1094 [(set_attr_alternative "length"
1098 ;; the following is invalid - too complex!!! - just say 14 !!!
1099 ; [(set (attr "length") (plus (and (match_dup 2)
1101 ; (and (match_dup 2)
1102 ; (const_int 14))))])
1106 ;; can we get +-1 in the next pattern? should
1107 ;; have been caught by previous patterns!
1109 (define_insn "ashlhi3"
1110 [(set (match_operand:HI 0 "register_operand" "=r,r")
1111 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1112 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1116 if (GET_CODE(operands[2]) == CONST_INT)
1118 if (INTVAL(operands[2]) == 1)
1120 else if (INTVAL(operands[2]) == -1)
1124 return \"ash %2,%0\";
1126 [(set_attr "length" "2,4")])
1128 ;; Arithmetic right shift on the pdp works by negating the shift count.
1129 (define_expand "ashrhi3"
1130 [(set (match_operand:HI 0 "register_operand" "=r")
1131 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1132 (match_operand:HI 2 "general_operand" "g")))]
1136 operands[2] = negate_rtx (HImode, operands[2]);
1139 (define_expand "lshrhi3"
1140 [(match_operand:HI 0 "register_operand" "")
1141 (match_operand:HI 1 "register_operand" "")
1142 (match_operand:HI 2 "general_operand" "")]
1148 if (!TARGET_40_PLUS &&
1149 (GET_CODE (operands[2]) != CONST_INT ||
1150 (unsigned) INTVAL (operands[2]) > 3))
1152 emit_insn (gen_lsrhi1 (operands[0], operands[1]));
1153 if (GET_CODE (operands[2]) != CONST_INT)
1155 r = gen_reg_rtx (HImode);
1156 emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1157 emit_insn (gen_ashrhi3 (operands[0], operands[0], r));
1159 else if ((unsigned) INTVAL (operands[2]) != 1)
1161 emit_insn (gen_ashlhi3 (operands[0], operands[0],
1162 GEN_INT (1 - INTVAL (operands[2]))));
1171 (define_insn "absdf2"
1172 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1173 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1176 [(set_attr "length" "2,4")])
1181 (define_insn "negdf2"
1182 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
1183 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1186 [(set_attr "length" "2,4")])
1188 (define_insn "negdi2"
1189 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1190 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1195 pdp11_expand_operands (operands, exops, 1, NULL, either);
1197 output_asm_insn (\"com %0\", exops[3]);
1198 output_asm_insn (\"com %0\", exops[2]);
1199 output_asm_insn (\"com %0\", exops[1]);
1200 output_asm_insn (\"com %0\", exops[0]);
1201 output_asm_insn (\"add $1, %0\", exops[3]);
1202 output_asm_insn (\"adc %0\", exops[2]);
1203 output_asm_insn (\"adc %0\", exops[1]);
1204 output_asm_insn (\"adc %0\", exops[0]);
1208 [(set_attr "length" "18,34")])
1210 (define_insn "negsi2"
1211 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1212 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1217 pdp11_expand_operands (operands, exops, 1, NULL, either);
1219 output_asm_insn (\"com %0\", exops[1]);
1220 output_asm_insn (\"com %0\", exops[0]);
1221 output_asm_insn (\"add $1, %0\", exops[1]);
1222 output_asm_insn (\"adc %0\", exops[0]);
1226 [(set_attr "length" "12,20")])
1228 (define_insn "neg<mode>2"
1229 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1230 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1233 [(set_attr "length" "2,4")])
1236 ;; Unconditional and other jump instructions
1239 (label_ref (match_operand 0 "" "")))]
1243 if (get_attr_length (insn) == 2)
1247 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1249 (const_int MIN_BRANCH))
1250 (gt (minus (match_dup 0)
1252 (const_int MAX_BRANCH)))
1258 (label_ref (match_operand 0 "" "")))
1259 (clobber (const_int 1))]
1262 [(set_attr "length" "4")])
1264 (define_insn "tablejump"
1265 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1266 (use (label_ref (match_operand 1 "" "")))]
1272 [(set_attr "length" "2,2,4")])
1274 ;; indirect jump - let's be conservative!
1275 ;; allow only register_operand, even though we could also
1276 ;; allow labels etc.
1278 (define_insn "indirect_jump"
1279 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1283 ;;- jump to subroutine
1286 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1287 (match_operand:HI 1 "general_operand" "g,g"))
1288 ;; (use (reg:HI 0)) what was that ???
1290 ;;- Don't use operand 1 for most machines.
1293 [(set_attr "length" "2,4")])
1295 ;;- jump to subroutine
1296 (define_insn "call_value"
1297 [(set (match_operand 0 "" "")
1298 (call (match_operand:HI 1 "general_operand" "rR,Q")
1299 (match_operand:HI 2 "general_operand" "g,g")))
1300 ;; (use (reg:HI 0)) - what was that ????
1302 ;;- Don't use operand 2 for most machines.
1305 [(set_attr "length" "2,4")])
1316 (define_insn "muldf3"
1317 [(set (match_operand:DF 0 "register_operand" "=a,a")
1318 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1319 (match_operand:DF 2 "float_operand" "fR,QF")))]
1321 "{muld|mulf} %2, %0"
1322 [(set_attr "length" "2,4")])
1324 ;; 16 bit result multiply:
1325 ;; currently we multiply only into odd registers, so we don't use two
1326 ;; registers - but this is a bit inefficient at times. If we define
1327 ;; a register class for each register, then we can specify properly
1328 ;; which register need which scratch register ....
1330 (define_insn "mulhi3"
1331 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1332 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1333 (match_operand:HI 2 "float_operand" "rR,Qi")))]
1336 [(set_attr "length" "2,4")])
1339 (define_expand "mulhisi3"
1341 (match_operand:HI 1 "nonimmediate_operand" "g,g"))
1342 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1343 (mult:SI (truncate:HI
1345 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1347 "operands[3] = gen_lowpart(HImode, operands[1]);")
1350 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1351 (mult:SI (truncate:HI
1352 (match_operand:SI 1 "register_operand" "%0,0"))
1353 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1356 [(set_attr "length" "2,4")])
1358 ;(define_insn "mulhisi3"
1359 ; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1360 ; (mult:SI (truncate:HI
1361 ; (match_operand:SI 1 "register_operand" "%0,0"))
1362 ; (match_operand:HI 2 "general_operand" "rR,Qi")))]
1365 ; [(set_attr "length" "2,4")])
1368 (define_insn "divdf3"
1369 [(set (match_operand:DF 0 "register_operand" "=a,a")
1370 (div:DF (match_operand:DF 1 "register_operand" "0,0")
1371 (match_operand:DF 2 "general_operand" "fR,QF")))]
1373 "{divd|divf} %2, %0"
1374 [(set_attr "length" "2,4")])
1377 (define_expand "divhi3"
1378 [(set (subreg:HI (match_dup 1) 0)
1379 (div:HI (match_operand:SI 1 "register_operand" "0")
1380 (match_operand:HI 2 "general_operand" "g")))
1381 (set (match_operand:HI 0 "register_operand" "=r")
1382 (subreg:HI (match_dup 1) 0))]
1387 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1388 (div:HI (match_operand:SI 1 "general_operand" "0")
1389 (match_operand:HI 2 "general_operand" "g")))]
1392 [(set_attr "length" "4")])
1394 (define_expand "modhi3"
1395 [(set (subreg:HI (match_dup 1) 2)
1396 (mod:HI (match_operand:SI 1 "register_operand" "0")
1397 (match_operand:HI 2 "general_operand" "g")))
1398 (set (match_operand:HI 0 "register_operand" "=r")
1399 (subreg:HI (match_dup 1) 2))]
1404 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
1405 (mod:HI (match_operand:SI 1 "general_operand" "0")
1406 (match_operand:HI 2 "general_operand" "g")))]
1409 [(set_attr "length" "4")])
1411 ;(define_expand "divmodhi4"
1412 ; [(parallel [(set (subreg:HI (match_dup 1) 0)
1413 ; (div:HI (match_operand:SI 1 "register_operand" "0")
1414 ; (match_operand:HI 2 "general_operand" "g")))
1415 ; (set (subreg:HI (match_dup 1) 2)
1416 ; (mod:HI (match_dup 1)
1418 ; (set (match_operand:HI 3 "register_operand" "=r")
1419 ; (subreg:HI (match_dup 1) 2))
1420 ; (set (match_operand:HI 0 "register_operand" "=r")
1421 ; (subreg:HI (match_dup 1) 0))]
1426 ; [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1427 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1428 ; (match_operand:HI 2 "general_operand" "g")))
1429 ; (set (subreg:HI (match_dup 0) 2)
1430 ; (mod:HI (match_dup 1)
1436 ;; is rotate doing the right thing to be included here ????