PR/41822
[official-gcc.git] / gcc / config / pdp11 / pdp11.md
blob9cb4ef14ef46cf59677e19b36485b0a9cffe7adb
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    (RETVAL_REGNUM         0)
29    (FRAME_POINTER_REGNUM  5)
30    (STACK_POINTER_REGNUM  6)
31    (PC_REGNUM             7)
32    (AC0_REGNUM            8)
33    (AC3_REGNUM            11)
34    (AC4_REGNUM            12)
35    (AC5_REGNUM            13)
36    (FIRST_PSEUDO_REGISTER 14)
37    ;; Branch offset limits, as byte offsets from instruction address
38    (MIN_BRANCH            -254)
39    (MAX_BRANCH            256)
40    (MIN_SOB               -126)
41    (MAX_SOB               0)])
43 ;; HI is 16 bit
44 ;; QI is 8 bit 
46 ;; Integer modes supported on the PDP11, with a mapping from machine mode
47 ;; to mnemonic suffix.  SImode and DImode always are special cases.
48 (define_mode_iterator PDPint [QI HI])
49 (define_mode_attr  isfx [(QI "b") (HI "")])
51 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
53 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
54 ;;- updates for most instructions.
56 ;;- Operand classes for the register allocator:
58 ;; Compare instructions.
60 ;; currently we only support df floats, which saves us quite some
61 ;; hassle switching the FP mode! 
62 ;; we assume that CPU is always in long float mode, and 
63 ;; 16 bit integer mode - currently, the prologue for main does this,
64 ;; but maybe we should just set up a NEW crt0 properly, 
65 ;; -- and what about signal handling code?
66 ;; (we don't even let sf floats in the register file, so
67 ;; we only should have to worry about truncating and widening 
68 ;; when going to memory)
70 ;; abort() call by g++ - must define libfunc for cmp_optab
71 ;; and ucmp_optab for mode SImode, because we don't have that!!!
72 ;; - yet since no libfunc is there, we abort ()
74 ;; The only thing that remains to be done then is output 
75 ;; the floats in a way the assembler can handle it (and 
76 ;; if you're really into it, use a PDP11 float emulation
77 ;; library to do floating point constant folding - but 
78 ;; I guess you'll get reasonable results even when not
79 ;; doing this)
80 ;; the last thing to do is fix the UPDATE_CC macro to check
81 ;; for floating point condition codes, and set cc_status
82 ;; properly, also setting the CC_IN_FCCR flag. 
84 ;; define attributes
85 ;; currently type is only fpu or arith or unknown, maybe branch later ?
86 ;; default is arith
87 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
89 ;; length default is 2 bytes each
90 (define_attr "length" "" (const_int 2))
92 ;; a user's asm statement
93 (define_asm_attributes
94   [(set_attr "type" "unknown")
95 ; length for asm is the max length per statement.  That would be
96 ; 5 words, for a floating point instruction with a literal constant
97 ; argument.
98    (set_attr "length" "10")])
100 ;; define function units
102 ;; arithmetic - values here immediately when next insn issued
103 ;; or does it mean the number of cycles after this insn was issued?
104 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
106 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
107 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
109 ;; compare
110 (define_insn "*cmpdf"
111   [(set (cc0)
112         (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F")
113                  (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))]
114   "TARGET_FPU"
115   "*
117   cc_status.flags = CC_IN_FPU;
118   if (which_alternative == 0 || which_alternative == 2)
119     return \"{tstd|tstf} %0\;cfcc\";
120   else
121     return \"{cmpd|cmpf} %0, %1\;cfcc\";
123   [(set_attr "length" "4,4,6,6,12")]) 
125 (define_insn "*cmphi"
126   [(set (cc0)
127         (compare (match_operand:HI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
128                  (match_operand:HI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
129   ""
130   "@
131    tst %0
132    cmp %0,%1
133    cmp %0,%1
134    tst %0
135    cmp %0,%1
136    cmp %0,%1"
137   [(set_attr "length" "2,2,4,4,4,6")])
139 (define_insn "*cmpqi"
140   [(set (cc0)
141         (compare (match_operand:QI 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
142                  (match_operand:QI 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
143   ""
144   "@
145    tstb %0
146    cmpb %0,%1
147    cmpb %0,%1
148    tstb %0
149    cmpb %0,%1
150    cmpb %0,%1"
151   [(set_attr "length" "2,2,4,4,4,6")])
152                            
154 ;; sob instruction - we need an assembler which can make this instruction
155 ;; valid under _all_ circumstances!
157 (define_insn ""
158   [(set (pc)
159         (if_then_else
160          (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
161                       (const_int -1))
162              (const_int 0))
163          (label_ref (match_operand 1 "" ""))
164          (pc)))
165    (set (match_dup 0)
166         (plus:HI (match_dup 0)
167                  (const_int -1)))]
168   "TARGET_40_PLUS"
169   "*
171  static int labelcount = 0;
172  static char buf[1000];
174  if (get_attr_length (insn) == 2)
175     return \"sob %0, %l1\";
177  /* emulate sob */
178  output_asm_insn (\"dec %0\", operands);
180  sprintf (buf, \"bge LONG_SOB%d\", labelcount);
181  output_asm_insn (buf, NULL);
183  output_asm_insn (\"jmp %l1\", operands);
185  sprintf (buf, \"LONG_SOB%d:\", labelcount++);
186  output_asm_insn (buf, NULL);
188  return \"\";
190   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
191                                                        (pc))
192                                                 (const_int MIN_SOB))
193                                            (gt (minus (match_dup 0)
194                                                        (pc))
195                                                 (const_int MAX_SOB)))
196                                       (const_int 8)
197                                       (const_int 2)))])
199 ;; These control RTL generation for conditional jump insns
200 ;; and match them for register allocation.
202 (define_expand "cbranchdf4"
203   [(set (cc0)
204         (compare (match_operand:DF 1 "general_operand")
205                  (match_operand:DF 2 "register_or_const0_operand")))
206    (set (pc)
207         (if_then_else (match_operator 0 "ordered_comparison_operator"
208                        [(cc0) (const_int 0)])
209                       (label_ref (match_operand 3 "" ""))
210                       (pc)))]
211   "TARGET_FPU"
212   "")
214 (define_expand "cbranchhi4"
215   [(set (cc0)
216         (compare (match_operand:HI 1 "general_operand")
217                  (match_operand:HI 2 "general_operand")))
218    (set (pc)
219         (if_then_else (match_operator 0 "ordered_comparison_operator"
220                        [(cc0) (const_int 0)])
221                       (label_ref (match_operand 3 "" ""))
222                       (pc)))]
223   ""
224   "")
226 (define_expand "cbranchqi4"
227   [(set (cc0)
228         (compare (match_operand:QI 1 "general_operand")
229                  (match_operand:QI 2 "general_operand")))
230    (set (pc)
231         (if_then_else (match_operator 0 "ordered_comparison_operator"
232                        [(cc0) (const_int 0)])
233                       (label_ref (match_operand 3 "" ""))
234                       (pc)))]
235   ""
236   "")
238 ;; problem with too short jump distance! we need an assembler which can 
239 ;; make this valid for all jump distances!
240 ;; e.g. gas!
242 ;; these must be changed to check for CC_IN_FCCR if float is to be 
243 ;; enabled
245 (define_insn "*branch"
246   [(set (pc)
247         (if_then_else (match_operator 0 "ordered_comparison_operator"
248                        [(cc0) (const_int 0)])
249                       (label_ref (match_operand 1 "" ""))
250                       (pc)))]
251   ""
252   "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
253   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
254                                                       (pc))
255                                                (const_int MIN_BRANCH))
256                                            (gt (minus (match_dup 1)
257                                                       (pc))
258                                                (const_int MAX_BRANCH)))
259                                       (const_int 6)
260                                       (const_int 2)))])
263 ;; These match inverted jump insns for register allocation.
265 (define_insn "*branch_inverted"
266   [(set (pc)
267         (if_then_else (match_operator 0 "ordered_comparison_operator"
268                        [(cc0) (const_int 0)])
269                       (pc)
270                       (label_ref (match_operand 1 "" ""))))]
271   ""
272   "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
273   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
274                                                       (pc))
275                                                (const_int MIN_BRANCH))
276                                            (gt (minus (match_dup 1)
277                                                       (pc))
278                                                (const_int MAX_BRANCH)))
279                                       (const_int 6)
280                                       (const_int 2)))])
282 ;; Move instructions
284 (define_insn "movdi"
285   [(set (match_operand:DI 0 "general_operand" "=g,rm,o")
286         (match_operand:DI 1 "general_operand" "m,r,a"))]
287   ""
288   "* return output_move_quad (operands);"
289 ;; what's the mose expensive code - say twice movsi = 16
290   [(set_attr "length" "32,32,32")])
292 (define_insn "movsi"
293   [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
294         (match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
295   ""
296   "* return output_move_double (operands);"
297 ;; what's the most expensive code ? - I think 8!
298 ;; we could split it up and make several sub-cases...
299   [(set_attr "length" "4,6,8,16,16")])
301 (define_insn "movhi"
302   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
303         (match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
304   ""
305   "*
307   if (operands[1] == const0_rtx)
308     return \"clr %0\";
310   return \"mov %1, %0\";
312   [(set_attr "length" "2,4,4,6")])
314 (define_insn "movqi"
315   [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
316         (match_operand:QI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
317   ""
318   "*
320   if (operands[1] == const0_rtx)
321     return \"clrb %0\";
323   return \"movb %1, %0\";
325   [(set_attr "length" "2,4,4,6")])
327 (define_insn "movdf"
328   [(set (match_operand:DF 0 "float_operand" "=a,fR,a,Q,g")
329         (match_operand:DF 1 "float_operand" "fFR,a,Q,a,g"))]
330   "TARGET_FPU"
331   "* if (which_alternative ==0 || which_alternative == 2)
332        return \"ldd %1, %0\";
333      else if (which_alternative == 1 || which_alternative == 3)
334        return \"std %1, %0\";
335      else 
336        return output_move_quad (operands); "
337 ;; just a guess..
338   [(set_attr "length" "2,2,10,10,32")])
340 (define_insn "movsf"
341   [(set (match_operand:SF 0 "float_operand" "=a,fR,a,Q,g")
342         (match_operand:SF 1 "float_operand" "fFR,a,Q,a,g"))]
343   "TARGET_FPU"
344   "* if (which_alternative ==0 || which_alternative == 2)
345        return \"{ldcfd|movof} %1, %0\";
346      else if (which_alternative == 1 || which_alternative == 3)
347        return \"{stcdf|movfo} %1, %0\";
348      else 
349        return output_move_double (operands); "
350 ;; just a guess..
351   [(set_attr "length" "2,2,10,10,16")])
353 ;; maybe fiddle a bit with move_ratio, then 
354 ;; let constraints only accept a register ...
356 (define_expand "movmemhi"
357   [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
358                    (match_operand:BLK 1 "general_operand" "g,g"))
359               (use (match_operand:HI 2 "general_operand" "n,&mr"))
360               (use (match_operand:HI 3 "immediate_operand" "i,i"))
361               (clobber (match_scratch:HI 4 "=&r,X"))
362               (clobber (match_dup 5))
363               (clobber (match_dup 6))
364               (clobber (match_dup 2))])]
365   "(TARGET_BCOPY_BUILTIN)"
366   "
368   operands[0]
369     = replace_equiv_address (operands[0],
370                              copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
371   operands[1]
372     = replace_equiv_address (operands[1],
373                              copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
375   operands[5] = XEXP (operands[0], 0);
376   operands[6] = XEXP (operands[1], 0);
380 (define_insn "" ; "movmemhi"
381   [(set (mem:BLK (match_operand 0 "pmode_register_operand" "+r,r"))
382         (mem:BLK (match_operand 1 "pmode_register_operand" "+r,r")))
383    (use (match_operand:HI 2 "general_operand" "+n,&r"))
384    (use (match_operand:HI 3 "immediate_operand" "i,i"))
385    (clobber (match_scratch:HI 4 "=&r,X"))
386    (clobber (match_dup 0))
387    (clobber (match_dup 1))
388    (clobber (match_dup 2))]
389   "(TARGET_BCOPY_BUILTIN)"
390   "* return output_block_move (operands);"
391 ;;; just a guess
392   [(set_attr "length" "80")])
393    
396 ;;- truncation instructions
398 (define_insn  "truncdfsf2"
399   [(set (match_operand:SF 0 "general_operand" "=f,R,Q")
400         (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
401   "TARGET_FPU"
402   "* if (which_alternative ==0)
403      {
404        return \"\";
405      }
406      else if (which_alternative == 1)
407        return \"{stcdf|movfo} %1, %0\";
408      else 
409        return \"{stcdf|movfo} %1, %0\";
410   "
411   [(set_attr "length" "0,2,4")])
414 (define_expand "truncsihi2"
415   [(set (match_operand:HI 0 "general_operand" "=g")
416         (subreg:HI 
417           (match_operand:SI 1 "general_operand" "or")
418           0))]
419   ""
420   "")
423 ;;- zero extension instructions
425 (define_insn "zero_extendqihi2"
426   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
427         (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
428   ""
429   "bic $0177400, %0"
430   [(set_attr "length" "4,6")])
431                          
432 (define_expand "zero_extendhisi2"
433   [(set (subreg:HI 
434           (match_dup 0)
435           2)
436         (match_operand:HI 1 "register_operand" "r"))
437    (set (subreg:HI 
438           (match_operand:SI 0 "register_operand" "=r")
439           0)
440         (const_int 0))]
441   ""
442   "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
445 ;;- sign extension instructions
447 (define_insn "extendsfdf2"
448   [(set (match_operand:DF 0 "register_operand" "=f,a,a")
449         (float_extend:DF (match_operand:SF 1 "general_operand" "f,R,Q")))]
450   "TARGET_FPU"
451   "@
452    /* nothing */
453    {ldcfd|movof} %1, %0
454    {ldcfd|movof} %1, %0"
455   [(set_attr "length" "0,2,4")])
457 ;; does movb sign extend in register-to-register move?
458 (define_insn "extendqihi2"
459   [(set (match_operand:HI 0 "register_operand" "=r,r")
460         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
461   ""
462   "movb %1, %0"
463   [(set_attr "length" "2,4")])
465 (define_insn "extendqisi2"
466   [(set (match_operand:SI 0 "register_operand" "=r,r")
467         (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
468   "TARGET_40_PLUS"
469   "*
471   rtx latehalf[2];
473   /* make register pair available */
474   latehalf[0] = operands[0];
475   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
477   output_asm_insn(\"movb %1, %0\", operands);
478   output_asm_insn(\"sxt %0\", latehalf);
479     
480   return \"\";
482   [(set_attr "length" "4,6")])
484 ;; maybe we have to use define_expand to say that we have the instruction,
485 ;; unconditionally, and then match dependent on CPU type:
487 (define_expand "extendhisi2"
488   [(set (match_operand:SI 0 "general_operand" "=g")
489         (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
490   ""
491   "")
492   
493 (define_insn "" ; "extendhisi2"
494   [(set (match_operand:SI 0 "general_operand" "=o,<,r")
495         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
496   "TARGET_40_PLUS"
497   "*
499   rtx latehalf[2];
501   /* we don't want to mess with auto increment */
502   
503   switch (which_alternative)
504   {
505     case 0:
507       latehalf[0] = operands[0];
508       operands[0] = adjust_address(operands[0], HImode, 2);
509   
510       output_asm_insn(\"mov %1, %0\", operands);
511       output_asm_insn(\"sxt %0\", latehalf);
513       return \"\";
515     case 1:
517       /* - auto-decrement - right direction ;-) */
518       output_asm_insn(\"mov %1, %0\", operands);
519       output_asm_insn(\"sxt %0\", operands);
521       return \"\";
523     case 2:
525       /* make register pair available */
526       latehalf[0] = operands[0];
527       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
529       output_asm_insn(\"mov %1, %0\", operands);
530       output_asm_insn(\"sxt %0\", latehalf);
532       return \"\";
534     default:
536       gcc_unreachable ();
537   }
539   [(set_attr "length" "10,6,6")])
542 (define_insn ""
543   [(set (match_operand:SI 0 "register_operand" "=r")
544         (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
545   "(! TARGET_40_PLUS)"
546   "*
548   static int count = 0;
549   char buf[100];
550   rtx lateoperands[2];
552   lateoperands[0] = operands[0];
553   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
555   output_asm_insn(\"tst %0\", operands);
556   sprintf(buf, \"bge extendhisi%d\", count);
557   output_asm_insn(buf, NULL);
558   output_asm_insn(\"mov -1, %0\", lateoperands);
559   sprintf(buf, \"bne extendhisi%d\", count+1);
560   output_asm_insn(buf, NULL);
561   sprintf(buf, \"\\nextendhisi%d:\", count);
562   output_asm_insn(buf, NULL);
563   output_asm_insn(\"clr %0\", lateoperands);
564   sprintf(buf, \"\\nextendhisi%d:\", count+1);
565   output_asm_insn(buf, NULL);
567   count += 2;
569   return \"\";
571   [(set_attr "length" "12")])
573 ;; make float to int and vice versa 
574 ;; using the cc_status.flag field we could probably cut down
575 ;; on seti and setl
576 ;; assume that we are normally in double and integer mode -
577 ;; what do pdp library routines do to fpu mode ?
579 (define_insn "floatsidf2"
580   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
581         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
582   "TARGET_FPU"
583   "* if (which_alternative ==0)
584      {
585        rtx latehalf[2];
587        latehalf[0] = NULL; 
588        latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
589        output_asm_insn(\"mov %1, -(sp)\", latehalf);
590        output_asm_insn(\"mov %1, -(sp)\", operands);
591        
592        output_asm_insn(\"setl\", operands);
593        output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
594        output_asm_insn(\"seti\", operands);
595        return \"\";
596      }
597      else if (which_alternative == 1)
598        return \"setl\;{ldcld|movif} %1, %0\;seti\";
599      else 
600        return \"setl\;{ldcld|movif} %1, %0\;seti\";
601   "
602   [(set_attr "length" "10,6,8")])
604 (define_insn "floathidf2"
605   [(set (match_operand:DF 0 "register_operand" "=a,a")
606         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
607   "TARGET_FPU"
608   "{ldcid|movif} %1, %0"
609   [(set_attr "length" "2,4")])
610         
611 ;; cut float to int
612 (define_insn "fix_truncdfsi2"
613   [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
614         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
615   "TARGET_FPU"
616   "* if (which_alternative ==0)
617      {
618        output_asm_insn(\"setl\", operands);
619        output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
620        output_asm_insn(\"seti\", operands);
621        output_asm_insn(\"mov (sp)+, %0\", operands);
622        operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
623        output_asm_insn(\"mov (sp)+, %0\", operands);
624        return \"\";
625      }
626      else if (which_alternative == 1)
627        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
628      else 
629        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
630   "
631   [(set_attr "length" "10,6,8")])
633 (define_insn "fix_truncdfhi2"
634   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
635         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
636   "TARGET_FPU"
637   "{stcdi|movfi} %1, %0"
638   [(set_attr "length" "2,4")])
641 ;;- arithmetic instructions
642 ;;- add instructions
644 (define_insn "adddf3"
645   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
646         (plus:DF (match_operand:DF 1 "register_operand" "%0,0,0")
647                  (match_operand:DF 2 "general_operand" "fR,Q,F")))]
648   "TARGET_FPU"
649   "{addd|addf} %2, %0"
650   [(set_attr "length" "2,4,10")])
652 (define_insn "addsi3"
653   [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
654         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
655                  (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
656   ""
657   "*
658 { /* Here we trust that operands don't overlap 
660      or is lateoperands the low word?? - looks like it! */
662   rtx lateoperands[3];
663   
664   lateoperands[0] = operands[0];
666   if (REG_P (operands[0]))
667     operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
668   else
669     operands[0] = adjust_address (operands[0], HImode, 2);
670   
671   if (! CONSTANT_P(operands[2]))
672   {
673     lateoperands[2] = operands[2];
675     if (REG_P (operands[2]))
676       operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
677     else
678       operands[2] = adjust_address (operands[2], HImode, 2);
680     output_asm_insn (\"add %2, %0\", operands);
681     output_asm_insn (\"adc %0\", lateoperands);
682     output_asm_insn (\"add %2, %0\", lateoperands);
683     return \"\";
684   }
686   lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
687   operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
688   
689   if (INTVAL(operands[2]))
690   { 
691     output_asm_insn (\"add %2, %0\", operands);
692     output_asm_insn (\"adc %0\", lateoperands);
693   }
695   if (INTVAL(lateoperands[2]))
696     output_asm_insn (\"add %2, %0\", lateoperands);
698   return \"\";
700   [(set_attr "length" "6,10,12,16,6,2,10,10,6,16")])
702 (define_insn "addhi3"
703   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
704         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
705                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
706   ""
707   "*
709   if (GET_CODE (operands[2]) == CONST_INT)
710     {
711       if (INTVAL(operands[2]) == 1)
712         return \"inc %0\";
713       else if (INTVAL(operands[2]) == -1)
714         return \"dec %0\";
715     }
717   return \"add %2, %0\";
719   [(set_attr "length" "2,4,4,6")])
721 (define_insn "addqi3"
722   [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
723         (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
724                  (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
725   ""
726   "*
728   if (GET_CODE (operands[2]) == CONST_INT)
729     {
730       if (INTVAL(operands[2]) == 1)
731         return \"incb %0\";
732       else if (INTVAL(operands[2]) == -1)
733         return \"decb %0\";
734     }
736   return \"add %2, %0\";
738   [(set_attr "length" "2,4,4,6")])
741 ;;- subtract instructions
742 ;; we don't have to care for constant second 
743 ;; args, since they are canonical plus:xx now!
744 ;; also for minus:DF ??
746 (define_insn "subdf3"
747   [(set (match_operand:DF 0 "register_operand" "=a,a")
748         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
749                   (match_operand:DF 2 "general_operand" "fR,Q")))]
750   "TARGET_FPU"
751   "{subd|subf} %2, %0"
752   [(set_attr "length" "2,4")])
754 (define_insn "subsi3"
755   [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
756         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
757                   (match_operand:SI 2 "general_operand" "r,o,r,o")))]
758   ""
759   "*
760 { /* Here we trust that operands don't overlap 
762      or is lateoperands the low word?? - looks like it! */
764   rtx lateoperands[3];
765   
766   lateoperands[0] = operands[0];
768   if (REG_P (operands[0]))
769     operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
770   else
771     operands[0] = adjust_address (operands[0], HImode, 2);
772   
773   lateoperands[2] = operands[2];
775   if (REG_P (operands[2]))
776     operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
777   else
778     operands[2] = adjust_address (operands[2], HImode, 2);
780   output_asm_insn (\"sub %2, %0\", operands);
781   output_asm_insn (\"sbc %0\", lateoperands);
782   output_asm_insn (\"sub %2, %0\", lateoperands);
783   return \"\";
785 ;; offsettable memory addresses always are expensive!!!
786   [(set_attr "length" "6,10,12,16")])
788 (define_insn "subhi3"
789   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
790         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
791                   (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
792   ""
793   "*
795   gcc_assert (GET_CODE (operands[2]) != CONST_INT);
797   return \"sub %2, %0\";
799   [(set_attr "length" "2,4,4,6")])
801 (define_insn "subqi3"
802   [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
803         (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
804                   (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
805   ""
806   "*
808   gcc_assert (GET_CODE (operands[2]) != CONST_INT);
810   return \"sub %2, %0\";
812   [(set_attr "length" "2,4,4,6")])
814 ;;;;- and instructions
815 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
817 (define_expand "and<mode>3"
818   [(set (match_operand:PDPint 0 "general_operand" "")
819         (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
820                    (match_operand:PDPint 2 "general_operand" "")))]
821   ""
822   "
824   rtx op1 = operands[1];
826   /* If there is a constant argument, complement that one.
827      Similarly, if one of the inputs is the same as the output,
828      complement the other input.  */
829   if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
830       rtx_equal_p (operands[0], operands[1]))
831     {
832       operands[1] = operands[2];
833       operands[2] = op1;
834       op1 = operands[1];
835     }
837   if (CONST_INT_P (op1))
838     operands[1] = GEN_INT (~INTVAL (op1));
839   else
840     operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
843 (define_insn "*and<mode>"
844   [(set (match_operand:PDPint 0 "general_operand" "=rR,rR,Q,Q")
845         (and:PDPint
846              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
847              (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
848   ""
849   "bic<PDPint:isfx> %1, %0"
850   [(set_attr "length" "2,4,4,6")])
852 ;;- Bit set (inclusive or) instructions
853 (define_insn "iorsi3"
854   [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
855         (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
856                   (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
857   ""
858   "*
859 { /* Here we trust that operands don't overlap 
861      or is lateoperands the low word?? - looks like it! */
863   rtx lateoperands[3];
864   
865   lateoperands[0] = operands[0];
867   if (REG_P (operands[0]))
868     operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
869   else
870     operands[0] = adjust_address (operands[0], HImode, 2);
871   
872   if (! CONSTANT_P(operands[2]))
873     {
874       lateoperands[2] = operands[2];
876       if (REG_P (operands[2]))
877         operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
878       else
879         operands[2] = adjust_address (operands[2], HImode, 2);
881       output_asm_insn (\"bis %2, %0\", operands);
882       output_asm_insn (\"bis %2, %0\", lateoperands);
883       return \"\";
884     }
886   lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
887   operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
888   
889   /* these have different lengths, so we should have 
890      different constraints! */
891   if (INTVAL(operands[2]))
892     output_asm_insn (\"bis %2, %0\", operands);
894   if (INTVAL(lateoperands[2]))
895     output_asm_insn (\"bis %2, %0\", lateoperands);
897   return \"\";
899   [(set_attr "length" "4,8,8,12,4,4,8,6,6,12")])
901 (define_insn "iorhi3"
902   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
903         (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
904                 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
905   ""
906   "bis %2, %0"
907   [(set_attr "length" "2,4,4,6")])
909 (define_insn "iorqi3"
910   [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
911         (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
912                 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
913   ""
914   "bisb %2, %0")
916 ;;- xor instructions
917 (define_insn "xorsi3"
918   [(set (match_operand:SI 0 "register_operand" "=r")
919         (xor:SI (match_operand:SI 1 "register_operand" "%0")
920                 (match_operand:SI 2 "register_operand" "r")))]
921   "TARGET_40_PLUS"
922   "*
923 { /* Here we trust that operands don't overlap */
925   rtx lateoperands[3];
927   lateoperands[0] = operands[0];
928   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
930   if (REG_P(operands[2]))
931     {
932       lateoperands[2] = operands[2];
933       operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
935       output_asm_insn (\"xor %2, %0\", operands);
936       output_asm_insn (\"xor %2, %0\", lateoperands);
938       return \"\";
939     }
942   [(set_attr "length" "4")])
944 (define_insn "xorhi3"
945   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
946         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
947                 (match_operand:HI 2 "register_operand" "r,r")))]
948   "TARGET_40_PLUS"
949   "xor %2, %0"
950   [(set_attr "length" "2,4")])
952 ;;- one complement instructions
954 (define_insn "one_cmplhi2"
955   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
956         (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
957   ""
958   "com %0"
959   [(set_attr "length" "2,4")])
961 (define_insn "one_cmplqi2"
962   [(set (match_operand:QI 0 "general_operand" "=rR,rR")
963         (not:QI (match_operand:QI 1 "general_operand" "0,g")))]
964   ""
965   "@
966   comb %0
967   movb %1, %0\; comb %0"
968   [(set_attr "length" "2,4")])
970 ;;- arithmetic shift instructions
971 (define_insn "ashlsi3"
972   [(set (match_operand:SI 0 "register_operand" "=r,r")
973         (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
974                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
975   "TARGET_40_PLUS"
976   "ashc %2,%0"
977   [(set_attr "length" "2,4")])
979 ;; Arithmetic right shift on the pdp works by negating the shift count.
980 (define_expand "ashrsi3"
981   [(set (match_operand:SI 0 "register_operand" "=r")
982         (ashift:SI (match_operand:SI 1 "register_operand" "0")
983                    (match_operand:HI 2 "general_operand" "g")))]
984   ""
985   "
987   operands[2] = negate_rtx (HImode, operands[2]);
990 ;; define asl aslb asr asrb - ashc missing!
992 ;; asl 
993 (define_insn "" 
994   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
995         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
996                    (const_int 1)))]
997   ""
998   "asl %0"
999   [(set_attr "length" "2,4")])
1001 ;; and another possibility for asr is << -1
1002 ;; might cause problems since -1 can also be encoded as 65535!
1003 ;; not in gcc2 ??? 
1005 ;; asr
1006 (define_insn "" 
1007   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1008         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1009                    (const_int -1)))]
1010   ""
1011   "asr %0"
1012   [(set_attr "length" "2,4")])
1014 ;; lsr
1015 (define_insn "" 
1016   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1017         (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1018                    (const_int 1)))]
1019   ""
1020   "clc\;ror %0"
1021   [(set_attr "length" "2,4")])
1023 (define_insn "lshrsi3"
1024   [(set (match_operand:SI 0 "register_operand" "=r")
1025         (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1026                    (const_int 1)))]
1027   ""
1030   rtx lateoperands[2];
1032   lateoperands[0] = operands[0];
1033   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1035   lateoperands[1] = operands[1];
1036   operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1038   output_asm_insn (\"clc\", operands);
1039   output_asm_insn (\"ror %0\", lateoperands);
1040   output_asm_insn (\"ror %0\", operands);
1042   return \"\";
1044   [(set_attr "length" "10")])
1046 ;; shift is by arbitrary count is expensive, 
1047 ;; shift by one cheap - so let's do that, if
1048 ;; space doesn't matter
1049 (define_insn "" 
1050   [(set (match_operand:HI 0 "general_operand" "=r")
1051         (ashift:HI (match_operand:HI 1 "general_operand" "0")
1052                    (match_operand:HI 2 "expand_shift_operand" "O")))]
1053   "! optimize_size"
1054   "*
1056   register int i;
1058   for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1059     if (INTVAL(operands[2]) < 0)
1060       output_asm_insn(\"asr %0\", operands);
1061     else
1062       output_asm_insn(\"asl %0\", operands);
1063       
1064   return \"\";
1066 ;; longest is 4
1067   [(set (attr "length") (const_int 8))])
1069 ;; aslb
1070 (define_insn "" 
1071   [(set (match_operand:QI 0 "general_operand" "=r,o")
1072         (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1073                    (match_operand:HI 2 "const_int_operand" "n,n")))]
1074   ""
1075   "*
1076 { /* allowing predec or post_inc is possible, but hairy! */
1077   int i, cnt;
1079   cnt = INTVAL(operands[2]) & 0x0007;
1081   for (i=0 ; i < cnt ; i++)
1082        output_asm_insn(\"aslb %0\", operands);
1084   return \"\";
1086 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1087   [(set_attr_alternative "length" 
1088                          [(const_int 14)
1089                           (const_int 28)])])
1091 ;;; asr 
1092 ;(define_insn "" 
1093 ;  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1094 ;       (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1095 ;                    (const_int 1)))]
1096 ;  ""
1097 ;  "asr %0"
1098 ;  [(set_attr "length" "2,4")])
1100 ;; asrb
1101 (define_insn "" 
1102   [(set (match_operand:QI 0 "general_operand" "=r,o")
1103         (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1104                      (match_operand:HI 2 "const_int_operand" "n,n")))]
1105   ""
1106   "*
1107 { /* allowing predec or post_inc is possible, but hairy! */
1108   int i, cnt;
1110   cnt = INTVAL(operands[2]) & 0x0007;
1112   for (i=0 ; i < cnt ; i++)
1113        output_asm_insn(\"asrb %0\", operands);
1115   return \"\";
1117   [(set_attr_alternative "length" 
1118                          [(const_int 14)
1119                           (const_int 28)])])
1121 ;; the following is invalid - too complex!!! - just say 14 !!!
1122 ;  [(set (attr "length") (plus (and (match_dup 2)
1123 ;                                   (const_int 14))
1124 ;                              (and (match_dup 2)
1125 ;                                   (const_int 14))))])
1129 ;; can we get +-1 in the next pattern? should 
1130 ;; have been caught by previous patterns!
1132 (define_insn "ashlhi3"
1133   [(set (match_operand:HI 0 "register_operand" "=r,r")
1134         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1135                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
1136   "TARGET_40_PLUS"
1137   "*
1139   if (GET_CODE(operands[2]) == CONST_INT)
1140     {
1141       if (INTVAL(operands[2]) == 1)
1142         return \"asl %0\";
1143       else if (INTVAL(operands[2]) == -1)
1144         return \"asr %0\";
1145     }
1147   return \"ash %2,%0\";
1149   [(set_attr "length" "2,4")])
1151 ;; Arithmetic right shift on the pdp works by negating the shift count.
1152 (define_expand "ashrhi3"
1153   [(set (match_operand:HI 0 "register_operand" "=r")
1154         (ashift:HI (match_operand:HI 1 "register_operand" "0")
1155                    (match_operand:HI 2 "general_operand" "g")))]
1156   ""
1157   "
1159   operands[2] = negate_rtx (HImode, operands[2]);
1162 ;;;;- logical shift instructions
1163 ;;(define_insn "lshrsi3"
1164 ;;  [(set (match_operand:HI 0 "register_operand" "=r")
1165 ;;      (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1166 ;;                   (match_operand:HI 2 "general_operand" "rI")))]
1167 ;;  ""
1168 ;;  "srl %0,%2")
1170 ;; absolute 
1172 (define_insn "absdf2"
1173   [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1174         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1175   "TARGET_FPU"
1176   "{absd|absf} %0"
1177   [(set_attr "length" "2,4")])
1179 (define_insn "abshi2"
1180   [(set (match_operand:HI 0 "general_operand" "=r,o")
1181         (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
1182   "TARGET_ABSHI_BUILTIN"
1183   "*
1185   static int count = 0;
1186   char buf[200];
1187         
1188   output_asm_insn(\"tst %0\", operands);
1189   sprintf(buf, \"bge abshi%d\", count);
1190   output_asm_insn(buf, NULL);
1191   output_asm_insn(\"neg %0\", operands);
1192   sprintf(buf, \"\\nabshi%d:\", count++);
1193   output_asm_insn(buf, NULL);
1195   return \"\";
1197   [(set_attr "length" "6,10")])
1200 ;; define expand abshi - is much better !!! - but
1201 ;; will it be optimized into an abshi2 ?
1202 ;; it will leave better code, because the tsthi might be 
1203 ;; optimized away!!
1204 ; -- just a thought - don't have time to check 
1206 ;(define_expand "abshi2"
1207 ;  [(match_operand:HI 0 "general_operand" "")
1208 ;   (match_operand:HI 1 "general_operand" "")]
1209 ;  ""
1210 ;  "
1212 ;  rtx label = gen_label_rtx ();
1214 ;  /* do I need this? */
1215 ;  do_pending_stack_adjust ();
1217 ;  emit_move_insn (operands[0], operands[1]);
1219 ;  emit_insn (gen_tsthi (operands[0]));
1220 ;  emit_insn (gen_bge (label1));
1222 ;  emit_insn (gen_neghi(operands[0], operands[0])
1223 ;  
1224 ;  emit_barrier ();
1226 ;  emit_label (label);
1228 ;  /* allow REG_NOTES to be set on last insn (labels don't have enough
1229 ;     fields, and can't be used for REG_NOTES anyway).  */
1230 ;  emit_use (stack_pointer_rtx);
1231 ;  DONE;
1232 ;}")
1234 ;; negate insns
1236 (define_insn "negdf2"
1237   [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1238         (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1239   "TARGET_FPU"
1240   "{negd|negf} %0"
1241   [(set_attr "length" "2,4")])
1243 (define_insn "negsi2"
1244   [(set (match_operand:SI 0 "register_operand" "=r")
1245         (neg:SI (match_operand:SI 1 "general_operand" "0")))]
1246   ""
1249   rtx lateoperands[2];
1251   lateoperands[0] = operands[0];
1252   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1254   lateoperands[1] = operands[1];
1255   operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1257   output_asm_insn (\"com %0\", operands);
1258   output_asm_insn (\"com %0\", lateoperands);
1259   output_asm_insn (\"inc %0\", operands);
1260   output_asm_insn (\"adc %0\", lateoperands);
1262   return \"\";
1264   [(set_attr "length" "10")])
1266 (define_insn "neghi2"
1267   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1268         (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
1269   ""
1270   "neg %0"
1271   [(set_attr "length" "2,4")])
1273 (define_insn "negqi2"
1274   [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1275         (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
1276   ""
1277   "negb %0"
1278   [(set_attr "length" "2,4")])
1281 ;; Unconditional and other jump instructions
1282 (define_insn "jump"
1283   [(set (pc)
1284         (label_ref (match_operand 0 "" "")))]
1285   ""
1286   "*
1288  if (get_attr_length (insn) == 2)
1289     return \"br %l0\";
1290  return \"jmp %l0\";
1292   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1293                                                       (pc))
1294                                                (const_int MIN_BRANCH))
1295                                            (gt (minus (match_dup 0)
1296                                                       (pc))
1297                                                (const_int MAX_BRANCH)))
1298                                       (const_int 4)
1299                                       (const_int 2)))])
1301 (define_insn ""
1302   [(set (pc)
1303     (label_ref (match_operand 0 "" "")))
1304    (clobber (const_int 1))]
1305   ""
1306   "jmp %l0"
1307   [(set_attr "length" "4")])
1309 (define_insn "tablejump"
1310   [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1311    (use (label_ref (match_operand 1 "" "")))]
1312   ""
1313   "jmp %0"
1314   [(set_attr "length" "2,4")])
1316 ;; indirect jump - let's be conservative!
1317 ;; allow only register_operand, even though we could also 
1318 ;; allow labels etc.
1320 (define_insn "indirect_jump"
1321   [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1322   ""
1323   "jmp (%0)")
1325 ;;- jump to subroutine
1327 (define_insn "call"
1328   [(call (match_operand:HI 0 "general_operand" "rR,Q")
1329          (match_operand:HI 1 "general_operand" "g,g"))
1330 ;;   (use (reg:HI 0)) what was that ???
1331   ]
1332   ;;- Don't use operand 1 for most machines.
1333   ""
1334   "jsr pc, %0"
1335   [(set_attr "length" "2,4")])
1337 ;;- jump to subroutine
1338 (define_insn "call_value"
1339   [(set (match_operand 0 "" "")
1340         (call (match_operand:HI 1 "general_operand" "rR,Q")
1341               (match_operand:HI 2 "general_operand" "g,g")))
1342 ;;   (use (reg:HI 0)) - what was that ????
1343   ]
1344   ;;- Don't use operand 2 for most machines.
1345   ""
1346   "jsr pc, %1"
1347   [(set_attr "length" "2,4")])
1349 ;;- nop instruction
1350 (define_insn "nop"
1351   [(const_int 0)]
1352   ""
1353   "nop")
1356 ;;- multiply 
1358 (define_insn "muldf3"
1359   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1360         (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
1361                  (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1362   "TARGET_FPU"
1363   "{muld|mulf} %2, %0"
1364   [(set_attr "length" "2,4,10")])
1366 ;; 16 bit result multiply:
1367 ;; currently we multiply only into odd registers, so we don't use two 
1368 ;; registers - but this is a bit inefficient at times. If we define 
1369 ;; a register class for each register, then we can specify properly 
1370 ;; which register need which scratch register ....
1372 (define_insn "mulhi3"
1373   [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1374         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1375                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1376   "TARGET_40_PLUS"
1377   "mul %2, %0"
1378   [(set_attr "length" "2,4")])
1380 ;; 32 bit result
1381 (define_expand "mulhisi3"
1382   [(set (match_dup 3)
1383         (match_operand:HI 1 "general_operand" "g,g"))
1384    (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1385         (mult:SI (truncate:HI 
1386                   (match_dup 0))
1387                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1388   "TARGET_40_PLUS"
1389   "operands[3] = gen_lowpart(HImode, operands[1]);")
1391 (define_insn ""
1392   [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1393         (mult:SI (truncate:HI 
1394                   (match_operand:SI 1 "register_operand" "%0,0"))
1395                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1396   "TARGET_40_PLUS"
1397   "mul %2, %0"
1398   [(set_attr "length" "2,4")])
1400 ;(define_insn "mulhisi3"
1401 ;  [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1402 ;       (mult:SI (truncate:HI 
1403 ;                  (match_operand:SI 1 "register_operand" "%0,0"))
1404 ;                (match_operand:HI 2 "general_operand" "rR,Qi")))]
1405 ;  "TARGET_40_PLUS"
1406 ;  "mul %2, %0"
1407 ;  [(set_attr "length" "2,4")])
1409 ;;- divide
1410 (define_insn "divdf3"
1411   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1412         (div:DF (match_operand:DF 1 "register_operand" "0,0,0")
1413                 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1414   "TARGET_FPU"
1415   "{divd|divf} %2, %0"
1416   [(set_attr "length" "2,4,10")])
1418          
1419 (define_expand "divhi3"
1420   [(set (subreg:HI (match_dup 1) 0)
1421         (div:HI (match_operand:SI 1 "general_operand" "0")
1422                 (match_operand:HI 2 "general_operand" "g")))
1423    (set (match_operand:HI 0 "general_operand" "=r")
1424         (subreg:HI (match_dup 1) 0))]
1425   "TARGET_40_PLUS"
1426   "")
1428 (define_insn ""
1429   [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1430         (div:HI (match_operand:SI 1 "general_operand" "0")
1431                 (match_operand:HI 2 "general_operand" "g")))]
1432   "TARGET_40_PLUS"
1433   "div %2,%0"
1434   [(set_attr "length" "4")])
1436 (define_expand "modhi3"
1437   [(set (subreg:HI (match_dup 1) 2)
1438         (mod:HI (match_operand:SI 1 "general_operand" "0")
1439                 (match_operand:HI 2 "general_operand" "g")))
1440    (set (match_operand:HI 0 "general_operand" "=r")
1441         (subreg:HI (match_dup 1) 2))]
1442   "TARGET_40_PLUS"
1443   "")
1445 (define_insn ""
1446   [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 2)
1447         (mod:HI (match_operand:SI 1 "general_operand" "0")
1448                 (match_operand:HI 2 "general_operand" "g")))]
1449   "TARGET_40_PLUS"
1450   "div %2,%0"
1451   [(set_attr "length" "4")])
1453 ;(define_expand "divmodhi4"
1454 ;  [(parallel [(set (subreg:HI (match_dup 1) 0)
1455 ;                  (div:HI (match_operand:SI 1 "general_operand" "0")
1456 ;                          (match_operand:HI 2 "general_operand" "g")))
1457 ;              (set (subreg:HI (match_dup 1) 2)
1458 ;                  (mod:HI (match_dup 1)
1459 ;                          (match_dup 2)))])
1460 ;   (set (match_operand:HI 3 "general_operand" "=r")
1461 ;        (subreg:HI (match_dup 1) 2))
1462 ;   (set (match_operand:HI 0 "general_operand" "=r")
1463 ;        (subreg:HI (match_dup 1) 0))]
1464 ;  "TARGET_40_PLUS"
1465 ;  "")
1467 ;(define_insn ""
1468 ;  [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1469 ;                  (div:HI (match_operand:SI 1 "general_operand" "0")
1470 ;                          (match_operand:HI 2 "general_operand" "g")))
1471 ;   (set (subreg:HI (match_dup 0) 2)
1472 ;                  (mod:HI (match_dup 1)
1473 ;                          (match_dup 2)))]
1474 ;  "TARGET_40_PLUS"
1475 ;  "div %2, %0")
1477    
1478 ;; is rotate doing the right thing to be included here ????