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 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
31 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
32 ;;- updates for most instructions.
34 ;;- Operand classes for the register allocator:
36 ;; Compare instructions.
38 ;; currently we only support df floats, which saves us quite some
39 ;; hassle switching the FP mode!
40 ;; we assume that CPU is always in long float mode, and
41 ;; 16 bit integer mode - currently, the prologue for main does this,
42 ;; but maybe we should just set up a NEW crt0 properly,
43 ;; -- and what about signal handling code?
44 ;; (we don't even let sf floats in the register file, so
45 ;; we only should have to worry about truncating and widening
46 ;; when going to memory)
48 ;; abort() call by g++ - must define libfunc for cmp_optab
49 ;; and ucmp_optab for mode SImode, because we don't have that!!!
50 ;; - yet since no libfunc is there, we abort ()
52 ;; The only thing that remains to be done then is output
53 ;; the floats in a way the assembler can handle it (and
54 ;; if you're really into it, use a PDP11 float emulation
55 ;; library to do floating point constant folding - but
56 ;; I guess you'll get reasonable results even when not
58 ;; the last thing to do is fix the UPDATE_CC macro to check
59 ;; for floating point condition codes, and set cc_status
60 ;; properly, also setting the CC_IN_FCCR flag.
63 ;; currently type is only fpu or arith or unknown, maybe branch later ?
65 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
67 ;; length default is 1 word each
68 (define_attr "length" "" (const_int 1))
70 ;; a user's asm statement
71 (define_asm_attributes
72 [(set_attr "type" "unknown")
73 ; all bets are off how long it is - make it 256, forces long jumps
74 ; whenever jumping around it !!!
75 (set_attr "length" "256")])
77 ;; define function units
79 ;; arithmetic - values here immediately when next insn issued
80 ;; or does it mean the number of cycles after this insn was issued?
81 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
83 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
84 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
89 (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F")
90 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))]
94 cc_status.flags = CC_IN_FPU;
95 if (which_alternative == 0 || which_alternative == 2)
96 return \"{tstd|tstf} %0\;cfcc\";
98 return \"{cmpd|cmpf} %0, %1\;cfcc\";
100 [(set_attr "length" "2,2,3,3,6")])
102 (define_insn "*cmphi"
104 (compare (match_operand:HI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
105 (match_operand:HI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
114 [(set_attr "length" "1,1,2,2,2,3")])
116 (define_insn "*cmpqi"
118 (compare (match_operand:QI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
119 (match_operand:QI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
128 [(set_attr "length" "1,1,2,2,2,3")])
131 ;; sob instruction - we need an assembler which can make this instruction
132 ;; valid under _all_ circumstances!
137 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
140 (label_ref (match_operand 1 "" ""))
143 (plus:HI (match_dup 0)
148 static int labelcount = 0;
149 static char buf[1000];
151 if (get_attr_length (insn) == 1)
152 return \"sob %0, %l1\";
155 output_asm_insn (\"dec %0\", operands);
157 sprintf (buf, \"bge LONG_SOB%d\", labelcount);
158 output_asm_insn (buf, NULL);
160 output_asm_insn (\"jmp %l1\", operands);
162 sprintf (buf, \"LONG_SOB%d:\", labelcount++);
163 output_asm_insn (buf, NULL);
167 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
170 (ge (minus (match_dup 0)
176 ;; These control RTL generation for conditional jump insns
177 ;; and match them for register allocation.
179 (define_expand "cbranchdf4"
181 (compare (match_operand:DF 1 "general_operand")
182 (match_operand:DF 2 "general_operand")))
184 (if_then_else (match_operator 0 "ordered_comparison_operator"
185 [(cc0) (const_int 0)])
186 (label_ref (match_operand 3 "" ""))
191 (define_expand "cbranchhi4"
193 (compare (match_operand:HI 1 "general_operand")
194 (match_operand:HI 2 "general_operand")))
196 (if_then_else (match_operator 0 "ordered_comparison_operator"
197 [(cc0) (const_int 0)])
198 (label_ref (match_operand 3 "" ""))
203 (define_expand "cbranchqi4"
205 (compare (match_operand:QI 1 "general_operand")
206 (match_operand:QI 2 "general_operand")))
208 (if_then_else (match_operator 0 "ordered_comparison_operator"
209 [(cc0) (const_int 0)])
210 (label_ref (match_operand 3 "" ""))
215 ;; problem with too short jump distance! we need an assembler which can
216 ;; make this valid for all jump distances!
219 ;; these must be changed to check for CC_IN_FCCR if float is to be
222 (define_insn "*branch"
224 (if_then_else (match_operator 0 "ordered_comparison_operator"
225 [(cc0) (const_int 0)])
226 (label_ref (match_operand 1 "" ""))
229 "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
230 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1)
233 (ge (minus (match_dup 1)
240 ;; These match inverted jump insns for register allocation.
242 (define_insn "*branch_inverted"
244 (if_then_else (match_operator 0 "ordered_comparison_operator"
245 [(cc0) (const_int 0)])
247 (label_ref (match_operand 1 "" ""))))]
249 "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
250 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1)
253 (ge (minus (match_dup 1)
262 [(set (match_operand:DI 0 "general_operand" "=g,rm,o")
263 (match_operand:DI 1 "general_operand" "m,r,a"))]
265 "* return output_move_quad (operands);"
266 ;; what's the mose expensive code - say twice movsi = 16
267 [(set_attr "length" "16,16,16")])
270 [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
271 (match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
273 "* return output_move_double (operands);"
274 ;; what's the most expensive code ? - I think 8!
275 ;; we could split it up and make several sub-cases...
276 [(set_attr "length" "2,3,4,8,8")])
279 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
280 (match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
284 if (operands[1] == const0_rtx)
287 return \"mov %1, %0\";
289 [(set_attr "length" "1,2,2,3")])
292 [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
293 (match_operand:QI 1 "general_operand" "g"))]
297 if (operands[1] == const0_rtx)
300 return \"movb %1, %0\";
302 [(set_attr "length" "1")])
304 ;; do we have to supply all these moves? e.g. to
305 ;; NO_LOAD_FPU_REGs ?
307 [(set (match_operand:DF 0 "general_operand" "=a,fR,a,Q,g")
308 (match_operand:DF 1 "general_operand" "fFR,a,Q,a,g"))]
310 "* if (which_alternative ==0 || which_alternative == 2)
311 return \"ldd %1, %0\";
312 else if (which_alternative == 1 || which_alternative == 3)
313 return \"std %1, %0\";
315 return output_move_quad (operands); "
317 [(set_attr "length" "1,1,5,5,16")])
320 [(set (match_operand:SF 0 "general_operand" "=g,r,g")
321 (match_operand:SF 1 "general_operand" "r,rmF,g"))]
323 "* return output_move_double (operands);"
324 [(set_attr "length" "8,8,8")])
326 ;; maybe fiddle a bit with move_ratio, then
327 ;; let constraints only accept a register ...
329 (define_expand "movmemhi"
330 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
331 (match_operand:BLK 1 "general_operand" "g,g"))
332 (use (match_operand:HI 2 "general_operand" "n,&mr"))
333 (use (match_operand:HI 3 "immediate_operand" "i,i"))
334 (clobber (match_scratch:HI 4 "=&r,X"))
335 (clobber (match_dup 5))
336 (clobber (match_dup 6))
337 (clobber (match_dup 2))])]
338 "(TARGET_BCOPY_BUILTIN)"
342 = replace_equiv_address (operands[0],
343 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
345 = replace_equiv_address (operands[1],
346 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
348 operands[5] = XEXP (operands[0], 0);
349 operands[6] = XEXP (operands[1], 0);
353 (define_insn "" ; "movmemhi"
354 [(set (mem:BLK (match_operand 0 "pmode_register_operand" "+r,r"))
355 (mem:BLK (match_operand 1 "pmode_register_operand" "+r,r")))
356 (use (match_operand:HI 2 "general_operand" "+n,&r"))
357 (use (match_operand:HI 3 "immediate_operand" "i,i"))
358 (clobber (match_scratch:HI 4 "=&r,X"))
359 (clobber (match_dup 0))
360 (clobber (match_dup 1))
361 (clobber (match_dup 2))]
362 "(TARGET_BCOPY_BUILTIN)"
363 "* return output_block_move (operands);"
365 [(set_attr "length" "40")])
369 ;;- truncation instructions
371 (define_insn "truncdfsf2"
372 [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
373 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
375 "* if (which_alternative ==0)
377 output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
378 output_asm_insn(\"mov (sp)+, %0\", operands);
379 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
380 output_asm_insn(\"mov (sp)+, %0\", operands);
383 else if (which_alternative == 1)
384 return \"{stcdf|movfo} %1, %0\";
386 return \"{stcdf|movfo} %1, %0\";
388 [(set_attr "length" "3,1,2")])
391 (define_expand "truncsihi2"
392 [(set (match_operand:HI 0 "general_operand" "=g")
394 (match_operand:SI 1 "general_operand" "or")
400 ;;- zero extension instructions
402 (define_insn "zero_extendqihi2"
403 [(set (match_operand:HI 0 "general_operand" "=r")
404 (zero_extend:HI (match_operand:QI 1 "general_operand" "0")))]
407 [(set_attr "length" "2")])
409 (define_expand "zero_extendhisi2"
413 (match_operand:HI 1 "register_operand" "r"))
415 (match_operand:SI 0 "register_operand" "=r")
419 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
422 ;;- sign extension instructions
424 (define_insn "extendsfdf2"
425 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
426 (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
429 mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
431 {ldcfd|movof} %1, %0"
432 [(set_attr "length" "2,1,2")])
434 ;; does movb sign extend in register-to-register move?
435 (define_insn "extendqihi2"
436 [(set (match_operand:HI 0 "register_operand" "=r,r")
437 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
440 [(set_attr "length" "1,2")])
442 (define_insn "extendqisi2"
443 [(set (match_operand:SI 0 "register_operand" "=r,r")
444 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
450 /* make register pair available */
451 latehalf[0] = operands[0];
452 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
454 output_asm_insn(\"movb %1, %0\", operands);
455 output_asm_insn(\"sxt %0\", latehalf);
459 [(set_attr "length" "2,3")])
461 ;; maybe we have to use define_expand to say that we have the instruction,
462 ;; unconditionally, and then match dependent on CPU type:
464 (define_expand "extendhisi2"
465 [(set (match_operand:SI 0 "general_operand" "=g")
466 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
470 (define_insn "" ; "extendhisi2"
471 [(set (match_operand:SI 0 "general_operand" "=o,<,r")
472 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
478 /* we don't want to mess with auto increment */
480 switch (which_alternative)
484 latehalf[0] = operands[0];
485 operands[0] = adjust_address(operands[0], HImode, 2);
487 output_asm_insn(\"mov %1, %0\", operands);
488 output_asm_insn(\"sxt %0\", latehalf);
494 /* - auto-decrement - right direction ;-) */
495 output_asm_insn(\"mov %1, %0\", operands);
496 output_asm_insn(\"sxt %0\", operands);
502 /* make register pair available */
503 latehalf[0] = operands[0];
504 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
506 output_asm_insn(\"mov %1, %0\", operands);
507 output_asm_insn(\"sxt %0\", latehalf);
516 [(set_attr "length" "5,3,3")])
520 [(set (match_operand:SI 0 "register_operand" "=r")
521 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
525 static int count = 0;
529 lateoperands[0] = operands[0];
530 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
532 output_asm_insn(\"tst %0\", operands);
533 sprintf(buf, \"bge extendhisi%d\", count);
534 output_asm_insn(buf, NULL);
535 output_asm_insn(\"mov -1, %0\", lateoperands);
536 sprintf(buf, \"bne extendhisi%d\", count+1);
537 output_asm_insn(buf, NULL);
538 sprintf(buf, \"\\nextendhisi%d:\", count);
539 output_asm_insn(buf, NULL);
540 output_asm_insn(\"clr %0\", lateoperands);
541 sprintf(buf, \"\\nextendhisi%d:\", count+1);
542 output_asm_insn(buf, NULL);
548 [(set_attr "length" "6")])
550 ;; make float to int and vice versa
551 ;; using the cc_status.flag field we could probably cut down
553 ;; assume that we are normally in double and integer mode -
554 ;; what do pdp library routines do to fpu mode ?
556 (define_insn "floatsidf2"
557 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
558 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
560 "* if (which_alternative ==0)
565 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
566 output_asm_insn(\"mov %1, -(sp)\", latehalf);
567 output_asm_insn(\"mov %1, -(sp)\", operands);
569 output_asm_insn(\"setl\", operands);
570 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
571 output_asm_insn(\"seti\", operands);
574 else if (which_alternative == 1)
575 return \"setl\;{ldcld|movif} %1, %0\;seti\";
577 return \"setl\;{ldcld|movif} %1, %0\;seti\";
579 [(set_attr "length" "5,3,4")])
581 (define_insn "floathidf2"
582 [(set (match_operand:DF 0 "register_operand" "=a,a")
583 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
585 "{ldcid|movif} %1, %0"
586 [(set_attr "length" "1,2")])
589 (define_insn "fix_truncdfsi2"
590 [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
591 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
593 "* if (which_alternative ==0)
595 output_asm_insn(\"setl\", operands);
596 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
597 output_asm_insn(\"seti\", operands);
598 output_asm_insn(\"mov (sp)+, %0\", operands);
599 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
600 output_asm_insn(\"mov (sp)+, %0\", operands);
603 else if (which_alternative == 1)
604 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
606 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
608 [(set_attr "length" "5,3,4")])
610 (define_insn "fix_truncdfhi2"
611 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
612 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
614 "{stcdi|movfi} %1, %0"
615 [(set_attr "length" "1,2")])
618 ;;- arithmetic instructions
621 (define_insn "adddf3"
622 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
623 (plus:DF (match_operand:DF 1 "register_operand" "%0,0,0")
624 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
627 [(set_attr "length" "1,2,5")])
629 (define_insn "addsi3"
630 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
631 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
632 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
635 { /* Here we trust that operands don't overlap
637 or is lateoperands the low word?? - looks like it! */
641 lateoperands[0] = operands[0];
643 if (REG_P (operands[0]))
644 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
646 operands[0] = adjust_address (operands[0], HImode, 2);
648 if (! CONSTANT_P(operands[2]))
650 lateoperands[2] = operands[2];
652 if (REG_P (operands[2]))
653 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
655 operands[2] = adjust_address (operands[2], HImode, 2);
657 output_asm_insn (\"add %2, %0\", operands);
658 output_asm_insn (\"adc %0\", lateoperands);
659 output_asm_insn (\"add %2, %0\", lateoperands);
663 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
664 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
666 if (INTVAL(operands[2]))
668 output_asm_insn (\"add %2, %0\", operands);
669 output_asm_insn (\"adc %0\", lateoperands);
672 if (INTVAL(lateoperands[2]))
673 output_asm_insn (\"add %2, %0\", lateoperands);
677 [(set_attr "length" "3,5,6,8,3,1,5,5,3,8")])
679 (define_insn "addhi3"
680 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
681 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
682 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
686 if (GET_CODE (operands[2]) == CONST_INT)
688 if (INTVAL(operands[2]) == 1)
690 else if (INTVAL(operands[2]) == -1)
694 return \"add %2, %0\";
696 [(set_attr "length" "1,2,2,3")])
698 (define_insn "addqi3"
699 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
700 (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
701 (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
705 if (GET_CODE (operands[2]) == CONST_INT)
707 if (INTVAL(operands[2]) == 1)
709 else if (INTVAL(operands[2]) == -1)
713 return \"add %2, %0\";
715 [(set_attr "length" "1,2,2,3")])
718 ;;- subtract instructions
719 ;; we don't have to care for constant second
720 ;; args, since they are canonical plus:xx now!
721 ;; also for minus:DF ??
723 (define_insn "subdf3"
724 [(set (match_operand:DF 0 "register_operand" "=a,a")
725 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
726 (match_operand:DF 2 "general_operand" "fR,Q")))]
729 [(set_attr "length" "1,2")])
731 (define_insn "subsi3"
732 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
733 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
734 (match_operand:SI 2 "general_operand" "r,o,r,o")))]
737 { /* Here we trust that operands don't overlap
739 or is lateoperands the low word?? - looks like it! */
743 lateoperands[0] = operands[0];
745 if (REG_P (operands[0]))
746 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
748 operands[0] = adjust_address (operands[0], HImode, 2);
750 lateoperands[2] = operands[2];
752 if (REG_P (operands[2]))
753 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
755 operands[2] = adjust_address (operands[2], HImode, 2);
757 output_asm_insn (\"sub %2, %0\", operands);
758 output_asm_insn (\"sbc %0\", lateoperands);
759 output_asm_insn (\"sub %2, %0\", lateoperands);
762 ;; offsettable memory addresses always are expensive!!!
763 [(set_attr "length" "3,5,6,8")])
765 (define_insn "subhi3"
766 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
767 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
768 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
772 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
774 return \"sub %2, %0\";
776 [(set_attr "length" "1,2,2,3")])
778 (define_insn "subqi3"
779 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
780 (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
781 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
785 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
787 return \"sub %2, %0\";
789 [(set_attr "length" "1,2,2,3")])
791 ;;;;- and instructions
792 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
794 (define_insn "andsi3"
795 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
796 (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
797 (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
800 { /* Here we trust that operands don't overlap
802 or is lateoperands the low word?? - looks like it! */
806 lateoperands[0] = operands[0];
808 if (REG_P (operands[0]))
809 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
811 operands[0] = adjust_address (operands[0], HImode, 2);
813 if (! CONSTANT_P(operands[2]))
815 lateoperands[2] = operands[2];
817 if (REG_P (operands[2]))
818 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
820 operands[2] = adjust_address (operands[2], HImode, 2);
822 output_asm_insn (\"bic %2, %0\", operands);
823 output_asm_insn (\"bic %2, %0\", lateoperands);
827 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
828 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
830 /* these have different lengths, so we should have
831 different constraints! */
832 if (INTVAL(operands[2]))
833 output_asm_insn (\"bic %2, %0\", operands);
835 if (INTVAL(lateoperands[2]))
836 output_asm_insn (\"bic %2, %0\", lateoperands);
840 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
842 (define_insn "andhi3"
843 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
844 (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
845 (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
848 [(set_attr "length" "1,2,2,3")])
850 (define_insn "andqi3"
851 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
852 (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
853 (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
856 [(set_attr "length" "1,2,2,3")])
858 ;;- Bit set (inclusive or) instructions
859 (define_insn "iorsi3"
860 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
861 (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
862 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
865 { /* Here we trust that operands don't overlap
867 or is lateoperands the low word?? - looks like it! */
871 lateoperands[0] = operands[0];
873 if (REG_P (operands[0]))
874 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
876 operands[0] = adjust_address (operands[0], HImode, 2);
878 if (! CONSTANT_P(operands[2]))
880 lateoperands[2] = operands[2];
882 if (REG_P (operands[2]))
883 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
885 operands[2] = adjust_address (operands[2], HImode, 2);
887 output_asm_insn (\"bis %2, %0\", operands);
888 output_asm_insn (\"bis %2, %0\", lateoperands);
892 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
893 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
895 /* these have different lengths, so we should have
896 different constraints! */
897 if (INTVAL(operands[2]))
898 output_asm_insn (\"bis %2, %0\", operands);
900 if (INTVAL(lateoperands[2]))
901 output_asm_insn (\"bis %2, %0\", lateoperands);
905 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
907 (define_insn "iorhi3"
908 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
909 (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
910 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
913 [(set_attr "length" "1,2,2,3")])
915 (define_insn "iorqi3"
916 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
917 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
918 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
923 (define_insn "xorsi3"
924 [(set (match_operand:SI 0 "register_operand" "=r")
925 (xor:SI (match_operand:SI 1 "register_operand" "%0")
926 (match_operand:SI 2 "register_operand" "r")))]
929 { /* Here we trust that operands don't overlap */
933 lateoperands[0] = operands[0];
934 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
936 if (REG_P(operands[2]))
938 lateoperands[2] = operands[2];
939 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
941 output_asm_insn (\"xor %2, %0\", operands);
942 output_asm_insn (\"xor %2, %0\", lateoperands);
948 [(set_attr "length" "2")])
950 (define_insn "xorhi3"
951 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
952 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
953 (match_operand:HI 2 "register_operand" "r,r")))]
956 [(set_attr "length" "1,2")])
958 ;;- one complement instructions
960 (define_insn "one_cmplhi2"
961 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
962 (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
965 [(set_attr "length" "1,2")])
967 (define_insn "one_cmplqi2"
968 [(set (match_operand:QI 0 "general_operand" "=rR,rR")
969 (not:QI (match_operand:QI 1 "general_operand" "0,g")))]
973 movb %1, %0\; comb %0"
974 [(set_attr "length" "1,2")])
976 ;;- arithmetic shift instructions
977 (define_insn "ashlsi3"
978 [(set (match_operand:SI 0 "register_operand" "=r,r")
979 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
980 (match_operand:HI 2 "general_operand" "rR,Qi")))]
983 [(set_attr "length" "1,2")])
985 ;; Arithmetic right shift on the pdp works by negating the shift count.
986 (define_expand "ashrsi3"
987 [(set (match_operand:SI 0 "register_operand" "=r")
988 (ashift:SI (match_operand:SI 1 "register_operand" "0")
989 (match_operand:HI 2 "general_operand" "g")))]
993 operands[2] = negate_rtx (HImode, operands[2]);
996 ;; define asl aslb asr asrb - ashc missing!
1000 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1001 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1005 [(set_attr "length" "1,2")])
1007 ;; and another possibility for asr is << -1
1008 ;; might cause problems since -1 can also be encoded as 65535!
1013 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1014 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1018 [(set_attr "length" "1,2")])
1022 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1023 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1027 [(set_attr "length" "1,2")])
1029 (define_insn "lshrsi3"
1030 [(set (match_operand:SI 0 "register_operand" "=r")
1031 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1036 rtx lateoperands[2];
1038 lateoperands[0] = operands[0];
1039 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1041 lateoperands[1] = operands[1];
1042 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1044 output_asm_insn (\"clc\", operands);
1045 output_asm_insn (\"ror %0\", lateoperands);
1046 output_asm_insn (\"ror %0\", operands);
1050 [(set_attr "length" "5")])
1052 ;; shift is by arbitrary count is expensive,
1053 ;; shift by one cheap - so let's do that, if
1054 ;; space doesn't matter
1056 [(set (match_operand:HI 0 "general_operand" "=r")
1057 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1058 (match_operand:HI 2 "expand_shift_operand" "O")))]
1064 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1065 if (INTVAL(operands[2]) < 0)
1066 output_asm_insn(\"asr %0\", operands);
1068 output_asm_insn(\"asl %0\", operands);
1073 [(set (attr "length") (const_int 4))])
1077 [(set (match_operand:QI 0 "general_operand" "=r,o")
1078 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1079 (match_operand:HI 2 "const_int_operand" "n,n")))]
1082 { /* allowing predec or post_inc is possible, but hairy! */
1085 cnt = INTVAL(operands[2]) & 0x0007;
1087 for (i=0 ; i < cnt ; i++)
1088 output_asm_insn(\"aslb %0\", operands);
1092 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1093 [(set_attr_alternative "length"
1099 ; [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1100 ; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1104 ; [(set_attr "length" "1,2")])
1108 [(set (match_operand:QI 0 "general_operand" "=r,o")
1109 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1110 (match_operand:HI 2 "const_int_operand" "n,n")))]
1113 { /* allowing predec or post_inc is possible, but hairy! */
1116 cnt = INTVAL(operands[2]) & 0x0007;
1118 for (i=0 ; i < cnt ; i++)
1119 output_asm_insn(\"asrb %0\", operands);
1123 [(set_attr_alternative "length"
1127 ;; the following is invalid - too complex!!! - just say 14 !!!
1128 ; [(set (attr "length") (plus (and (match_dup 2)
1130 ; (and (match_dup 2)
1131 ; (const_int 7))))])
1135 ;; can we get +-1 in the next pattern? should
1136 ;; have been caught by previous patterns!
1138 (define_insn "ashlhi3"
1139 [(set (match_operand:HI 0 "register_operand" "=r,r")
1140 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1141 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1145 if (GET_CODE(operands[2]) == CONST_INT)
1147 if (INTVAL(operands[2]) == 1)
1149 else if (INTVAL(operands[2]) == -1)
1153 return \"ash %2,%0\";
1155 [(set_attr "length" "1,2")])
1157 ;; Arithmetic right shift on the pdp works by negating the shift count.
1158 (define_expand "ashrhi3"
1159 [(set (match_operand:HI 0 "register_operand" "=r")
1160 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1161 (match_operand:HI 2 "general_operand" "g")))]
1165 operands[2] = negate_rtx (HImode, operands[2]);
1168 ;;;;- logical shift instructions
1169 ;;(define_insn "lshrsi3"
1170 ;; [(set (match_operand:HI 0 "register_operand" "=r")
1171 ;; (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1172 ;; (match_operand:HI 2 "general_operand" "rI")))]
1178 (define_insn "absdf2"
1179 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1180 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1183 [(set_attr "length" "1,2")])
1185 (define_insn "abshi2"
1186 [(set (match_operand:HI 0 "general_operand" "=r,o")
1187 (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
1188 "TARGET_ABSHI_BUILTIN"
1191 static int count = 0;
1194 output_asm_insn(\"tst %0\", operands);
1195 sprintf(buf, \"bge abshi%d\", count);
1196 output_asm_insn(buf, NULL);
1197 output_asm_insn(\"neg %0\", operands);
1198 sprintf(buf, \"\\nabshi%d:\", count++);
1199 output_asm_insn(buf, NULL);
1203 [(set_attr "length" "3,5")])
1206 ;; define expand abshi - is much better !!! - but
1207 ;; will it be optimized into an abshi2 ?
1208 ;; it will leave better code, because the tsthi might be
1210 ; -- just a thought - don't have time to check
1212 ;(define_expand "abshi2"
1213 ; [(match_operand:HI 0 "general_operand" "")
1214 ; (match_operand:HI 1 "general_operand" "")]
1218 ; rtx label = gen_label_rtx ();
1220 ; /* do I need this? */
1221 ; do_pending_stack_adjust ();
1223 ; emit_move_insn (operands[0], operands[1]);
1225 ; emit_insn (gen_tsthi (operands[0]));
1226 ; emit_insn (gen_bge (label1));
1228 ; emit_insn (gen_neghi(operands[0], operands[0])
1232 ; emit_label (label);
1234 ; /* allow REG_NOTES to be set on last insn (labels don't have enough
1235 ; fields, and can't be used for REG_NOTES anyway). */
1236 ; emit_use (stack_pointer_rtx);
1242 (define_insn "negdf2"
1243 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1244 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1247 [(set_attr "length" "1,2")])
1249 (define_insn "negsi2"
1250 [(set (match_operand:SI 0 "register_operand" "=r")
1251 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
1255 rtx lateoperands[2];
1257 lateoperands[0] = operands[0];
1258 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1260 lateoperands[1] = operands[1];
1261 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1263 output_asm_insn (\"com %0\", operands);
1264 output_asm_insn (\"com %0\", lateoperands);
1265 output_asm_insn (\"inc %0\", operands);
1266 output_asm_insn (\"adc %0\", lateoperands);
1270 [(set_attr "length" "5")])
1272 (define_insn "neghi2"
1273 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1274 (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
1277 [(set_attr "length" "1,2")])
1279 (define_insn "negqi2"
1280 [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1281 (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
1284 [(set_attr "length" "1,2")])
1287 ;; Unconditional and other jump instructions
1290 (label_ref (match_operand 0 "" "")))]
1293 [(set_attr "length" "2")])
1297 (label_ref (match_operand 0 "" "")))
1298 (clobber (const_int 1))]
1301 [(set_attr "length" "2")])
1303 (define_insn "tablejump"
1304 [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1305 (use (label_ref (match_operand 1 "" "")))]
1308 [(set_attr "length" "1,2")])
1310 ;; indirect jump - let's be conservative!
1311 ;; allow only register_operand, even though we could also
1312 ;; allow labels etc.
1314 (define_insn "indirect_jump"
1315 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1319 ;;- jump to subroutine
1322 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1323 (match_operand:HI 1 "general_operand" "g,g"))
1324 ;; (use (reg:HI 0)) what was that ???
1326 ;;- Don't use operand 1 for most machines.
1329 [(set_attr "length" "1,2")])
1331 ;;- jump to subroutine
1332 (define_insn "call_value"
1333 [(set (match_operand 0 "" "")
1334 (call (match_operand:HI 1 "general_operand" "rR,Q")
1335 (match_operand:HI 2 "general_operand" "g,g")))
1336 ;; (use (reg:HI 0)) - what was that ????
1338 ;;- Don't use operand 2 for most machines.
1341 [(set_attr "length" "1,2")])
1352 (define_insn "muldf3"
1353 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1354 (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
1355 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1357 "{muld|mulf} %2, %0"
1358 [(set_attr "length" "1,2,5")])
1360 ;; 16 bit result multiply:
1361 ;; currently we multiply only into odd registers, so we don't use two
1362 ;; registers - but this is a bit inefficient at times. If we define
1363 ;; a register class for each register, then we can specify properly
1364 ;; which register need which scratch register ....
1366 (define_insn "mulhi3"
1367 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1368 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1369 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1372 [(set_attr "length" "1,2")])
1375 (define_expand "mulhisi3"
1377 (match_operand:HI 1 "general_operand" "g,g"))
1378 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1379 (mult:SI (truncate:HI
1381 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1383 "operands[3] = gen_lowpart(HImode, operands[1]);")
1386 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1387 (mult:SI (truncate:HI
1388 (match_operand:SI 1 "register_operand" "%0,0"))
1389 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1392 [(set_attr "length" "1,2")])
1394 ;(define_insn "mulhisi3"
1395 ; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1396 ; (mult:SI (truncate:HI
1397 ; (match_operand:SI 1 "register_operand" "%0,0"))
1398 ; (match_operand:HI 2 "general_operand" "rR,Qi")))]
1401 ; [(set_attr "length" "1,2")])
1404 (define_insn "divdf3"
1405 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1406 (div:DF (match_operand:DF 1 "register_operand" "0,0,0")
1407 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1409 "{divd|divf} %2, %0"
1410 [(set_attr "length" "1,2,5")])
1413 (define_expand "divhi3"
1414 [(set (subreg:HI (match_dup 1) 0)
1415 (div:HI (match_operand:SI 1 "general_operand" "0")
1416 (match_operand:HI 2 "general_operand" "g")))
1417 (set (match_operand:HI 0 "general_operand" "=r")
1418 (subreg:HI (match_dup 1) 0))]
1423 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1424 (div:HI (match_operand:SI 1 "general_operand" "0")
1425 (match_operand:HI 2 "general_operand" "g")))]
1428 [(set_attr "length" "2")])
1430 (define_expand "modhi3"
1431 [(set (subreg:HI (match_dup 1) 2)
1432 (mod:HI (match_operand:SI 1 "general_operand" "0")
1433 (match_operand:HI 2 "general_operand" "g")))
1434 (set (match_operand:HI 0 "general_operand" "=r")
1435 (subreg:HI (match_dup 1) 2))]
1440 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 2)
1441 (mod:HI (match_operand:SI 1 "general_operand" "0")
1442 (match_operand:HI 2 "general_operand" "g")))]
1445 [(set_attr "length" "2")])
1447 ;(define_expand "divmodhi4"
1448 ; [(parallel [(set (subreg:HI (match_dup 1) 0)
1449 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1450 ; (match_operand:HI 2 "general_operand" "g")))
1451 ; (set (subreg:HI (match_dup 1) 2)
1452 ; (mod:HI (match_dup 1)
1454 ; (set (match_operand:HI 3 "general_operand" "=r")
1455 ; (subreg:HI (match_dup 1) 2))
1456 ; (set (match_operand:HI 0 "general_operand" "=r")
1457 ; (subreg:HI (match_dup 1) 0))]
1462 ; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1463 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1464 ; (match_operand:HI 2 "general_operand" "g")))
1465 ; (set (subreg:HI (match_dup 0) 2)
1466 ; (mod:HI (match_dup 1)
1472 ;; is rotate doing the right thing to be included here ????