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")
29 (FRAME_POINTER_REGNUM 5)
30 (STACK_POINTER_REGNUM 6)
36 (FIRST_PSEUDO_REGISTER 14)
37 ;; Branch offset limits, as byte offsets from instruction address
46 ;; Integer modes supported on the PDP11, with a mapping from machine mode
47 ;; to mnemonic suffix. SImode and DImode always are special cases.
48 (define_mode_iterator PDPint [QI HI])
49 (define_mode_attr isfx [(QI "b") (HI "")])
51 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
53 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
54 ;;- updates for most instructions.
56 ;;- Operand classes for the register allocator:
58 ;; Compare instructions.
60 ;; currently we only support df floats, which saves us quite some
61 ;; hassle switching the FP mode!
62 ;; we assume that CPU is always in long float mode, and
63 ;; 16 bit integer mode - currently, the prologue for main does this,
64 ;; but maybe we should just set up a NEW crt0 properly,
65 ;; -- and what about signal handling code?
66 ;; (we don't even let sf floats in the register file, so
67 ;; we only should have to worry about truncating and widening
68 ;; when going to memory)
70 ;; abort() call by g++ - must define libfunc for cmp_optab
71 ;; and ucmp_optab for mode SImode, because we don't have that!!!
72 ;; - yet since no libfunc is there, we abort ()
74 ;; The only thing that remains to be done then is output
75 ;; the floats in a way the assembler can handle it (and
76 ;; if you're really into it, use a PDP11 float emulation
77 ;; library to do floating point constant folding - but
78 ;; I guess you'll get reasonable results even when not
80 ;; the last thing to do is fix the UPDATE_CC macro to check
81 ;; for floating point condition codes, and set cc_status
82 ;; properly, also setting the CC_IN_FCCR flag.
85 ;; currently type is only fpu or arith or unknown, maybe branch later ?
87 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
89 ;; length default is 2 bytes each
90 (define_attr "length" "" (const_int 2))
92 ;; a user's asm statement
93 (define_asm_attributes
94 [(set_attr "type" "unknown")
95 ; length for asm is the max length per statement. That would be
96 ; 5 words, for a floating point instruction with a literal constant
98 (set_attr "length" "10")])
100 ;; define function units
102 ;; arithmetic - values here immediately when next insn issued
103 ;; or does it mean the number of cycles after this insn was issued?
104 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
106 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
107 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
110 (define_insn "*cmpdf"
112 (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F")
113 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))]
117 cc_status.flags = CC_IN_FPU;
118 if (which_alternative == 0 || which_alternative == 2)
119 return \"{tstd|tstf} %0\;cfcc\";
121 return \"{cmpd|cmpf} %0, %1\;cfcc\";
123 [(set_attr "length" "4,4,6,6,12")])
125 (define_insn "*cmphi"
127 (compare (match_operand:HI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
128 (match_operand:HI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
137 [(set_attr "length" "2,2,4,4,4,6")])
139 (define_insn "*cmpqi"
141 (compare (match_operand:QI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
142 (match_operand:QI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
151 [(set_attr "length" "2,2,4,4,4,6")])
154 ;; sob instruction - we need an assembler which can make this instruction
155 ;; valid under _all_ circumstances!
160 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
163 (label_ref (match_operand 1 "" ""))
166 (plus:HI (match_dup 0)
171 static int labelcount = 0;
172 static char buf[1000];
174 if (get_attr_length (insn) == 2)
175 return \"sob %0, %l1\";
178 output_asm_insn (\"dec %0\", operands);
180 sprintf (buf, \"bge LONG_SOB%d\", labelcount);
181 output_asm_insn (buf, NULL);
183 output_asm_insn (\"jmp %l1\", operands);
185 sprintf (buf, \"LONG_SOB%d:\", labelcount++);
186 output_asm_insn (buf, NULL);
190 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
193 (gt (minus (match_dup 0)
195 (const_int MAX_SOB)))
199 ;; These control RTL generation for conditional jump insns
200 ;; and match them for register allocation.
202 (define_expand "cbranchdf4"
204 (compare (match_operand:DF 1 "general_operand")
205 (match_operand:DF 2 "register_or_const0_operand")))
207 (if_then_else (match_operator 0 "ordered_comparison_operator"
208 [(cc0) (const_int 0)])
209 (label_ref (match_operand 3 "" ""))
214 (define_expand "cbranchhi4"
216 (compare (match_operand:HI 1 "general_operand")
217 (match_operand:HI 2 "general_operand")))
219 (if_then_else (match_operator 0 "ordered_comparison_operator"
220 [(cc0) (const_int 0)])
221 (label_ref (match_operand 3 "" ""))
226 (define_expand "cbranchqi4"
228 (compare (match_operand:QI 1 "general_operand")
229 (match_operand:QI 2 "general_operand")))
231 (if_then_else (match_operator 0 "ordered_comparison_operator"
232 [(cc0) (const_int 0)])
233 (label_ref (match_operand 3 "" ""))
238 ;; problem with too short jump distance! we need an assembler which can
239 ;; make this valid for all jump distances!
242 ;; these must be changed to check for CC_IN_FCCR if float is to be
245 (define_insn "*branch"
247 (if_then_else (match_operator 0 "ordered_comparison_operator"
248 [(cc0) (const_int 0)])
249 (label_ref (match_operand 1 "" ""))
252 "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
253 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
255 (const_int MIN_BRANCH))
256 (gt (minus (match_dup 1)
258 (const_int MAX_BRANCH)))
263 ;; These match inverted jump insns for register allocation.
265 (define_insn "*branch_inverted"
267 (if_then_else (match_operator 0 "ordered_comparison_operator"
268 [(cc0) (const_int 0)])
270 (label_ref (match_operand 1 "" ""))))]
272 "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
273 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
275 (const_int MIN_BRANCH))
276 (gt (minus (match_dup 1)
278 (const_int MAX_BRANCH)))
285 [(set (match_operand:DI 0 "general_operand" "=g,rm,o")
286 (match_operand:DI 1 "general_operand" "m,r,a"))]
288 "* return output_move_quad (operands);"
289 ;; what's the mose expensive code - say twice movsi = 16
290 [(set_attr "length" "32,32,32")])
293 [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
294 (match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
296 "* return output_move_double (operands);"
297 ;; what's the most expensive code ? - I think 8!
298 ;; we could split it up and make several sub-cases...
299 [(set_attr "length" "4,6,8,16,16")])
302 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
303 (match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
307 if (operands[1] == const0_rtx)
310 return \"mov %1, %0\";
312 [(set_attr "length" "2,4,4,6")])
315 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
316 (match_operand:QI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
320 if (operands[1] == const0_rtx)
323 return \"movb %1, %0\";
325 [(set_attr "length" "2,4,4,6")])
328 [(set (match_operand:DF 0 "float_operand" "=a,fR,a,Q,g")
329 (match_operand:DF 1 "float_operand" "fFR,a,Q,a,g"))]
331 "* if (which_alternative ==0 || which_alternative == 2)
332 return \"ldd %1, %0\";
333 else if (which_alternative == 1 || which_alternative == 3)
334 return \"std %1, %0\";
336 return output_move_quad (operands); "
338 [(set_attr "length" "2,2,10,10,32")])
341 [(set (match_operand:SF 0 "float_operand" "=a,fR,a,Q,g")
342 (match_operand:SF 1 "float_operand" "fFR,a,Q,a,g"))]
344 "* if (which_alternative ==0 || which_alternative == 2)
345 return \"{ldcfd|movof} %1, %0\";
346 else if (which_alternative == 1 || which_alternative == 3)
347 return \"{stcdf|movfo} %1, %0\";
349 return output_move_double (operands); "
351 [(set_attr "length" "2,2,10,10,16")])
353 ;; maybe fiddle a bit with move_ratio, then
354 ;; let constraints only accept a register ...
356 (define_expand "movmemhi"
357 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
358 (match_operand:BLK 1 "general_operand" "g,g"))
359 (use (match_operand:HI 2 "general_operand" "n,&mr"))
360 (use (match_operand:HI 3 "immediate_operand" "i,i"))
361 (clobber (match_scratch:HI 4 "=&r,X"))
362 (clobber (match_dup 5))
363 (clobber (match_dup 6))
364 (clobber (match_dup 2))])]
365 "(TARGET_BCOPY_BUILTIN)"
369 = replace_equiv_address (operands[0],
370 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
372 = replace_equiv_address (operands[1],
373 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
375 operands[5] = XEXP (operands[0], 0);
376 operands[6] = XEXP (operands[1], 0);
380 (define_insn "" ; "movmemhi"
381 [(set (mem:BLK (match_operand 0 "pmode_register_operand" "+r,r"))
382 (mem:BLK (match_operand 1 "pmode_register_operand" "+r,r")))
383 (use (match_operand:HI 2 "general_operand" "+n,&r"))
384 (use (match_operand:HI 3 "immediate_operand" "i,i"))
385 (clobber (match_scratch:HI 4 "=&r,X"))
386 (clobber (match_dup 0))
387 (clobber (match_dup 1))
388 (clobber (match_dup 2))]
389 "(TARGET_BCOPY_BUILTIN)"
390 "* return output_block_move (operands);"
392 [(set_attr "length" "80")])
396 ;;- truncation instructions
398 (define_insn "truncdfsf2"
399 [(set (match_operand:SF 0 "general_operand" "=f,R,Q")
400 (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
402 "* if (which_alternative ==0)
406 else if (which_alternative == 1)
407 return \"{stcdf|movfo} %1, %0\";
409 return \"{stcdf|movfo} %1, %0\";
411 [(set_attr "length" "0,2,4")])
414 (define_expand "truncsihi2"
415 [(set (match_operand:HI 0 "general_operand" "=g")
417 (match_operand:SI 1 "general_operand" "or")
423 ;;- zero extension instructions
425 (define_insn "zero_extendqihi2"
426 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
427 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
430 [(set_attr "length" "4,6")])
432 (define_expand "zero_extendhisi2"
436 (match_operand:HI 1 "register_operand" "r"))
438 (match_operand:SI 0 "register_operand" "=r")
442 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
445 ;;- sign extension instructions
447 (define_insn "extendsfdf2"
448 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
449 (float_extend:DF (match_operand:SF 1 "general_operand" "f,R,Q")))]
454 {ldcfd|movof} %1, %0"
455 [(set_attr "length" "0,2,4")])
457 ;; does movb sign extend in register-to-register move?
458 (define_insn "extendqihi2"
459 [(set (match_operand:HI 0 "register_operand" "=r,r")
460 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
463 [(set_attr "length" "2,4")])
465 (define_insn "extendqisi2"
466 [(set (match_operand:SI 0 "register_operand" "=r,r")
467 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
473 /* make register pair available */
474 latehalf[0] = operands[0];
475 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
477 output_asm_insn(\"movb %1, %0\", operands);
478 output_asm_insn(\"sxt %0\", latehalf);
482 [(set_attr "length" "4,6")])
484 ;; maybe we have to use define_expand to say that we have the instruction,
485 ;; unconditionally, and then match dependent on CPU type:
487 (define_expand "extendhisi2"
488 [(set (match_operand:SI 0 "general_operand" "=g")
489 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
493 (define_insn "" ; "extendhisi2"
494 [(set (match_operand:SI 0 "general_operand" "=o,<,r")
495 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
501 /* we don't want to mess with auto increment */
503 switch (which_alternative)
507 latehalf[0] = operands[0];
508 operands[0] = adjust_address(operands[0], HImode, 2);
510 output_asm_insn(\"mov %1, %0\", operands);
511 output_asm_insn(\"sxt %0\", latehalf);
517 /* - auto-decrement - right direction ;-) */
518 output_asm_insn(\"mov %1, %0\", operands);
519 output_asm_insn(\"sxt %0\", operands);
525 /* make register pair available */
526 latehalf[0] = operands[0];
527 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
529 output_asm_insn(\"mov %1, %0\", operands);
530 output_asm_insn(\"sxt %0\", latehalf);
539 [(set_attr "length" "10,6,6")])
543 [(set (match_operand:SI 0 "register_operand" "=r")
544 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
548 static int count = 0;
552 lateoperands[0] = operands[0];
553 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
555 output_asm_insn(\"tst %0\", operands);
556 sprintf(buf, \"bge extendhisi%d\", count);
557 output_asm_insn(buf, NULL);
558 output_asm_insn(\"mov -1, %0\", lateoperands);
559 sprintf(buf, \"bne extendhisi%d\", count+1);
560 output_asm_insn(buf, NULL);
561 sprintf(buf, \"\\nextendhisi%d:\", count);
562 output_asm_insn(buf, NULL);
563 output_asm_insn(\"clr %0\", lateoperands);
564 sprintf(buf, \"\\nextendhisi%d:\", count+1);
565 output_asm_insn(buf, NULL);
571 [(set_attr "length" "12")])
573 ;; make float to int and vice versa
574 ;; using the cc_status.flag field we could probably cut down
576 ;; assume that we are normally in double and integer mode -
577 ;; what do pdp library routines do to fpu mode ?
579 (define_insn "floatsidf2"
580 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
581 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
583 "* if (which_alternative ==0)
588 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
589 output_asm_insn(\"mov %1, -(sp)\", latehalf);
590 output_asm_insn(\"mov %1, -(sp)\", operands);
592 output_asm_insn(\"setl\", operands);
593 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
594 output_asm_insn(\"seti\", operands);
597 else if (which_alternative == 1)
598 return \"setl\;{ldcld|movif} %1, %0\;seti\";
600 return \"setl\;{ldcld|movif} %1, %0\;seti\";
602 [(set_attr "length" "10,6,8")])
604 (define_insn "floathidf2"
605 [(set (match_operand:DF 0 "register_operand" "=a,a")
606 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
608 "{ldcid|movif} %1, %0"
609 [(set_attr "length" "2,4")])
612 (define_insn "fix_truncdfsi2"
613 [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
614 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
616 "* if (which_alternative ==0)
618 output_asm_insn(\"setl\", operands);
619 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
620 output_asm_insn(\"seti\", operands);
621 output_asm_insn(\"mov (sp)+, %0\", operands);
622 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
623 output_asm_insn(\"mov (sp)+, %0\", operands);
626 else if (which_alternative == 1)
627 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
629 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
631 [(set_attr "length" "10,6,8")])
633 (define_insn "fix_truncdfhi2"
634 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
635 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
637 "{stcdi|movfi} %1, %0"
638 [(set_attr "length" "2,4")])
641 ;;- arithmetic instructions
644 (define_insn "adddf3"
645 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
646 (plus:DF (match_operand:DF 1 "register_operand" "%0,0,0")
647 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
650 [(set_attr "length" "2,4,10")])
652 (define_insn "addsi3"
653 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
654 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
655 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
658 { /* Here we trust that operands don't overlap
660 or is lateoperands the low word?? - looks like it! */
664 lateoperands[0] = operands[0];
666 if (REG_P (operands[0]))
667 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
669 operands[0] = adjust_address (operands[0], HImode, 2);
671 if (! CONSTANT_P(operands[2]))
673 lateoperands[2] = operands[2];
675 if (REG_P (operands[2]))
676 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
678 operands[2] = adjust_address (operands[2], HImode, 2);
680 output_asm_insn (\"add %2, %0\", operands);
681 output_asm_insn (\"adc %0\", lateoperands);
682 output_asm_insn (\"add %2, %0\", lateoperands);
686 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
687 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
689 if (INTVAL(operands[2]))
691 output_asm_insn (\"add %2, %0\", operands);
692 output_asm_insn (\"adc %0\", lateoperands);
695 if (INTVAL(lateoperands[2]))
696 output_asm_insn (\"add %2, %0\", lateoperands);
700 [(set_attr "length" "6,10,12,16,6,2,10,10,6,16")])
702 (define_insn "addhi3"
703 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
704 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
705 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
709 if (GET_CODE (operands[2]) == CONST_INT)
711 if (INTVAL(operands[2]) == 1)
713 else if (INTVAL(operands[2]) == -1)
717 return \"add %2, %0\";
719 [(set_attr "length" "2,4,4,6")])
721 (define_insn "addqi3"
722 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
723 (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
724 (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
728 if (GET_CODE (operands[2]) == CONST_INT)
730 if (INTVAL(operands[2]) == 1)
732 else if (INTVAL(operands[2]) == -1)
736 return \"add %2, %0\";
738 [(set_attr "length" "2,4,4,6")])
741 ;;- subtract instructions
742 ;; we don't have to care for constant second
743 ;; args, since they are canonical plus:xx now!
744 ;; also for minus:DF ??
746 (define_insn "subdf3"
747 [(set (match_operand:DF 0 "register_operand" "=a,a")
748 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
749 (match_operand:DF 2 "general_operand" "fR,Q")))]
752 [(set_attr "length" "2,4")])
754 (define_insn "subsi3"
755 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
756 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
757 (match_operand:SI 2 "general_operand" "r,o,r,o")))]
760 { /* Here we trust that operands don't overlap
762 or is lateoperands the low word?? - looks like it! */
766 lateoperands[0] = operands[0];
768 if (REG_P (operands[0]))
769 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
771 operands[0] = adjust_address (operands[0], HImode, 2);
773 lateoperands[2] = operands[2];
775 if (REG_P (operands[2]))
776 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
778 operands[2] = adjust_address (operands[2], HImode, 2);
780 output_asm_insn (\"sub %2, %0\", operands);
781 output_asm_insn (\"sbc %0\", lateoperands);
782 output_asm_insn (\"sub %2, %0\", lateoperands);
785 ;; offsettable memory addresses always are expensive!!!
786 [(set_attr "length" "6,10,12,16")])
788 (define_insn "subhi3"
789 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
790 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
791 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
795 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
797 return \"sub %2, %0\";
799 [(set_attr "length" "2,4,4,6")])
801 (define_insn "subqi3"
802 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
803 (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
804 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
808 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
810 return \"sub %2, %0\";
812 [(set_attr "length" "2,4,4,6")])
814 ;;;;- and instructions
815 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
817 (define_expand "and<mode>3"
818 [(set (match_operand:PDPint 0 "general_operand" "")
819 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
820 (match_operand:PDPint 2 "general_operand" "")))]
824 rtx op1 = operands[1];
826 /* If there is a constant argument, complement that one.
827 Similarly, if one of the inputs is the same as the output,
828 complement the other input. */
829 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
830 rtx_equal_p (operands[0], operands[1]))
832 operands[1] = operands[2];
837 if (CONST_INT_P (op1))
838 operands[1] = GEN_INT (~INTVAL (op1));
840 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
843 (define_insn "*and<mode>"
844 [(set (match_operand:PDPint 0 "general_operand" "=rR,rR,Q,Q")
846 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
847 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
849 "bic<PDPint:isfx> %1, %0"
850 [(set_attr "length" "2,4,4,6")])
852 ;;- Bit set (inclusive or) instructions
853 (define_insn "iorsi3"
854 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
855 (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
856 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
859 { /* Here we trust that operands don't overlap
861 or is lateoperands the low word?? - looks like it! */
865 lateoperands[0] = operands[0];
867 if (REG_P (operands[0]))
868 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
870 operands[0] = adjust_address (operands[0], HImode, 2);
872 if (! CONSTANT_P(operands[2]))
874 lateoperands[2] = operands[2];
876 if (REG_P (operands[2]))
877 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
879 operands[2] = adjust_address (operands[2], HImode, 2);
881 output_asm_insn (\"bis %2, %0\", operands);
882 output_asm_insn (\"bis %2, %0\", lateoperands);
886 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
887 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
889 /* these have different lengths, so we should have
890 different constraints! */
891 if (INTVAL(operands[2]))
892 output_asm_insn (\"bis %2, %0\", operands);
894 if (INTVAL(lateoperands[2]))
895 output_asm_insn (\"bis %2, %0\", lateoperands);
899 [(set_attr "length" "4,8,8,12,4,4,8,6,6,12")])
901 (define_insn "iorhi3"
902 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
903 (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
904 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
907 [(set_attr "length" "2,4,4,6")])
909 (define_insn "iorqi3"
910 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
911 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
912 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
917 (define_insn "xorsi3"
918 [(set (match_operand:SI 0 "register_operand" "=r")
919 (xor:SI (match_operand:SI 1 "register_operand" "%0")
920 (match_operand:SI 2 "register_operand" "r")))]
923 { /* Here we trust that operands don't overlap */
927 lateoperands[0] = operands[0];
928 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
930 if (REG_P(operands[2]))
932 lateoperands[2] = operands[2];
933 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
935 output_asm_insn (\"xor %2, %0\", operands);
936 output_asm_insn (\"xor %2, %0\", lateoperands);
942 [(set_attr "length" "4")])
944 (define_insn "xorhi3"
945 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
946 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
947 (match_operand:HI 2 "register_operand" "r,r")))]
950 [(set_attr "length" "2,4")])
952 ;;- one complement instructions
954 (define_insn "one_cmplhi2"
955 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
956 (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
959 [(set_attr "length" "2,4")])
961 (define_insn "one_cmplqi2"
962 [(set (match_operand:QI 0 "general_operand" "=rR,rR")
963 (not:QI (match_operand:QI 1 "general_operand" "0,g")))]
967 movb %1, %0\; comb %0"
968 [(set_attr "length" "2,4")])
970 ;;- arithmetic shift instructions
971 (define_insn "ashlsi3"
972 [(set (match_operand:SI 0 "register_operand" "=r,r")
973 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
974 (match_operand:HI 2 "general_operand" "rR,Qi")))]
977 [(set_attr "length" "2,4")])
979 ;; Arithmetic right shift on the pdp works by negating the shift count.
980 (define_expand "ashrsi3"
981 [(set (match_operand:SI 0 "register_operand" "=r")
982 (ashift:SI (match_operand:SI 1 "register_operand" "0")
983 (match_operand:HI 2 "general_operand" "g")))]
987 operands[2] = negate_rtx (HImode, operands[2]);
990 ;; define asl aslb asr asrb - ashc missing!
994 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
995 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
999 [(set_attr "length" "2,4")])
1001 ;; and another possibility for asr is << -1
1002 ;; might cause problems since -1 can also be encoded as 65535!
1007 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1008 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1012 [(set_attr "length" "2,4")])
1016 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1017 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1021 [(set_attr "length" "2,4")])
1023 (define_insn "lshrsi3"
1024 [(set (match_operand:SI 0 "register_operand" "=r")
1025 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1030 rtx lateoperands[2];
1032 lateoperands[0] = operands[0];
1033 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1035 lateoperands[1] = operands[1];
1036 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1038 output_asm_insn (\"clc\", operands);
1039 output_asm_insn (\"ror %0\", lateoperands);
1040 output_asm_insn (\"ror %0\", operands);
1044 [(set_attr "length" "10")])
1046 ;; shift is by arbitrary count is expensive,
1047 ;; shift by one cheap - so let's do that, if
1048 ;; space doesn't matter
1050 [(set (match_operand:HI 0 "general_operand" "=r")
1051 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1052 (match_operand:HI 2 "expand_shift_operand" "O")))]
1058 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1059 if (INTVAL(operands[2]) < 0)
1060 output_asm_insn(\"asr %0\", operands);
1062 output_asm_insn(\"asl %0\", operands);
1067 [(set (attr "length") (const_int 8))])
1071 [(set (match_operand:QI 0 "general_operand" "=r,o")
1072 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1073 (match_operand:HI 2 "const_int_operand" "n,n")))]
1076 { /* allowing predec or post_inc is possible, but hairy! */
1079 cnt = INTVAL(operands[2]) & 0x0007;
1081 for (i=0 ; i < cnt ; i++)
1082 output_asm_insn(\"aslb %0\", operands);
1086 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1087 [(set_attr_alternative "length"
1093 ; [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1094 ; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1098 ; [(set_attr "length" "2,4")])
1102 [(set (match_operand:QI 0 "general_operand" "=r,o")
1103 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1104 (match_operand:HI 2 "const_int_operand" "n,n")))]
1107 { /* allowing predec or post_inc is possible, but hairy! */
1110 cnt = INTVAL(operands[2]) & 0x0007;
1112 for (i=0 ; i < cnt ; i++)
1113 output_asm_insn(\"asrb %0\", operands);
1117 [(set_attr_alternative "length"
1121 ;; the following is invalid - too complex!!! - just say 14 !!!
1122 ; [(set (attr "length") (plus (and (match_dup 2)
1124 ; (and (match_dup 2)
1125 ; (const_int 14))))])
1129 ;; can we get +-1 in the next pattern? should
1130 ;; have been caught by previous patterns!
1132 (define_insn "ashlhi3"
1133 [(set (match_operand:HI 0 "register_operand" "=r,r")
1134 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1135 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1139 if (GET_CODE(operands[2]) == CONST_INT)
1141 if (INTVAL(operands[2]) == 1)
1143 else if (INTVAL(operands[2]) == -1)
1147 return \"ash %2,%0\";
1149 [(set_attr "length" "2,4")])
1151 ;; Arithmetic right shift on the pdp works by negating the shift count.
1152 (define_expand "ashrhi3"
1153 [(set (match_operand:HI 0 "register_operand" "=r")
1154 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1155 (match_operand:HI 2 "general_operand" "g")))]
1159 operands[2] = negate_rtx (HImode, operands[2]);
1162 ;;;;- logical shift instructions
1163 ;;(define_insn "lshrsi3"
1164 ;; [(set (match_operand:HI 0 "register_operand" "=r")
1165 ;; (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1166 ;; (match_operand:HI 2 "general_operand" "rI")))]
1172 (define_insn "absdf2"
1173 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1174 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1177 [(set_attr "length" "2,4")])
1179 (define_insn "abshi2"
1180 [(set (match_operand:HI 0 "general_operand" "=r,o")
1181 (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
1182 "TARGET_ABSHI_BUILTIN"
1185 static int count = 0;
1188 output_asm_insn(\"tst %0\", operands);
1189 sprintf(buf, \"bge abshi%d\", count);
1190 output_asm_insn(buf, NULL);
1191 output_asm_insn(\"neg %0\", operands);
1192 sprintf(buf, \"\\nabshi%d:\", count++);
1193 output_asm_insn(buf, NULL);
1197 [(set_attr "length" "6,10")])
1200 ;; define expand abshi - is much better !!! - but
1201 ;; will it be optimized into an abshi2 ?
1202 ;; it will leave better code, because the tsthi might be
1204 ; -- just a thought - don't have time to check
1206 ;(define_expand "abshi2"
1207 ; [(match_operand:HI 0 "general_operand" "")
1208 ; (match_operand:HI 1 "general_operand" "")]
1212 ; rtx label = gen_label_rtx ();
1214 ; /* do I need this? */
1215 ; do_pending_stack_adjust ();
1217 ; emit_move_insn (operands[0], operands[1]);
1219 ; emit_insn (gen_tsthi (operands[0]));
1220 ; emit_insn (gen_bge (label1));
1222 ; emit_insn (gen_neghi(operands[0], operands[0])
1226 ; emit_label (label);
1228 ; /* allow REG_NOTES to be set on last insn (labels don't have enough
1229 ; fields, and can't be used for REG_NOTES anyway). */
1230 ; emit_use (stack_pointer_rtx);
1236 (define_insn "negdf2"
1237 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1238 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1241 [(set_attr "length" "2,4")])
1243 (define_insn "negsi2"
1244 [(set (match_operand:SI 0 "register_operand" "=r")
1245 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
1249 rtx lateoperands[2];
1251 lateoperands[0] = operands[0];
1252 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1254 lateoperands[1] = operands[1];
1255 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1257 output_asm_insn (\"com %0\", operands);
1258 output_asm_insn (\"com %0\", lateoperands);
1259 output_asm_insn (\"inc %0\", operands);
1260 output_asm_insn (\"adc %0\", lateoperands);
1264 [(set_attr "length" "10")])
1266 (define_insn "neghi2"
1267 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1268 (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
1271 [(set_attr "length" "2,4")])
1273 (define_insn "negqi2"
1274 [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1275 (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
1278 [(set_attr "length" "2,4")])
1281 ;; Unconditional and other jump instructions
1284 (label_ref (match_operand 0 "" "")))]
1288 if (get_attr_length (insn) == 2)
1292 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1294 (const_int MIN_BRANCH))
1295 (gt (minus (match_dup 0)
1297 (const_int MAX_BRANCH)))
1303 (label_ref (match_operand 0 "" "")))
1304 (clobber (const_int 1))]
1307 [(set_attr "length" "4")])
1309 (define_insn "tablejump"
1310 [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1311 (use (label_ref (match_operand 1 "" "")))]
1314 [(set_attr "length" "2,4")])
1316 ;; indirect jump - let's be conservative!
1317 ;; allow only register_operand, even though we could also
1318 ;; allow labels etc.
1320 (define_insn "indirect_jump"
1321 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1325 ;;- jump to subroutine
1328 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1329 (match_operand:HI 1 "general_operand" "g,g"))
1330 ;; (use (reg:HI 0)) what was that ???
1332 ;;- Don't use operand 1 for most machines.
1335 [(set_attr "length" "2,4")])
1337 ;;- jump to subroutine
1338 (define_insn "call_value"
1339 [(set (match_operand 0 "" "")
1340 (call (match_operand:HI 1 "general_operand" "rR,Q")
1341 (match_operand:HI 2 "general_operand" "g,g")))
1342 ;; (use (reg:HI 0)) - what was that ????
1344 ;;- Don't use operand 2 for most machines.
1347 [(set_attr "length" "2,4")])
1358 (define_insn "muldf3"
1359 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1360 (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
1361 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1363 "{muld|mulf} %2, %0"
1364 [(set_attr "length" "2,4,10")])
1366 ;; 16 bit result multiply:
1367 ;; currently we multiply only into odd registers, so we don't use two
1368 ;; registers - but this is a bit inefficient at times. If we define
1369 ;; a register class for each register, then we can specify properly
1370 ;; which register need which scratch register ....
1372 (define_insn "mulhi3"
1373 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1374 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1375 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1378 [(set_attr "length" "2,4")])
1381 (define_expand "mulhisi3"
1383 (match_operand:HI 1 "general_operand" "g,g"))
1384 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1385 (mult:SI (truncate:HI
1387 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1389 "operands[3] = gen_lowpart(HImode, operands[1]);")
1392 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1393 (mult:SI (truncate:HI
1394 (match_operand:SI 1 "register_operand" "%0,0"))
1395 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1398 [(set_attr "length" "2,4")])
1400 ;(define_insn "mulhisi3"
1401 ; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1402 ; (mult:SI (truncate:HI
1403 ; (match_operand:SI 1 "register_operand" "%0,0"))
1404 ; (match_operand:HI 2 "general_operand" "rR,Qi")))]
1407 ; [(set_attr "length" "2,4")])
1410 (define_insn "divdf3"
1411 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1412 (div:DF (match_operand:DF 1 "register_operand" "0,0,0")
1413 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1415 "{divd|divf} %2, %0"
1416 [(set_attr "length" "2,4,10")])
1419 (define_expand "divhi3"
1420 [(set (subreg:HI (match_dup 1) 0)
1421 (div:HI (match_operand:SI 1 "general_operand" "0")
1422 (match_operand:HI 2 "general_operand" "g")))
1423 (set (match_operand:HI 0 "general_operand" "=r")
1424 (subreg:HI (match_dup 1) 0))]
1429 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1430 (div:HI (match_operand:SI 1 "general_operand" "0")
1431 (match_operand:HI 2 "general_operand" "g")))]
1434 [(set_attr "length" "4")])
1436 (define_expand "modhi3"
1437 [(set (subreg:HI (match_dup 1) 2)
1438 (mod:HI (match_operand:SI 1 "general_operand" "0")
1439 (match_operand:HI 2 "general_operand" "g")))
1440 (set (match_operand:HI 0 "general_operand" "=r")
1441 (subreg:HI (match_dup 1) 2))]
1446 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 2)
1447 (mod:HI (match_operand:SI 1 "general_operand" "0")
1448 (match_operand:HI 2 "general_operand" "g")))]
1451 [(set_attr "length" "4")])
1453 ;(define_expand "divmodhi4"
1454 ; [(parallel [(set (subreg:HI (match_dup 1) 0)
1455 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1456 ; (match_operand:HI 2 "general_operand" "g")))
1457 ; (set (subreg:HI (match_dup 1) 2)
1458 ; (mod:HI (match_dup 1)
1460 ; (set (match_operand:HI 3 "general_operand" "=r")
1461 ; (subreg:HI (match_dup 1) 2))
1462 ; (set (match_operand:HI 0 "general_operand" "=r")
1463 ; (subreg:HI (match_dup 1) 0))]
1468 ; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1469 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1470 ; (match_operand:HI 2 "general_operand" "g")))
1471 ; (set (subreg:HI (match_dup 0) 2)
1472 ; (mod:HI (match_dup 1)
1478 ;; is rotate doing the right thing to be included here ????