PR tree-optimization/84480 - bogus -Wstringop-truncation despite assignment with...
[official-gcc.git] / gcc / config / pdp11 / pdp11.md
blob8ad1c2163304d2adcc3489a83bf3abf02fd2114e
1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994-2018 Free Software Foundation, Inc.
3 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 (include "predicates.md")
22 (include "constraints.md")
24 (define_c_enum "unspecv"
25   [
26     UNSPECV_BLOCKAGE
27     UNSPECV_SETD
28     UNSPECV_SETI
29   ])
31 (define_constants
32   [
33    ;; Register numbers
34    (R0_REGNUM             0)
35    (RETVAL_REGNUM         0)
36    (HARD_FRAME_POINTER_REGNUM  5)
37    (STACK_POINTER_REGNUM  6)
38    (PC_REGNUM             7)
39    (AC0_REGNUM            8)
40    (AC3_REGNUM            11)
41    (AC4_REGNUM            12)
42    (AC5_REGNUM            13)
43    ;; The next two are not physical registers but are used for addressing
44    ;; arguments.
45    (FRAME_POINTER_REGNUM  14)
46    (ARG_POINTER_REGNUM    15)
47    (FIRST_PSEUDO_REGISTER 16)
48    ;; Branch offset limits, as byte offsets from instruction address
49    (MIN_BRANCH            -254)
50    (MAX_BRANCH            256)
51    (MIN_SOB               -126)
52    (MAX_SOB               0)])
54 ;; HI is 16 bit
55 ;; QI is 8 bit 
57 ;; Integer modes supported on the PDP11, with a mapping from machine mode
58 ;; to mnemonic suffix.  SImode and DImode always are special cases.
59 (define_mode_iterator PDPint [QI HI])
60 (define_mode_attr  isfx [(QI "b") (HI "")])
62 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
64 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
65 ;;- updates for most instructions.
67 ;;- Operand classes for the register allocator:
69 ;; Compare instructions.
71 ;; currently we only support df floats, which saves us quite some
72 ;; hassle switching the FP mode! 
73 ;; we assume that CPU is always in long float mode, and 
74 ;; 16 bit integer mode - currently, the prologue for main does this,
75 ;; but maybe we should just set up a NEW crt0 properly, 
76 ;; -- and what about signal handling code?
77 ;; (we don't even let sf floats in the register file, so
78 ;; we only should have to worry about truncating and widening 
79 ;; when going to memory)
81 ;; abort() call by g++ - must define libfunc for cmp_optab
82 ;; and ucmp_optab for mode SImode, because we don't have that!!!
83 ;; - yet since no libfunc is there, we abort ()
85 ;; The only thing that remains to be done then is output 
86 ;; the floats in a way the assembler can handle it (and 
87 ;; if you're really into it, use a PDP11 float emulation
88 ;; library to do floating point constant folding - but 
89 ;; I guess you'll get reasonable results even when not
90 ;; doing this)
91 ;; the last thing to do is fix the UPDATE_CC macro to check
92 ;; for floating point condition codes, and set cc_status
93 ;; properly, also setting the CC_IN_FCCR flag. 
95 ;; define attributes
96 ;; currently type is only fpu or arith or unknown, maybe branch later ?
97 ;; default is arith
98 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
100 ;; length default is 2 bytes each
101 (define_attr "length" "" (const_int 2))
103 ;; a user's asm statement
104 (define_asm_attributes
105   [(set_attr "type" "unknown")
106 ; length for asm is the max length per statement.  That would be
107 ; 3 words, for a two-operand instruction with extra word addressing
108 ; modes for both operands.
109    (set_attr "length" "6")])
111 ;; define function units
113 ;; Prologue and epilogue support.
115 (define_expand "prologue"
116   [(const_int 0)]
117   ""
119   pdp11_expand_prologue ();
120   DONE;
123 (define_expand "epilogue"
124   [(const_int 0)]
125   ""
127   pdp11_expand_epilogue ();
128   DONE;
131 (define_expand "return"
132   [(return)]
133   "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
134   "")
136 (define_insn "*rts"
137   [(return)]
138   ""
139   "rts pc")
141 (define_insn "blockage"
142   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
143   ""
144   ""
145   [(set_attr "length" "0")])
147 (define_insn "setd"
148   [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
149   ""
150   "setd")
152 (define_insn "seti"
153   [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
154   ""
155   "seti")
157 ;; arithmetic - values here immediately when next insn issued
158 ;; or does it mean the number of cycles after this insn was issued?
159 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
161 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
162 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
164 ;; compare
165 (define_insn "*cmpdf"
166   [(set (cc0)
167         (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
168                  (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
169   "TARGET_FPU"
170   "*
172   cc_status.flags = CC_IN_FPU;
173   if (which_alternative == 0 || which_alternative == 2)
174     return \"{tstd|tstf} %0\;cfcc\";
175   else
176     return \"{cmpd|cmpf} %0, %1\;cfcc\";
178   [(set_attr "length" "4,4,6,6")]) 
180 (define_insn "*cmp<mode>"
181   [(set (cc0)
182         (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
183                  (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
184   ""
185   "@
186    tst<PDPint:isfx> %0
187    cmp<PDPint:isfx> %0,%1
188    cmp<PDPint:isfx> %0,%1
189    tst<PDPint:isfx> %0
190    cmp<PDPint:isfx> %0,%1
191    cmp<PDPint:isfx> %0,%1"
192   [(set_attr "length" "2,2,4,4,4,6")])
194 ;; sob instruction - we need an assembler which can make this instruction
195 ;; valid under _all_ circumstances!
197 (define_insn ""
198   [(set (pc)
199         (if_then_else
200          (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
201                       (const_int -1))
202              (const_int 0))
203          (label_ref (match_operand 1 "" ""))
204          (pc)))
205    (set (match_dup 0)
206         (plus:HI (match_dup 0)
207                  (const_int -1)))]
208   "TARGET_40_PLUS"
209   "*
211  static int labelcount = 0;
212  static char buf[1000];
214  if (get_attr_length (insn) == 2)
215     return \"sob %0, %l1\";
217  /* emulate sob */
218  output_asm_insn (\"dec %0\", operands);
220  sprintf (buf, \"bge LONG_SOB%d\", labelcount);
221  output_asm_insn (buf, NULL);
223  output_asm_insn (\"jmp %l1\", operands);
225  sprintf (buf, \"LONG_SOB%d:\", labelcount++);
226  output_asm_insn (buf, NULL);
228  return \"\";
230   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
231                                                        (pc))
232                                                 (const_int MIN_SOB))
233                                            (gt (minus (match_dup 0)
234                                                        (pc))
235                                                 (const_int MAX_SOB)))
236                                       (const_int 8)
237                                       (const_int 2)))])
239 ;; These control RTL generation for conditional jump insns
240 ;; and match them for register allocation.
242 (define_expand "cbranchdf4"
243   [(set (cc0)
244         (compare (match_operand:DF 1 "general_operand")
245                  (match_operand:DF 2 "register_or_const0_operand")))
246    (set (pc)
247         (if_then_else (match_operator 0 "ordered_comparison_operator"
248                        [(cc0) (const_int 0)])
249                       (label_ref (match_operand 3 "" ""))
250                       (pc)))]
251   "TARGET_FPU"
252   "")
254 (define_expand "cbranch<mode>4"
255   [(set (cc0)
256         (compare (match_operand:PDPint 1 "general_operand")
257                  (match_operand:PDPint 2 "general_operand")))
258    (set (pc)
259         (if_then_else (match_operator 0 "ordered_comparison_operator"
260                        [(cc0) (const_int 0)])
261                       (label_ref (match_operand 3 "" ""))
262                       (pc)))]
263   ""
264   "")
266 ;; problem with too short jump distance! we need an assembler which can 
267 ;; make this valid for all jump distances!
268 ;; e.g. gas!
270 ;; these must be changed to check for CC_IN_FCCR if float is to be 
271 ;; enabled
273 (define_insn "*branch"
274   [(set (pc)
275         (if_then_else (match_operator 0 "ordered_comparison_operator"
276                        [(cc0) (const_int 0)])
277                       (label_ref (match_operand 1 "" ""))
278                       (pc)))]
279   ""
280   "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
281   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
282                                                       (pc))
283                                                (const_int MIN_BRANCH))
284                                            (gt (minus (match_dup 1)
285                                                       (pc))
286                                                (const_int MAX_BRANCH)))
287                                       (const_int 6)
288                                       (const_int 2)))])
291 ;; These match inverted jump insns for register allocation.
293 (define_insn "*branch_inverted"
294   [(set (pc)
295         (if_then_else (match_operator 0 "ordered_comparison_operator"
296                        [(cc0) (const_int 0)])
297                       (pc)
298                       (label_ref (match_operand 1 "" ""))))]
299   ""
300   "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
301   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
302                                                       (pc))
303                                                (const_int MIN_BRANCH))
304                                            (gt (minus (match_dup 1)
305                                                       (pc))
306                                                (const_int MAX_BRANCH)))
307                                       (const_int 6)
308                                       (const_int 2)))])
310 ;; Move instructions
312 (define_insn "movdi"
313   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
314         (match_operand:DI 1 "general_operand" "rN,g"))]
315   ""
316   "* return output_move_multiple (operands);"
317 ;; what's the mose expensive code - say twice movsi = 16
318   [(set_attr "length" "16,32")])
320 (define_insn "movsi"
321   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
322         (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
323   ""
324   "* return output_move_multiple (operands);"
325 ;; what's the most expensive code ? - I think 8!
326 ;; we could split it up and make several sub-cases...
327   [(set_attr "length" "4,6,8,16")])
329 (define_insn "mov<mode>"
330   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
331         (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
332   ""
333   "*
335   if (operands[1] == const0_rtx)
336     return \"clr<PDPint:isfx> %0\";
338   return \"mov<PDPint:isfx> %1, %0\";
340   [(set_attr "length" "2,4,4,6")])
342 (define_insn "movdf"
343   [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
344         (match_operand:DF 1 "float_operand" "fR,a,FQ,a,g"))]
345   "TARGET_FPU"
346   "* if (which_alternative ==0 || which_alternative == 2)
347        return \"ldd %1, %0\";
348      else if (which_alternative == 1 || which_alternative == 3)
349        return \"std %1, %0\";
350      else 
351        return output_move_multiple (operands); "
352 ;; last one is worst-case
353   [(set_attr "length" "2,2,4,4,24")])
355 (define_insn "movsf"
356   [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
357         (match_operand:SF 1 "float_operand" "fR,a,FQ,a,g"))]
358   "TARGET_FPU"
359   "* if (which_alternative ==0 || which_alternative == 2)
360        return \"{ldcfd|movof} %1, %0\";
361      else if (which_alternative == 1 || which_alternative == 3)
362        return \"{stcdf|movfo} %1, %0\";
363      else 
364        return output_move_multiple (operands); "
365 ;; last one is worst-case
366   [(set_attr "length" "2,2,4,4,12")])
368 ;; maybe fiddle a bit with move_ratio, then 
369 ;; let constraints only accept a register ...
371 (define_expand "movmemhi"
372   [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
373                    (match_operand:BLK 1 "general_operand" "g,g"))
374               (use (match_operand:HI 2 "general_operand" "n,mr"))
375               (use (match_operand:HI 3 "immediate_operand" "i,i"))
376               (clobber (match_scratch:HI 6 "=&r,X"))
377               (clobber (match_dup 4))
378               (clobber (match_dup 5))
379               (clobber (match_dup 2))])]
380   "(TARGET_BCOPY_BUILTIN)"
381   "
383   operands[0]
384     = replace_equiv_address (operands[0],
385                              copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
386   operands[1]
387     = replace_equiv_address (operands[1],
388                              copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
390   operands[4] = XEXP (operands[0], 0);
391   operands[5] = XEXP (operands[1], 0);
395 (define_insn "movmemhi1"
396   [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
397         (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
398    (use (match_operand:HI 2 "general_operand" "n,r"))
399    (use (match_operand:HI 3 "immediate_operand" "i,i"))
400    (clobber (match_scratch:HI 4 "=&r,X"))
401    (clobber (match_dup 0))
402    (clobber (match_dup 1))
403    (clobber (match_dup 2))]
404   "(TARGET_BCOPY_BUILTIN)"
405   "* return output_block_move (operands);"
406 ;;; just a guess
407   [(set_attr "length" "80")])
408    
411 ;;- truncation instructions
413 (define_insn  "truncdfsf2"
414   [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
415         (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
416   "TARGET_FPU"
417   "* if (which_alternative ==0)
418      {
419        return \"\";
420      }
421      else if (which_alternative == 1)
422        return \"{stcdf|movfo} %1, %0\";
423      else 
424        return \"{stcdf|movfo} %1, %0\";
425   "
426   [(set_attr "length" "0,2,4")])
429 (define_expand "truncsihi2"
430   [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
431         (subreg:HI 
432           (match_operand:SI 1 "general_operand" "or")
433           0))]
434   ""
435   "")
438 ;;- zero extension instructions
440 (define_insn "zero_extendqihi2"
441   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
442         (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
443   ""
444   "bic $0177400, %0"
445   [(set_attr "length" "4,6")])
446                          
447 (define_expand "zero_extendhisi2"
448   [(set (subreg:HI 
449           (match_dup 0)
450           2)
451         (match_operand:HI 1 "register_operand" "r"))
452    (set (subreg:HI 
453           (match_operand:SI 0 "register_operand" "=r")
454           0)
455         (const_int 0))]
456   ""
457   "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
460 ;;- sign extension instructions
462 (define_insn "extendsfdf2"
463   [(set (match_operand:DF 0 "register_operand" "=f,a,a")
464         (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
465   "TARGET_FPU"
466   "@
467    /* nothing */
468    {ldcfd|movof} %1, %0
469    {ldcfd|movof} %1, %0"
470   [(set_attr "length" "0,2,4")])
472 ;; does movb sign extend in register-to-register move?
473 (define_insn "extendqihi2"
474   [(set (match_operand:HI 0 "register_operand" "=r,r")
475         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
476   ""
477   "movb %1, %0"
478   [(set_attr "length" "2,4")])
480 (define_insn "extendqisi2"
481   [(set (match_operand:SI 0 "register_operand" "=r,r")
482         (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
483   "TARGET_40_PLUS"
484   "*
486   rtx latehalf[2];
488   /* make register pair available */
489   latehalf[0] = operands[0];
490   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
492   output_asm_insn(\"movb %1, %0\", operands);
493   output_asm_insn(\"sxt %0\", latehalf);
494     
495   return \"\";
497   [(set_attr "length" "4,6")])
499 ;; maybe we have to use define_expand to say that we have the instruction,
500 ;; unconditionally, and then match dependent on CPU type:
502 (define_expand "extendhisi2"
503   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
504         (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
505   ""
506   "")
507   
508 (define_insn "" ; "extendhisi2"
509   [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
510         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
511   "TARGET_40_PLUS"
512   "*
514   rtx latehalf[2];
516   /* we don't want to mess with auto increment */
517   
518   switch (which_alternative)
519   {
520     case 0:
522       latehalf[0] = operands[0];
523       operands[0] = adjust_address(operands[0], HImode, 2);
524   
525       output_asm_insn(\"mov %1, %0\", operands);
526       output_asm_insn(\"sxt %0\", latehalf);
528       return \"\";
530     case 1:
532       /* - auto-decrement - right direction ;-) */
533       output_asm_insn(\"mov %1, %0\", operands);
534       output_asm_insn(\"sxt %0\", operands);
536       return \"\";
538     case 2:
540       /* make register pair available */
541       latehalf[0] = operands[0];
542       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
544       output_asm_insn(\"mov %1, %0\", operands);
545       output_asm_insn(\"sxt %0\", latehalf);
547       return \"\";
549     default:
551       gcc_unreachable ();
552   }
554   [(set_attr "length" "10,6,6")])
557 (define_insn ""
558   [(set (match_operand:SI 0 "register_operand" "=r")
559         (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
560   "(! TARGET_40_PLUS)"
561   "*
563   static int count = 0;
564   char buf[100];
565   rtx lateoperands[2];
567   lateoperands[0] = operands[0];
568   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
570   output_asm_insn(\"tst %0\", operands);
571   sprintf(buf, \"bge extendhisi%d\", count);
572   output_asm_insn(buf, NULL);
573   output_asm_insn(\"mov -1, %0\", lateoperands);
574   sprintf(buf, \"bne extendhisi%d\", count+1);
575   output_asm_insn(buf, NULL);
576   sprintf(buf, \"\\nextendhisi%d:\", count);
577   output_asm_insn(buf, NULL);
578   output_asm_insn(\"clr %0\", lateoperands);
579   sprintf(buf, \"\\nextendhisi%d:\", count+1);
580   output_asm_insn(buf, NULL);
582   count += 2;
584   return \"\";
586   [(set_attr "length" "12")])
588 ;; make float to int and vice versa 
589 ;; using the cc_status.flag field we could probably cut down
590 ;; on seti and setl
591 ;; assume that we are normally in double and integer mode -
592 ;; what do pdp library routines do to fpu mode ?
594 (define_insn "floatsidf2"
595   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
596         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
597   "TARGET_FPU"
598   "* if (which_alternative ==0)
599      {
600        rtx latehalf[2];
602        latehalf[0] = NULL; 
603        latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
604        output_asm_insn(\"mov %1, -(sp)\", latehalf);
605        output_asm_insn(\"mov %1, -(sp)\", operands);
606        
607        output_asm_insn(\"setl\", operands);
608        output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
609        output_asm_insn(\"seti\", operands);
610        return \"\";
611      }
612      else if (which_alternative == 1)
613        return \"setl\;{ldcld|movif} %1, %0\;seti\";
614      else 
615        return \"setl\;{ldcld|movif} %1, %0\;seti\";
616   "
617   [(set_attr "length" "10,6,8")])
619 (define_insn "floathidf2"
620   [(set (match_operand:DF 0 "register_operand" "=a,a")
621         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
622   "TARGET_FPU"
623   "{ldcid|movif} %1, %0"
624   [(set_attr "length" "2,4")])
625         
626 ;; cut float to int
627 (define_insn "fix_truncdfsi2"
628   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
629         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
630   "TARGET_FPU"
631   "* if (which_alternative ==0)
632      {
633        output_asm_insn(\"setl\", operands);
634        output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
635        output_asm_insn(\"seti\", operands);
636        output_asm_insn(\"mov (sp)+, %0\", operands);
637        operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
638        output_asm_insn(\"mov (sp)+, %0\", operands);
639        return \"\";
640      }
641      else if (which_alternative == 1)
642        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
643      else 
644        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
645   "
646   [(set_attr "length" "10,6,8")])
648 (define_insn "fix_truncdfhi2"
649   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
650         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
651   "TARGET_FPU"
652   "{stcdi|movfi} %1, %0"
653   [(set_attr "length" "2,4")])
656 ;;- arithmetic instructions
657 ;;- add instructions
659 (define_insn "adddf3"
660   [(set (match_operand:DF 0 "register_operand" "=a,a")
661         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
662                  (match_operand:DF 2 "general_operand" "fR,QF")))]
663   "TARGET_FPU"
664   "{addd|addf} %2, %0"
665   [(set_attr "length" "2,4")])
667 (define_insn "adddi3"
668   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
669         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
670                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
671   ""
672   "*
674   rtx inops[2];
675   rtx exops[4][2];
676   
677   inops[0] = operands[0];
678   inops[1] = operands[2];
679   pdp11_expand_operands (inops, exops, 2, NULL, either);
680   
681   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
682     output_asm_insn (\"add %1, %0\", exops[0]);
683   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
684   {
685     output_asm_insn (\"add %1, %0\", exops[1]);
686     output_asm_insn (\"adc %0\", exops[0]);
687   }
688   if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
689   {
690     output_asm_insn (\"add %1, %0\", exops[2]);
691     output_asm_insn (\"adc %0\", exops[1]);
692     output_asm_insn (\"adc %0\", exops[0]);
693   }
694   if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
695   {
696     output_asm_insn (\"add %1, %0\", exops[3]);
697     output_asm_insn (\"adc %0\", exops[2]);
698     output_asm_insn (\"adc %0\", exops[1]);
699     output_asm_insn (\"adc %0\", exops[0]);
700   }
702   return \"\";
704   [(set_attr "length" "20,28,40,48")])
706 ;; Note that the register operand is not marked earlyclobber.
707 ;; The reason is that SI values go in register pairs, so they
708 ;; can't partially overlap.  They can be either disjoint, or
709 ;; source and destination can be equal.  The latter case is 
710 ;; handled properly because of the ordering of the individual
711 ;; instructions used.  Specifically, carry from the low to the
712 ;; high word is added at the end, so the adding of the high parts
713 ;; will always used the original high part and not a high part
714 ;; modified by carry (which would amount to double carry).
715 (define_insn "addsi3"
716   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
717         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
718                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
719   ""
720   "*
722   rtx inops[2];
723   rtx exops[2][2];
724   
725   inops[0] = operands[0];
726   inops[1] = operands[2];
727   pdp11_expand_operands (inops, exops, 2, NULL, either);
728   
729   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
730     output_asm_insn (\"add %1, %0\", exops[0]);
731   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
732   {
733     output_asm_insn (\"add %1, %0\", exops[1]);
734     output_asm_insn (\"adc %0\", exops[0]);
735   }
737   return \"\";
739   [(set_attr "length" "6,10,12,16")])
741 (define_insn "addhi3"
742   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
743         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
744                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
745   ""
746   "*
748   if (GET_CODE (operands[2]) == CONST_INT)
749     {
750       if (INTVAL(operands[2]) == 1)
751         return \"inc %0\";
752       else if (INTVAL(operands[2]) == -1)
753         return \"dec %0\";
754     }
756   return \"add %2, %0\";
758   [(set_attr "length" "2,4,4,6")])
761 ;;- subtract instructions
762 ;; we don't have to care for constant second 
763 ;; args, since they are canonical plus:xx now!
764 ;; also for minus:DF ??
766 (define_insn "subdf3"
767   [(set (match_operand:DF 0 "register_operand" "=a,a")
768         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
769                   (match_operand:DF 2 "general_operand" "fR,Q")))]
770   "TARGET_FPU"
771   "{subd|subf} %2, %0"
772   [(set_attr "length" "2,4")])
774 (define_insn "subdi3"
775   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
776         (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
777                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
778   ""
779   "*
781   rtx inops[2];
782   rtx exops[4][2];
783   
784   inops[0] = operands[0];
785   inops[1] = operands[2];
786   pdp11_expand_operands (inops, exops, 2, NULL, either);
787   
788   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
789     output_asm_insn (\"sub %1, %0\", exops[0]);
790   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
791   {
792     output_asm_insn (\"sub %1, %0\", exops[1]);
793     output_asm_insn (\"sbc %0\", exops[0]);
794   }
795   if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
796   {
797     output_asm_insn (\"sub %1, %0\", exops[2]);
798     output_asm_insn (\"sbc %0\", exops[1]);
799     output_asm_insn (\"sbc %0\", exops[0]);
800   }
801   if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
802   {
803     output_asm_insn (\"sub %1, %0\", exops[3]);
804     output_asm_insn (\"sbc %0\", exops[2]);
805     output_asm_insn (\"sbc %0\", exops[1]);
806     output_asm_insn (\"sbc %0\", exops[0]);
807   }
809   return \"\";
811   [(set_attr "length" "20,28,40,48")])
813 (define_insn "subsi3"
814   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
815         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
816                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
817   ""
818   "*
820   rtx inops[2];
821   rtx exops[2][2];
822   
823   inops[0] = operands[0];
824   inops[1] = operands[2];
825   pdp11_expand_operands (inops, exops, 2, NULL, either);
826   
827   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
828     output_asm_insn (\"sub %1, %0\", exops[0]);
829   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
830   {
831     output_asm_insn (\"sub %1, %0\", exops[1]);
832     output_asm_insn (\"sbc %0\", exops[0]);
833   }
835   return \"\";
837   [(set_attr "length" "6,10,12,16")])
839 (define_insn "subhi3"
840   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
841         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
842                   (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
843   ""
844   "*
846   gcc_assert (GET_CODE (operands[2]) != CONST_INT);
848   return \"sub %2, %0\";
850   [(set_attr "length" "2,4,4,6")])
852 ;;;;- and instructions
853 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
855 (define_expand "and<mode>3"
856   [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
857         (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
858                    (match_operand:PDPint 2 "general_operand" "")))]
859   ""
860   "
862   rtx op1 = operands[1];
864   /* If there is a constant argument, complement that one.
865      Similarly, if one of the inputs is the same as the output,
866      complement the other input.  */
867   if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
868       rtx_equal_p (operands[0], operands[1]))
869     {
870       operands[1] = operands[2];
871       operands[2] = op1;
872       op1 = operands[1];
873     }
875   if (CONST_INT_P (op1))
876     operands[1] = GEN_INT (~INTVAL (op1));
877   else
878     operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
881 (define_insn "*bic<mode>"
882   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
883         (and:PDPint
884              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
885              (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
886   ""
887   "bic<PDPint:isfx> %1, %0"
888   [(set_attr "length" "2,4,4,6")])
890 ;;- Bit set (inclusive or) instructions
891 (define_insn "ior<mode>3"
892   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
893         (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
894                 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
895   ""
896   "bis<PDPint:isfx> %2, %0"
897   [(set_attr "length" "2,4,4,6")])
899 ;;- xor instructions
900 (define_insn "xorhi3"
901   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
902         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
903                 (match_operand:HI 2 "register_operand" "r,r")))]
904   "TARGET_40_PLUS"
905   "xor %2, %0"
906   [(set_attr "length" "2,4")])
908 ;;- one complement instructions
910 (define_insn "one_cmpl<mode>2"
911   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
912         (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
913   ""
914   "com<PDPint:isfx> %0"
915   [(set_attr "length" "2,4")])
917 ;;- arithmetic shift instructions
918 (define_insn "ashlsi3"
919   [(set (match_operand:SI 0 "register_operand" "=r,r")
920         (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
921                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
922   "TARGET_40_PLUS"
923   "ashc %2,%0"
924   [(set_attr "length" "2,4")])
926 ;; Arithmetic right shift on the pdp works by negating the shift count.
927 (define_expand "ashrsi3"
928   [(set (match_operand:SI 0 "register_operand" "=r")
929         (ashift:SI (match_operand:SI 1 "register_operand" "0")
930                    (match_operand:HI 2 "general_operand" "g")))]
931   ""
932   "
934   operands[2] = negate_rtx (HImode, operands[2]);
937 ;; define asl aslb asr asrb - ashc missing!
939 ;; asl 
940 (define_insn "" 
941   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
942         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
943                    (const_int 1)))]
944   ""
945   "asl %0"
946   [(set_attr "length" "2,4")])
948 ;; and another possibility for asr is << -1
949 ;; might cause problems since -1 can also be encoded as 65535!
950 ;; not in gcc2 ??? 
952 ;; asr
953 (define_insn "" 
954   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
955         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
956                    (const_int -1)))]
957   ""
958   "asr %0"
959   [(set_attr "length" "2,4")])
961 ;; lsr
962 (define_insn "lsrhi1" 
963   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
964         (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
965                    (const_int 1)))]
966   ""
967   "clc\;ror %0"
968   [(set_attr "length" "2,4")])
970 (define_insn "lsrsi1"
971   [(set (match_operand:SI 0 "register_operand" "=r")
972         (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
973                    (const_int 1)))]
974   ""
977   rtx lateoperands[2];
979   lateoperands[0] = operands[0];
980   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
982   lateoperands[1] = operands[1];
983   operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
985   output_asm_insn (\"clc\", operands);
986   output_asm_insn (\"ror %0\", lateoperands);
987   output_asm_insn (\"ror %0\", operands);
989   return \"\";
991   [(set_attr "length" "10")])
993 (define_expand "lshrsi3"
994   [(match_operand:SI 0 "register_operand" "")
995    (match_operand:SI 1 "register_operand" "0")
996    (match_operand:HI 2 "general_operand" "")]
997   ""
998   "
1000   rtx r;
1002   if (!TARGET_40_PLUS &&
1003       (GET_CODE (operands[2]) != CONST_INT ||
1004        (unsigned) INTVAL (operands[2]) > 3))
1005     FAIL;
1006   emit_insn (gen_lsrsi1 (operands[0], operands[1]));
1007   if (GET_CODE (operands[2]) != CONST_INT)
1008     {
1009       r = gen_reg_rtx (HImode);
1010       emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1011       emit_insn (gen_ashrsi3 (operands[0], operands[0], r));
1012     }
1013   else if ((unsigned) INTVAL (operands[2]) != 1)
1014     {
1015       emit_insn (gen_ashlsi3 (operands[0], operands[0],
1016                               GEN_INT (1 - INTVAL (operands[2]))));
1017     }
1018   DONE;
1023 ;; shift is by arbitrary count is expensive, 
1024 ;; shift by one cheap - so let's do that, if
1025 ;; space doesn't matter
1026 (define_insn "" 
1027   [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
1028         (ashift:HI (match_operand:HI 1 "general_operand" "0")
1029                    (match_operand:HI 2 "expand_shift_operand" "O")))]
1030   "! optimize_size"
1031   "*
1033   register int i;
1035   for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1036     if (INTVAL(operands[2]) < 0)
1037       output_asm_insn(\"asr %0\", operands);
1038     else
1039       output_asm_insn(\"asl %0\", operands);
1040       
1041   return \"\";
1043 ;; longest is 4
1044   [(set (attr "length") (const_int 8))])
1046 ;; aslb
1047 (define_insn "" 
1048   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1049         (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1050                    (match_operand:HI 2 "const_int_operand" "n,n")))]
1051   ""
1052   "*
1053 { /* allowing predec or post_inc is possible, but hairy! */
1054   int i, cnt;
1056   cnt = INTVAL(operands[2]) & 0x0007;
1058   for (i=0 ; i < cnt ; i++)
1059        output_asm_insn(\"aslb %0\", operands);
1061   return \"\";
1063 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1064   [(set_attr_alternative "length" 
1065                          [(const_int 14)
1066                           (const_int 28)])])
1068 ;;; asr 
1069 ;(define_insn "" 
1070 ;  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1071 ;       (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1072 ;                    (const_int 1)))]
1073 ;  ""
1074 ;  "asr %0"
1075 ;  [(set_attr "length" "2,4")])
1077 ;; asrb
1078 (define_insn "" 
1079   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1080         (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1081                      (match_operand:HI 2 "const_int_operand" "n,n")))]
1082   ""
1083   "*
1084 { /* allowing predec or post_inc is possible, but hairy! */
1085   int i, cnt;
1087   cnt = INTVAL(operands[2]) & 0x0007;
1089   for (i=0 ; i < cnt ; i++)
1090        output_asm_insn(\"asrb %0\", operands);
1092   return \"\";
1094   [(set_attr_alternative "length" 
1095                          [(const_int 14)
1096                           (const_int 28)])])
1098 ;; the following is invalid - too complex!!! - just say 14 !!!
1099 ;  [(set (attr "length") (plus (and (match_dup 2)
1100 ;                                   (const_int 14))
1101 ;                              (and (match_dup 2)
1102 ;                                   (const_int 14))))])
1106 ;; can we get +-1 in the next pattern? should 
1107 ;; have been caught by previous patterns!
1109 (define_insn "ashlhi3"
1110   [(set (match_operand:HI 0 "register_operand" "=r,r")
1111         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1112                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
1113   "TARGET_40_PLUS"
1114   "*
1116   if (GET_CODE(operands[2]) == CONST_INT)
1117     {
1118       if (INTVAL(operands[2]) == 1)
1119         return \"asl %0\";
1120       else if (INTVAL(operands[2]) == -1)
1121         return \"asr %0\";
1122     }
1124   return \"ash %2,%0\";
1126   [(set_attr "length" "2,4")])
1128 ;; Arithmetic right shift on the pdp works by negating the shift count.
1129 (define_expand "ashrhi3"
1130   [(set (match_operand:HI 0 "register_operand" "=r")
1131         (ashift:HI (match_operand:HI 1 "register_operand" "0")
1132                    (match_operand:HI 2 "general_operand" "g")))]
1133   ""
1134   "
1136   operands[2] = negate_rtx (HImode, operands[2]);
1139 (define_expand "lshrhi3"
1140   [(match_operand:HI 0 "register_operand" "")
1141    (match_operand:HI 1 "register_operand" "")
1142    (match_operand:HI 2 "general_operand" "")]
1143   ""
1144   "
1146   rtx r;
1148   if (!TARGET_40_PLUS &&
1149       (GET_CODE (operands[2]) != CONST_INT ||
1150        (unsigned) INTVAL (operands[2]) > 3))
1151     FAIL;
1152   emit_insn (gen_lsrhi1 (operands[0], operands[1]));
1153   if (GET_CODE (operands[2]) != CONST_INT)
1154     {
1155       r = gen_reg_rtx (HImode);
1156       emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1157       emit_insn (gen_ashrhi3 (operands[0], operands[0], r));
1158     }
1159   else if ((unsigned) INTVAL (operands[2]) != 1)
1160     {
1161       emit_insn (gen_ashlhi3 (operands[0], operands[0],
1162                               GEN_INT (1 - INTVAL (operands[2]))));
1163     }
1164   DONE;
1169 ;; absolute 
1171 (define_insn "absdf2"
1172   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1173         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1174   "TARGET_FPU"
1175   "{absd|absf} %0"
1176   [(set_attr "length" "2,4")])
1179 ;; negate insns
1181 (define_insn "negdf2"
1182   [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
1183         (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1184   "TARGET_FPU"
1185   "{negd|negf} %0"
1186   [(set_attr "length" "2,4")])
1188 (define_insn "negdi2"
1189   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1190         (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1191   ""
1193   rtx exops[4][2];
1194   
1195   pdp11_expand_operands (operands, exops, 1, NULL, either);
1197   output_asm_insn (\"com %0\", exops[3]);
1198   output_asm_insn (\"com %0\", exops[2]);
1199   output_asm_insn (\"com %0\", exops[1]);
1200   output_asm_insn (\"com %0\", exops[0]);
1201   output_asm_insn (\"add $1, %0\", exops[3]);
1202   output_asm_insn (\"adc %0\", exops[2]);
1203   output_asm_insn (\"adc %0\", exops[1]);
1204   output_asm_insn (\"adc %0\", exops[0]);
1206   return \"\";
1208 [(set_attr "length" "18,34")])
1210 (define_insn "negsi2"
1211   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1212         (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1213   ""
1215   rtx exops[2][2];
1216   
1217   pdp11_expand_operands (operands, exops, 1, NULL, either);
1219   output_asm_insn (\"com %0\", exops[1]);
1220   output_asm_insn (\"com %0\", exops[0]);
1221   output_asm_insn (\"add $1, %0\", exops[1]);
1222   output_asm_insn (\"adc %0\", exops[0]);
1224   return \"\";
1226 [(set_attr "length" "12,20")])
1228 (define_insn "neg<mode>2"
1229   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1230         (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1231   ""
1232   "neg<isfx> %0"
1233   [(set_attr "length" "2,4")])
1236 ;; Unconditional and other jump instructions
1237 (define_insn "jump"
1238   [(set (pc)
1239         (label_ref (match_operand 0 "" "")))]
1240   ""
1241   "*
1243  if (get_attr_length (insn) == 2)
1244     return \"br %l0\";
1245  return \"jmp %l0\";
1247   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1248                                                       (pc))
1249                                                (const_int MIN_BRANCH))
1250                                            (gt (minus (match_dup 0)
1251                                                       (pc))
1252                                                (const_int MAX_BRANCH)))
1253                                       (const_int 4)
1254                                       (const_int 2)))])
1256 (define_insn ""
1257   [(set (pc)
1258     (label_ref (match_operand 0 "" "")))
1259    (clobber (const_int 1))]
1260   ""
1261   "jmp %l0"
1262   [(set_attr "length" "4")])
1264 (define_insn "tablejump"
1265   [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1266    (use (label_ref (match_operand 1 "" "")))]
1267   ""
1268   "@
1269   jmp (%0)
1270   jmp %@%0
1271   jmp %@%0"
1272   [(set_attr "length" "2,2,4")])
1274 ;; indirect jump - let's be conservative!
1275 ;; allow only register_operand, even though we could also 
1276 ;; allow labels etc.
1278 (define_insn "indirect_jump"
1279   [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1280   ""
1281   "jmp (%0)")
1283 ;;- jump to subroutine
1285 (define_insn "call"
1286   [(call (match_operand:HI 0 "general_operand" "rR,Q")
1287          (match_operand:HI 1 "general_operand" "g,g"))
1288 ;;   (use (reg:HI 0)) what was that ???
1289   ]
1290   ;;- Don't use operand 1 for most machines.
1291   ""
1292   "jsr pc, %0"
1293   [(set_attr "length" "2,4")])
1295 ;;- jump to subroutine
1296 (define_insn "call_value"
1297   [(set (match_operand 0 "" "")
1298         (call (match_operand:HI 1 "general_operand" "rR,Q")
1299               (match_operand:HI 2 "general_operand" "g,g")))
1300 ;;   (use (reg:HI 0)) - what was that ????
1301   ]
1302   ;;- Don't use operand 2 for most machines.
1303   ""
1304   "jsr pc, %1"
1305   [(set_attr "length" "2,4")])
1307 ;;- nop instruction
1308 (define_insn "nop"
1309   [(const_int 0)]
1310   ""
1311   "nop")
1314 ;;- multiply 
1316 (define_insn "muldf3"
1317   [(set (match_operand:DF 0 "register_operand" "=a,a")
1318         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1319                  (match_operand:DF 2 "float_operand" "fR,QF")))]
1320   "TARGET_FPU"
1321   "{muld|mulf} %2, %0"
1322   [(set_attr "length" "2,4")])
1324 ;; 16 bit result multiply:
1325 ;; currently we multiply only into odd registers, so we don't use two 
1326 ;; registers - but this is a bit inefficient at times. If we define 
1327 ;; a register class for each register, then we can specify properly 
1328 ;; which register need which scratch register ....
1330 (define_insn "mulhi3"
1331   [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1332         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1333                  (match_operand:HI 2 "float_operand" "rR,Qi")))]
1334   "TARGET_40_PLUS"
1335   "mul %2, %0"
1336   [(set_attr "length" "2,4")])
1338 ;; 32 bit result
1339 (define_expand "mulhisi3"
1340   [(set (match_dup 3)
1341         (match_operand:HI 1 "nonimmediate_operand" "g,g"))
1342    (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1343         (mult:SI (truncate:HI 
1344                   (match_dup 0))
1345                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1346   "TARGET_40_PLUS"
1347   "operands[3] = gen_lowpart(HImode, operands[1]);")
1349 (define_insn ""
1350   [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1351         (mult:SI (truncate:HI 
1352                   (match_operand:SI 1 "register_operand" "%0,0"))
1353                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1354   "TARGET_40_PLUS"
1355   "mul %2, %0"
1356   [(set_attr "length" "2,4")])
1358 ;(define_insn "mulhisi3"
1359 ;  [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1360 ;       (mult:SI (truncate:HI 
1361 ;                  (match_operand:SI 1 "register_operand" "%0,0"))
1362 ;                (match_operand:HI 2 "general_operand" "rR,Qi")))]
1363 ;  "TARGET_40_PLUS"
1364 ;  "mul %2, %0"
1365 ;  [(set_attr "length" "2,4")])
1367 ;;- divide
1368 (define_insn "divdf3"
1369   [(set (match_operand:DF 0 "register_operand" "=a,a")
1370         (div:DF (match_operand:DF 1 "register_operand" "0,0")
1371                 (match_operand:DF 2 "general_operand" "fR,QF")))]
1372   "TARGET_FPU"
1373   "{divd|divf} %2, %0"
1374   [(set_attr "length" "2,4")])
1376          
1377 (define_expand "divhi3"
1378   [(set (subreg:HI (match_dup 1) 0)
1379         (div:HI (match_operand:SI 1 "register_operand" "0")
1380                 (match_operand:HI 2 "general_operand" "g")))
1381    (set (match_operand:HI 0 "register_operand" "=r")
1382         (subreg:HI (match_dup 1) 0))]
1383   "TARGET_40_PLUS"
1384   "")
1386 (define_insn ""
1387   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1388         (div:HI (match_operand:SI 1 "general_operand" "0")
1389                 (match_operand:HI 2 "general_operand" "g")))]
1390   "TARGET_40_PLUS"
1391   "div %2,%0"
1392   [(set_attr "length" "4")])
1394 (define_expand "modhi3"
1395   [(set (subreg:HI (match_dup 1) 2)
1396         (mod:HI (match_operand:SI 1 "register_operand" "0")
1397                 (match_operand:HI 2 "general_operand" "g")))
1398    (set (match_operand:HI 0 "register_operand" "=r")
1399         (subreg:HI (match_dup 1) 2))]
1400   "TARGET_40_PLUS"
1401   "")
1403 (define_insn ""
1404   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
1405         (mod:HI (match_operand:SI 1 "general_operand" "0")
1406                 (match_operand:HI 2 "general_operand" "g")))]
1407   "TARGET_40_PLUS"
1408   "div %2,%0"
1409   [(set_attr "length" "4")])
1411 ;(define_expand "divmodhi4"
1412 ;  [(parallel [(set (subreg:HI (match_dup 1) 0)
1413 ;                  (div:HI (match_operand:SI 1 "register_operand" "0")
1414 ;                          (match_operand:HI 2 "general_operand" "g")))
1415 ;              (set (subreg:HI (match_dup 1) 2)
1416 ;                  (mod:HI (match_dup 1)
1417 ;                          (match_dup 2)))])
1418 ;   (set (match_operand:HI 3 "register_operand" "=r")
1419 ;        (subreg:HI (match_dup 1) 2))
1420 ;   (set (match_operand:HI 0 "register_operand" "=r")
1421 ;        (subreg:HI (match_dup 1) 0))]
1422 ;  "TARGET_40_PLUS"
1423 ;  "")
1425 ;(define_insn ""
1426 ;  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1427 ;                  (div:HI (match_operand:SI 1 "general_operand" "0")
1428 ;                          (match_operand:HI 2 "general_operand" "g")))
1429 ;   (set (subreg:HI (match_dup 0) 2)
1430 ;                  (mod:HI (match_dup 1)
1431 ;                          (match_dup 2)))]
1432 ;  "TARGET_40_PLUS"
1433 ;  "div %2, %0")
1435    
1436 ;; is rotate doing the right thing to be included here ????