OSDN Git Service

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