Merge from mainline (168000:168310).
[official-gcc/graphite-test-results.git] / gcc / config / pdp11 / pdp11.md
blob0566d9a66ab0456e9298e07c5dd3c42e925a2282
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)
11 ;; any later version.
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3.  If not see
20 ;; <http://www.gnu.org/licenses/>.
22 (include "predicates.md")
23 (include "constraints.md")
25 (define_constants
26   [
27    ;; Register numbers
28    (R0_REGNUM             0)
29    (RETVAL_REGNUM         0)
30    (HARD_FRAME_POINTER_REGNUM  5)
31    (STACK_POINTER_REGNUM  6)
32    (PC_REGNUM             7)
33    (AC0_REGNUM            8)
34    (AC3_REGNUM            11)
35    (AC4_REGNUM            12)
36    (AC5_REGNUM            13)
37    ;; The next two are not physical registers but are used for addressing
38    ;; arguments.
39    (FRAME_POINTER_REGNUM  14)
40    (ARG_POINTER_REGNUM    15)
41    (FIRST_PSEUDO_REGISTER 16)
42    ;; Branch offset limits, as byte offsets from instruction address
43    (MIN_BRANCH            -254)
44    (MAX_BRANCH            256)
45    (MIN_SOB               -126)
46    (MAX_SOB               0)])
48 ;; HI is 16 bit
49 ;; QI is 8 bit 
51 ;; Integer modes supported on the PDP11, with a mapping from machine mode
52 ;; to mnemonic suffix.  SImode and DImode always are special cases.
53 (define_mode_iterator PDPint [QI HI])
54 (define_mode_attr  isfx [(QI "b") (HI "")])
56 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
58 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
59 ;;- updates for most instructions.
61 ;;- Operand classes for the register allocator:
63 ;; Compare instructions.
65 ;; currently we only support df floats, which saves us quite some
66 ;; hassle switching the FP mode! 
67 ;; we assume that CPU is always in long float mode, and 
68 ;; 16 bit integer mode - currently, the prologue for main does this,
69 ;; but maybe we should just set up a NEW crt0 properly, 
70 ;; -- and what about signal handling code?
71 ;; (we don't even let sf floats in the register file, so
72 ;; we only should have to worry about truncating and widening 
73 ;; when going to memory)
75 ;; abort() call by g++ - must define libfunc for cmp_optab
76 ;; and ucmp_optab for mode SImode, because we don't have that!!!
77 ;; - yet since no libfunc is there, we abort ()
79 ;; The only thing that remains to be done then is output 
80 ;; the floats in a way the assembler can handle it (and 
81 ;; if you're really into it, use a PDP11 float emulation
82 ;; library to do floating point constant folding - but 
83 ;; I guess you'll get reasonable results even when not
84 ;; doing this)
85 ;; the last thing to do is fix the UPDATE_CC macro to check
86 ;; for floating point condition codes, and set cc_status
87 ;; properly, also setting the CC_IN_FCCR flag. 
89 ;; define attributes
90 ;; currently type is only fpu or arith or unknown, maybe branch later ?
91 ;; default is arith
92 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
94 ;; length default is 2 bytes each
95 (define_attr "length" "" (const_int 2))
97 ;; a user's asm statement
98 (define_asm_attributes
99   [(set_attr "type" "unknown")
100 ; length for asm is the max length per statement.  That would be
101 ; 3 words, for a two-operand instruction with extra word addressing
102 ; modes for both operands.
103    (set_attr "length" "6")])
105 ;; define function units
107 ;; arithmetic - values here immediately when next insn issued
108 ;; or does it mean the number of cycles after this insn was issued?
109 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
111 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
112 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
114 ;; compare
115 (define_insn "*cmpdf"
116   [(set (cc0)
117         (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
118                  (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
119   "TARGET_FPU"
120   "*
122   cc_status.flags = CC_IN_FPU;
123   if (which_alternative == 0 || which_alternative == 2)
124     return \"{tstd|tstf} %0\;cfcc\";
125   else
126     return \"{cmpd|cmpf} %0, %1\;cfcc\";
128   [(set_attr "length" "4,4,6,6")]) 
130 (define_insn "*cmp<mode>"
131   [(set (cc0)
132         (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
133                  (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
134   ""
135   "@
136    tst<PDPint:isfx> %0
137    cmp<PDPint:isfx> %0,%1
138    cmp<PDPint:isfx> %0,%1
139    tst<PDPint:isfx> %0
140    cmp<PDPint:isfx> %0,%1
141    cmp<PDPint:isfx> %0,%1"
142   [(set_attr "length" "2,2,4,4,4,6")])
144 ;; sob instruction - we need an assembler which can make this instruction
145 ;; valid under _all_ circumstances!
147 (define_insn ""
148   [(set (pc)
149         (if_then_else
150          (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
151                       (const_int -1))
152              (const_int 0))
153          (label_ref (match_operand 1 "" ""))
154          (pc)))
155    (set (match_dup 0)
156         (plus:HI (match_dup 0)
157                  (const_int -1)))]
158   "TARGET_40_PLUS"
159   "*
161  static int labelcount = 0;
162  static char buf[1000];
164  if (get_attr_length (insn) == 2)
165     return \"sob %0, %l1\";
167  /* emulate sob */
168  output_asm_insn (\"dec %0\", operands);
170  sprintf (buf, \"bge LONG_SOB%d\", labelcount);
171  output_asm_insn (buf, NULL);
173  output_asm_insn (\"jmp %l1\", operands);
175  sprintf (buf, \"LONG_SOB%d:\", labelcount++);
176  output_asm_insn (buf, NULL);
178  return \"\";
180   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
181                                                        (pc))
182                                                 (const_int MIN_SOB))
183                                            (gt (minus (match_dup 0)
184                                                        (pc))
185                                                 (const_int MAX_SOB)))
186                                       (const_int 8)
187                                       (const_int 2)))])
189 ;; These control RTL generation for conditional jump insns
190 ;; and match them for register allocation.
192 (define_expand "cbranchdf4"
193   [(set (cc0)
194         (compare (match_operand:DF 1 "general_operand")
195                  (match_operand:DF 2 "register_or_const0_operand")))
196    (set (pc)
197         (if_then_else (match_operator 0 "ordered_comparison_operator"
198                        [(cc0) (const_int 0)])
199                       (label_ref (match_operand 3 "" ""))
200                       (pc)))]
201   "TARGET_FPU"
202   "")
204 (define_expand "cbranch<mode>4"
205   [(set (cc0)
206         (compare (match_operand:PDPint 1 "general_operand")
207                  (match_operand:PDPint 2 "general_operand")))
208    (set (pc)
209         (if_then_else (match_operator 0 "ordered_comparison_operator"
210                        [(cc0) (const_int 0)])
211                       (label_ref (match_operand 3 "" ""))
212                       (pc)))]
213   ""
214   "")
216 ;; problem with too short jump distance! we need an assembler which can 
217 ;; make this valid for all jump distances!
218 ;; e.g. gas!
220 ;; these must be changed to check for CC_IN_FCCR if float is to be 
221 ;; enabled
223 (define_insn "*branch"
224   [(set (pc)
225         (if_then_else (match_operator 0 "ordered_comparison_operator"
226                        [(cc0) (const_int 0)])
227                       (label_ref (match_operand 1 "" ""))
228                       (pc)))]
229   ""
230   "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
231   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
232                                                       (pc))
233                                                (const_int MIN_BRANCH))
234                                            (gt (minus (match_dup 1)
235                                                       (pc))
236                                                (const_int MAX_BRANCH)))
237                                       (const_int 6)
238                                       (const_int 2)))])
241 ;; These match inverted jump insns for register allocation.
243 (define_insn "*branch_inverted"
244   [(set (pc)
245         (if_then_else (match_operator 0 "ordered_comparison_operator"
246                        [(cc0) (const_int 0)])
247                       (pc)
248                       (label_ref (match_operand 1 "" ""))))]
249   ""
250   "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
251   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
252                                                       (pc))
253                                                (const_int MIN_BRANCH))
254                                            (gt (minus (match_dup 1)
255                                                       (pc))
256                                                (const_int MAX_BRANCH)))
257                                       (const_int 6)
258                                       (const_int 2)))])
260 ;; Move instructions
262 (define_insn "movdi"
263   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
264         (match_operand:DI 1 "general_operand" "rN,g"))]
265   ""
266   "* return output_move_multiple (operands);"
267 ;; what's the mose expensive code - say twice movsi = 16
268   [(set_attr "length" "16,32")])
270 (define_insn "movsi"
271   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
272         (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
273   ""
274   "* return output_move_multiple (operands);"
275 ;; what's the most expensive code ? - I think 8!
276 ;; we could split it up and make several sub-cases...
277   [(set_attr "length" "4,6,8,16")])
279 (define_insn "mov<mode>"
280   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
281         (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
282   ""
283   "*
285   if (operands[1] == const0_rtx)
286     return \"clr<PDPint:isfx> %0\";
288   return \"mov<PDPint:isfx> %1, %0\";
290   [(set_attr "length" "2,4,4,6")])
292 (define_insn "movdf"
293   [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
294         (match_operand:DF 1 "float_operand" "fR,a,FQ,a,g"))]
295   "TARGET_FPU"
296   "* if (which_alternative ==0 || which_alternative == 2)
297        return \"ldd %1, %0\";
298      else if (which_alternative == 1 || which_alternative == 3)
299        return \"std %1, %0\";
300      else 
301        return output_move_multiple (operands); "
302 ;; last one is worst-case
303   [(set_attr "length" "2,2,4,4,24")])
305 (define_insn "movsf"
306   [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
307         (match_operand:SF 1 "float_operand" "fR,a,FQ,a,g"))]
308   "TARGET_FPU"
309   "* if (which_alternative ==0 || which_alternative == 2)
310        return \"{ldcfd|movof} %1, %0\";
311      else if (which_alternative == 1 || which_alternative == 3)
312        return \"{stcdf|movfo} %1, %0\";
313      else 
314        return output_move_multiple (operands); "
315 ;; last one is worst-case
316   [(set_attr "length" "2,2,4,4,12")])
318 ;; maybe fiddle a bit with move_ratio, then 
319 ;; let constraints only accept a register ...
321 (define_expand "movmemhi"
322   [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
323                    (match_operand:BLK 1 "general_operand" "g,g"))
324               (use (match_operand:HI 2 "general_operand" "n,&mr"))
325               (use (match_operand:HI 3 "immediate_operand" "i,i"))
326               (clobber (match_scratch:HI 4 "=&r,X"))
327               (clobber (match_dup 5))
328               (clobber (match_dup 6))
329               (clobber (match_dup 2))])]
330   "(TARGET_BCOPY_BUILTIN)"
331   "
333   operands[0]
334     = replace_equiv_address (operands[0],
335                              copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
336   operands[1]
337     = replace_equiv_address (operands[1],
338                              copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
340   operands[5] = XEXP (operands[0], 0);
341   operands[6] = XEXP (operands[1], 0);
345 (define_insn "" ; "movmemhi"
346   [(set (mem:BLK (match_operand 0 "pmode_register_operand" "+r,r"))
347         (mem:BLK (match_operand 1 "pmode_register_operand" "+r,r")))
348    (use (match_operand:HI 2 "general_operand" "+n,&r"))
349    (use (match_operand:HI 3 "immediate_operand" "i,i"))
350    (clobber (match_scratch:HI 4 "=&r,X"))
351    (clobber (match_dup 0))
352    (clobber (match_dup 1))
353    (clobber (match_dup 2))]
354   "(TARGET_BCOPY_BUILTIN)"
355   "* return output_block_move (operands);"
356 ;;; just a guess
357   [(set_attr "length" "80")])
358    
361 ;;- truncation instructions
363 (define_insn  "truncdfsf2"
364   [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
365         (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
366   "TARGET_FPU"
367   "* if (which_alternative ==0)
368      {
369        return \"\";
370      }
371      else if (which_alternative == 1)
372        return \"{stcdf|movfo} %1, %0\";
373      else 
374        return \"{stcdf|movfo} %1, %0\";
375   "
376   [(set_attr "length" "0,2,4")])
379 (define_expand "truncsihi2"
380   [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
381         (subreg:HI 
382           (match_operand:SI 1 "general_operand" "or")
383           0))]
384   ""
385   "")
388 ;;- zero extension instructions
390 (define_insn "zero_extendqihi2"
391   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
392         (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
393   ""
394   "bic $0177400, %0"
395   [(set_attr "length" "4,6")])
396                          
397 (define_expand "zero_extendhisi2"
398   [(set (subreg:HI 
399           (match_dup 0)
400           2)
401         (match_operand:HI 1 "register_operand" "r"))
402    (set (subreg:HI 
403           (match_operand:SI 0 "register_operand" "=r")
404           0)
405         (const_int 0))]
406   ""
407   "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
410 ;;- sign extension instructions
412 (define_insn "extendsfdf2"
413   [(set (match_operand:DF 0 "register_operand" "=f,a,a")
414         (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
415   "TARGET_FPU"
416   "@
417    /* nothing */
418    {ldcfd|movof} %1, %0
419    {ldcfd|movof} %1, %0"
420   [(set_attr "length" "0,2,4")])
422 ;; does movb sign extend in register-to-register move?
423 (define_insn "extendqihi2"
424   [(set (match_operand:HI 0 "register_operand" "=r,r")
425         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
426   ""
427   "movb %1, %0"
428   [(set_attr "length" "2,4")])
430 (define_insn "extendqisi2"
431   [(set (match_operand:SI 0 "register_operand" "=r,r")
432         (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
433   "TARGET_40_PLUS"
434   "*
436   rtx latehalf[2];
438   /* make register pair available */
439   latehalf[0] = operands[0];
440   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
442   output_asm_insn(\"movb %1, %0\", operands);
443   output_asm_insn(\"sxt %0\", latehalf);
444     
445   return \"\";
447   [(set_attr "length" "4,6")])
449 ;; maybe we have to use define_expand to say that we have the instruction,
450 ;; unconditionally, and then match dependent on CPU type:
452 (define_expand "extendhisi2"
453   [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
454         (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
455   ""
456   "")
457   
458 (define_insn "" ; "extendhisi2"
459   [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
460         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
461   "TARGET_40_PLUS"
462   "*
464   rtx latehalf[2];
466   /* we don't want to mess with auto increment */
467   
468   switch (which_alternative)
469   {
470     case 0:
472       latehalf[0] = operands[0];
473       operands[0] = adjust_address(operands[0], HImode, 2);
474   
475       output_asm_insn(\"mov %1, %0\", operands);
476       output_asm_insn(\"sxt %0\", latehalf);
478       return \"\";
480     case 1:
482       /* - auto-decrement - right direction ;-) */
483       output_asm_insn(\"mov %1, %0\", operands);
484       output_asm_insn(\"sxt %0\", operands);
486       return \"\";
488     case 2:
490       /* make register pair available */
491       latehalf[0] = operands[0];
492       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
494       output_asm_insn(\"mov %1, %0\", operands);
495       output_asm_insn(\"sxt %0\", latehalf);
497       return \"\";
499     default:
501       gcc_unreachable ();
502   }
504   [(set_attr "length" "10,6,6")])
507 (define_insn ""
508   [(set (match_operand:SI 0 "register_operand" "=r")
509         (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
510   "(! TARGET_40_PLUS)"
511   "*
513   static int count = 0;
514   char buf[100];
515   rtx lateoperands[2];
517   lateoperands[0] = operands[0];
518   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
520   output_asm_insn(\"tst %0\", operands);
521   sprintf(buf, \"bge extendhisi%d\", count);
522   output_asm_insn(buf, NULL);
523   output_asm_insn(\"mov -1, %0\", lateoperands);
524   sprintf(buf, \"bne extendhisi%d\", count+1);
525   output_asm_insn(buf, NULL);
526   sprintf(buf, \"\\nextendhisi%d:\", count);
527   output_asm_insn(buf, NULL);
528   output_asm_insn(\"clr %0\", lateoperands);
529   sprintf(buf, \"\\nextendhisi%d:\", count+1);
530   output_asm_insn(buf, NULL);
532   count += 2;
534   return \"\";
536   [(set_attr "length" "12")])
538 ;; make float to int and vice versa 
539 ;; using the cc_status.flag field we could probably cut down
540 ;; on seti and setl
541 ;; assume that we are normally in double and integer mode -
542 ;; what do pdp library routines do to fpu mode ?
544 (define_insn "floatsidf2"
545   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
546         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
547   "TARGET_FPU"
548   "* if (which_alternative ==0)
549      {
550        rtx latehalf[2];
552        latehalf[0] = NULL; 
553        latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
554        output_asm_insn(\"mov %1, -(sp)\", latehalf);
555        output_asm_insn(\"mov %1, -(sp)\", operands);
556        
557        output_asm_insn(\"setl\", operands);
558        output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
559        output_asm_insn(\"seti\", operands);
560        return \"\";
561      }
562      else if (which_alternative == 1)
563        return \"setl\;{ldcld|movif} %1, %0\;seti\";
564      else 
565        return \"setl\;{ldcld|movif} %1, %0\;seti\";
566   "
567   [(set_attr "length" "10,6,8")])
569 (define_insn "floathidf2"
570   [(set (match_operand:DF 0 "register_operand" "=a,a")
571         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
572   "TARGET_FPU"
573   "{ldcid|movif} %1, %0"
574   [(set_attr "length" "2,4")])
575         
576 ;; cut float to int
577 (define_insn "fix_truncdfsi2"
578   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
579         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
580   "TARGET_FPU"
581   "* if (which_alternative ==0)
582      {
583        output_asm_insn(\"setl\", operands);
584        output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
585        output_asm_insn(\"seti\", operands);
586        output_asm_insn(\"mov (sp)+, %0\", operands);
587        operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
588        output_asm_insn(\"mov (sp)+, %0\", operands);
589        return \"\";
590      }
591      else if (which_alternative == 1)
592        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
593      else 
594        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
595   "
596   [(set_attr "length" "10,6,8")])
598 (define_insn "fix_truncdfhi2"
599   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
600         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
601   "TARGET_FPU"
602   "{stcdi|movfi} %1, %0"
603   [(set_attr "length" "2,4")])
606 ;;- arithmetic instructions
607 ;;- add instructions
609 (define_insn "adddf3"
610   [(set (match_operand:DF 0 "register_operand" "=a,a")
611         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
612                  (match_operand:DF 2 "general_operand" "fR,QF")))]
613   "TARGET_FPU"
614   "{addd|addf} %2, %0"
615   [(set_attr "length" "2,4")])
617 (define_insn "adddi3"
618   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
619         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
620                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
621   ""
622   "*
624   rtx inops[2];
625   rtx exops[4][2];
626   
627   inops[0] = operands[0];
628   inops[1] = operands[2];
629   pdp11_expand_operands (inops, exops, 2, NULL, either);
630   
631   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
632     output_asm_insn (\"add %1, %0\", exops[0]);
633   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
634   {
635     output_asm_insn (\"add %1, %0\", exops[1]);
636     output_asm_insn (\"adc %0\", exops[0]);
637   }
638   if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
639   {
640     output_asm_insn (\"add %1, %0\", exops[2]);
641     output_asm_insn (\"adc %0\", exops[1]);
642     output_asm_insn (\"adc %0\", exops[0]);
643   }
644   if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
645   {
646     output_asm_insn (\"add %1, %0\", exops[3]);
647     output_asm_insn (\"adc %0\", exops[2]);
648     output_asm_insn (\"adc %0\", exops[1]);
649     output_asm_insn (\"adc %0\", exops[0]);
650   }
652   return \"\";
654   [(set_attr "length" "20,28,40,48")])
656 ;; Note that the register operand is not marked earlyclobber.
657 ;; The reason is that SI values go in register pairs, so they
658 ;; can't partially overlap.  They can be either disjoint, or
659 ;; source and destination can be equal.  The latter case is 
660 ;; handled properly because of the ordering of the individual
661 ;; instructions used.  Specifically, carry from the low to the
662 ;; high word is added at the end, so the adding of the high parts
663 ;; will always used the original high part and not a high part
664 ;; modified by carry (which would amount to double carry).
665 (define_insn "addsi3"
666   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
667         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
668                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
669   ""
670   "*
672   rtx inops[2];
673   rtx exops[2][2];
674   
675   inops[0] = operands[0];
676   inops[1] = operands[2];
677   pdp11_expand_operands (inops, exops, 2, NULL, either);
678   
679   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
680     output_asm_insn (\"add %1, %0\", exops[0]);
681   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
682   {
683     output_asm_insn (\"add %1, %0\", exops[1]);
684     output_asm_insn (\"adc %0\", exops[0]);
685   }
687   return \"\";
689   [(set_attr "length" "6,10,12,16")])
691 (define_insn "addhi3"
692   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
693         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
694                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
695   ""
696   "*
698   if (GET_CODE (operands[2]) == CONST_INT)
699     {
700       if (INTVAL(operands[2]) == 1)
701         return \"inc %0\";
702       else if (INTVAL(operands[2]) == -1)
703         return \"dec %0\";
704     }
706   return \"add %2, %0\";
708   [(set_attr "length" "2,4,4,6")])
711 ;;- subtract instructions
712 ;; we don't have to care for constant second 
713 ;; args, since they are canonical plus:xx now!
714 ;; also for minus:DF ??
716 (define_insn "subdf3"
717   [(set (match_operand:DF 0 "register_operand" "=a,a")
718         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
719                   (match_operand:DF 2 "general_operand" "fR,Q")))]
720   "TARGET_FPU"
721   "{subd|subf} %2, %0"
722   [(set_attr "length" "2,4")])
724 (define_insn "subdi3"
725   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
726         (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
727                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
728   ""
729   "*
731   rtx inops[2];
732   rtx exops[4][2];
733   
734   inops[0] = operands[0];
735   inops[1] = operands[2];
736   pdp11_expand_operands (inops, exops, 2, NULL, either);
737   
738   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
739     output_asm_insn (\"sub %1, %0\", exops[0]);
740   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
741   {
742     output_asm_insn (\"sub %1, %0\", exops[1]);
743     output_asm_insn (\"sbc %0\", exops[0]);
744   }
745   if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
746   {
747     output_asm_insn (\"sub %1, %0\", exops[2]);
748     output_asm_insn (\"sbc %0\", exops[1]);
749     output_asm_insn (\"sbc %0\", exops[0]);
750   }
751   if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
752   {
753     output_asm_insn (\"sub %1, %0\", exops[3]);
754     output_asm_insn (\"sbc %0\", exops[2]);
755     output_asm_insn (\"sbc %0\", exops[1]);
756     output_asm_insn (\"sbc %0\", exops[0]);
757   }
759   return \"\";
761   [(set_attr "length" "20,28,40,48")])
763 (define_insn "subsi3"
764   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
765         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
766                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
767   ""
768   "*
770   rtx inops[2];
771   rtx exops[2][2];
772   
773   inops[0] = operands[0];
774   inops[1] = operands[2];
775   pdp11_expand_operands (inops, exops, 2, NULL, either);
776   
777   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
778     output_asm_insn (\"sub %1, %0\", exops[0]);
779   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
780   {
781     output_asm_insn (\"sub %1, %0\", exops[1]);
782     output_asm_insn (\"sbc %0\", exops[0]);
783   }
785   return \"\";
787   [(set_attr "length" "6,10,12,16")])
789 (define_insn "subhi3"
790   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
791         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
792                   (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
793   ""
794   "*
796   gcc_assert (GET_CODE (operands[2]) != CONST_INT);
798   return \"sub %2, %0\";
800   [(set_attr "length" "2,4,4,6")])
802 ;;;;- and instructions
803 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
805 (define_expand "and<mode>3"
806   [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
807         (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
808                    (match_operand:PDPint 2 "general_operand" "")))]
809   ""
810   "
812   rtx op1 = operands[1];
814   /* If there is a constant argument, complement that one.
815      Similarly, if one of the inputs is the same as the output,
816      complement the other input.  */
817   if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
818       rtx_equal_p (operands[0], operands[1]))
819     {
820       operands[1] = operands[2];
821       operands[2] = op1;
822       op1 = operands[1];
823     }
825   if (CONST_INT_P (op1))
826     operands[1] = GEN_INT (~INTVAL (op1));
827   else
828     operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
831 (define_insn "*bic<mode>"
832   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
833         (and:PDPint
834              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
835              (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
836   ""
837   "bic<PDPint:isfx> %1, %0"
838   [(set_attr "length" "2,4,4,6")])
840 ;;- Bit set (inclusive or) instructions
841 (define_insn "ior<mode>3"
842   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
843         (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
844                 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
845   ""
846   "bis<PDPint:isfx> %2, %0"
847   [(set_attr "length" "2,4,4,6")])
849 ;;- xor instructions
850 (define_insn "xorhi3"
851   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
852         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
853                 (match_operand:HI 2 "register_operand" "r,r")))]
854   "TARGET_40_PLUS"
855   "xor %2, %0"
856   [(set_attr "length" "2,4")])
858 ;;- one complement instructions
860 (define_insn "one_cmpl<mode>2"
861   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
862         (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
863   ""
864   "com<PDPint:isfx> %0"
865   [(set_attr "length" "2,4")])
867 ;;- arithmetic shift instructions
868 (define_insn "ashlsi3"
869   [(set (match_operand:SI 0 "register_operand" "=r,r")
870         (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
871                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
872   "TARGET_40_PLUS"
873   "ashc %2,%0"
874   [(set_attr "length" "2,4")])
876 ;; Arithmetic right shift on the pdp works by negating the shift count.
877 (define_expand "ashrsi3"
878   [(set (match_operand:SI 0 "register_operand" "=r")
879         (ashift:SI (match_operand:SI 1 "register_operand" "0")
880                    (match_operand:HI 2 "general_operand" "g")))]
881   ""
882   "
884   operands[2] = negate_rtx (HImode, operands[2]);
887 ;; define asl aslb asr asrb - ashc missing!
889 ;; asl 
890 (define_insn "" 
891   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
892         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
893                    (const_int 1)))]
894   ""
895   "asl %0"
896   [(set_attr "length" "2,4")])
898 ;; and another possibility for asr is << -1
899 ;; might cause problems since -1 can also be encoded as 65535!
900 ;; not in gcc2 ??? 
902 ;; asr
903 (define_insn "" 
904   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
905         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
906                    (const_int -1)))]
907   ""
908   "asr %0"
909   [(set_attr "length" "2,4")])
911 ;; lsr
912 (define_insn "lsrhi1" 
913   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
914         (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
915                    (const_int 1)))]
916   ""
917   "clc\;ror %0"
918   [(set_attr "length" "2,4")])
920 (define_insn "lsrsi1"
921   [(set (match_operand:SI 0 "register_operand" "=r")
922         (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
923                    (const_int 1)))]
924   ""
927   rtx lateoperands[2];
929   lateoperands[0] = operands[0];
930   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
932   lateoperands[1] = operands[1];
933   operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
935   output_asm_insn (\"clc\", operands);
936   output_asm_insn (\"ror %0\", lateoperands);
937   output_asm_insn (\"ror %0\", operands);
939   return \"\";
941   [(set_attr "length" "10")])
943 (define_expand "lshrsi3"
944   [(match_operand:SI 0 "register_operand" "")
945    (match_operand:SI 1 "register_operand" "0")
946    (match_operand:HI 2 "general_operand" "")]
947   ""
948   "
950   rtx r;
952   if (!TARGET_40_PLUS &&
953       (GET_CODE (operands[2]) != CONST_INT ||
954        (unsigned) INTVAL (operands[2]) > 3))
955     FAIL;
956   emit_insn (gen_lsrsi1 (operands[0], operands[1]));
957   if (GET_CODE (operands[2]) != CONST_INT)
958     {
959       r = gen_reg_rtx (HImode);
960       emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
961       emit_insn (gen_ashrsi3 (operands[0], operands[0], r));
962     }
963   else if ((unsigned) INTVAL (operands[2]) != 1)
964     {
965       emit_insn (gen_ashlsi3 (operands[0], operands[0],
966                               GEN_INT (1 - INTVAL (operands[2]))));
967     }
968   DONE;
973 ;; shift is by arbitrary count is expensive, 
974 ;; shift by one cheap - so let's do that, if
975 ;; space doesn't matter
976 (define_insn "" 
977   [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
978         (ashift:HI (match_operand:HI 1 "general_operand" "0")
979                    (match_operand:HI 2 "expand_shift_operand" "O")))]
980   "! optimize_size"
981   "*
983   register int i;
985   for (i = 1; i <= abs(INTVAL(operands[2])); i++)
986     if (INTVAL(operands[2]) < 0)
987       output_asm_insn(\"asr %0\", operands);
988     else
989       output_asm_insn(\"asl %0\", operands);
990       
991   return \"\";
993 ;; longest is 4
994   [(set (attr "length") (const_int 8))])
996 ;; aslb
997 (define_insn "" 
998   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
999         (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1000                    (match_operand:HI 2 "const_int_operand" "n,n")))]
1001   ""
1002   "*
1003 { /* allowing predec or post_inc is possible, but hairy! */
1004   int i, cnt;
1006   cnt = INTVAL(operands[2]) & 0x0007;
1008   for (i=0 ; i < cnt ; i++)
1009        output_asm_insn(\"aslb %0\", operands);
1011   return \"\";
1013 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1014   [(set_attr_alternative "length" 
1015                          [(const_int 14)
1016                           (const_int 28)])])
1018 ;;; asr 
1019 ;(define_insn "" 
1020 ;  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1021 ;       (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1022 ;                    (const_int 1)))]
1023 ;  ""
1024 ;  "asr %0"
1025 ;  [(set_attr "length" "2,4")])
1027 ;; asrb
1028 (define_insn "" 
1029   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
1030         (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1031                      (match_operand:HI 2 "const_int_operand" "n,n")))]
1032   ""
1033   "*
1034 { /* allowing predec or post_inc is possible, but hairy! */
1035   int i, cnt;
1037   cnt = INTVAL(operands[2]) & 0x0007;
1039   for (i=0 ; i < cnt ; i++)
1040        output_asm_insn(\"asrb %0\", operands);
1042   return \"\";
1044   [(set_attr_alternative "length" 
1045                          [(const_int 14)
1046                           (const_int 28)])])
1048 ;; the following is invalid - too complex!!! - just say 14 !!!
1049 ;  [(set (attr "length") (plus (and (match_dup 2)
1050 ;                                   (const_int 14))
1051 ;                              (and (match_dup 2)
1052 ;                                   (const_int 14))))])
1056 ;; can we get +-1 in the next pattern? should 
1057 ;; have been caught by previous patterns!
1059 (define_insn "ashlhi3"
1060   [(set (match_operand:HI 0 "register_operand" "=r,r")
1061         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1062                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
1063   "TARGET_40_PLUS"
1064   "*
1066   if (GET_CODE(operands[2]) == CONST_INT)
1067     {
1068       if (INTVAL(operands[2]) == 1)
1069         return \"asl %0\";
1070       else if (INTVAL(operands[2]) == -1)
1071         return \"asr %0\";
1072     }
1074   return \"ash %2,%0\";
1076   [(set_attr "length" "2,4")])
1078 ;; Arithmetic right shift on the pdp works by negating the shift count.
1079 (define_expand "ashrhi3"
1080   [(set (match_operand:HI 0 "register_operand" "=r")
1081         (ashift:HI (match_operand:HI 1 "register_operand" "0")
1082                    (match_operand:HI 2 "general_operand" "g")))]
1083   ""
1084   "
1086   operands[2] = negate_rtx (HImode, operands[2]);
1089 (define_expand "lshrhi3"
1090   [(match_operand:HI 0 "register_operand" "")
1091    (match_operand:HI 1 "register_operand" "")
1092    (match_operand:HI 2 "general_operand" "")]
1093   ""
1094   "
1096   rtx r;
1098   if (!TARGET_40_PLUS &&
1099       (GET_CODE (operands[2]) != CONST_INT ||
1100        (unsigned) INTVAL (operands[2]) > 3))
1101     FAIL;
1102   emit_insn (gen_lsrhi1 (operands[0], operands[1]));
1103   if (GET_CODE (operands[2]) != CONST_INT)
1104     {
1105       r = gen_reg_rtx (HImode);
1106       emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
1107       emit_insn (gen_ashrhi3 (operands[0], operands[0], r));
1108     }
1109   else if ((unsigned) INTVAL (operands[2]) != 1)
1110     {
1111       emit_insn (gen_ashlhi3 (operands[0], operands[0],
1112                               GEN_INT (1 - INTVAL (operands[2]))));
1113     }
1114   DONE;
1119 ;; absolute 
1121 (define_insn "absdf2"
1122   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1123         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1124   "TARGET_FPU"
1125   "{absd|absf} %0"
1126   [(set_attr "length" "2,4")])
1129 ;; negate insns
1131 (define_insn "negdf2"
1132   [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
1133         (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1134   "TARGET_FPU"
1135   "{negd|negf} %0"
1136   [(set_attr "length" "2,4")])
1138 (define_insn "negdi2"
1139   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1140         (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1141   ""
1143   rtx exops[4][2];
1144   
1145   pdp11_expand_operands (operands, exops, 1, NULL, either);
1147   output_asm_insn (\"com %0\", exops[3]);
1148   output_asm_insn (\"com %0\", exops[2]);
1149   output_asm_insn (\"com %0\", exops[1]);
1150   output_asm_insn (\"com %0\", exops[0]);
1151   output_asm_insn (\"add $1, %0\", exops[3]);
1152   output_asm_insn (\"adc %0\", exops[2]);
1153   output_asm_insn (\"adc %0\", exops[1]);
1154   output_asm_insn (\"adc %0\", exops[0]);
1156   return \"\";
1158 [(set_attr "length" "18,34")])
1160 (define_insn "negsi2"
1161   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1162         (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1163   ""
1165   rtx exops[2][2];
1166   
1167   pdp11_expand_operands (operands, exops, 1, NULL, either);
1169   output_asm_insn (\"com %0\", exops[1]);
1170   output_asm_insn (\"com %0\", exops[0]);
1171   output_asm_insn (\"add $1, %0\", exops[1]);
1172   output_asm_insn (\"adc %0\", exops[0]);
1174   return \"\";
1176 [(set_attr "length" "12,20")])
1178 (define_insn "neg<mode>2"
1179   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1180         (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1181   ""
1182   "neg<isfx> %0"
1183   [(set_attr "length" "2,4")])
1186 ;; Unconditional and other jump instructions
1187 (define_insn "jump"
1188   [(set (pc)
1189         (label_ref (match_operand 0 "" "")))]
1190   ""
1191   "*
1193  if (get_attr_length (insn) == 2)
1194     return \"br %l0\";
1195  return \"jmp %l0\";
1197   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1198                                                       (pc))
1199                                                (const_int MIN_BRANCH))
1200                                            (gt (minus (match_dup 0)
1201                                                       (pc))
1202                                                (const_int MAX_BRANCH)))
1203                                       (const_int 4)
1204                                       (const_int 2)))])
1206 (define_insn ""
1207   [(set (pc)
1208     (label_ref (match_operand 0 "" "")))
1209    (clobber (const_int 1))]
1210   ""
1211   "jmp %l0"
1212   [(set_attr "length" "4")])
1214 (define_insn "tablejump"
1215   [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1216    (use (label_ref (match_operand 1 "" "")))]
1217   ""
1218   "jmp %0"
1219   [(set_attr "length" "2,4")])
1221 ;; indirect jump - let's be conservative!
1222 ;; allow only register_operand, even though we could also 
1223 ;; allow labels etc.
1225 (define_insn "indirect_jump"
1226   [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1227   ""
1228   "jmp (%0)")
1230 ;;- jump to subroutine
1232 (define_insn "call"
1233   [(call (match_operand:HI 0 "general_operand" "rR,Q")
1234          (match_operand:HI 1 "general_operand" "g,g"))
1235 ;;   (use (reg:HI 0)) what was that ???
1236   ]
1237   ;;- Don't use operand 1 for most machines.
1238   ""
1239   "jsr pc, %0"
1240   [(set_attr "length" "2,4")])
1242 ;;- jump to subroutine
1243 (define_insn "call_value"
1244   [(set (match_operand 0 "" "")
1245         (call (match_operand:HI 1 "general_operand" "rR,Q")
1246               (match_operand:HI 2 "general_operand" "g,g")))
1247 ;;   (use (reg:HI 0)) - what was that ????
1248   ]
1249   ;;- Don't use operand 2 for most machines.
1250   ""
1251   "jsr pc, %1"
1252   [(set_attr "length" "2,4")])
1254 ;;- nop instruction
1255 (define_insn "nop"
1256   [(const_int 0)]
1257   ""
1258   "nop")
1261 ;;- multiply 
1263 (define_insn "muldf3"
1264   [(set (match_operand:DF 0 "register_operand" "=a,a")
1265         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1266                  (match_operand:DF 2 "float_operand" "fR,QF")))]
1267   "TARGET_FPU"
1268   "{muld|mulf} %2, %0"
1269   [(set_attr "length" "2,4")])
1271 ;; 16 bit result multiply:
1272 ;; currently we multiply only into odd registers, so we don't use two 
1273 ;; registers - but this is a bit inefficient at times. If we define 
1274 ;; a register class for each register, then we can specify properly 
1275 ;; which register need which scratch register ....
1277 (define_insn "mulhi3"
1278   [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1279         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1280                  (match_operand:HI 2 "float_operand" "rR,Qi")))]
1281   "TARGET_40_PLUS"
1282   "mul %2, %0"
1283   [(set_attr "length" "2,4")])
1285 ;; 32 bit result
1286 (define_expand "mulhisi3"
1287   [(set (match_dup 3)
1288         (match_operand:HI 1 "nonimmediate_operand" "g,g"))
1289    (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1290         (mult:SI (truncate:HI 
1291                   (match_dup 0))
1292                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1293   "TARGET_40_PLUS"
1294   "operands[3] = gen_lowpart(HImode, operands[1]);")
1296 (define_insn ""
1297   [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1298         (mult:SI (truncate:HI 
1299                   (match_operand:SI 1 "register_operand" "%0,0"))
1300                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1301   "TARGET_40_PLUS"
1302   "mul %2, %0"
1303   [(set_attr "length" "2,4")])
1305 ;(define_insn "mulhisi3"
1306 ;  [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1307 ;       (mult:SI (truncate:HI 
1308 ;                  (match_operand:SI 1 "register_operand" "%0,0"))
1309 ;                (match_operand:HI 2 "general_operand" "rR,Qi")))]
1310 ;  "TARGET_40_PLUS"
1311 ;  "mul %2, %0"
1312 ;  [(set_attr "length" "2,4")])
1314 ;;- divide
1315 (define_insn "divdf3"
1316   [(set (match_operand:DF 0 "register_operand" "=a,a")
1317         (div:DF (match_operand:DF 1 "register_operand" "0,0")
1318                 (match_operand:DF 2 "general_operand" "fR,QF")))]
1319   "TARGET_FPU"
1320   "{divd|divf} %2, %0"
1321   [(set_attr "length" "2,4")])
1323          
1324 (define_expand "divhi3"
1325   [(set (subreg:HI (match_dup 1) 0)
1326         (div:HI (match_operand:SI 1 "register_operand" "0")
1327                 (match_operand:HI 2 "general_operand" "g")))
1328    (set (match_operand:HI 0 "register_operand" "=r")
1329         (subreg:HI (match_dup 1) 0))]
1330   "TARGET_40_PLUS"
1331   "")
1333 (define_insn ""
1334   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1335         (div:HI (match_operand:SI 1 "general_operand" "0")
1336                 (match_operand:HI 2 "general_operand" "g")))]
1337   "TARGET_40_PLUS"
1338   "div %2,%0"
1339   [(set_attr "length" "4")])
1341 (define_expand "modhi3"
1342   [(set (subreg:HI (match_dup 1) 2)
1343         (mod:HI (match_operand:SI 1 "register_operand" "0")
1344                 (match_operand:HI 2 "general_operand" "g")))
1345    (set (match_operand:HI 0 "register_operand" "=r")
1346         (subreg:HI (match_dup 1) 2))]
1347   "TARGET_40_PLUS"
1348   "")
1350 (define_insn ""
1351   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
1352         (mod:HI (match_operand:SI 1 "general_operand" "0")
1353                 (match_operand:HI 2 "general_operand" "g")))]
1354   "TARGET_40_PLUS"
1355   "div %2,%0"
1356   [(set_attr "length" "4")])
1358 ;(define_expand "divmodhi4"
1359 ;  [(parallel [(set (subreg:HI (match_dup 1) 0)
1360 ;                  (div:HI (match_operand:SI 1 "register_operand" "0")
1361 ;                          (match_operand:HI 2 "general_operand" "g")))
1362 ;              (set (subreg:HI (match_dup 1) 2)
1363 ;                  (mod:HI (match_dup 1)
1364 ;                          (match_dup 2)))])
1365 ;   (set (match_operand:HI 3 "register_operand" "=r")
1366 ;        (subreg:HI (match_dup 1) 2))
1367 ;   (set (match_operand:HI 0 "register_operand" "=r")
1368 ;        (subreg:HI (match_dup 1) 0))]
1369 ;  "TARGET_40_PLUS"
1370 ;  "")
1372 ;(define_insn ""
1373 ;  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
1374 ;                  (div:HI (match_operand:SI 1 "general_operand" "0")
1375 ;                          (match_operand:HI 2 "general_operand" "g")))
1376 ;   (set (subreg:HI (match_dup 0) 2)
1377 ;                  (mod:HI (match_dup 1)
1378 ;                          (match_dup 2)))]
1379 ;  "TARGET_40_PLUS"
1380 ;  "div %2, %0")
1382    
1383 ;; is rotate doing the right thing to be included here ????