1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2004, 2005
3 ;; 2007, 2008, 2010 Free Software Foundation, Inc.
4 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
22 (include "predicates.md")
23 (include "constraints.md")
25 (define_c_enum "unspecv"
37 (HARD_FRAME_POINTER_REGNUM 5)
38 (STACK_POINTER_REGNUM 6)
44 ;; The next two are not physical registers but are used for addressing
46 (FRAME_POINTER_REGNUM 14)
47 (ARG_POINTER_REGNUM 15)
48 (FIRST_PSEUDO_REGISTER 16)
49 ;; Branch offset limits, as byte offsets from instruction address
58 ;; Integer modes supported on the PDP11, with a mapping from machine mode
59 ;; to mnemonic suffix. SImode and DImode always are special cases.
60 (define_mode_iterator PDPint [QI HI])
61 (define_mode_attr isfx [(QI "b") (HI "")])
63 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
65 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
66 ;;- updates for most instructions.
68 ;;- Operand classes for the register allocator:
70 ;; Compare instructions.
72 ;; currently we only support df floats, which saves us quite some
73 ;; hassle switching the FP mode!
74 ;; we assume that CPU is always in long float mode, and
75 ;; 16 bit integer mode - currently, the prologue for main does this,
76 ;; but maybe we should just set up a NEW crt0 properly,
77 ;; -- and what about signal handling code?
78 ;; (we don't even let sf floats in the register file, so
79 ;; we only should have to worry about truncating and widening
80 ;; when going to memory)
82 ;; abort() call by g++ - must define libfunc for cmp_optab
83 ;; and ucmp_optab for mode SImode, because we don't have that!!!
84 ;; - yet since no libfunc is there, we abort ()
86 ;; The only thing that remains to be done then is output
87 ;; the floats in a way the assembler can handle it (and
88 ;; if you're really into it, use a PDP11 float emulation
89 ;; library to do floating point constant folding - but
90 ;; I guess you'll get reasonable results even when not
92 ;; the last thing to do is fix the UPDATE_CC macro to check
93 ;; for floating point condition codes, and set cc_status
94 ;; properly, also setting the CC_IN_FCCR flag.
97 ;; currently type is only fpu or arith or unknown, maybe branch later ?
99 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
101 ;; length default is 2 bytes each
102 (define_attr "length" "" (const_int 2))
104 ;; a user's asm statement
105 (define_asm_attributes
106 [(set_attr "type" "unknown")
107 ; length for asm is the max length per statement. That would be
108 ; 3 words, for a two-operand instruction with extra word addressing
109 ; modes for both operands.
110 (set_attr "length" "6")])
112 ;; define function units
114 ;; Prologue and epilogue support.
116 (define_expand "prologue"
120 pdp11_expand_prologue ();
124 (define_expand "epilogue"
128 pdp11_expand_epilogue ();
132 (define_expand "return"
134 "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
142 (define_insn "blockage"
143 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
146 [(set_attr "length" "0")])
149 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
154 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
158 ;; arithmetic - values here immediately when next insn issued
159 ;; or does it mean the number of cycles after this insn was issued?
160 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
162 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
163 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
166 (define_insn "*cmpdf"
168 (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
169 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
173 cc_status.flags = CC_IN_FPU;
174 if (which_alternative == 0 || which_alternative == 2)
175 return \"{tstd|tstf} %0\;cfcc\";
177 return \"{cmpd|cmpf} %0, %1\;cfcc\";
179 [(set_attr "length" "4,4,6,6")])
181 (define_insn "*cmp<mode>"
183 (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
184 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
188 cmp<PDPint:isfx> %0,%1
189 cmp<PDPint:isfx> %0,%1
191 cmp<PDPint:isfx> %0,%1
192 cmp<PDPint:isfx> %0,%1"
193 [(set_attr "length" "2,2,4,4,4,6")])
195 ;; sob instruction - we need an assembler which can make this instruction
196 ;; valid under _all_ circumstances!
201 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
204 (label_ref (match_operand 1 "" ""))
207 (plus:HI (match_dup 0)
212 static int labelcount = 0;
213 static char buf[1000];
215 if (get_attr_length (insn) == 2)
216 return \"sob %0, %l1\";
219 output_asm_insn (\"dec %0\", operands);
221 sprintf (buf, \"bge LONG_SOB%d\", labelcount);
222 output_asm_insn (buf, NULL);
224 output_asm_insn (\"jmp %l1\", operands);
226 sprintf (buf, \"LONG_SOB%d:\", labelcount++);
227 output_asm_insn (buf, NULL);
231 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
234 (gt (minus (match_dup 0)
236 (const_int MAX_SOB)))
240 ;; These control RTL generation for conditional jump insns
241 ;; and match them for register allocation.
243 (define_expand "cbranchdf4"
245 (compare (match_operand:DF 1 "general_operand")
246 (match_operand:DF 2 "register_or_const0_operand")))
248 (if_then_else (match_operator 0 "ordered_comparison_operator"
249 [(cc0) (const_int 0)])
250 (label_ref (match_operand 3 "" ""))
255 (define_expand "cbranch<mode>4"
257 (compare (match_operand:PDPint 1 "general_operand")
258 (match_operand:PDPint 2 "general_operand")))
260 (if_then_else (match_operator 0 "ordered_comparison_operator"
261 [(cc0) (const_int 0)])
262 (label_ref (match_operand 3 "" ""))
267 ;; problem with too short jump distance! we need an assembler which can
268 ;; make this valid for all jump distances!
271 ;; these must be changed to check for CC_IN_FCCR if float is to be
274 (define_insn "*branch"
276 (if_then_else (match_operator 0 "ordered_comparison_operator"
277 [(cc0) (const_int 0)])
278 (label_ref (match_operand 1 "" ""))
281 "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
282 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
284 (const_int MIN_BRANCH))
285 (gt (minus (match_dup 1)
287 (const_int MAX_BRANCH)))
292 ;; These match inverted jump insns for register allocation.
294 (define_insn "*branch_inverted"
296 (if_then_else (match_operator 0 "ordered_comparison_operator"
297 [(cc0) (const_int 0)])
299 (label_ref (match_operand 1 "" ""))))]
301 "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
302 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
304 (const_int MIN_BRANCH))
305 (gt (minus (match_dup 1)
307 (const_int MAX_BRANCH)))
314 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
315 (match_operand:DI 1 "general_operand" "rN,g"))]
317 "* return output_move_multiple (operands);"
318 ;; what's the mose expensive code - say twice movsi = 16
319 [(set_attr "length" "16,32")])
322 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
323 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
325 "* return output_move_multiple (operands);"
326 ;; what's the most expensive code ? - I think 8!
327 ;; we could split it up and make several sub-cases...
328 [(set_attr "length" "4,6,8,16")])
330 (define_insn "mov<mode>"
331 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
332 (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
336 if (operands[1] == const0_rtx)
337 return \"clr<PDPint:isfx> %0\";
339 return \"mov<PDPint:isfx> %1, %0\";
341 [(set_attr "length" "2,4,4,6")])
344 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
345 (match_operand:DF 1 "float_operand" "fR,a,FQ,a,g"))]
347 "* if (which_alternative ==0 || which_alternative == 2)
348 return \"ldd %1, %0\";
349 else if (which_alternative == 1 || which_alternative == 3)
350 return \"std %1, %0\";
352 return output_move_multiple (operands); "
353 ;; last one is worst-case
354 [(set_attr "length" "2,2,4,4,24")])
357 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
358 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,g"))]
360 "* if (which_alternative ==0 || which_alternative == 2)
361 return \"{ldcfd|movof} %1, %0\";
362 else if (which_alternative == 1 || which_alternative == 3)
363 return \"{stcdf|movfo} %1, %0\";
365 return output_move_multiple (operands); "
366 ;; last one is worst-case
367 [(set_attr "length" "2,2,4,4,12")])
369 ;; maybe fiddle a bit with move_ratio, then
370 ;; let constraints only accept a register ...
372 (define_expand "movmemhi"
373 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
374 (match_operand:BLK 1 "general_operand" "g,g"))
375 (use (match_operand:HI 2 "general_operand" "n,mr"))
376 (use (match_operand:HI 3 "immediate_operand" "i,i"))
377 (clobber (match_scratch:HI 4 "=&r,X"))
378 (clobber (match_dup 5))
379 (clobber (match_dup 6))
380 (clobber (match_dup 2))])]
381 "(TARGET_BCOPY_BUILTIN)"
385 = replace_equiv_address (operands[0],
386 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
388 = replace_equiv_address (operands[1],
389 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
391 operands[5] = XEXP (operands[0], 0);
392 operands[6] = XEXP (operands[1], 0);
396 (define_insn "movmemhi1"
397 [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
398 (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
399 (use (match_operand:HI 2 "general_operand" "n,r"))
400 (use (match_operand:HI 3 "immediate_operand" "i,i"))
401 (clobber (match_scratch:HI 4 "=&r,X"))
402 (clobber (match_dup 0))
403 (clobber (match_dup 1))
404 (clobber (match_dup 2))]
405 "(TARGET_BCOPY_BUILTIN)"
406 "* return output_block_move (operands);"
408 [(set_attr "length" "80")])
412 ;;- truncation instructions
414 (define_insn "truncdfsf2"
415 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
416 (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
418 "* if (which_alternative ==0)
422 else if (which_alternative == 1)
423 return \"{stcdf|movfo} %1, %0\";
425 return \"{stcdf|movfo} %1, %0\";
427 [(set_attr "length" "0,2,4")])
430 (define_expand "truncsihi2"
431 [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
433 (match_operand:SI 1 "general_operand" "or")
439 ;;- zero extension instructions
441 (define_insn "zero_extendqihi2"
442 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
443 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
446 [(set_attr "length" "4,6")])
448 (define_expand "zero_extendhisi2"
452 (match_operand:HI 1 "register_operand" "r"))
454 (match_operand:SI 0 "register_operand" "=r")
458 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
461 ;;- sign extension instructions
463 (define_insn "extendsfdf2"
464 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
465 (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
470 {ldcfd|movof} %1, %0"
471 [(set_attr "length" "0,2,4")])
473 ;; does movb sign extend in register-to-register move?
474 (define_insn "extendqihi2"
475 [(set (match_operand:HI 0 "register_operand" "=r,r")
476 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
479 [(set_attr "length" "2,4")])
481 (define_insn "extendqisi2"
482 [(set (match_operand:SI 0 "register_operand" "=r,r")
483 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
489 /* make register pair available */
490 latehalf[0] = operands[0];
491 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
493 output_asm_insn(\"movb %1, %0\", operands);
494 output_asm_insn(\"sxt %0\", latehalf);
498 [(set_attr "length" "4,6")])
500 ;; maybe we have to use define_expand to say that we have the instruction,
501 ;; unconditionally, and then match dependent on CPU type:
503 (define_expand "extendhisi2"
504 [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
505 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
509 (define_insn "" ; "extendhisi2"
510 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
511 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
517 /* we don't want to mess with auto increment */
519 switch (which_alternative)
523 latehalf[0] = operands[0];
524 operands[0] = adjust_address(operands[0], HImode, 2);
526 output_asm_insn(\"mov %1, %0\", operands);
527 output_asm_insn(\"sxt %0\", latehalf);
533 /* - auto-decrement - right direction ;-) */
534 output_asm_insn(\"mov %1, %0\", operands);
535 output_asm_insn(\"sxt %0\", operands);
541 /* make register pair available */
542 latehalf[0] = operands[0];
543 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
545 output_asm_insn(\"mov %1, %0\", operands);
546 output_asm_insn(\"sxt %0\", latehalf);
555 [(set_attr "length" "10,6,6")])
559 [(set (match_operand:SI 0 "register_operand" "=r")
560 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
564 static int count = 0;
568 lateoperands[0] = operands[0];
569 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
571 output_asm_insn(\"tst %0\", operands);
572 sprintf(buf, \"bge extendhisi%d\", count);
573 output_asm_insn(buf, NULL);
574 output_asm_insn(\"mov -1, %0\", lateoperands);
575 sprintf(buf, \"bne extendhisi%d\", count+1);
576 output_asm_insn(buf, NULL);
577 sprintf(buf, \"\\nextendhisi%d:\", count);
578 output_asm_insn(buf, NULL);
579 output_asm_insn(\"clr %0\", lateoperands);
580 sprintf(buf, \"\\nextendhisi%d:\", count+1);
581 output_asm_insn(buf, NULL);
587 [(set_attr "length" "12")])
589 ;; make float to int and vice versa
590 ;; using the cc_status.flag field we could probably cut down
592 ;; assume that we are normally in double and integer mode -
593 ;; what do pdp library routines do to fpu mode ?
595 (define_insn "floatsidf2"
596 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
597 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
599 "* if (which_alternative ==0)
604 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
605 output_asm_insn(\"mov %1, -(sp)\", latehalf);
606 output_asm_insn(\"mov %1, -(sp)\", operands);
608 output_asm_insn(\"setl\", operands);
609 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
610 output_asm_insn(\"seti\", operands);
613 else if (which_alternative == 1)
614 return \"setl\;{ldcld|movif} %1, %0\;seti\";
616 return \"setl\;{ldcld|movif} %1, %0\;seti\";
618 [(set_attr "length" "10,6,8")])
620 (define_insn "floathidf2"
621 [(set (match_operand:DF 0 "register_operand" "=a,a")
622 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
624 "{ldcid|movif} %1, %0"
625 [(set_attr "length" "2,4")])
628 (define_insn "fix_truncdfsi2"
629 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
630 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
632 "* if (which_alternative ==0)
634 output_asm_insn(\"setl\", operands);
635 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
636 output_asm_insn(\"seti\", operands);
637 output_asm_insn(\"mov (sp)+, %0\", operands);
638 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
639 output_asm_insn(\"mov (sp)+, %0\", operands);
642 else if (which_alternative == 1)
643 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
645 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
647 [(set_attr "length" "10,6,8")])
649 (define_insn "fix_truncdfhi2"
650 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
651 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
653 "{stcdi|movfi} %1, %0"
654 [(set_attr "length" "2,4")])
657 ;;- arithmetic instructions
660 (define_insn "adddf3"
661 [(set (match_operand:DF 0 "register_operand" "=a,a")
662 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
663 (match_operand:DF 2 "general_operand" "fR,QF")))]
666 [(set_attr "length" "2,4")])
668 (define_insn "adddi3"
669 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
670 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
671 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
678 inops[0] = operands[0];
679 inops[1] = operands[2];
680 pdp11_expand_operands (inops, exops, 2, NULL, either);
682 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
683 output_asm_insn (\"add %1, %0\", exops[0]);
684 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
686 output_asm_insn (\"add %1, %0\", exops[1]);
687 output_asm_insn (\"adc %0\", exops[0]);
689 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
691 output_asm_insn (\"add %1, %0\", exops[2]);
692 output_asm_insn (\"adc %0\", exops[1]);
693 output_asm_insn (\"adc %0\", exops[0]);
695 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
697 output_asm_insn (\"add %1, %0\", exops[3]);
698 output_asm_insn (\"adc %0\", exops[2]);
699 output_asm_insn (\"adc %0\", exops[1]);
700 output_asm_insn (\"adc %0\", exops[0]);
705 [(set_attr "length" "20,28,40,48")])
707 ;; Note that the register operand is not marked earlyclobber.
708 ;; The reason is that SI values go in register pairs, so they
709 ;; can't partially overlap. They can be either disjoint, or
710 ;; source and destination can be equal. The latter case is
711 ;; handled properly because of the ordering of the individual
712 ;; instructions used. Specifically, carry from the low to the
713 ;; high word is added at the end, so the adding of the high parts
714 ;; will always used the original high part and not a high part
715 ;; modified by carry (which would amount to double carry).
716 (define_insn "addsi3"
717 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
718 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
719 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
726 inops[0] = operands[0];
727 inops[1] = operands[2];
728 pdp11_expand_operands (inops, exops, 2, NULL, either);
730 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
731 output_asm_insn (\"add %1, %0\", exops[0]);
732 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
734 output_asm_insn (\"add %1, %0\", exops[1]);
735 output_asm_insn (\"adc %0\", exops[0]);
740 [(set_attr "length" "6,10,12,16")])
742 (define_insn "addhi3"
743 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
744 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
745 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
749 if (GET_CODE (operands[2]) == CONST_INT)
751 if (INTVAL(operands[2]) == 1)
753 else if (INTVAL(operands[2]) == -1)
757 return \"add %2, %0\";
759 [(set_attr "length" "2,4,4,6")])
762 ;;- subtract instructions
763 ;; we don't have to care for constant second
764 ;; args, since they are canonical plus:xx now!
765 ;; also for minus:DF ??
767 (define_insn "subdf3"
768 [(set (match_operand:DF 0 "register_operand" "=a,a")
769 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
770 (match_operand:DF 2 "general_operand" "fR,Q")))]
773 [(set_attr "length" "2,4")])
775 (define_insn "subdi3"
776 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
777 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
778 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
785 inops[0] = operands[0];
786 inops[1] = operands[2];
787 pdp11_expand_operands (inops, exops, 2, NULL, either);
789 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
790 output_asm_insn (\"sub %1, %0\", exops[0]);
791 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
793 output_asm_insn (\"sub %1, %0\", exops[1]);
794 output_asm_insn (\"sbc %0\", exops[0]);
796 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
798 output_asm_insn (\"sub %1, %0\", exops[2]);
799 output_asm_insn (\"sbc %0\", exops[1]);
800 output_asm_insn (\"sbc %0\", exops[0]);
802 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
804 output_asm_insn (\"sub %1, %0\", exops[3]);
805 output_asm_insn (\"sbc %0\", exops[2]);
806 output_asm_insn (\"sbc %0\", exops[1]);
807 output_asm_insn (\"sbc %0\", exops[0]);
812 [(set_attr "length" "20,28,40,48")])
814 (define_insn "subsi3"
815 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
816 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
817 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
824 inops[0] = operands[0];
825 inops[1] = operands[2];
826 pdp11_expand_operands (inops, exops, 2, NULL, either);
828 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
829 output_asm_insn (\"sub %1, %0\", exops[0]);
830 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
832 output_asm_insn (\"sub %1, %0\", exops[1]);
833 output_asm_insn (\"sbc %0\", exops[0]);
838 [(set_attr "length" "6,10,12,16")])
840 (define_insn "subhi3"
841 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
842 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
843 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
847 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
849 return \"sub %2, %0\";
851 [(set_attr "length" "2,4,4,6")])
853 ;;;;- and instructions
854 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
856 (define_expand "and<mode>3"
857 [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
858 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
859 (match_operand:PDPint 2 "general_operand" "")))]
863 rtx op1 = operands[1];
865 /* If there is a constant argument, complement that one.
866 Similarly, if one of the inputs is the same as the output,
867 complement the other input. */
868 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
869 rtx_equal_p (operands[0], operands[1]))
871 operands[1] = operands[2];
876 if (CONST_INT_P (op1))
877 operands[1] = GEN_INT (~INTVAL (op1));
879 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
882 (define_insn "*bic<mode>"
883 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
885 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
886 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
888 "bic<PDPint:isfx> %1, %0"
889 [(set_attr "length" "2,4,4,6")])
891 ;;- Bit set (inclusive or) instructions
892 (define_insn "ior<mode>3"
893 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
894 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
895 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
897 "bis<PDPint:isfx> %2, %0"
898 [(set_attr "length" "2,4,4,6")])
901 (define_insn "xorhi3"
902 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
903 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
904 (match_operand:HI 2 "register_operand" "r,r")))]
907 [(set_attr "length" "2,4")])
909 ;;- one complement instructions
911 (define_insn "one_cmpl<mode>2"
912 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
913 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
915 "com<PDPint:isfx> %0"
916 [(set_attr "length" "2,4")])
918 ;;- arithmetic shift instructions
919 (define_insn "ashlsi3"
920 [(set (match_operand:SI 0 "register_operand" "=r,r")
921 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
922 (match_operand:HI 2 "general_operand" "rR,Qi")))]
925 [(set_attr "length" "2,4")])
927 ;; Arithmetic right shift on the pdp works by negating the shift count.
928 (define_expand "ashrsi3"
929 [(set (match_operand:SI 0 "register_operand" "=r")
930 (ashift:SI (match_operand:SI 1 "register_operand" "0")
931 (match_operand:HI 2 "general_operand" "g")))]
935 operands[2] = negate_rtx (HImode, operands[2]);
938 ;; define asl aslb asr asrb - ashc missing!
942 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
943 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
947 [(set_attr "length" "2,4")])
949 ;; and another possibility for asr is << -1
950 ;; might cause problems since -1 can also be encoded as 65535!
955 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
956 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
960 [(set_attr "length" "2,4")])
963 (define_insn "lsrhi1"
964 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
965 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
969 [(set_attr "length" "2,4")])
971 (define_insn "lsrsi1"
972 [(set (match_operand:SI 0 "register_operand" "=r")
973 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
980 lateoperands[0] = operands[0];
981 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
983 lateoperands[1] = operands[1];
984 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
986 output_asm_insn (\"clc\", operands);
987 output_asm_insn (\"ror %0\", lateoperands);
988 output_asm_insn (\"ror %0\", operands);
992 [(set_attr "length" "10")])
994 (define_expand "lshrsi3"
995 [(match_operand:SI 0 "register_operand" "")
996 (match_operand:SI 1 "register_operand" "0")
997 (match_operand:HI 2 "general_operand" "")]
1003 if (!TARGET_40_PLUS &&
1004 (GET_CODE (operands[2]) != CONST_INT ||
1005 (unsigned) INTVAL (operands[2]) > 3))
1007 emit_insn (gen_lsrsi1 (operands[0], operands[1]));
1008 if (GET_CODE (operands[2]) != CONST_INT)
1010 r = gen_reg_rtx (HImode);
1011 emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1012 emit_insn (gen_ashrsi3 (operands[0], operands[0], r));
1014 else if ((unsigned) INTVAL (operands[2]) != 1)
1016 emit_insn (gen_ashlsi3 (operands[0], operands[0],
1017 GEN_INT (1 - INTVAL (operands[2]))));
1024 ;; shift is by arbitrary count is expensive,
1025 ;; shift by one cheap - so let's do that, if
1026 ;; space doesn't matter
1028 [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
1029 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1030 (match_operand:HI 2 "expand_shift_operand" "O")))]
1036 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1037 if (INTVAL(operands[2]) < 0)
1038 output_asm_insn(\"asr %0\", operands);
1040 output_asm_insn(\"asl %0\", operands);
1045 [(set (attr "length") (const_int 8))])
1049 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1050 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1051 (match_operand:HI 2 "const_int_operand" "n,n")))]
1054 { /* allowing predec or post_inc is possible, but hairy! */
1057 cnt = INTVAL(operands[2]) & 0x0007;
1059 for (i=0 ; i < cnt ; i++)
1060 output_asm_insn(\"aslb %0\", operands);
1064 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1065 [(set_attr_alternative "length"
1071 ; [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1072 ; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1076 ; [(set_attr "length" "2,4")])
1080 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1081 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1082 (match_operand:HI 2 "const_int_operand" "n,n")))]
1085 { /* allowing predec or post_inc is possible, but hairy! */
1088 cnt = INTVAL(operands[2]) & 0x0007;
1090 for (i=0 ; i < cnt ; i++)
1091 output_asm_insn(\"asrb %0\", operands);
1095 [(set_attr_alternative "length"
1099 ;; the following is invalid - too complex!!! - just say 14 !!!
1100 ; [(set (attr "length") (plus (and (match_dup 2)
1102 ; (and (match_dup 2)
1103 ; (const_int 14))))])
1107 ;; can we get +-1 in the next pattern? should
1108 ;; have been caught by previous patterns!
1110 (define_insn "ashlhi3"
1111 [(set (match_operand:HI 0 "register_operand" "=r,r")
1112 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1113 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1117 if (GET_CODE(operands[2]) == CONST_INT)
1119 if (INTVAL(operands[2]) == 1)
1121 else if (INTVAL(operands[2]) == -1)
1125 return \"ash %2,%0\";
1127 [(set_attr "length" "2,4")])
1129 ;; Arithmetic right shift on the pdp works by negating the shift count.
1130 (define_expand "ashrhi3"
1131 [(set (match_operand:HI 0 "register_operand" "=r")
1132 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1133 (match_operand:HI 2 "general_operand" "g")))]
1137 operands[2] = negate_rtx (HImode, operands[2]);
1140 (define_expand "lshrhi3"
1141 [(match_operand:HI 0 "register_operand" "")
1142 (match_operand:HI 1 "register_operand" "")
1143 (match_operand:HI 2 "general_operand" "")]
1149 if (!TARGET_40_PLUS &&
1150 (GET_CODE (operands[2]) != CONST_INT ||
1151 (unsigned) INTVAL (operands[2]) > 3))
1153 emit_insn (gen_lsrhi1 (operands[0], operands[1]));
1154 if (GET_CODE (operands[2]) != CONST_INT)
1156 r = gen_reg_rtx (HImode);
1157 emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1158 emit_insn (gen_ashrhi3 (operands[0], operands[0], r));
1160 else if ((unsigned) INTVAL (operands[2]) != 1)
1162 emit_insn (gen_ashlhi3 (operands[0], operands[0],
1163 GEN_INT (1 - INTVAL (operands[2]))));
1172 (define_insn "absdf2"
1173 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1174 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1177 [(set_attr "length" "2,4")])
1182 (define_insn "negdf2"
1183 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
1184 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1187 [(set_attr "length" "2,4")])
1189 (define_insn "negdi2"
1190 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1191 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1196 pdp11_expand_operands (operands, exops, 1, NULL, either);
1198 output_asm_insn (\"com %0\", exops[3]);
1199 output_asm_insn (\"com %0\", exops[2]);
1200 output_asm_insn (\"com %0\", exops[1]);
1201 output_asm_insn (\"com %0\", exops[0]);
1202 output_asm_insn (\"add $1, %0\", exops[3]);
1203 output_asm_insn (\"adc %0\", exops[2]);
1204 output_asm_insn (\"adc %0\", exops[1]);
1205 output_asm_insn (\"adc %0\", exops[0]);
1209 [(set_attr "length" "18,34")])
1211 (define_insn "negsi2"
1212 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1213 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1218 pdp11_expand_operands (operands, exops, 1, NULL, either);
1220 output_asm_insn (\"com %0\", exops[1]);
1221 output_asm_insn (\"com %0\", exops[0]);
1222 output_asm_insn (\"add $1, %0\", exops[1]);
1223 output_asm_insn (\"adc %0\", exops[0]);
1227 [(set_attr "length" "12,20")])
1229 (define_insn "neg<mode>2"
1230 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1231 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1234 [(set_attr "length" "2,4")])
1237 ;; Unconditional and other jump instructions
1240 (label_ref (match_operand 0 "" "")))]
1244 if (get_attr_length (insn) == 2)
1248 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1250 (const_int MIN_BRANCH))
1251 (gt (minus (match_dup 0)
1253 (const_int MAX_BRANCH)))
1259 (label_ref (match_operand 0 "" "")))
1260 (clobber (const_int 1))]
1263 [(set_attr "length" "4")])
1265 (define_insn "tablejump"
1266 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1267 (use (label_ref (match_operand 1 "" "")))]
1273 [(set_attr "length" "2,2,4")])
1275 ;; indirect jump - let's be conservative!
1276 ;; allow only register_operand, even though we could also
1277 ;; allow labels etc.
1279 (define_insn "indirect_jump"
1280 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1284 ;;- jump to subroutine
1287 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1288 (match_operand:HI 1 "general_operand" "g,g"))
1289 ;; (use (reg:HI 0)) what was that ???
1291 ;;- Don't use operand 1 for most machines.
1294 [(set_attr "length" "2,4")])
1296 ;;- jump to subroutine
1297 (define_insn "call_value"
1298 [(set (match_operand 0 "" "")
1299 (call (match_operand:HI 1 "general_operand" "rR,Q")
1300 (match_operand:HI 2 "general_operand" "g,g")))
1301 ;; (use (reg:HI 0)) - what was that ????
1303 ;;- Don't use operand 2 for most machines.
1306 [(set_attr "length" "2,4")])
1317 (define_insn "muldf3"
1318 [(set (match_operand:DF 0 "register_operand" "=a,a")
1319 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1320 (match_operand:DF 2 "float_operand" "fR,QF")))]
1322 "{muld|mulf} %2, %0"
1323 [(set_attr "length" "2,4")])
1325 ;; 16 bit result multiply:
1326 ;; currently we multiply only into odd registers, so we don't use two
1327 ;; registers - but this is a bit inefficient at times. If we define
1328 ;; a register class for each register, then we can specify properly
1329 ;; which register need which scratch register ....
1331 (define_insn "mulhi3"
1332 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1333 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1334 (match_operand:HI 2 "float_operand" "rR,Qi")))]
1337 [(set_attr "length" "2,4")])
1340 (define_expand "mulhisi3"
1342 (match_operand:HI 1 "nonimmediate_operand" "g,g"))
1343 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1344 (mult:SI (truncate:HI
1346 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1348 "operands[3] = gen_lowpart(HImode, operands[1]);")
1351 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1352 (mult:SI (truncate:HI
1353 (match_operand:SI 1 "register_operand" "%0,0"))
1354 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1357 [(set_attr "length" "2,4")])
1359 ;(define_insn "mulhisi3"
1360 ; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1361 ; (mult:SI (truncate:HI
1362 ; (match_operand:SI 1 "register_operand" "%0,0"))
1363 ; (match_operand:HI 2 "general_operand" "rR,Qi")))]
1366 ; [(set_attr "length" "2,4")])
1369 (define_insn "divdf3"
1370 [(set (match_operand:DF 0 "register_operand" "=a,a")
1371 (div:DF (match_operand:DF 1 "register_operand" "0,0")
1372 (match_operand:DF 2 "general_operand" "fR,QF")))]
1374 "{divd|divf} %2, %0"
1375 [(set_attr "length" "2,4")])
1378 (define_expand "divhi3"
1379 [(set (subreg:HI (match_dup 1) 0)
1380 (div:HI (match_operand:SI 1 "register_operand" "0")
1381 (match_operand:HI 2 "general_operand" "g")))
1382 (set (match_operand:HI 0 "register_operand" "=r")
1383 (subreg:HI (match_dup 1) 0))]
1388 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1389 (div:HI (match_operand:SI 1 "general_operand" "0")
1390 (match_operand:HI 2 "general_operand" "g")))]
1393 [(set_attr "length" "4")])
1395 (define_expand "modhi3"
1396 [(set (subreg:HI (match_dup 1) 2)
1397 (mod:HI (match_operand:SI 1 "register_operand" "0")
1398 (match_operand:HI 2 "general_operand" "g")))
1399 (set (match_operand:HI 0 "register_operand" "=r")
1400 (subreg:HI (match_dup 1) 2))]
1405 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
1406 (mod:HI (match_operand:SI 1 "general_operand" "0")
1407 (match_operand:HI 2 "general_operand" "g")))]
1410 [(set_attr "length" "4")])
1412 ;(define_expand "divmodhi4"
1413 ; [(parallel [(set (subreg:HI (match_dup 1) 0)
1414 ; (div:HI (match_operand:SI 1 "register_operand" "0")
1415 ; (match_operand:HI 2 "general_operand" "g")))
1416 ; (set (subreg:HI (match_dup 1) 2)
1417 ; (mod:HI (match_dup 1)
1419 ; (set (match_operand:HI 3 "register_operand" "=r")
1420 ; (subreg:HI (match_dup 1) 2))
1421 ; (set (match_operand:HI 0 "register_operand" "=r")
1422 ; (subreg:HI (match_dup 1) 0))]
1427 ; [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1428 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1429 ; (match_operand:HI 2 "general_operand" "g")))
1430 ; (set (subreg:HI (match_dup 0) 2)
1431 ; (mod:HI (match_dup 1)
1437 ;; is rotate doing the right thing to be included here ????