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 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 ;; Match CONST_DOUBLE zero for tstd/tstf.
23 (define_predicate "register_or_const0_operand"
24 (ior (match_operand 0 "register_operand")
25 (match_test "op == CONST0_RTX (GET_MODE (op))")))
31 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
33 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
34 ;;- updates for most instructions.
36 ;;- Operand classes for the register allocator:
38 ;; Compare instructions.
40 ;; currently we only support df floats, which saves us quite some
41 ;; hassle switching the FP mode!
42 ;; we assume that CPU is always in long float mode, and
43 ;; 16 bit integer mode - currently, the prologue for main does this,
44 ;; but maybe we should just set up a NEW crt0 properly,
45 ;; -- and what about signal handling code?
46 ;; (we don't even let sf floats in the register file, so
47 ;; we only should have to worry about truncating and widening
48 ;; when going to memory)
50 ;; abort() call by g++ - must define libfunc for cmp_optab
51 ;; and ucmp_optab for mode SImode, because we don't have that!!!
52 ;; - yet since no libfunc is there, we abort ()
54 ;; The only thing that remains to be done then is output
55 ;; the floats in a way the assembler can handle it (and
56 ;; if you're really into it, use a PDP11 float emulation
57 ;; library to do floating point constant folding - but
58 ;; I guess you'll get reasonable results even when not
60 ;; the last thing to do is fix the UPDATE_CC macro to check
61 ;; for floating point condition codes, and set cc_status
62 ;; properly, also setting the CC_IN_FCCR flag.
65 ;; currently type is only fpu or arith or unknown, maybe branch later ?
67 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
69 ;; length default is 1 word each
70 (define_attr "length" "" (const_int 1))
72 ;; a user's asm statement
73 (define_asm_attributes
74 [(set_attr "type" "unknown")
75 ; all bets are off how long it is - make it 256, forces long jumps
76 ; whenever jumping around it !!!
77 (set_attr "length" "256")])
79 ;; define function units
81 ;; arithmetic - values here immediately when next insn issued
82 ;; or does it mean the number of cycles after this insn was issued?
83 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
85 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
86 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
91 (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F")
92 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))]
96 cc_status.flags = CC_IN_FPU;
97 if (which_alternative == 0 || which_alternative == 2)
98 return \"{tstd|tstf} %0, %1\;cfcc\";
100 return \"{cmpd|cmpf} %0, %1\;cfcc\";
102 [(set_attr "length" "2,2,3,3,6")])
104 (define_insn "*cmphi"
106 (compare (match_operand:HI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
107 (match_operand:HI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
116 [(set_attr "length" "1,1,2,2,2,3")])
118 (define_insn "*cmpqi"
120 (compare (match_operand:QI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
121 (match_operand:QI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
130 [(set_attr "length" "1,1,2,2,2,3")])
133 ;; sob instruction - we need an assembler which can make this instruction
134 ;; valid under _all_ circumstances!
139 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
142 (label_ref (match_operand 1 "" ""))
145 (plus:HI (match_dup 0)
150 static int labelcount = 0;
151 static char buf[1000];
153 if (get_attr_length (insn) == 1)
154 return \"sob %0, %l1\";
157 output_asm_insn (\"dec %0\", operands);
159 sprintf (buf, \"bge LONG_SOB%d\", labelcount);
160 output_asm_insn (buf, NULL);
162 output_asm_insn (\"jmp %l1\", operands);
164 sprintf (buf, \"LONG_SOB%d:\", labelcount++);
165 output_asm_insn (buf, NULL);
169 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
172 (ge (minus (match_dup 0)
178 ;; These control RTL generation for conditional jump insns
179 ;; and match them for register allocation.
181 (define_expand "cbranchdf4"
183 (compare (match_operand:DF 1 "general_operand")
184 (match_operand:DF 2 "general_operand")))
186 (if_then_else (match_operator 0 "ordered_comparison_operator"
187 [(cc0) (const_int 0)])
188 (label_ref (match_operand 3 "" ""))
193 (define_expand "cbranchhi4"
195 (compare (match_operand:HI 1 "general_operand")
196 (match_operand:HI 2 "general_operand")))
198 (if_then_else (match_operator 0 "ordered_comparison_operator"
199 [(cc0) (const_int 0)])
200 (label_ref (match_operand 3 "" ""))
205 (define_expand "cbranchqi4"
207 (compare (match_operand:QI 1 "general_operand")
208 (match_operand:QI 2 "general_operand")))
210 (if_then_else (match_operator 0 "ordered_comparison_operator"
211 [(cc0) (const_int 0)])
212 (label_ref (match_operand 3 "" ""))
217 ;; problem with too short jump distance! we need an assembler which can
218 ;; make this valid for all jump distances!
221 ;; these must be changed to check for CC_IN_FCCR if float is to be
224 (define_insn "*branch"
226 (if_then_else (match_operator 0 "ordered_comparison_operator"
227 [(cc0) (const_int 0)])
228 (label_ref (match_operand 1 "" ""))
231 "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
232 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1)
235 (ge (minus (match_dup 1)
242 ;; These match inverted jump insns for register allocation.
244 (define_insn "*branch_inverted"
246 (if_then_else (match_operator 0 "ordered_comparison_operator"
247 [(cc0) (const_int 0)])
249 (label_ref (match_operand 1 "" ""))))]
251 "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
252 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 1)
255 (ge (minus (match_dup 1)
264 [(set (match_operand:DI 0 "general_operand" "=g,rm,o")
265 (match_operand:DI 1 "general_operand" "m,r,a"))]
267 "* return output_move_quad (operands);"
268 ;; what's the mose expensive code - say twice movsi = 16
269 [(set_attr "length" "16,16,16")])
272 [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
273 (match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
275 "* return output_move_double (operands);"
276 ;; what's the most expensive code ? - I think 8!
277 ;; we could split it up and make several sub-cases...
278 [(set_attr "length" "2,3,4,8,8")])
281 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
282 (match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
286 if (operands[1] == const0_rtx)
289 return \"mov %1, %0\";
291 [(set_attr "length" "1,2,2,3")])
294 [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
295 (match_operand:QI 1 "general_operand" "g"))]
299 if (operands[1] == const0_rtx)
302 return \"movb %1, %0\";
304 [(set_attr "length" "1")])
306 ;; do we have to supply all these moves? e.g. to
307 ;; NO_LOAD_FPU_REGs ?
309 [(set (match_operand:DF 0 "general_operand" "=a,fR,a,Q,m")
310 (match_operand:DF 1 "general_operand" "fFR,a,Q,a,m"))]
312 "* if (which_alternative ==0)
313 return \"ldd %1, %0\";
314 else if (which_alternative == 1)
315 return \"std %1, %0\";
317 return output_move_quad (operands); "
319 [(set_attr "length" "1,1,5,5,16")])
322 [(set (match_operand:SF 0 "general_operand" "=g,r,g")
323 (match_operand:SF 1 "general_operand" "r,rmF,g"))]
325 "* return output_move_double (operands);"
326 [(set_attr "length" "8,8,8")])
328 ;; maybe fiddle a bit with move_ratio, then
329 ;; let constraints only accept a register ...
331 (define_expand "movmemhi"
332 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
333 (match_operand:BLK 1 "general_operand" "g,g"))
334 (use (match_operand:HI 2 "arith_operand" "n,&mr"))
335 (use (match_operand:HI 3 "immediate_operand" "i,i"))
336 (clobber (match_scratch:HI 4 "=&r,X"))
337 (clobber (match_dup 5))
338 (clobber (match_dup 6))
339 (clobber (match_dup 2))])]
340 "(TARGET_BCOPY_BUILTIN)"
344 = replace_equiv_address (operands[0],
345 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
347 = replace_equiv_address (operands[1],
348 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
350 operands[5] = XEXP (operands[0], 0);
351 operands[6] = XEXP (operands[1], 0);
355 (define_insn "" ; "movmemhi"
356 [(set (mem:BLK (match_operand:HI 0 "general_operand" "=r,r"))
357 (mem:BLK (match_operand:HI 1 "general_operand" "r,r")))
358 (use (match_operand:HI 2 "arith_operand" "n,&r"))
359 (use (match_operand:HI 3 "immediate_operand" "i,i"))
360 (clobber (match_scratch:HI 4 "=&r,X"))
361 (clobber (match_dup 0))
362 (clobber (match_dup 1))
363 (clobber (match_dup 2))]
364 "(TARGET_BCOPY_BUILTIN)"
365 "* return output_block_move (operands);"
367 [(set_attr "length" "40")])
371 ;;- truncation instructions
373 (define_insn "truncdfsf2"
374 [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
375 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
377 "* if (which_alternative ==0)
379 output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
380 output_asm_insn(\"mov (sp)+, %0\", operands);
381 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
382 output_asm_insn(\"mov (sp)+, %0\", operands);
385 else if (which_alternative == 1)
386 return \"{stcdf|movfo} %1, %0\";
388 return \"{stcdf|movfo} %1, %0\";
390 [(set_attr "length" "3,1,2")])
393 (define_expand "truncsihi2"
394 [(set (match_operand:HI 0 "general_operand" "=g")
396 (match_operand:SI 1 "general_operand" "or")
402 ;;- zero extension instructions
404 (define_insn "zero_extendqihi2"
405 [(set (match_operand:HI 0 "general_operand" "=r")
406 (zero_extend:HI (match_operand:QI 1 "general_operand" "0")))]
409 [(set_attr "length" "2")])
411 (define_expand "zero_extendhisi2"
415 (match_operand:HI 1 "register_operand" "r"))
417 (match_operand:SI 0 "register_operand" "=r")
421 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
424 ;;- sign extension instructions
426 (define_insn "extendsfdf2"
427 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
428 (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
431 mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
433 {ldcfd|movof} %1, %0"
434 [(set_attr "length" "2,1,2")])
436 ;; does movb sign extend in register-to-register move?
437 (define_insn "extendqihi2"
438 [(set (match_operand:HI 0 "register_operand" "=r,r")
439 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
442 [(set_attr "length" "1,2")])
444 (define_insn "extendqisi2"
445 [(set (match_operand:SI 0 "register_operand" "=r,r")
446 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
452 /* make register pair available */
453 latehalf[0] = operands[0];
454 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
456 output_asm_insn(\"movb %1, %0\", operands);
457 output_asm_insn(\"sxt %0\", latehalf);
461 [(set_attr "length" "2,3")])
463 ;; maybe we have to use define_expand to say that we have the instruction,
464 ;; unconditionally, and then match dependent on CPU type:
466 (define_expand "extendhisi2"
467 [(set (match_operand:SI 0 "general_operand" "=g")
468 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
472 (define_insn "" ; "extendhisi2"
473 [(set (match_operand:SI 0 "general_operand" "=o,<,r")
474 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
480 /* we don't want to mess with auto increment */
482 switch (which_alternative)
486 latehalf[0] = operands[0];
487 operands[0] = adjust_address(operands[0], HImode, 2);
489 output_asm_insn(\"mov %1, %0\", operands);
490 output_asm_insn(\"sxt %0\", latehalf);
496 /* - auto-decrement - right direction ;-) */
497 output_asm_insn(\"mov %1, %0\", operands);
498 output_asm_insn(\"sxt %0\", operands);
504 /* make register pair available */
505 latehalf[0] = operands[0];
506 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
508 output_asm_insn(\"mov %1, %0\", operands);
509 output_asm_insn(\"sxt %0\", latehalf);
518 [(set_attr "length" "5,3,3")])
522 [(set (match_operand:SI 0 "register_operand" "=r")
523 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
527 static int count = 0;
531 lateoperands[0] = operands[0];
532 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
534 output_asm_insn(\"tst %0\", operands);
535 sprintf(buf, \"bge extendhisi%d\", count);
536 output_asm_insn(buf, NULL);
537 output_asm_insn(\"mov -1, %0\", lateoperands);
538 sprintf(buf, \"bne extendhisi%d\", count+1);
539 output_asm_insn(buf, NULL);
540 sprintf(buf, \"\\nextendhisi%d:\", count);
541 output_asm_insn(buf, NULL);
542 output_asm_insn(\"clr %0\", lateoperands);
543 sprintf(buf, \"\\nextendhisi%d:\", count+1);
544 output_asm_insn(buf, NULL);
550 [(set_attr "length" "6")])
552 ;; make float to int and vice versa
553 ;; using the cc_status.flag field we could probably cut down
555 ;; assume that we are normally in double and integer mode -
556 ;; what do pdp library routines do to fpu mode ?
558 (define_insn "floatsidf2"
559 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
560 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
562 "* if (which_alternative ==0)
567 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
568 output_asm_insn(\"mov %1, -(sp)\", latehalf);
569 output_asm_insn(\"mov %1, -(sp)\", operands);
571 output_asm_insn(\"setl\", operands);
572 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
573 output_asm_insn(\"seti\", operands);
576 else if (which_alternative == 1)
577 return \"setl\;{ldcld|movif} %1, %0\;seti\";
579 return \"setl\;{ldcld|movif} %1, %0\;seti\";
581 [(set_attr "length" "5,3,4")])
583 (define_insn "floathidf2"
584 [(set (match_operand:DF 0 "register_operand" "=a,a")
585 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
587 "{ldcid|movif} %1, %0"
588 [(set_attr "length" "1,2")])
591 (define_insn "fix_truncdfsi2"
592 [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
593 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
595 "* if (which_alternative ==0)
597 output_asm_insn(\"setl\", operands);
598 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
599 output_asm_insn(\"seti\", operands);
600 output_asm_insn(\"mov (sp)+, %0\", operands);
601 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
602 output_asm_insn(\"mov (sp)+, %0\", operands);
605 else if (which_alternative == 1)
606 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
608 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
610 [(set_attr "length" "5,3,4")])
612 (define_insn "fix_truncdfhi2"
613 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
614 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
616 "{stcdi|movfi} %1, %0"
617 [(set_attr "length" "1,2")])
620 ;;- arithmetic instructions
623 (define_insn "adddf3"
624 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
625 (plus:DF (match_operand:DF 1 "register_operand" "%0,0,0")
626 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
629 [(set_attr "length" "1,2,5")])
631 (define_insn "addsi3"
632 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
633 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
634 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
637 { /* Here we trust that operands don't overlap
639 or is lateoperands the low word?? - looks like it! */
643 lateoperands[0] = operands[0];
645 if (REG_P (operands[0]))
646 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
648 operands[0] = adjust_address (operands[0], HImode, 2);
650 if (! CONSTANT_P(operands[2]))
652 lateoperands[2] = operands[2];
654 if (REG_P (operands[2]))
655 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
657 operands[2] = adjust_address (operands[2], HImode, 2);
659 output_asm_insn (\"add %2, %0\", operands);
660 output_asm_insn (\"adc %0\", lateoperands);
661 output_asm_insn (\"add %2, %0\", lateoperands);
665 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
666 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
668 if (INTVAL(operands[2]))
670 output_asm_insn (\"add %2, %0\", operands);
671 output_asm_insn (\"adc %0\", lateoperands);
674 if (INTVAL(lateoperands[2]))
675 output_asm_insn (\"add %2, %0\", lateoperands);
679 [(set_attr "length" "3,5,6,8,3,1,5,5,3,8")])
681 (define_insn "addhi3"
682 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
683 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
684 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
688 if (GET_CODE (operands[2]) == CONST_INT)
690 if (INTVAL(operands[2]) == 1)
692 else if (INTVAL(operands[2]) == -1)
696 return \"add %2, %0\";
698 [(set_attr "length" "1,2,2,3")])
700 (define_insn "addqi3"
701 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
702 (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
703 (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
707 if (GET_CODE (operands[2]) == CONST_INT)
709 if (INTVAL(operands[2]) == 1)
711 else if (INTVAL(operands[2]) == -1)
715 return \"add %2, %0\";
717 [(set_attr "length" "1,2,2,3")])
720 ;;- subtract instructions
721 ;; we don't have to care for constant second
722 ;; args, since they are canonical plus:xx now!
723 ;; also for minus:DF ??
725 (define_insn "subdf3"
726 [(set (match_operand:DF 0 "register_operand" "=a,a")
727 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
728 (match_operand:DF 2 "general_operand" "fR,Q")))]
731 [(set_attr "length" "1,2")])
733 (define_insn "subsi3"
734 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
735 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
736 (match_operand:SI 2 "general_operand" "r,o,r,o")))]
739 { /* Here we trust that operands don't overlap
741 or is lateoperands the low word?? - looks like it! */
745 lateoperands[0] = operands[0];
747 if (REG_P (operands[0]))
748 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
750 operands[0] = adjust_address (operands[0], HImode, 2);
752 lateoperands[2] = operands[2];
754 if (REG_P (operands[2]))
755 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
757 operands[2] = adjust_address (operands[2], HImode, 2);
759 output_asm_insn (\"sub %2, %0\", operands);
760 output_asm_insn (\"sbc %0\", lateoperands);
761 output_asm_insn (\"sub %2, %0\", lateoperands);
764 ;; offsettable memory addresses always are expensive!!!
765 [(set_attr "length" "3,5,6,8")])
767 (define_insn "subhi3"
768 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
769 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
770 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
774 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
776 return \"sub %2, %0\";
778 [(set_attr "length" "1,2,2,3")])
780 (define_insn "subqi3"
781 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
782 (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
783 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
787 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
789 return \"sub %2, %0\";
791 [(set_attr "length" "1,2,2,3")])
793 ;;;;- and instructions
794 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
796 (define_insn "andsi3"
797 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
798 (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
799 (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
802 { /* Here we trust that operands don't overlap
804 or is lateoperands the low word?? - looks like it! */
808 lateoperands[0] = operands[0];
810 if (REG_P (operands[0]))
811 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
813 operands[0] = adjust_address (operands[0], HImode, 2);
815 if (! CONSTANT_P(operands[2]))
817 lateoperands[2] = operands[2];
819 if (REG_P (operands[2]))
820 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
822 operands[2] = adjust_address (operands[2], HImode, 2);
824 output_asm_insn (\"bic %2, %0\", operands);
825 output_asm_insn (\"bic %2, %0\", lateoperands);
829 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
830 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
832 /* these have different lengths, so we should have
833 different constraints! */
834 if (INTVAL(operands[2]))
835 output_asm_insn (\"bic %2, %0\", operands);
837 if (INTVAL(lateoperands[2]))
838 output_asm_insn (\"bic %2, %0\", lateoperands);
842 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
844 (define_insn "andhi3"
845 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
846 (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
847 (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
850 [(set_attr "length" "1,2,2,3")])
852 (define_insn "andqi3"
853 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
854 (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
855 (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
858 [(set_attr "length" "1,2,2,3")])
860 ;;- Bit set (inclusive or) instructions
861 (define_insn "iorsi3"
862 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
863 (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
864 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
867 { /* Here we trust that operands don't overlap
869 or is lateoperands the low word?? - looks like it! */
873 lateoperands[0] = operands[0];
875 if (REG_P (operands[0]))
876 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
878 operands[0] = adjust_address (operands[0], HImode, 2);
880 if (! CONSTANT_P(operands[2]))
882 lateoperands[2] = operands[2];
884 if (REG_P (operands[2]))
885 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
887 operands[2] = adjust_address (operands[2], HImode, 2);
889 output_asm_insn (\"bis %2, %0\", operands);
890 output_asm_insn (\"bis %2, %0\", lateoperands);
894 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
895 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
897 /* these have different lengths, so we should have
898 different constraints! */
899 if (INTVAL(operands[2]))
900 output_asm_insn (\"bis %2, %0\", operands);
902 if (INTVAL(lateoperands[2]))
903 output_asm_insn (\"bis %2, %0\", lateoperands);
907 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
909 (define_insn "iorhi3"
910 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
911 (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
912 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
915 [(set_attr "length" "1,2,2,3")])
917 (define_insn "iorqi3"
918 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
919 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
920 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
925 (define_insn "xorsi3"
926 [(set (match_operand:SI 0 "register_operand" "=r")
927 (xor:SI (match_operand:SI 1 "register_operand" "%0")
928 (match_operand:SI 2 "arith_operand" "r")))]
931 { /* Here we trust that operands don't overlap */
935 lateoperands[0] = operands[0];
936 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
938 if (REG_P(operands[2]))
940 lateoperands[2] = operands[2];
941 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
943 output_asm_insn (\"xor %2, %0\", operands);
944 output_asm_insn (\"xor %2, %0\", lateoperands);
950 [(set_attr "length" "2")])
952 (define_insn "xorhi3"
953 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
954 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
955 (match_operand:HI 2 "register_operand" "r,r")))]
958 [(set_attr "length" "1,2")])
960 ;;- one complement instructions
962 (define_insn "one_cmplhi2"
963 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
964 (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
967 [(set_attr "length" "1,2")])
969 (define_insn "one_cmplqi2"
970 [(set (match_operand:QI 0 "general_operand" "=rR,rR")
971 (not:QI (match_operand:QI 1 "general_operand" "0,g")))]
975 movb %1, %0\; comb %0"
976 [(set_attr "length" "1,2")])
978 ;;- arithmetic shift instructions
979 (define_insn "ashlsi3"
980 [(set (match_operand:SI 0 "register_operand" "=r,r")
981 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
982 (match_operand:HI 2 "general_operand" "rR,Qi")))]
985 [(set_attr "length" "1,2")])
987 ;; Arithmetic right shift on the pdp works by negating the shift count.
988 (define_expand "ashrsi3"
989 [(set (match_operand:SI 0 "register_operand" "=r")
990 (ashift:SI (match_operand:SI 1 "register_operand" "0")
991 (match_operand:HI 2 "general_operand" "g")))]
995 operands[2] = negate_rtx (HImode, operands[2]);
998 ;; define asl aslb asr asrb - ashc missing!
1002 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1003 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1007 [(set_attr "length" "1,2")])
1009 ;; and another possibility for asr is << -1
1010 ;; might cause problems since -1 can also be encoded as 65535!
1015 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1016 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1020 [(set_attr "length" "1,2")])
1024 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1025 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1029 [(set_attr "length" "1,2")])
1031 (define_insn "lshrsi3"
1032 [(set (match_operand:SI 0 "register_operand" "=r")
1033 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1038 rtx lateoperands[2];
1040 lateoperands[0] = operands[0];
1041 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1043 lateoperands[1] = operands[1];
1044 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1046 output_asm_insn (\"clc\", operands);
1047 output_asm_insn (\"ror %0\", lateoperands);
1048 output_asm_insn (\"ror %0\", operands);
1052 [(set_attr "length" "5")])
1054 ;; shift is by arbitrary count is expensive,
1055 ;; shift by one cheap - so let's do that, if
1056 ;; space doesn't matter
1058 [(set (match_operand:HI 0 "general_operand" "=r")
1059 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1060 (match_operand:HI 2 "expand_shift_operand" "O")))]
1066 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1067 if (INTVAL(operands[2]) < 0)
1068 output_asm_insn(\"asr %0\", operands);
1070 output_asm_insn(\"asl %0\", operands);
1075 [(set (attr "length") (const_int 4))])
1079 [(set (match_operand:QI 0 "general_operand" "=r,o")
1080 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1081 (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1084 { /* allowing predec or post_inc is possible, but hairy! */
1087 cnt = INTVAL(operands[2]) & 0x0007;
1089 for (i=0 ; i < cnt ; i++)
1090 output_asm_insn(\"aslb %0\", operands);
1094 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1095 [(set_attr_alternative "length"
1101 ; [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1102 ; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1106 ; [(set_attr "length" "1,2")])
1110 [(set (match_operand:QI 0 "general_operand" "=r,o")
1111 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1112 (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1115 { /* allowing predec or post_inc is possible, but hairy! */
1118 cnt = INTVAL(operands[2]) & 0x0007;
1120 for (i=0 ; i < cnt ; i++)
1121 output_asm_insn(\"asrb %0\", operands);
1125 [(set_attr_alternative "length"
1129 ;; the following is invalid - too complex!!! - just say 14 !!!
1130 ; [(set (attr "length") (plus (and (match_dup 2)
1132 ; (and (match_dup 2)
1133 ; (const_int 7))))])
1137 ;; can we get +-1 in the next pattern? should
1138 ;; have been caught by previous patterns!
1140 (define_insn "ashlhi3"
1141 [(set (match_operand:HI 0 "register_operand" "=r,r")
1142 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1143 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1147 if (GET_CODE(operands[2]) == CONST_INT)
1149 if (INTVAL(operands[2]) == 1)
1151 else if (INTVAL(operands[2]) == -1)
1155 return \"ash %2,%0\";
1157 [(set_attr "length" "1,2")])
1159 ;; Arithmetic right shift on the pdp works by negating the shift count.
1160 (define_expand "ashrhi3"
1161 [(set (match_operand:HI 0 "register_operand" "=r")
1162 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1163 (match_operand:HI 2 "general_operand" "g")))]
1167 operands[2] = negate_rtx (HImode, operands[2]);
1170 ;;;;- logical shift instructions
1171 ;;(define_insn "lshrsi3"
1172 ;; [(set (match_operand:HI 0 "register_operand" "=r")
1173 ;; (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1174 ;; (match_operand:HI 2 "arith_operand" "rI")))]
1180 (define_insn "absdf2"
1181 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1182 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1185 [(set_attr "length" "1,2")])
1187 (define_insn "abshi2"
1188 [(set (match_operand:HI 0 "general_operand" "=r,o")
1189 (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
1190 "TARGET_ABSHI_BUILTIN"
1193 static int count = 0;
1196 output_asm_insn(\"tst %0\", operands);
1197 sprintf(buf, \"bge abshi%d\", count);
1198 output_asm_insn(buf, NULL);
1199 output_asm_insn(\"neg %0\", operands);
1200 sprintf(buf, \"\\nabshi%d:\", count++);
1201 output_asm_insn(buf, NULL);
1205 [(set_attr "length" "3,5")])
1208 ;; define expand abshi - is much better !!! - but
1209 ;; will it be optimized into an abshi2 ?
1210 ;; it will leave better code, because the tsthi might be
1212 ; -- just a thought - don't have time to check
1214 ;(define_expand "abshi2"
1215 ; [(match_operand:HI 0 "general_operand" "")
1216 ; (match_operand:HI 1 "general_operand" "")]
1220 ; rtx label = gen_label_rtx ();
1222 ; /* do I need this? */
1223 ; do_pending_stack_adjust ();
1225 ; emit_move_insn (operands[0], operands[1]);
1227 ; emit_insn (gen_tsthi (operands[0]));
1228 ; emit_insn (gen_bge (label1));
1230 ; emit_insn (gen_neghi(operands[0], operands[0])
1234 ; emit_label (label);
1236 ; /* allow REG_NOTES to be set on last insn (labels don't have enough
1237 ; fields, and can't be used for REG_NOTES anyway). */
1238 ; emit_use (stack_pointer_rtx);
1244 (define_insn "negdf2"
1245 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1246 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1249 [(set_attr "length" "1,2")])
1251 (define_insn "negsi2"
1252 [(set (match_operand:SI 0 "register_operand" "=r")
1253 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
1257 rtx lateoperands[2];
1259 lateoperands[0] = operands[0];
1260 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1262 lateoperands[1] = operands[1];
1263 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1265 output_asm_insn (\"com %0\", operands);
1266 output_asm_insn (\"com %0\", lateoperands);
1267 output_asm_insn (\"inc %0\", operands);
1268 output_asm_insn (\"adc %0\", lateoperands);
1272 [(set_attr "length" "5")])
1274 (define_insn "neghi2"
1275 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1276 (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
1279 [(set_attr "length" "1,2")])
1281 (define_insn "negqi2"
1282 [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1283 (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
1286 [(set_attr "length" "1,2")])
1289 ;; Unconditional and other jump instructions
1292 (label_ref (match_operand 0 "" "")))]
1295 [(set_attr "length" "2")])
1299 (label_ref (match_operand 0 "" "")))
1300 (clobber (const_int 1))]
1303 [(set_attr "length" "2")])
1305 (define_insn "tablejump"
1306 [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1307 (use (label_ref (match_operand 1 "" "")))]
1310 [(set_attr "length" "1,2")])
1312 ;; indirect jump - let's be conservative!
1313 ;; allow only register_operand, even though we could also
1314 ;; allow labels etc.
1316 (define_insn "indirect_jump"
1317 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1321 ;;- jump to subroutine
1324 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1325 (match_operand:HI 1 "general_operand" "g,g"))
1326 ;; (use (reg:HI 0)) what was that ???
1328 ;;- Don't use operand 1 for most machines.
1331 [(set_attr "length" "1,2")])
1333 ;;- jump to subroutine
1334 (define_insn "call_value"
1335 [(set (match_operand 0 "" "")
1336 (call (match_operand:HI 1 "general_operand" "rR,Q")
1337 (match_operand:HI 2 "general_operand" "g,g")))
1338 ;; (use (reg:HI 0)) - what was that ????
1340 ;;- Don't use operand 2 for most machines.
1343 [(set_attr "length" "1,2")])
1354 (define_insn "muldf3"
1355 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1356 (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
1357 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1359 "{muld|mulf} %2, %0"
1360 [(set_attr "length" "1,2,5")])
1362 ;; 16 bit result multiply:
1363 ;; currently we multiply only into odd registers, so we don't use two
1364 ;; registers - but this is a bit inefficient at times. If we define
1365 ;; a register class for each register, then we can specify properly
1366 ;; which register need which scratch register ....
1368 (define_insn "mulhi3"
1369 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1370 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1371 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1374 [(set_attr "length" "1,2")])
1377 (define_expand "mulhisi3"
1379 (match_operand:HI 1 "general_operand" "g,g"))
1380 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1381 (mult:SI (truncate:HI
1383 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1385 "operands[3] = gen_lowpart(HImode, operands[1]);")
1388 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1389 (mult:SI (truncate:HI
1390 (match_operand:SI 1 "register_operand" "%0,0"))
1391 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1394 [(set_attr "length" "1,2")])
1396 ;(define_insn "mulhisi3"
1397 ; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1398 ; (mult:SI (truncate:HI
1399 ; (match_operand:SI 1 "register_operand" "%0,0"))
1400 ; (match_operand:HI 2 "general_operand" "rR,Qi")))]
1403 ; [(set_attr "length" "1,2")])
1406 (define_insn "divdf3"
1407 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1408 (div:DF (match_operand:DF 1 "register_operand" "0,0,0")
1409 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1411 "{divd|divf} %2, %0"
1412 [(set_attr "length" "1,2,5")])
1415 (define_expand "divhi3"
1416 [(set (subreg:HI (match_dup 1) 0)
1417 (div:HI (match_operand:SI 1 "general_operand" "0")
1418 (match_operand:HI 2 "general_operand" "g")))
1419 (set (match_operand:HI 0 "general_operand" "=r")
1420 (subreg:HI (match_dup 1) 0))]
1425 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1426 (div:HI (match_operand:SI 1 "general_operand" "0")
1427 (match_operand:HI 2 "general_operand" "g")))]
1430 [(set_attr "length" "2")])
1432 (define_expand "modhi3"
1433 [(set (subreg:HI (match_dup 1) 2)
1434 (mod:HI (match_operand:SI 1 "general_operand" "0")
1435 (match_operand:HI 2 "general_operand" "g")))
1436 (set (match_operand:HI 0 "general_operand" "=r")
1437 (subreg:HI (match_dup 1) 2))]
1442 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 2)
1443 (mod:HI (match_operand:SI 1 "general_operand" "0")
1444 (match_operand:HI 2 "general_operand" "g")))]
1447 [(set_attr "length" "2")])
1449 ;(define_expand "divmodhi4"
1450 ; [(parallel [(set (subreg:HI (match_dup 1) 0)
1451 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1452 ; (match_operand:HI 2 "general_operand" "g")))
1453 ; (set (subreg:HI (match_dup 1) 2)
1454 ; (mod:HI (match_dup 1)
1456 ; (set (match_operand:HI 3 "general_operand" "=r")
1457 ; (subreg:HI (match_dup 1) 2))
1458 ; (set (match_operand:HI 0 "general_operand" "=r")
1459 ; (subreg:HI (match_dup 1) 0))]
1464 ; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1465 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1466 ; (match_operand:HI 2 "general_operand" "g")))
1467 ; (set (subreg:HI (match_dup 0) 2)
1468 ; (mod:HI (match_dup 1)
1474 ;; is rotate doing the right thing to be included here ????