Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / config / pdp11 / pdp11.md
blob52d3937a39c0a7bb6ec1103c27ea23d0ddbc3313
1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2004
3 ;; 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 2, 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 COPYING.  If not, write to
20 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
21 ;; Boston, MA 02111-1307, USA.
24 ;; HI is 16 bit
25 ;; QI is 8 bit 
27 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
29 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
30 ;;- updates for most instructions.
32 ;;- Operand classes for the register allocator:
34 ;; Compare instructions.
36 ;; currently we only support df floats, which saves us quite some
37 ;; hassle switching the FP mode! 
38 ;; we assume that CPU is always in long float mode, and 
39 ;; 16 bit integer mode - currently, the prologue for main does this,
40 ;; but maybe we should just set up a NEW crt0 properly, 
41 ;; -- and what about signal handling code?
42 ;; (we don't even let sf floats in the register file, so
43 ;; we only should have to worry about truncating and widening 
44 ;; when going to memory)
46 ;; abort() call by g++ - must define libfunc for cmp_optab
47 ;; and ucmp_optab for mode SImode, because we don't have that!!!
48 ;; - yet since no libfunc is there, we abort ()
50 ;; The only thing that remains to be done then is output 
51 ;; the floats in a way the assembler can handle it (and 
52 ;; if you're really into it, use a PDP11 float emulation
53 ;; library to do floating point constant folding - but 
54 ;; I guess you'll get reasonable results even when not
55 ;; doing this)
56 ;; the last thing to do is fix the UPDATE_CC macro to check
57 ;; for floating point condition codes, and set cc_status
58 ;; properly, also setting the CC_IN_FCCR flag. 
60 ;; define attributes
61 ;; currently type is only fpu or arith or unknown, maybe branch later ?
62 ;; default is arith
63 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
65 ;; length default is 1 word each
66 (define_attr "length" "" (const_int 1))
68 ;; a user's asm statement
69 (define_asm_attributes
70   [(set_attr "type" "unknown")
71 ; all bets are off how long it is - make it 256, forces long jumps 
72 ; whenever jumping around it !!!
73    (set_attr "length" "256")])
75 ;; define function units
77 ;; arithmetic - values here immediately when next insn issued
78 ;; or does it mean the number of cycles after this insn was issued?
79 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
81 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
82 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
84 ;; compare
85 (define_insn "cmpdf"
86   [(set (cc0)
87         (compare (match_operand:DF 0 "general_operand" "fR,Q,F")
88                  (match_operand:DF 1 "register_operand" "a,a,a")))]
89   "TARGET_FPU"
90   "*
92   cc_status.flags = CC_IN_FPU;
93   return \"{cmpd|cmpf} %0, %1\;cfcc\";
95   [(set_attr "length" "2,3,6")])
97 ;; a bit of brain damage, maybe inline later - 
98 ;; problem is - gcc seems to NEED SImode because 
99 ;; of the cmp weirdness - maybe change gcc to handle this?
101 (define_expand "cmpsi"
102   [(set (reg:SI 0)
103         (match_operand:SI 0 "general_operand" "g"))
104    (set (reg:SI 2)
105         (match_operand:SI 1 "general_operand" "g"))
106    (parallel [(set (cc0)
107                    (compare (reg:SI 0)
108                             (reg:SI 2)))
109               (clobber (reg:SI 0))])]
110   "0" ;; disable for test
111   "")
113 ;; check for next insn for branch code - does this still
114 ;; work in gcc 2.* ?
116 (define_insn ""
117   [(set (cc0)
118         (compare (reg:SI 0)
119                  (reg:SI 2)))
120    (clobber (reg:SI 0))]
121   ""
122   "*
124   rtx br_insn = NEXT_INSN (insn);
125   RTX_CODE br_code;
127   if (GET_CODE (br_insn) != JUMP_INSN)
128     abort();
129   br_code =  GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
130   
131   switch(br_code)
132   {
133     case GEU:
134     case LTU:
135     case GTU:
136     case LEU:
137       
138       return \"jsr pc, ___ucmpsi\;cmp $1,r0\";
140     case GE:
141     case LT:
142     case GT:
143     case LE:
144     case EQ:
145     case NE:
147       return \"jsr pc, ___cmpsi\;tst r0\";
149     default:
151       abort();
152   }
154   [(set_attr "length" "4")])
157 (define_insn "cmphi"
158   [(set (cc0)
159         (compare (match_operand:HI 0 "general_operand" "rR,rR,Qi,Qi")
160                  (match_operand:HI 1 "general_operand" "rR,Qi,rR,Qi")))]
161   ""
162   "cmp %0,%1"
163   [(set_attr "length" "1,2,2,3")])
165 (define_insn "cmpqi"
166   [(set (cc0)
167         (compare (match_operand:QI 0 "general_operand" "rR,rR,Qi,Qi")
168                  (match_operand:QI 1 "general_operand" "rR,Qi,rR,Qi")))]
169   ""
170   "cmpb %0,%1"
171   [(set_attr "length" "1,2,2,3")])
172                            
174 ;; We have to have this because cse can optimize the previous pattern
175 ;; into this one.
177 (define_insn "tstdf"
178   [(set (cc0)
179         (match_operand:DF 0 "general_operand" "fR,Q"))]
180   "TARGET_FPU"
181   "*
183   cc_status.flags = CC_IN_FPU;
184   return \"{tstd|tstf} %0\;cfcc\";
186   [(set_attr "length" "2,3")])
189 (define_expand "tstsi"
190   [(set (reg:SI 0)
191         (match_operand:SI 0 "general_operand" "g"))
192    (parallel [(set (cc0)
193                    (reg:SI 0))
194               (clobber (reg:SI 0))])]
195   "0" ;; disable for test
196   "")
198 (define_insn ""
199   [(set (cc0)
200         (reg:SI 0))
201    (clobber (reg:SI 0))]
202   ""
203   "jsr pc, ___tstsi\;tst r0"
204   [(set_attr "length" "3")])
207 (define_insn "tsthi"
208   [(set (cc0)
209         (match_operand:HI 0 "general_operand" "rR,Q"))]
210   ""
211   "tst %0"
212   [(set_attr "length" "1,2")])
214 (define_insn "tstqi"
215   [(set (cc0)
216         (match_operand:QI 0 "general_operand" "rR,Q"))]
217   ""
218   "tstb %0"
219   [(set_attr "length" "1,2")])
221 ;; sob instruction - we need an assembler which can make this instruction
222 ;; valid under _all_ circumstances!
224 (define_insn ""
225   [(set (pc)
226         (if_then_else
227          (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
228                       (const_int -1))
229              (const_int 0))
230          (label_ref (match_operand 1 "" ""))
231          (pc)))
232    (set (match_dup 0)
233         (plus:HI (match_dup 0)
234                  (const_int -1)))]
235   "TARGET_40_PLUS"
236   "*
238  static int labelcount = 0;
239  static char buf[1000];
241  if (get_attr_length (insn) == 1)
242     return \"sob %0, %l1\";
244  /* emulate sob */
245  output_asm_insn (\"dec %0\", operands);
247  sprintf (buf, \"bge LONG_SOB%d\", labelcount);
248  output_asm_insn (buf, NULL);
250  output_asm_insn (\"jmp %l1\", operands);
252  sprintf (buf, \"LONG_SOB%d:\", labelcount++);
253  output_asm_insn (buf, NULL);
255  return \"\";
257   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
258                                                        (pc))
259                                                 (const_int -256))
260                                            (ge (minus (match_dup 0)
261                                                        (pc))
262                                                 (const_int 0)))
263                                       (const_int 4)
264                                       (const_int 1)))])
266 ;; These control RTL generation for conditional jump insns
267 ;; and match them for register allocation.
269 ;; problem with too short jump distance! we need an assembler which can 
270 ;; make this valid for all jump distances!
271 ;; e.g. gas!
273 ;; these must be changed to check for CC_IN_FCCR if float is to be 
274 ;; enabled
276 (define_insn "beq"
277   [(set (pc)
278         (if_then_else (eq (cc0)
279                           (const_int 0))
280                       (label_ref (match_operand 0 "" ""))
281                       (pc)))]
282   ""
283   "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
284   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
285                                                       (pc))
286                                                (const_int -128))
287                                            (ge (minus (match_dup 0)
288                                                       (pc))
289                                                (const_int 128)))
290                                       (const_int 3)
291                                       (const_int 1)))])
294 (define_insn "bne"
295   [(set (pc)
296         (if_then_else (ne (cc0)
297                           (const_int 0))
298                       (label_ref (match_operand 0 "" ""))
299                       (pc)))]
300   ""
301   "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
302   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
303                                                       (pc))
304                                                (const_int -128))
305                                            (ge (minus (match_dup 0)
306                                                       (pc))
307                                                (const_int 128)))
308                                       (const_int 3)
309                                       (const_int 1)))])
311 (define_insn "bgt"
312   [(set (pc)
313         (if_then_else (gt (cc0)
314                           (const_int 0))
315                       (label_ref (match_operand 0 "" ""))
316                       (pc)))]
317   ""
318   "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
319   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
320                                                       (pc))
321                                                (const_int -128))
322                                            (ge (minus (match_dup 0)
323                                                       (pc))
324                                                (const_int 128)))
325                                       (const_int 3)
326                                       (const_int 1)))])
328 (define_insn "bgtu"
329   [(set (pc)
330         (if_then_else (gtu (cc0)
331                            (const_int 0))
332                       (label_ref (match_operand 0 "" ""))
333                       (pc)))]
334   ""
335   "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
336   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
337                                                       (pc))
338                                                (const_int -128))
339                                            (ge (minus (match_dup 0)
340                                                       (pc))
341                                                (const_int 128)))
342                                       (const_int 3)
343                                       (const_int 1)))])
345 (define_insn "blt"
346   [(set (pc)
347         (if_then_else (lt (cc0)
348                           (const_int 0))
349                       (label_ref (match_operand 0 "" ""))
350                       (pc)))]
351   ""
352   "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
353   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
354                                                       (pc))
355                                                (const_int -128))
356                                            (ge (minus (match_dup 0)
357                                                       (pc))
358                                                (const_int 128)))
359                                       (const_int 3)
360                                       (const_int 1)))])
363 (define_insn "bltu"
364   [(set (pc)
365         (if_then_else (ltu (cc0)
366                            (const_int 0))
367                       (label_ref (match_operand 0 "" ""))
368                       (pc)))]
369   ""
370   "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
371   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
372                                                       (pc))
373                                                (const_int -128))
374                                            (ge (minus (match_dup 0)
375                                                       (pc))
376                                                (const_int 128)))
377                                       (const_int 3)
378                                       (const_int 1)))])
380 (define_insn "bge"
381   [(set (pc)
382         (if_then_else (ge (cc0)
383                           (const_int 0))
384                       (label_ref (match_operand 0 "" ""))
385                       (pc)))]
386   ""
387   "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
388   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
389                                                       (pc))
390                                                (const_int -128))
391                                            (ge (minus (match_dup 0)
392                                                       (pc))
393                                                (const_int 128)))
394                                       (const_int 3)
395                                       (const_int 1)))])
397 (define_insn "bgeu"
398   [(set (pc)
399         (if_then_else (geu (cc0)
400                            (const_int 0))
401                       (label_ref (match_operand 0 "" ""))
402                       (pc)))]
403   ""
404   "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
405   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
406                                                       (pc))
407                                                (const_int -128))
408                                            (ge (minus (match_dup 0)
409                                                       (pc))
410                                                (const_int 128)))
411                                       (const_int 3)
412                                       (const_int 1)))])
414 (define_insn "ble"
415   [(set (pc)
416         (if_then_else (le (cc0)
417                           (const_int 0))
418                       (label_ref (match_operand 0 "" ""))
419                       (pc)))]
420   ""
421   "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
422   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
423                                                       (pc))
424                                                (const_int -128))
425                                            (ge (minus (match_dup 0)
426                                                       (pc))
427                                                (const_int 128)))
428                                       (const_int 3)
429                                       (const_int 1)))])
431 (define_insn "bleu"
432   [(set (pc)
433         (if_then_else (leu (cc0)
434                            (const_int 0))
435                       (label_ref (match_operand 0 "" ""))
436                       (pc)))]
437   ""
438   "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
439   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
440                                                       (pc))
441                                                (const_int -128))
442                                            (ge (minus (match_dup 0)
443                                                       (pc))
444                                                (const_int 128)))
445                                       (const_int 3)
446                                       (const_int 1)))])
449 ;; These match inverted jump insns for register allocation.
451 (define_insn ""
452   [(set (pc)
453         (if_then_else (eq (cc0)
454                           (const_int 0))
455                       (pc)
456                       (label_ref (match_operand 0 "" ""))))]
457   ""
458   "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
459   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
460                                                       (pc))
461                                                (const_int -128))
462                                            (ge (minus (match_dup 0)
463                                                       (pc))
464                                                (const_int 128)))
465                                       (const_int 3)
466                                       (const_int 1)))])
468 (define_insn ""
469   [(set (pc)
470         (if_then_else (ne (cc0)
471                           (const_int 0))
472                       (pc)
473                       (label_ref (match_operand 0 "" ""))))]
474   ""
475   "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
476   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
477                                                       (pc))
478                                                (const_int -128))
479                                            (ge (minus (match_dup 0)
480                                                       (pc))
481                                                (const_int 128)))
482                                       (const_int 3)
483                                       (const_int 1)))])
485 (define_insn ""
486   [(set (pc)
487         (if_then_else (gt (cc0)
488                           (const_int 0))
489                       (pc)
490                       (label_ref (match_operand 0 "" ""))))]
491   ""
492   "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
493   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
494                                                       (pc))
495                                                (const_int -128))
496                                            (ge (minus (match_dup 0)
497                                                       (pc))
498                                                (const_int 128)))
499                                       (const_int 3)
500                                       (const_int 1)))])
502 (define_insn ""
503   [(set (pc)
504         (if_then_else (gtu (cc0)
505                            (const_int 0))
506                       (pc)
507                       (label_ref (match_operand 0 "" ""))))]
508   ""
509   "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
510   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
511                                                       (pc))
512                                                (const_int -128))
513                                            (ge (minus (match_dup 0)
514                                                       (pc))
515                                                (const_int 128)))
516                                       (const_int 3)
517                                       (const_int 1)))])
519 (define_insn ""
520   [(set (pc)
521         (if_then_else (lt (cc0)
522                           (const_int 0))
523                       (pc)
524                       (label_ref (match_operand 0 "" ""))))]
525   ""
526   "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
527   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
528                                                       (pc))
529                                                (const_int -128))
530                                            (ge (minus (match_dup 0)
531                                                       (pc))
532                                                (const_int 128)))
533                                       (const_int 3)
534                                       (const_int 1)))])
536 (define_insn ""
537   [(set (pc)
538         (if_then_else (ltu (cc0)
539                            (const_int 0))
540                       (pc)
541                       (label_ref (match_operand 0 "" ""))))]
542   ""
543   "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
544   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
545                                                       (pc))
546                                                (const_int -128))
547                                            (ge (minus (match_dup 0)
548                                                       (pc))
549                                                (const_int 128)))
550                                       (const_int 3)
551                                       (const_int 1)))])
553 (define_insn ""
554   [(set (pc)
555         (if_then_else (ge (cc0)
556                           (const_int 0))
557                       (pc)
558                       (label_ref (match_operand 0 "" ""))))]
559   ""  
560   "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
561   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
562                                                       (pc))
563                                                (const_int -128))
564                                            (ge (minus (match_dup 0)
565                                                       (pc))
566                                                (const_int 128)))
567                                       (const_int 3)
568                                       (const_int 1)))])
570 (define_insn ""
571   [(set (pc)
572         (if_then_else (geu (cc0)
573                            (const_int 0))
574                       (pc)
575                       (label_ref (match_operand 0 "" ""))))]
576   ""
577   "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
578   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
579                                                       (pc))
580                                                (const_int -128))
581                                            (ge (minus (match_dup 0)
582                                                       (pc))
583                                                (const_int 128)))
584                                       (const_int 3)
585                                       (const_int 1)))])
587 (define_insn ""
588   [(set (pc)
589         (if_then_else (le (cc0)
590                           (const_int 0))
591                       (pc)
592                       (label_ref (match_operand 0 "" ""))))]
593   ""
594   "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
595   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
596                                                       (pc))
597                                                (const_int -128))
598                                            (ge (minus (match_dup 0)
599                                                       (pc))
600                                                (const_int 128)))
601                                       (const_int 3)
602                                       (const_int 1)))])
604 (define_insn ""
605   [(set (pc)
606         (if_then_else (leu (cc0)
607                            (const_int 0))
608                       (pc)
609                       (label_ref (match_operand 0 "" ""))))]
610   ""
611   "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
612   [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
613                                                       (pc))
614                                                (const_int -128))
615                                            (ge (minus (match_dup 0)
616                                                       (pc))
617                                                (const_int 128)))
618                                       (const_int 3)
619                                       (const_int 1)))])
621 ;; Move instructions
623 (define_insn "movdi"
624   [(set (match_operand:DI 0 "general_operand" "=g,rm,o")
625         (match_operand:DI 1 "general_operand" "m,r,a"))]
626   ""
627   "* return output_move_quad (operands);"
628 ;; what's the mose expensive code - say twice movsi = 16
629   [(set_attr "length" "16,16,16")])
631 (define_insn "movsi"
632   [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
633         (match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
634   ""
635   "* return output_move_double (operands);"
636 ;; what's the most expensive code ? - I think 8!
637 ;; we could split it up and make several sub-cases...
638   [(set_attr "length" "2,3,4,8,8")])
640 (define_insn "movhi"
641   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
642         (match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
643   ""
644   "*
646   if (operands[1] == const0_rtx)
647     return \"clr %0\";
649   return \"mov %1, %0\";
651   [(set_attr "length" "1,2,2,3")])
653 (define_insn "movqi"
654   [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
655         (match_operand:QI 1 "general_operand" "g"))]
656   ""
657   "*
659   if (operands[1] == const0_rtx)
660     return \"clrb %0\";
662   return \"movb %1, %0\";
664   [(set_attr "length" "1")])
666 ;; do we have to supply all these moves? e.g. to 
667 ;; NO_LOAD_FPU_REGs ? 
668 (define_insn "movdf"
669   [(set (match_operand:DF 0 "general_operand" "=a,fR,a,Q,m")
670         (match_operand:DF 1 "general_operand" "fFR,a,Q,a,m"))]
671   ""
672   "* if (which_alternative ==0)
673        return \"ldd %1, %0\";
674      else if (which_alternative == 1)
675        return \"std %1, %0\";
676      else 
677        return output_move_quad (operands); "
678 ;; just a guess..
679   [(set_attr "length" "1,1,5,5,16")])
681 (define_insn "movsf"
682   [(set (match_operand:SF 0 "general_operand" "=g,r,g")
683         (match_operand:SF 1 "general_operand" "r,rmF,g"))]
684   "TARGET_FPU"
685   "* return output_move_double (operands);"
686   [(set_attr "length" "8,8,8")])
688 ;; maybe fiddle a bit with move_ratio, then 
689 ;; let constraints only accept a register ...
691 (define_expand "movmemhi"
692   [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
693                    (match_operand:BLK 1 "general_operand" "g,g"))
694               (use (match_operand:HI 2 "arith_operand" "n,&mr"))
695               (use (match_operand:HI 3 "immediate_operand" "i,i"))
696               (clobber (match_scratch:HI 4 "=&r,X"))
697               (clobber (match_dup 5))
698               (clobber (match_dup 6))
699               (clobber (match_dup 2))])]
700   "(TARGET_BCOPY_BUILTIN)"
701   "
703   operands[0]
704     = replace_equiv_address (operands[0],
705                              copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
706   operands[1]
707     = replace_equiv_address (operands[1],
708                              copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
710   operands[5] = XEXP (operands[0], 0);
711   operands[6] = XEXP (operands[1], 0);
715 (define_insn "" ; "movmemhi"
716   [(set (mem:BLK (match_operand:HI 0 "general_operand" "=r,r"))
717         (mem:BLK (match_operand:HI 1 "general_operand" "r,r")))
718    (use (match_operand:HI 2 "arith_operand" "n,&r"))
719    (use (match_operand:HI 3 "immediate_operand" "i,i"))
720    (clobber (match_scratch:HI 4 "=&r,X"))
721    (clobber (match_dup 0))
722    (clobber (match_dup 1))
723    (clobber (match_dup 2))]
724   "(TARGET_BCOPY_BUILTIN)"
725   "* return output_block_move (operands);"
726 ;;; just a guess
727   [(set_attr "length" "40")])
728    
731 ;;- truncation instructions
733 (define_insn  "truncdfsf2"
734   [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
735         (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
736   "TARGET_FPU"
737   "* if (which_alternative ==0)
738      {
739        output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
740        output_asm_insn(\"mov (sp)+, %0\", operands);
741        operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
742        output_asm_insn(\"mov (sp)+, %0\", operands);
743        return \"\";
744      }
745      else if (which_alternative == 1)
746        return \"{stcdf|movfo} %1, %0\";
747      else 
748        return \"{stcdf|movfo} %1, %0\";
749   "
750   [(set_attr "length" "3,1,2")])
753 (define_expand "truncsihi2"
754   [(set (match_operand:HI 0 "general_operand" "=g")
755         (subreg:HI 
756           (match_operand:SI 1 "general_operand" "or")
757           0))]
758   ""
759   "")
762 ;;- zero extension instructions
764 (define_insn "zero_extendqihi2"
765   [(set (match_operand:HI 0 "general_operand" "=r")
766         (zero_extend:HI (match_operand:QI 1 "general_operand" "0")))]
767   ""
768   "bic $0177400, %0"
769   [(set_attr "length" "2")])
770                          
771 (define_expand "zero_extendhisi2"
772   [(set (subreg:HI 
773           (match_dup 0)
774           2)
775         (match_operand:HI 1 "register_operand" "r"))
776    (set (subreg:HI 
777           (match_operand:SI 0 "register_operand" "=r")
778           0)
779         (const_int 0))]
780   ""
781   "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
784 ;;- sign extension instructions
786 (define_insn "extendsfdf2"
787   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
788         (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
789   "TARGET_FPU"
790   "@
791    mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
792    {ldcfd|movof} %1, %0
793    {ldcfd|movof} %1, %0"
794   [(set_attr "length" "2,1,2")])
796 ;; does movb sign extend in register-to-register move?
797 (define_insn "extendqihi2"
798   [(set (match_operand:HI 0 "register_operand" "=r,r")
799         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
800   ""
801   "movb %1, %0"
802   [(set_attr "length" "1,2")])
804 (define_insn "extendqisi2"
805   [(set (match_operand:SI 0 "register_operand" "=r,r")
806         (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
807   "TARGET_40_PLUS"
808   "*
810   rtx latehalf[2];
812   /* make register pair available */
813   latehalf[0] = operands[0];
814   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
816   output_asm_insn(\"movb %1, %0\", operands);
817   output_asm_insn(\"sxt %0\", latehalf);
818     
819   return \"\";
821   [(set_attr "length" "2,3")])
823 ;; maybe we have to use define_expand to say that we have the instruction,
824 ;; unconditionally, and then match dependent on CPU type:
826 (define_expand "extendhisi2"
827   [(set (match_operand:SI 0 "general_operand" "=g")
828         (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
829   ""
830   "")
831   
832 (define_insn "" ; "extendhisi2"
833   [(set (match_operand:SI 0 "general_operand" "=o,<,r")
834         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
835   "TARGET_40_PLUS"
836   "*
838   rtx latehalf[2];
840   /* we don't want to mess with auto increment */
841   
842   switch (which_alternative)
843   {
844     case 0:
846       latehalf[0] = operands[0];
847       operands[0] = adjust_address(operands[0], HImode, 2);
848   
849       output_asm_insn(\"mov %1, %0\", operands);
850       output_asm_insn(\"sxt %0\", latehalf);
852       return \"\";
854     case 1:
856       /* - auto-decrement - right direction ;-) */
857       output_asm_insn(\"mov %1, %0\", operands);
858       output_asm_insn(\"sxt %0\", operands);
860       return \"\";
862     case 2:
864       /* make register pair available */
865       latehalf[0] = operands[0];
866       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
868       output_asm_insn(\"mov %1, %0\", operands);
869       output_asm_insn(\"sxt %0\", latehalf);
871       return \"\";
873     default:
875       abort();
876   }
878   [(set_attr "length" "5,3,3")])
881 (define_insn ""
882   [(set (match_operand:SI 0 "register_operand" "=r")
883         (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
884   "(! TARGET_40_PLUS)"
885   "*
887   static int count = 0;
888   char buf[100];
889   rtx lateoperands[2];
891   lateoperands[0] = operands[0];
892   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
894   output_asm_insn(\"tst %0\", operands);
895   sprintf(buf, \"bge extendhisi%d\", count);
896   output_asm_insn(buf, NULL);
897   output_asm_insn(\"mov -1, %0\", lateoperands);
898   sprintf(buf, \"bne extendhisi%d\", count+1);
899   output_asm_insn(buf, NULL);
900   sprintf(buf, \"\\nextendhisi%d:\", count);
901   output_asm_insn(buf, NULL);
902   output_asm_insn(\"clr %0\", lateoperands);
903   sprintf(buf, \"\\nextendhisi%d:\", count+1);
904   output_asm_insn(buf, NULL);
906   count += 2;
908   return \"\";
910   [(set_attr "length" "6")])
912 ;; make float to int and vice versa 
913 ;; using the cc_status.flag field we could probably cut down
914 ;; on seti and setl
915 ;; assume that we are normally in double and integer mode -
916 ;; what do pdp library routines do to fpu mode ?
918 (define_insn "floatsidf2"
919   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
920         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
921   "TARGET_FPU"
922   "* if (which_alternative ==0)
923      {
924        rtx latehalf[2];
926        latehalf[0] = NULL; 
927        latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
928        output_asm_insn(\"mov %1, -(sp)\", latehalf);
929        output_asm_insn(\"mov %1, -(sp)\", operands);
930        
931        output_asm_insn(\"setl\", operands);
932        output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
933        output_asm_insn(\"seti\", operands);
934        return \"\";
935      }
936      else if (which_alternative == 1)
937        return \"setl\;{ldcld|movif} %1, %0\;seti\";
938      else 
939        return \"setl\;{ldcld|movif} %1, %0\;seti\";
940   "
941   [(set_attr "length" "5,3,4")])
943 (define_insn "floathidf2"
944   [(set (match_operand:DF 0 "register_operand" "=a,a")
945         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
946   "TARGET_FPU"
947   "{ldcid|movif} %1, %0"
948   [(set_attr "length" "1,2")])
949         
950 ;; cut float to int
951 (define_insn "fix_truncdfsi2"
952   [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
953         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
954   "TARGET_FPU"
955   "* if (which_alternative ==0)
956      {
957        output_asm_insn(\"setl\", operands);
958        output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
959        output_asm_insn(\"seti\", operands);
960        output_asm_insn(\"mov (sp)+, %0\", operands);
961        operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
962        output_asm_insn(\"mov (sp)+, %0\", operands);
963        return \"\";
964      }
965      else if (which_alternative == 1)
966        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
967      else 
968        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
969   "
970   [(set_attr "length" "5,3,4")])
972 (define_insn "fix_truncdfhi2"
973   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
974         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
975   "TARGET_FPU"
976   "{stcdi|movfi} %1, %0"
977   [(set_attr "length" "1,2")])
980 ;;- arithmetic instructions
981 ;;- add instructions
983 (define_insn "adddf3"
984   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
985         (plus:DF (match_operand:DF 1 "register_operand" "%0,0,0")
986                  (match_operand:DF 2 "general_operand" "fR,Q,F")))]
987   "TARGET_FPU"
988   "{addd|addf} %2, %0"
989   [(set_attr "length" "1,2,5")])
991 (define_insn "addsi3"
992   [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
993         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
994                  (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
995   ""
996   "*
997 { /* Here we trust that operands don't overlap 
999      or is lateoperands the low word?? - looks like it! */
1001   rtx lateoperands[3];
1002   
1003   lateoperands[0] = operands[0];
1005   if (REG_P (operands[0]))
1006     operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1007   else
1008     operands[0] = adjust_address (operands[0], HImode, 2);
1009   
1010   if (! CONSTANT_P(operands[2]))
1011   {
1012     lateoperands[2] = operands[2];
1014     if (REG_P (operands[2]))
1015       operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1016     else
1017       operands[2] = adjust_address (operands[2], HImode, 2);
1019     output_asm_insn (\"add %2, %0\", operands);
1020     output_asm_insn (\"adc %0\", lateoperands);
1021     output_asm_insn (\"add %2, %0\", lateoperands);
1022     return \"\";
1023   }
1025   lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1026   operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1027   
1028   if (INTVAL(operands[2]))
1029   { 
1030     output_asm_insn (\"add %2, %0\", operands);
1031     output_asm_insn (\"adc %0\", lateoperands);
1032   }
1034   if (INTVAL(lateoperands[2]))
1035     output_asm_insn (\"add %2, %0\", lateoperands);
1037   return \"\";
1039   [(set_attr "length" "3,5,6,8,3,1,5,5,3,8")])
1041 (define_insn "addhi3"
1042   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1043         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1044                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1045   ""
1046   "*
1048   if (GET_CODE (operands[2]) == CONST_INT)
1049     {
1050       if (INTVAL(operands[2]) == 1)
1051         return \"inc %0\";
1052       else if (INTVAL(operands[2]) == -1)
1053         return \"dec %0\";
1054     }
1056   return \"add %2, %0\";
1058   [(set_attr "length" "1,2,2,3")])
1060 (define_insn "addqi3"
1061   [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1062         (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
1063                  (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1064   ""
1065   "*
1067   if (GET_CODE (operands[2]) == CONST_INT)
1068     {
1069       if (INTVAL(operands[2]) == 1)
1070         return \"incb %0\";
1071       else if (INTVAL(operands[2]) == -1)
1072         return \"decb %0\";
1073     }
1075   return \"add %2, %0\";
1077   [(set_attr "length" "1,2,2,3")])
1080 ;;- subtract instructions
1081 ;; we don't have to care for constant second 
1082 ;; args, since they are canonical plus:xx now!
1083 ;; also for minus:DF ??
1085 (define_insn "subdf3"
1086   [(set (match_operand:DF 0 "register_operand" "=a,a")
1087         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1088                   (match_operand:DF 2 "general_operand" "fR,Q")))]
1089   "TARGET_FPU"
1090   "{subd|subf} %2, %0"
1091   [(set_attr "length" "1,2")])
1093 (define_insn "subsi3"
1094   [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
1095         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1096                   (match_operand:SI 2 "general_operand" "r,o,r,o")))]
1097   ""
1098   "*
1099 { /* Here we trust that operands don't overlap 
1101      or is lateoperands the low word?? - looks like it! */
1103   rtx lateoperands[3];
1104   
1105   lateoperands[0] = operands[0];
1107   if (REG_P (operands[0]))
1108     operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1109   else
1110     operands[0] = adjust_address (operands[0], HImode, 2);
1111   
1112   lateoperands[2] = operands[2];
1114   if (REG_P (operands[2]))
1115     operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1116   else
1117     operands[2] = adjust_address (operands[2], HImode, 2);
1119   output_asm_insn (\"sub %2, %0\", operands);
1120   output_asm_insn (\"sbc %0\", lateoperands);
1121   output_asm_insn (\"sub %2, %0\", lateoperands);
1122   return \"\";
1124 ;; offsettable memory addresses always are expensive!!!
1125   [(set_attr "length" "3,5,6,8")])
1127 (define_insn "subhi3"
1128   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1129         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1130                   (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
1131   ""
1132   "*
1134   if (GET_CODE (operands[2]) == CONST_INT)
1135     abort();
1137   return \"sub %2, %0\";
1139   [(set_attr "length" "1,2,2,3")])
1141 (define_insn "subqi3"
1142   [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1143         (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
1144                   (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
1145   ""
1146   "*
1148   if (GET_CODE (operands[2]) == CONST_INT)
1149     abort();
1151   return \"sub %2, %0\";
1153   [(set_attr "length" "1,2,2,3")])
1155 ;;;;- and instructions
1156 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1158 (define_insn "andsi3"
1159   [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
1160         (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
1161                 (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
1162   ""
1163   "*
1164 { /* Here we trust that operands don't overlap 
1166      or is lateoperands the low word?? - looks like it! */
1168   rtx lateoperands[3];
1169   
1170   lateoperands[0] = operands[0];
1172   if (REG_P (operands[0]))
1173     operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1174   else
1175     operands[0] = adjust_address (operands[0], HImode, 2);
1176   
1177   if (! CONSTANT_P(operands[2]))
1178   {
1179     lateoperands[2] = operands[2];
1181     if (REG_P (operands[2]))
1182       operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1183     else
1184       operands[2] = adjust_address (operands[2], HImode, 2);
1186     output_asm_insn (\"bic %2, %0\", operands);
1187     output_asm_insn (\"bic %2, %0\", lateoperands);
1188     return \"\";
1189   }
1191   lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1192   operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1193   
1194   /* these have different lengths, so we should have 
1195      different constraints! */
1196   if (INTVAL(operands[2]))
1197     output_asm_insn (\"bic %2, %0\", operands);
1199   if (INTVAL(lateoperands[2]))
1200     output_asm_insn (\"bic %2, %0\", lateoperands);
1202   return \"\";
1204   [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
1206 (define_insn "andhi3"
1207   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1208         (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1209                 (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
1210   ""
1211   "bic %2, %0"
1212   [(set_attr "length" "1,2,2,3")])
1214 (define_insn "andqi3"
1215   [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1216         (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
1217                 (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
1218   ""
1219   "bicb %2, %0"
1220   [(set_attr "length" "1,2,2,3")])
1222 ;;- Bit set (inclusive or) instructions
1223 (define_insn "iorsi3"
1224   [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
1225         (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
1226                   (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
1227   ""
1228   "*
1229 { /* Here we trust that operands don't overlap 
1231      or is lateoperands the low word?? - looks like it! */
1233   rtx lateoperands[3];
1234   
1235   lateoperands[0] = operands[0];
1237   if (REG_P (operands[0]))
1238     operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1239   else
1240     operands[0] = adjust_address (operands[0], HImode, 2);
1241   
1242   if (! CONSTANT_P(operands[2]))
1243     {
1244       lateoperands[2] = operands[2];
1246       if (REG_P (operands[2]))
1247         operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1248       else
1249         operands[2] = adjust_address (operands[2], HImode, 2);
1251       output_asm_insn (\"bis %2, %0\", operands);
1252       output_asm_insn (\"bis %2, %0\", lateoperands);
1253       return \"\";
1254     }
1256   lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1257   operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1258   
1259   /* these have different lengths, so we should have 
1260      different constraints! */
1261   if (INTVAL(operands[2]))
1262     output_asm_insn (\"bis %2, %0\", operands);
1264   if (INTVAL(lateoperands[2]))
1265     output_asm_insn (\"bis %2, %0\", lateoperands);
1267   return \"\";
1269   [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
1271 (define_insn "iorhi3"
1272   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1273         (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1274                 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
1275   ""
1276   "bis %2, %0"
1277   [(set_attr "length" "1,2,2,3")])
1279 (define_insn "iorqi3"
1280   [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1281         (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
1282                 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
1283   ""
1284   "bisb %2, %0")
1286 ;;- xor instructions
1287 (define_insn "xorsi3"
1288   [(set (match_operand:SI 0 "register_operand" "=r")
1289         (xor:SI (match_operand:SI 1 "register_operand" "%0")
1290                 (match_operand:SI 2 "arith_operand" "r")))]
1291   "TARGET_40_PLUS"
1292   "*
1293 { /* Here we trust that operands don't overlap */
1295   rtx lateoperands[3];
1297   lateoperands[0] = operands[0];
1298   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1300   if (REG_P(operands[2]))
1301     {
1302       lateoperands[2] = operands[2];
1303       operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1305       output_asm_insn (\"xor %2, %0\", operands);
1306       output_asm_insn (\"xor %2, %0\", lateoperands);
1308       return \"\";
1309     }
1312   [(set_attr "length" "2")])
1314 (define_insn "xorhi3"
1315   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1316         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1317                 (match_operand:HI 2 "register_operand" "r,r")))]
1318   "TARGET_40_PLUS"
1319   "xor %2, %0"
1320   [(set_attr "length" "1,2")])
1322 ;;- one complement instructions
1324 (define_insn "one_cmplhi2"
1325   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1326         (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
1327   ""
1328   "com %0"
1329   [(set_attr "length" "1,2")])
1331 (define_insn "one_cmplqi2"
1332   [(set (match_operand:QI 0 "general_operand" "=rR,rR")
1333         (not:QI (match_operand:QI 1 "general_operand" "0,g")))]
1334   ""
1335   "@
1336   comb %0
1337   movb %1, %0\; comb %0"
1338   [(set_attr "length" "1,2")])
1340 ;;- arithmetic shift instructions
1341 (define_insn "ashlsi3"
1342   [(set (match_operand:SI 0 "register_operand" "=r,r")
1343         (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
1344                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
1345   "TARGET_45"
1346   "ashc %2,%0"
1347   [(set_attr "length" "1,2")])
1349 ;; Arithmetic right shift on the pdp works by negating the shift count.
1350 (define_expand "ashrsi3"
1351   [(set (match_operand:SI 0 "register_operand" "=r")
1352         (ashift:SI (match_operand:SI 1 "register_operand" "0")
1353                    (match_operand:HI 2 "general_operand" "g")))]
1354   ""
1355   "
1357   operands[2] = negate_rtx (HImode, operands[2]);
1360 ;; define asl aslb asr asrb - ashc missing!
1362 ;; asl 
1363 (define_insn "" 
1364   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1365         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1366                    (const_int 1)))]
1367   ""
1368   "asl %0"
1369   [(set_attr "length" "1,2")])
1371 ;; and another possibility for asr is << -1
1372 ;; might cause problems since -1 can also be encoded as 65535!
1373 ;; not in gcc2 ??? 
1375 ;; asr
1376 (define_insn "" 
1377   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1378         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1379                    (const_int -1)))]
1380   ""
1381   "asr %0"
1382   [(set_attr "length" "1,2")])
1384 ;; lsr
1385 (define_insn "" 
1386   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1387         (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1388                    (const_int 1)))]
1389   ""
1390   "clc\;ror %0"
1391   [(set_attr "length" "1,2")])
1393 (define_insn "lshrsi3"
1394   [(set (match_operand:SI 0 "register_operand" "=r")
1395         (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1396                    (const_int 1)))]
1397   ""
1400   rtx lateoperands[2];
1402   lateoperands[0] = operands[0];
1403   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1405   lateoperands[1] = operands[1];
1406   operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1408   output_asm_insn (\"clc\", operands);
1409   output_asm_insn (\"ror %0\", lateoperands);
1410   output_asm_insn (\"ror %0\", operands);
1412   return \"\";
1414   [(set_attr "length" "5")])
1416 ;; shift is by arbitrary count is expensive, 
1417 ;; shift by one cheap - so let's do that, if
1418 ;; space doesn't matter
1419 (define_insn "" 
1420   [(set (match_operand:HI 0 "general_operand" "=r")
1421         (ashift:HI (match_operand:HI 1 "general_operand" "0")
1422                    (match_operand:HI 2 "expand_shift_operand" "O")))]
1423   "! optimize_size"
1424   "*
1426   register int i;
1428   for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1429     if (INTVAL(operands[2]) < 0)
1430       output_asm_insn(\"asr %0\", operands);
1431     else
1432       output_asm_insn(\"asl %0\", operands);
1433       
1434   return \"\";
1436 ;; longest is 4
1437   [(set (attr "length") (const_int 4))])
1439 ;; aslb
1440 (define_insn "" 
1441   [(set (match_operand:QI 0 "general_operand" "=r,o")
1442         (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1443                    (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1444   ""
1445   "*
1446 { /* allowing predec or post_inc is possible, but hairy! */
1447   int i, cnt;
1449   cnt = INTVAL(operands[2]) & 0x0007;
1451   for (i=0 ; i < cnt ; i++)
1452        output_asm_insn(\"aslb %0\", operands);
1454   return \"\";
1456 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1457   [(set_attr_alternative "length" 
1458                          [(const_int 7)
1459                           (const_int 14)])])
1461 ;;; asr 
1462 ;(define_insn "" 
1463 ;  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1464 ;       (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1465 ;                    (const_int 1)))]
1466 ;  ""
1467 ;  "asr %0"
1468 ;  [(set_attr "length" "1,2")])
1470 ;; asrb
1471 (define_insn "" 
1472   [(set (match_operand:QI 0 "general_operand" "=r,o")
1473         (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1474                      (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1475   ""
1476   "*
1477 { /* allowing predec or post_inc is possible, but hairy! */
1478   int i, cnt;
1480   cnt = INTVAL(operands[2]) & 0x0007;
1482   for (i=0 ; i < cnt ; i++)
1483        output_asm_insn(\"asrb %0\", operands);
1485   return \"\";
1487   [(set_attr_alternative "length" 
1488                          [(const_int 7)
1489                           (const_int 14)])])
1491 ;; the following is invalid - too complex!!! - just say 14 !!!
1492 ;  [(set (attr "length") (plus (and (match_dup 2)
1493 ;                                   (const_int 7))
1494 ;                              (and (match_dup 2)
1495 ;                                   (const_int 7))))])
1499 ;; can we get +-1 in the next pattern? should 
1500 ;; have been caught by previous patterns!
1502 (define_insn "ashlhi3"
1503   [(set (match_operand:HI 0 "register_operand" "=r,r")
1504         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1505                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
1506   ""
1507   "*
1509   if (GET_CODE(operands[2]) == CONST_INT)
1510     {
1511       if (INTVAL(operands[2]) == 1)
1512         return \"asl %0\";
1513       else if (INTVAL(operands[2]) == -1)
1514         return \"asr %0\";
1515     }
1517   return \"ash %2,%0\";
1519   [(set_attr "length" "1,2")])
1521 ;; Arithmetic right shift on the pdp works by negating the shift count.
1522 (define_expand "ashrhi3"
1523   [(set (match_operand:HI 0 "register_operand" "=r")
1524         (ashift:HI (match_operand:HI 1 "register_operand" "0")
1525                    (match_operand:HI 2 "general_operand" "g")))]
1526   ""
1527   "
1529   operands[2] = negate_rtx (HImode, operands[2]);
1532 ;;;;- logical shift instructions
1533 ;;(define_insn "lshrsi3"
1534 ;;  [(set (match_operand:HI 0 "register_operand" "=r")
1535 ;;      (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1536 ;;                   (match_operand:HI 2 "arith_operand" "rI")))]
1537 ;;  ""
1538 ;;  "srl %0,%2")
1540 ;; absolute 
1542 (define_insn "absdf2"
1543   [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1544         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1545   "TARGET_FPU"
1546   "{absd|absf} %0"
1547   [(set_attr "length" "1,2")])
1549 (define_insn "abshi2"
1550   [(set (match_operand:HI 0 "general_operand" "=r,o")
1551         (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
1552   "TARGET_ABSHI_BUILTIN"
1553   "*
1555   static int count = 0;
1556   char buf[200];
1557         
1558   output_asm_insn(\"tst %0\", operands);
1559   sprintf(buf, \"bge abshi%d\", count);
1560   output_asm_insn(buf, NULL);
1561   output_asm_insn(\"neg %0\", operands);
1562   sprintf(buf, \"\\nabshi%d:\", count++);
1563   output_asm_insn(buf, NULL);
1565   return \"\";
1567   [(set_attr "length" "3,5")])
1570 ;; define expand abshi - is much better !!! - but
1571 ;; will it be optimized into an abshi2 ?
1572 ;; it will leave better code, because the tsthi might be 
1573 ;; optimized away!!
1574 ; -- just a thought - don't have time to check 
1576 ;(define_expand "abshi2"
1577 ;  [(match_operand:HI 0 "general_operand" "")
1578 ;   (match_operand:HI 1 "general_operand" "")]
1579 ;  ""
1580 ;  "
1582 ;  rtx label = gen_label_rtx ();
1584 ;  /* do I need this? */
1585 ;  do_pending_stack_adjust ();
1587 ;  emit_move_insn (operands[0], operands[1]);
1589 ;  emit_insn (gen_tsthi (operands[0]));
1590 ;  emit_insn (gen_bge (label1));
1592 ;  emit_insn (gen_neghi(operands[0], operands[0])
1593 ;  
1594 ;  emit_barrier ();
1596 ;  emit_label (label);
1598 ;  /* allow REG_NOTES to be set on last insn (labels don't have enough
1599 ;     fields, and can't be used for REG_NOTES anyway).  */
1600 ;  emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
1601 ;  DONE;
1602 ;}")
1604 ;; negate insns
1606 (define_insn "negdf2"
1607   [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1608         (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1609   "TARGET_FPU"
1610   "{negd|negf} %0"
1611   [(set_attr "length" "1,2")])
1613 (define_insn "negsi2"
1614   [(set (match_operand:SI 0 "register_operand" "=r")
1615         (neg:SI (match_operand:SI 1 "general_operand" "0")))]
1616   ""
1619   rtx lateoperands[2];
1621   lateoperands[0] = operands[0];
1622   operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1624   lateoperands[1] = operands[1];
1625   operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1627   output_asm_insn (\"com %0\", operands);
1628   output_asm_insn (\"com %0\", lateoperands);
1629   output_asm_insn (\"inc %0\", operands);
1630   output_asm_insn (\"adc %0\", lateoperands);
1632   return \"\";
1634   [(set_attr "length" "5")])
1636 (define_insn "neghi2"
1637   [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1638         (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
1639   ""
1640   "neg %0"
1641   [(set_attr "length" "1,2")])
1643 (define_insn "negqi2"
1644   [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1645         (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
1646   ""
1647   "negb %0"
1648   [(set_attr "length" "1,2")])
1651 ;; Unconditional and other jump instructions
1652 (define_insn "jump"
1653   [(set (pc)
1654         (label_ref (match_operand 0 "" "")))]
1655   ""
1656   "jmp %l0"
1657   [(set_attr "length" "2")])
1659 (define_insn ""
1660   [(set (pc)
1661     (label_ref (match_operand 0 "" "")))
1662    (clobber (const_int 1))]
1663   ""
1664   "jmp %l0"
1665   [(set_attr "length" "2")])
1667 (define_insn "tablejump"
1668   [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1669    (use (label_ref (match_operand 1 "" "")))]
1670   ""
1671   "jmp %0"
1672   [(set_attr "length" "1,2")])
1674 ;; indirect jump - let's be conservative!
1675 ;; allow only register_operand, even though we could also 
1676 ;; allow labels etc.
1678 (define_insn "indirect_jump"
1679   [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1680   ""
1681   "jmp (%0)")
1683 ;;- jump to subroutine
1685 (define_insn "call"
1686   [(call (match_operand:HI 0 "general_operand" "rR,Q")
1687          (match_operand:HI 1 "general_operand" "g,g"))
1688 ;;   (use (reg:HI 0)) what was that ???
1689   ]
1690   ;;- Don't use operand 1 for most machines.
1691   ""
1692   "jsr pc, %0"
1693   [(set_attr "length" "1,2")])
1695 ;;- jump to subroutine
1696 (define_insn "call_value"
1697   [(set (match_operand 0 "" "")
1698         (call (match_operand:HI 1 "general_operand" "rR,Q")
1699               (match_operand:HI 2 "general_operand" "g,g")))
1700 ;;   (use (reg:HI 0)) - what was that ????
1701   ]
1702   ;;- Don't use operand 2 for most machines.
1703   ""
1704   "jsr pc, %1"
1705   [(set_attr "length" "1,2")])
1707 ;;- nop instruction
1708 (define_insn "nop"
1709   [(const_int 0)]
1710   ""
1711   "nop")
1714 ;;- multiply 
1716 (define_insn "muldf3"
1717   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1718         (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
1719                  (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1720   "TARGET_FPU"
1721   "{muld|mulf} %2, %0"
1722   [(set_attr "length" "1,2,5")])
1724 ;; 16 bit result multiply:
1725 ;; currently we multiply only into odd registers, so we don't use two 
1726 ;; registers - but this is a bit inefficient at times. If we define 
1727 ;; a register class for each register, then we can specify properly 
1728 ;; which register need which scratch register ....
1730 (define_insn "mulhi3"
1731   [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1732         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1733                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1734   "TARGET_45"
1735   "mul %2, %0"
1736   [(set_attr "length" "1,2")])
1738 ;; 32 bit result
1739 (define_expand "mulhisi3"
1740   [(set (match_dup 3)
1741         (match_operand:HI 1 "general_operand" "g,g"))
1742    (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1743         (mult:SI (truncate:HI 
1744                   (match_dup 0))
1745                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1746   "TARGET_45"
1747   "operands[3] = gen_lowpart(HImode, operands[1]);")
1749 (define_insn ""
1750   [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1751         (mult:SI (truncate:HI 
1752                   (match_operand:SI 1 "register_operand" "%0,0"))
1753                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1754   "TARGET_45"
1755   "mul %2, %0"
1756   [(set_attr "length" "1,2")])
1758 ;(define_insn "mulhisi3"
1759 ;  [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1760 ;       (mult:SI (truncate:HI 
1761 ;                  (match_operand:SI 1 "register_operand" "%0,0"))
1762 ;                (match_operand:HI 2 "general_operand" "rR,Qi")))]
1763 ;  "TARGET_45"
1764 ;  "mul %2, %0"
1765 ;  [(set_attr "length" "1,2")])
1767 ;;- divide
1768 (define_insn "divdf3"
1769   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1770         (div:DF (match_operand:DF 1 "register_operand" "0,0,0")
1771                 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1772   "TARGET_FPU"
1773   "{divd|divf} %2, %0"
1774   [(set_attr "length" "1,2,5")])
1776          
1777 (define_expand "divhi3"
1778   [(set (subreg:HI (match_dup 1) 0)
1779         (div:HI (match_operand:SI 1 "general_operand" "0")
1780                 (match_operand:HI 2 "general_operand" "g")))
1781    (set (match_operand:HI 0 "general_operand" "=r")
1782         (subreg:HI (match_dup 1) 0))]
1783   "TARGET_45"
1784   "")
1786 (define_insn ""
1787   [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1788         (div:HI (match_operand:SI 1 "general_operand" "0")
1789                 (match_operand:HI 2 "general_operand" "g")))]
1790   "TARGET_45"
1791   "div %2,%0"
1792   [(set_attr "length" "2")])
1794 (define_expand "modhi3"
1795   [(set (subreg:HI (match_dup 1) 2)
1796         (mod:HI (match_operand:SI 1 "general_operand" "0")
1797                 (match_operand:HI 2 "general_operand" "g")))
1798    (set (match_operand:HI 0 "general_operand" "=r")
1799         (subreg:HI (match_dup 1) 2))]
1800   "TARGET_45"
1801   "")
1803 (define_insn ""
1804   [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 2)
1805         (mod:HI (match_operand:SI 1 "general_operand" "0")
1806                 (match_operand:HI 2 "general_operand" "g")))]
1807   "TARGET_45"
1808   "div %2,%0"
1809   [(set_attr "length" "2")])
1811 ;(define_expand "divmodhi4"
1812 ;  [(parallel [(set (subreg:HI (match_dup 1) 0)
1813 ;                  (div:HI (match_operand:SI 1 "general_operand" "0")
1814 ;                          (match_operand:HI 2 "general_operand" "g")))
1815 ;              (set (subreg:HI (match_dup 1) 2)
1816 ;                  (mod:HI (match_dup 1)
1817 ;                          (match_dup 2)))])
1818 ;   (set (match_operand:HI 3 "general_operand" "=r")
1819 ;        (subreg:HI (match_dup 1) 2))
1820 ;   (set (match_operand:HI 0 "general_operand" "=r")
1821 ;        (subreg:HI (match_dup 1) 0))]
1822 ;  "TARGET_45"
1823 ;  "")
1825 ;(define_insn ""
1826 ;  [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1827 ;                  (div:HI (match_operand:SI 1 "general_operand" "0")
1828 ;                          (match_operand:HI 2 "general_operand" "g")))
1829 ;   (set (subreg:HI (match_dup 0) 2)
1830 ;                  (mod:HI (match_dup 1)
1831 ;                          (match_dup 2)))]
1832 ;  "TARGET_45"
1833 ;  "div %2, %0")
1835    
1836 ;; is rotate doing the right thing to be included here ????