OSDN Git Service

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