PR rtl-optimization/88018
[official-gcc.git] / gcc / config / pdp11 / pdp11.md
blobfc5efc7939013d3be9982f827aee653b31678ab7
1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994-2018 Free Software Foundation, Inc.
3 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 (include "predicates.md")
22 (include "constraints.md")
24 (define_c_enum "unspecv"
25   [
26     UNSPECV_BLOCKAGE
27     UNSPECV_SETD
28     UNSPECV_SETI
29     UNSPECV_MOVMEM
30   ])
32 (define_constants
33   [
34    ;; Register numbers
35    (R0_REGNUM             0)
36    (RETVAL_REGNUM         0)
37    (FRAME_POINTER_REGNUM  5)
38    (STACK_POINTER_REGNUM  6)
39    (PC_REGNUM             7)
40    (AC0_REGNUM            8)
41    (AC3_REGNUM            11)
42    (AC4_REGNUM            12)
43    (AC5_REGNUM            13)
44    ;; The next one is not a physical register but is used for
45    ;; addressing arguments.
46    (ARG_POINTER_REGNUM    14)
47    ;; Condition code registers
48    (CC_REGNUM             15)
49    (FCC_REGNUM            16)
50    ;; End of hard registers
51    (FIRST_PSEUDO_REGISTER 17)
52    
53    ;; Branch offset limits, as byte offsets from (pc).  That is NOT
54    ;; the same thing as "instruction address" -- it is for backward
55    ;; branches, but for forward branches it refers to the address
56    ;; following the instruction.  So the max forward distance
57    ;; matches what the processor handbook says, while the max
58    ;; backward branch is 2 less than the book.
59    (MIN_BRANCH            -254)
60    (MAX_BRANCH            254)
61    (MIN_SOB               -124)
62    (MAX_SOB               0)])
64 ;; DF is 64 bit
65 ;; SF is 32 bit
66 ;; SI is 32 bit
67 ;; HI is 16 bit
68 ;; QI is 8 bit 
70 ;; Integer modes supported on the PDP11, with a mapping from machine mode
71 ;; to mnemonic suffix.  SImode and DImode are usually special cases.
72 (define_mode_iterator PDPint [QI HI])
73 (define_mode_attr  isfx [(QI "b") (HI "")])
74 (define_mode_attr  mname [(QI "QImode") (HI "HImode") (SI "SImode") (DI "DImode")])
75 (define_mode_attr  e_mname [(QI "E_QImode") (HI "E_HImode") (SI "E_SImode") (DI "E_DImode")])
76 (define_mode_attr  hmode [(QI "hi") (HI "hi") (SI "si") (DI "di")])
78 ;; These are analogous for use in splitters and expanders.
79 (define_mode_iterator HSint [HI SI])
80 (define_mode_iterator QHSint [QI HI SI])
81 (define_mode_iterator QHSDint [QI HI SI DI])
83 (define_code_iterator SHF [ashift ashiftrt lshiftrt])
85 ;; Substitution to turn a CC clobber into a CC setter.  We have four of
86 ;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
87 (define_subst "cc_cc"
88   [(set (match_operand 0 "") (match_operand 1 ""))
89    (clobber (reg CC_REGNUM))]
90   ""
91   [(set (reg:CC CC_REGNUM)
92         (compare:CC (match_dup 1) (const_int 0)))
93    (set (match_dup 0) (match_dup 1))])
95 (define_subst "cc_ccnz"
96   [(set (match_operand 0 "") (match_operand 1 ""))
97    (clobber (reg CC_REGNUM))]
98   ""
99   [(set (reg:CCNZ CC_REGNUM)
100         (compare:CCNZ (match_dup 1) (const_int 0)))
101    (set (match_dup 0) (match_dup 1))])
103 (define_subst "fcc_cc"
104   [(set (match_operand 0 "") (match_operand 1 ""))
105    (clobber (reg FCC_REGNUM))]
106   ""
107   [(set (reg:CC FCC_REGNUM)
108         (compare:CC (match_dup 1) (const_int 0)))
109    (set (match_dup 0) (match_dup 1))])
111 (define_subst "fcc_ccnz"
112   [(set (match_operand 0 "") (match_operand 1 ""))
113    (clobber (reg FCC_REGNUM))]
114   ""
115   [(set (reg:CCNZ FCC_REGNUM)
116         (compare:CCNZ (match_dup 1) (const_int 0)))
117    (set (match_dup 0) (match_dup 1))])
119 (define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
120 (define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc")
121 (define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc")
122 (define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc")
124 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
126 ;; Compare instructions.
128 ;; currently we only support df floats, which saves us quite some
129 ;; hassle switching the FP mode! 
130 ;; we assume that CPU is always in long float mode, and 
131 ;; 16 bit integer mode - currently, the prologue for main does this,
132 ;; but maybe we should just set up a NEW crt0 properly, 
133 ;; -- and what about signal handling code?
134 ;; (we don't even let sf floats in the register file, so
135 ;; we only should have to worry about truncating and widening 
136 ;; when going to memory)
138 ;; abort() call by g++ - must define libfunc for cmp_optab
139 ;; and ucmp_optab for mode SImode, because we don't have that!!!
140 ;; - yet since no libfunc is there, we abort ()
142 ;; define attributes
143 ;; currently type is only fpu or arith or unknown, maybe branch later ?
144 ;; default is arith
145 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
147 ;; length default is 2 bytes each
148 (define_attr "length" "" (const_int 2))
150 ;; instruction base cost (not counting operands)
151 (define_attr "base_cost" "" (const_int 2))
153 ;; a user's asm statement
154 (define_asm_attributes
155   [(set_attr "type" "unknown")
156 ; length for asm is the max length per statement.  That would be
157 ; 3 words, for a two-operand instruction with extra word addressing
158 ; modes for both operands.
159    (set_attr "length" "6")])
161 ;; define function units
163 ;; Prologue and epilogue support.
165 (define_expand "prologue"
166   [(const_int 0)]
167   ""
169   pdp11_expand_prologue ();
170   DONE;
173 (define_expand "epilogue"
174   [(const_int 0)]
175   ""
177   pdp11_expand_epilogue ();
178   DONE;
181 (define_insn "rtspc"
182   [(return)]
183   ""
184   "rts\tpc")
186 (define_insn "blockage"
187   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
188   ""
189   ""
190   [(set_attr "length" "0")])
192 (define_insn "setd"
193   [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
194   ""
195   "setd")
197 (define_insn "seti"
198   [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
199   ""
200   "seti")
202 ;; arithmetic - values here immediately when next insn issued
203 ;; or does it mean the number of cycles after this insn was issued?
204 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
206 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
207 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
209 ;; compare
210 (define_insn "*cmpdf"
211   [(set (reg:CC FCC_REGNUM)
212         (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
213                     (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
214   "TARGET_FPU && reload_completed"
215   "*
217   if (which_alternative == 0 || which_alternative == 2)
218     return \"{tstd|tstf}\t%0\";
219   else
220     return \"{cmpd|cmpf}\t%0,%1\";
222   [(set_attr "length" "2,2,4,4")
223    (set_attr "base_cost" "4")
224    (set_attr "type" "fp")]) 
226 ;; Copy floating point processor condition code register to main CPU
227 ;; condition code register.
228 (define_insn "*cfcc"
229   [(set (reg CC_REGNUM) (reg FCC_REGNUM))]
230   "TARGET_FPU && reload_completed"
231   "cfcc")
233 (define_insn "cmp<mode>"
234   [(set (reg:CC CC_REGNUM)
235         (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
236                     (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
237   ""
238   "@
239    tst<PDPint:isfx>\t%0
240    cmp<PDPint:isfx>\t%0,%1
241    cmp<PDPint:isfx>\t%0,%1
242    tst<PDPint:isfx>\t%0
243    cmp<PDPint:isfx>\t%0,%1
244    cmp<PDPint:isfx>\t%0,%1"
245   [(set_attr "length" "2,2,4,4,4,6")])
247 ;; Two word compare
248 (define_insn "cmpsi"
249   [(set (reg:CC CC_REGNUM)
250         (compare:CC (match_operand:SI 0 "general_operand" "rDQi")
251                     (match_operand:SI 1 "general_operand" "rDQi")))]
252   ""
254   rtx inops[2];
255   rtx exops[2][2];
256   rtx lb[1];
257   
258   inops[0] = operands[0];
259   inops[1] = operands[1];
260   pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
261   lb[0] = gen_label_rtx ();
262   
263   if (CONST_INT_P (exops[0][1]) && INTVAL (exops[0][1]) == 0)
264    output_asm_insn ("tst\t%0", exops[0]);
265   else
266    output_asm_insn ("cmp\t%0,%1", exops[0]);
267   output_asm_insn ("bne\t%l0", lb);
268   if (CONST_INT_P (exops[1][1]) && INTVAL (exops[1][1]) == 0)
269    output_asm_insn ("tst\t%0", exops[1]);
270   else
271    output_asm_insn ("cmp\t%0,%1", exops[1]);
272   output_asm_label (lb[0]);
273   fputs (":\n", asm_out_file);
275   return "";
277   [(set (attr "length")
278         (symbol_ref "pdp11_cmp_length (operands, 2)"))
279    (set_attr "base_cost" "0")])
281 ;; Four word compare
282 (define_insn "cmpdi"
283   [(set (reg:CC CC_REGNUM)
284         (compare:CC (match_operand:DI 0 "general_operand" "rDQi")
285                     (match_operand:DI 1 "general_operand" "rDQi")))]
286   ""
288   rtx inops[4];
289   rtx exops[4][2];
290   rtx lb[1];
291   int i;
292   
293   inops[0] = operands[0];
294   inops[1] = operands[1];
295   pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
296   lb[0] = gen_label_rtx ();
298   for (i = 0; i < 3; i++)
299     {
300       if (CONST_INT_P (exops[i][1]) && INTVAL (exops[i][1]) == 0)
301         output_asm_insn ("tst\t%0", exops[i]);
302       else
303         output_asm_insn ("cmp\t%0,%1", exops[i]);
304        output_asm_insn ("bne\t%l0", lb);
305      }
306   if (CONST_INT_P (exops[3][1]) && INTVAL (exops[3][1]) == 0)
307    output_asm_insn ("tst\t%0", exops[3]);
308   else
309    output_asm_insn ("cmp\t%0,%1", exops[3]);
310   output_asm_label (lb[0]);
311    fputs (":\n", asm_out_file);
313   return "";
315   [(set (attr "length")
316         (symbol_ref "pdp11_cmp_length (operands, 2)"))
317    (set_attr "base_cost" "0")])
319 ;; sob instruction
321 ;; This expander has to check for mode match because the doloop pass
322 ;; in gcc that invokes it does not do so, i.e., it may attempt to apply
323 ;; this pattern even if the count operand is QI or SI mode.
324 (define_expand "doloop_end"
325   [(parallel [(set (pc)
326                    (if_then_else
327                     (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
328                         (const_int 1))
329                     (label_ref (match_operand 1 "" ""))
330                     (pc)))
331               (set (match_dup 0)
332                    (plus:HI (match_dup 0)
333                          (const_int -1)))])]
334   "TARGET_40_PLUS"
335   "{
336     if (GET_MODE (operands[0]) != HImode)
337       FAIL;
338   }")
340 ;; Do a define_split because some alternatives clobber CC.
341 ;; Some don't, but it isn't all that interesting to cover that case.
342 (define_insn_and_split "doloop_end_insn"
343   [(set (pc)
344         (if_then_else
345          (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
346              (const_int 1))
347          (label_ref (match_operand 1 "" ""))
348          (pc)))
349    (set (match_dup 0)
350         (plus:HI (match_dup 0)
351                  (const_int -1)))]
352   "TARGET_40_PLUS"
353   "#"
354   "&& reload_completed"
355   [(parallel [(set (pc)
356                    (if_then_else
357                     (ne (match_dup 0) (const_int 1))
358                     (label_ref (match_dup 1))
359                     (pc)))
360               (set (match_dup 0)
361                    (plus:HI (match_dup 0)
362                          (const_int -1)))
363               (clobber (reg:CC CC_REGNUM))])]
364   "")
366 ;; Note that there is a memory alternative here.  This is as documented
367 ;; in gccint, which says that doloop_end, since it has both a jump and
368 ;; an output interrupt "must handle its own reloads".  That translates
369 ;; to: must accept memory operands as valid though they may be deprecated.
370 (define_insn "doloop_end_nocc"
371   [(set (pc)
372         (if_then_else
373          (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
374              (const_int 1))
375          (label_ref (match_operand 1 "" ""))
376          (pc)))
377    (set (match_dup 0)
378         (plus:HI (match_dup 0)
379               (const_int -1)))
380    (clobber (reg:CC CC_REGNUM))]
381   "TARGET_40_PLUS && reload_completed"
382   "*
384  rtx lb[1];
386  if (get_attr_length (insn) == 2)
387     return \"sob\t%0,%l1\";
389  /* emulate sob */
390  lb[0] = gen_label_rtx ();
391  output_asm_insn (\"dec\t%0\", operands);
392  output_asm_insn (\"beq\t%l0\", lb);
393  output_asm_insn (\"jmp\t%l1\", operands);
395  output_asm_label (lb[0]);
396  fputs (\":\\n\", asm_out_file);
398  return \"\";
400   [(set (attr "length")
401         (if_then_else (eq (symbol_ref ("which_alternative")) (const_int 1))
402                           (const_int 10)
403                           (if_then_else (ior (lt (minus (match_dup 1) (pc))
404                                                  (const_int MIN_SOB))
405                                              (gt (minus (match_dup 1) (pc))
406                                                  (const_int MAX_SOB)))
407                                         (const_int 8)
408                                         (const_int 2))))])
410 ;; These control RTL generation for conditional jump insns
411 ;; and match them for register allocation.
412 ;; Post reload these get expanded into insns that actually
413 ;; manipulate the condition code registers.  We can't do that before
414 ;; because instructions generated by reload clobber condition codes (new
415 ;; CC design, type #2).
416 (define_insn_and_split "cbranchdf4"
417   [(set (pc)
418         (if_then_else (match_operator 0 "ordered_comparison_operator"
419                        [(match_operand:DF 1 "general_operand" "fg")
420                         (match_operand:DF 2 "general_operand" "a")])
421                       (label_ref (match_operand 3 "" ""))
422                       (pc)))]
423   "TARGET_FPU"
424   "#"
425   "&& reload_completed"
426   [(set (reg:CC FCC_REGNUM)
427         (compare:CC (match_dup 1) (match_dup 2)))
428    (set (pc)
429         (if_then_else (match_op_dup 0
430                       [(reg:CC FCC_REGNUM) (const_int 0)])
431                       (label_ref (match_dup 3))
432                       (pc)))]
433   "")
435 (define_insn_and_split "cbranch<mode>4"
436   [(set (pc)
437         (if_then_else (match_operator 0 "ordered_comparison_operator"
438                        [(match_operand:QHSDint 1 "general_operand" "g")
439                         (match_operand:QHSDint 2 "general_operand" "g")])
440                       (label_ref (match_operand 3 "" ""))
441                       (pc)))]
442   ""
443   "#"
444   "reload_completed"
445   [(set (reg:CC CC_REGNUM)
446         (compare:CC (match_dup 1) (match_dup 2)))
447    (set (pc)
448         (if_then_else (match_op_dup 0
449                       [(reg:CC CC_REGNUM) (const_int 0)])
450                       (label_ref (match_dup 3))
451                       (pc)))]
452   "")
454 ;; This splitter turns a branch on float condition into a branch on
455 ;; CPU condition, by adding a CFCC.
456 (define_split
457   [(set (pc)
458         (if_then_else (match_operator 0 "ordered_comparison_operator"
459                       [(reg:CC FCC_REGNUM) (const_int 0)])
460                       (label_ref (match_operand 1 "" ""))
461                       (pc)))]
462   "TARGET_FPU && reload_completed"
463   [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM))
464    (set (pc)
465         (if_then_else (match_op_dup 0
466                       [(reg:CC CC_REGNUM) (const_int 0)])
467                       (label_ref (match_dup 1))
468                       (pc)))]
469   "")
471 (define_insn "cond_branch"
472   [(set (pc)
473         (if_then_else (match_operator 0 "ordered_comparison_operator"
474                        [(reg:CC CC_REGNUM) (const_int 0)])
475                       (label_ref (match_operand 1 "" ""))
476                       (pc)))]
477   "reload_completed"
478   "* return output_jump (operands, 0, get_attr_length (insn));"
479   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
480                                                       (pc))
481                                                (const_int MIN_BRANCH))
482                                            (gt (minus (match_dup 1)
483                                                       (pc))
484                                                (const_int MAX_BRANCH)))
485                                       (const_int 6)
486                                       (const_int 2)))])
488 (define_insn "*branch"
489   [(set (pc)
490         (if_then_else (match_operator 0 "ccnz_operator"
491                        [(reg:CCNZ CC_REGNUM) (const_int 0)])
492                       (label_ref (match_operand 1 "" ""))
493                       (pc)))]
494   "reload_completed"
495   "* return output_jump (operands, 1, get_attr_length (insn));"
496   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
497                                                       (pc))
498                                                (const_int MIN_BRANCH))
499                                            (gt (minus (match_dup 1)
500                                                       (pc))
501                                                (const_int MAX_BRANCH)))
502                                       (const_int 6)
503                                       (const_int 2)))])
506 ;; Move instructions
508 ;; "length" is defined even though this pattern won't appear at
509 ;; assembly language output time.  But the length is used by
510 ;; pdp11_insn_cost, before the post-reload splitter adds the
511 ;; CC clobber to the insn.
512 (define_insn "movdi"
513   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
514         (match_operand:DI 1 "general_operand" "rN,g"))]
515   ""
516   ""
517   [(set_attr "length" "16,32")])
520 (define_insn "*movdi_nocc"
521   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
522         (match_operand:DI 1 "general_operand" "rN,g"))
523    (clobber (reg:CC CC_REGNUM))]
524   ""
525   "* return output_move_multiple (operands);"
526   [(set_attr "length" "16,32")])
528 (define_insn "movsi"
529   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
530         (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
531   ""
532   ""
533   [(set_attr "length" "4,6,8,16")])
535 (define_insn "*movsi_nocc"
536   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
537         (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))
538    (clobber (reg:CC CC_REGNUM))]
539   ""
540   "* return output_move_multiple (operands);"
541   [(set_attr "length" "4,6,8,16")])
543 ;; That long string of "Z" constraints enforces the restriction that
544 ;; a register source and auto increment or decrement destination must
545 ;; not use the same register, because that case is not consistently
546 ;; implemented across the PDP11 models.
547 ;; TODO: the same should be applied to insn like add, but this is not
548 ;; necessary yet because the incdec optimization pass does not apply
549 ;; that optimization to 3-operand insns at the moment.
550 (define_insn "mov<mode>"
551   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
552         (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))]
553   ""
554   ""
555   [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
557 ;; This splits all the integer moves: DI and SI modes as well as
558 ;; the simple machine operations.
559 (define_split 
560   [(set (match_operand:QHSDint 0 "nonimmediate_operand" "")
561         (match_operand:QHSDint 1 "general_operand" ""))]
562   "reload_completed"
563   [(parallel [(set (match_dup 0)
564                    (match_dup 1))
565               (clobber (reg:CC CC_REGNUM))])]
566   "")
567   
568 ;; MOV clears V
569 (define_insn "*mov<mode>_<cc_cc>"
570   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
571         (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))
572    (clobber (reg:CC CC_REGNUM))]
573   "reload_completed"
574   "*
576   if (operands[1] == const0_rtx)
577     return \"clr<PDPint:isfx>\t%0\";
579   return \"mov<PDPint:isfx>\t%1,%0\";
581   [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
583 ;; movdf has unusually complicated condition code handling, because
584 ;; load (into float register) updates the FCC, while store (from
585 ;; float register) leaves it untouched.
587 ;; 1. Loads are:  ac4, ac5, or non-register into load-register
588 ;; 2. Stores are: load-register to non-register, ac4, or ac5
589 ;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled
590 ;;    either as loads or as stores.
592 (define_expand "movdf"
593   [(set (match_operand:DF 0 "float_nonimm_operand" "")
594         (match_operand:DF 1 "float_operand" ""))]
595   "TARGET_FPU"
596   "")
598 ;; Splitter for all these cases.  Store is the first two
599 ;; alternatives, which are not split.  Note that case 3
600 ;; is treated as a store, i.e., not split.
601 (define_insn_and_split "movdf_split"
602   [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,FQ,a,a,a")
603         (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))]
604   "TARGET_FPU"
605   "*
606   gcc_assert (which_alternative < 2);
607   return \"std\t%1,%0\";
608   "
609   "&& reload_completed"
610   [(parallel [(set (match_dup 0)
611                    (match_dup 1))
612               (clobber (reg:CC FCC_REGNUM))])]
613   "{
614   if (GET_CODE (operands[1]) == REG && 
615       REGNO_REG_CLASS (REGNO (operands[1])) == LOAD_FPU_REGS)
616     FAIL;
617   }"
618   [(set_attr "length" "2,4,0,0,0")])
620 ;; Loads (case 1).  
621 (define_insn "*ldd<fcc_cc>"
622   [(set (match_operand:DF 0 "float_nonimm_operand" "=a,a,a")
623         (match_operand:DF 1 "float_operand" "hR,FQ,G"))
624    (clobber (reg:CC FCC_REGNUM))]
625   "TARGET_FPU && reload_completed"
626   "@
627   ldd\t%1,%0
628   ldd\t%1,%0
629   clrd\t%0"
630   [(set_attr "length" "2,4,2")])
632 ;; SFmode is easier because that uses convert load/store, which
633 ;; always change condition codes.
634 ;; Note that these insns are cheating a bit.  We actually have
635 ;; DFmode operands in the FPU registers, which is why the
636 ;; ldcfd and stcdf instructions appear.  But GCC likes to think
637 ;; of these as SFmode loads and does the conversion once in the
638 ;; register, at least in many cases.  So we pretend to do this,
639 ;; but then extend and truncate register-to-register are NOP and
640 ;; generate no code.
641 (define_insn_and_split "movsf"
642   [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
643         (match_operand:SF 1 "float_operand" "fRG,a,FQ,a,G"))]
644   "TARGET_FPU"
645   "#"
646   "&& reload_completed"
647   [(parallel [(set (match_dup 0)
648                    (match_dup 1))
649               (clobber (reg:CC FCC_REGNUM))])]
650   ""
651   [(set_attr "length" "2,2,4,4,2")])
652   
653 (define_insn "*movsf<fcc_ccnz>"
654   [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
655         (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G"))
656    (clobber (reg:CC FCC_REGNUM))]
657   "TARGET_FPU && reload_completed"
658   "@
659   {ldcfd|movof}\t%1,%0
660   {stcdf|movfo}\t%1,%0
661   {ldcfd|movof}\t%1,%0
662   {stcdf|movfo}\t%1,%0
663   clrf\t%0"
664   [(set_attr "length" "2,2,4,4,2")])
666 ;; Expand a block move.  We turn this into a move loop.
667 (define_expand "movmemhi"
668   [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
669               (match_operand:BLK 0 "general_operand" "=g")
670               (match_operand:BLK 1 "general_operand" "g")
671               (match_operand:HI 2 "immediate_operand" "i")
672               (match_operand:HI 3 "immediate_operand" "i")
673               (clobber (mem:BLK (scratch)))
674               (clobber (match_dup 0))
675               (clobber (match_dup 1))
676               (clobber (match_dup 2))])]
677   ""
678   "
680   int count;
681   count = INTVAL (operands[2]);
682   if (count == 0)
683     DONE;
684   if (INTVAL (operands [3]) >= 2 && (count & 1) == 0)
685     count >>= 1;
686   else
687     operands[3] = const1_rtx;
688   operands[2] = copy_to_mode_reg (HImode,
689                                   gen_rtx_CONST_INT (HImode, count));
691   /* Load BLKmode MEM addresses into scratch registers.  */
692   operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
693   operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
696 ;; Expand a block move.  We turn this into a move loop.
697 (define_insn_and_split "movmemhi1"
698   [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
699    (match_operand:HI 0 "register_operand" "+r")
700    (match_operand:HI 1 "register_operand" "+r")
701    (match_operand:HI 2 "register_operand" "+r")
702    (match_operand:HI 3 "immediate_operand" "i")
703    (clobber (mem:BLK (scratch)))
704    (clobber (match_dup 0))
705    (clobber (match_dup 1))
706    (clobber (match_dup 2))]
707   ""
708   "#"
709   "reload_completed"
710   [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
711               (match_dup 0)
712               (match_dup 1)
713               (match_dup 2)
714               (match_dup 3)
715               (clobber (mem:BLK (scratch)))
716               (clobber (match_dup 0))
717               (clobber (match_dup 1))
718               (clobber (match_dup 2))
719               (clobber (reg:CC CC_REGNUM))])]
720   "")
722 (define_insn "movmemhi_nocc"
723   [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
724    (match_operand:HI 0 "register_operand" "+r")
725    (match_operand:HI 1 "register_operand" "+r")
726    (match_operand:HI 2 "register_operand" "+r")
727    (match_operand:HI 3 "immediate_operand" "i")
728    (clobber (mem:BLK (scratch)))
729    (clobber (match_dup 0))
730    (clobber (match_dup 1))
731    (clobber (match_dup 2))
732    (clobber (reg:CC CC_REGNUM))]
733   "reload_completed"
734   "*
736   rtx lb[2];
737   
738   lb[0] = operands[2];
739   lb[1] = gen_label_rtx ();
740   
741   output_asm_label (lb[1]);
742   fputs (\":\n\", asm_out_file);
743   if (INTVAL (operands[3]) > 1)
744     output_asm_insn (\"mov\t(%1)+,(%0)+\", operands);
745   else
746     output_asm_insn (\"movb\t(%1)+,(%0)+\", operands);
747   if (TARGET_40_PLUS)
748     output_asm_insn (\"sob\t%0,%l1\", lb);
749   else
750     {
751       output_asm_insn (\"dec\t%0\", lb);
752       output_asm_insn (\"bne\t%l1\", lb);
753     }
754   return \"\";
756   [(set (attr "length")
757         (if_then_else (match_test "TARGET_40_PLUS")
758                       (const_int 4)
759                       (const_int 6)))])
761 ;;- truncation instructions
763 ;; We sometimes end up doing a register to register truncate,
764 ;; which isn't right because we actually load registers always
765 ;; with a DFmode value.  But even with PROMOTE the compiler
766 ;; doesn't always get that (so we don't use it).  That means
767 ;; a register to register truncate is a NOP.
768 (define_insn_and_split  "truncdfsf2"
769   [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
770         (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))]
771   "TARGET_FPU"
772   {
773     gcc_assert (which_alternative == 0);
774     return "";
775   }           
776   "&& reload_completed"
777   [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1)))
778               (clobber (reg:CC FCC_REGNUM))])]
779   "{
780   if (GET_CODE (operands[0]) == REG && 
781       GET_CODE (operands[1]) == REG && 
782       REGNO (operands[0]) == REGNO (operands[1]))
783     FAIL;
784   }"
785   [(set_attr "length" "0,0,0")])
787 (define_insn "*truncdfsf2_<fcc_cc>"
788   [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q")
789         (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a")))
790    (clobber (reg:CC FCC_REGNUM))]
791   "TARGET_FPU && reload_completed"
792    "{stcdf|movfo}\t%1,%0"
793   [(set_attr "length" "2,4")])
796 ;;- zero extension instruction
798 (define_insn_and_split "zero_extendqihi2"
799   [(set (match_operand:HI 0 "nonimmediate_operand" "=rD,Q,&r,&r")
800         (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0,rR,Q")))]
801   ""
802   "#"
803   "reload_completed"
804   [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
805               (clobber (reg:CC CC_REGNUM))])]
806   "{
807     rtx r;
809     if (!REG_P (operands[0]))
810       {
811         r = gen_rtx_MEM (QImode, operands[0]);
812         adjust_address (r, QImode, 1);
813         emit_move_insn (r, const0_rtx);
814         DONE;
815       }
816     else if (!REG_P (operands[1]) ||
817              REGNO (operands[0]) != REGNO (operands[1]))
818       {
819         /* Alternatives 2 and 3 */
820         emit_move_insn (operands[0], const0_rtx);
821         r = gen_rtx_REG (QImode, REGNO (operands[0]));
822         emit_insn (gen_iorqi3_nocc (r, r, operands[1]));
823         DONE;
824       }
825   }"
826   [(set_attr "length" "4,4,4,6")])
828 (define_insn "*zero_extendqihi2<cc_cc>"
829   [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
830                    (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))
831               (clobber (reg:CC CC_REGNUM))])]
832   "reload_completed"
833   "bic\t%#0177400,%0"
834   [(set_attr "length" "4,6")])
835                          
836 ;;- sign extension instructions
838 ;; We sometimes end up doing a register to register extend,
839 ;; which isn't right because we actually load registers always
840 ;; with a DFmode value.  But even with PROMOTE the compiler
841 ;; doesn't always get that (so we don't use it).  That means
842 ;; a register to register truncate is a NOP.
843 (define_insn_and_split "extendsfdf2"
844   [(set (match_operand:DF 0 "register_operand" "=f,a,a")
845         (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))]
846   "TARGET_FPU"
847   {
848     gcc_assert (which_alternative == 0);
849     return "";
850   }           
851   "&& reload_completed"
852   [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1)))
853               (clobber (reg:CC FCC_REGNUM))])]
854   "{
855   if (GET_CODE (operands[0]) == REG && 
856       GET_CODE (operands[1]) == REG && 
857       REGNO (operands[0]) == REGNO (operands[1]))
858     FAIL;
859   }"
860   [(set_attr "length" "0,0,0")])
862 (define_insn "*extendsfdf2_<fcc_cc>"
863   [(set (match_operand:DF 0 "register_operand" "=a,a")
864         (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q")))
865    (clobber (reg:CC FCC_REGNUM))]
866   "TARGET_FPU && reload_completed"
867   "{ldcfd|movof}\t%1,%0"
868   [(set_attr "length" "2,4")
869    (set_attr "base_cost" "6")])
871 ;; movb sign extends if destination is a register
872 (define_insn_and_split "extendqihi2"
873   [(set (match_operand:HI 0 "register_operand" "=r,r")
874         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
875   ""
876   "#"
877   "reload_completed"
878   [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
879               (clobber (reg:CC CC_REGNUM))])]
880   ""
881   [(set_attr "length" "2,4")])
883 ;; MOVB clears V
884 (define_insn "*extendqihi2<cc_cc>"
885   [(set (match_operand:HI 0 "register_operand" "=r,r")
886         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))
887    (clobber (reg:CC CC_REGNUM))]
888   "reload_completed"
889   "movb\t%1,%0"
890   [(set_attr "length" "2,4")])
892 (define_insn_and_split "extendhisi2"
893   [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
894         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
895   "TARGET_40_PLUS"
896   "#"
897   "&& reload_completed"
898   [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
899               (clobber (reg:CC CC_REGNUM))])]
900   ""
901   [(set_attr "length" "10,6,6")])
903 (define_insn "*extendhisi2_nocc"
904   [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
905         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))
906    (clobber (reg:CC CC_REGNUM))]
907   "TARGET_40_PLUS && reload_completed"
908   "*
910   rtx latehalf[2];
912   /* we don't want to mess with auto increment */
913   
914   switch (which_alternative)
915   {
916     case 0:
918       latehalf[0] = operands[0];
919       operands[0] = adjust_address(operands[0], HImode, 2);
920   
921       output_asm_insn(\"mov\t%1,%0\", operands);
922       output_asm_insn(\"sxt\t%0\", latehalf);
924       return \"\";
926     case 1:
928       /* - auto-decrement - right direction ;-) */
929       output_asm_insn(\"mov\t%1,%0\", operands);
930       output_asm_insn(\"sxt\t%0\", operands);
932       return \"\";
934     case 2:
936       /* make register pair available */
937       latehalf[0] = operands[0];
938       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
940       output_asm_insn(\"mov\t%1,%0\", operands);
941       output_asm_insn(\"sxt\t%0\", latehalf);
943       return \"\";
945     default:
947       gcc_unreachable ();
948   }
950   [(set_attr "length" "10,6,6")])
952 ;; make float to int and vice versa 
953 ;; assume that we are normally in double and integer mode -
954 ;; what do pdp library routines do to fpu mode ?
956 ;; Note: the hardware treats register source as
957 ;; a 16-bit (high order only) source, which isn't
958 ;; what we want.  But we do need to support register
959 ;; dest because gcc asks for it.
960 (define_insn_and_split "floatsidf2"
961   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
962         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
963   "TARGET_FPU"
964   "#"
965   "&& reload_completed"
966   [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
967               (clobber (reg:CC FCC_REGNUM))])]
968   ""
969   [(set_attr "length" "10,6,8")])
971 (define_insn "*floatsidf2<fcc_cc>"
972   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
973         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))
974    (clobber (reg:CC FCC_REGNUM))]
975   "TARGET_FPU && reload_completed"
976   "* if (which_alternative ==0)
977      {
978        rtx latehalf[2];
980        latehalf[0] = NULL; 
981        latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
982        output_asm_insn(\"mov\t%1,-(sp)\", latehalf);
983        output_asm_insn(\"mov\t%1,-(sp)\", operands);
984        
985        output_asm_insn(\"setl\", operands);
986        output_asm_insn(\"{ldcld|movif}\t(sp)+,%0\", operands);
987        output_asm_insn(\"seti\", operands);
988        return \"\";
989      }
990      else 
991        return \"setl\;{ldcld|movif}\t%1,%0\;seti\";
992   "
993   [(set_attr "length" "10,6,8")
994    (set_attr "base_cost" "12")])
996 (define_insn_and_split "floathidf2"
997   [(set (match_operand:DF 0 "register_operand" "=a,a")
998         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
999   "TARGET_FPU"
1000   "#"
1001   "&& reload_completed"
1002   [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
1003               (clobber (reg:CC FCC_REGNUM))])]
1004   ""
1005   [(set_attr "length" "2,4")])
1007 (define_insn "*floathidf2<fcc_cc>"
1008   [(set (match_operand:DF 0 "register_operand" "=a,a")
1009         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))
1010    (clobber (reg:CC FCC_REGNUM))]
1011   "TARGET_FPU && reload_completed"
1012   "{ldcid|movif}\t%1,%0"
1013   [(set_attr "length" "2,4")
1014    (set_attr "base_cost" "12")])
1016 ;; cut float to int
1018 ;; Note: the hardware treats register destination as
1019 ;; a 16-bit (high order only) destination, which isn't
1020 ;; what we want.  But we do need to support register
1021 ;; dest because gcc asks for it.
1022 (define_insn_and_split "fix_truncdfsi2"
1023   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
1024         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
1025   "TARGET_FPU"
1026   "#"
1027   "&& reload_completed"
1028   [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1))))
1029               (clobber (reg:CC CC_REGNUM))
1030               (clobber (reg:CC FCC_REGNUM))])]
1031   ""
1032   [(set_attr "length" "10,6,8")])
1034 ;; Note: this clobbers both sets of condition codes!
1035 (define_insn "*fix_truncdfsi2_nocc"
1036   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
1037         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))
1038    (clobber (reg:CC CC_REGNUM))
1039    (clobber (reg:CC FCC_REGNUM))]
1040   "TARGET_FPU && reload_completed"
1041   "* if (which_alternative ==0)
1042      {
1043        output_asm_insn(\"setl\", operands);
1044        output_asm_insn(\"{stcdl|movfi}\t%1,-(sp)\", operands);
1045        output_asm_insn(\"seti\", operands);
1046        output_asm_insn(\"mov\t(sp)+,%0\", operands);
1047        operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1048        output_asm_insn(\"mov\t(sp)+,%0\", operands);
1049        return \"\";
1050      }
1051      else 
1052        return \"setl\;{stcdl|movfi}\t%1,%0\;seti\";
1053   "
1054   [(set_attr "length" "10,6,8")
1055    (set_attr "base_cost" "12")])
1057 (define_insn_and_split "fix_truncdfhi2"
1058   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1059         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
1060   "TARGET_FPU"
1061   "#"
1062   "&& reload_completed"
1063   [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1))))
1064               (clobber (reg:CC CC_REGNUM))
1065               (clobber (reg:CC FCC_REGNUM))])]
1066   ""
1067   [(set_attr "length" "2,4")])
1069 ;; Note: this clobbers both sets of condition codes!
1070 (define_insn "*fix_truncdfhi2_nocc"
1071   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1072         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))
1073    (clobber (reg:CC CC_REGNUM))
1074    (clobber (reg:CC FCC_REGNUM))]
1075   "TARGET_FPU && reload_completed"
1076   "{stcdi|movfi}\t%1,%0"
1077   [(set_attr "length" "2,4")
1078    (set_attr "base_cost" "12")])
1081 ;;- arithmetic instructions
1082 ;;- add instructions
1084 (define_insn_and_split "adddf3"
1085   [(set (match_operand:DF 0 "register_operand" "=a,a")
1086         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
1087                  (match_operand:DF 2 "general_operand" "fR,QF")))]
1088   "TARGET_FPU"
1089   "#"
1090   "&& reload_completed"
1091   [(parallel [(set (match_dup 0)
1092                    (plus:DF (match_dup 1) (match_dup 2)))
1093               (clobber (reg:CC FCC_REGNUM))])]
1094   ""
1095   [(set_attr "length" "2,4")])
1097 ;; Float add sets V if overflow from add
1098 (define_insn "*adddf3<fcc_ccnz>"
1099   [(set (match_operand:DF 0 "register_operand" "=a,a")
1100         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
1101               (match_operand:DF 2 "general_operand" "fR,QF")))
1102    (clobber (reg:CC FCC_REGNUM))]
1103   "TARGET_FPU && reload_completed"
1104   "{addd|addf}\t%2,%0"
1105   [(set_attr "length" "2,4")
1106    (set_attr "base_cost" "6")])
1108 (define_insn_and_split "adddi3"
1109   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1110         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
1111                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1112   ""
1113   "#"
1114   "reload_completed"
1115   [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
1116               (clobber (reg:CC CC_REGNUM))])]
1117   ""
1118   [(set_attr "length" "20,28,40,48")])
1120 (define_insn "*adddi3_nocc"
1121   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1122         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
1123               (match_operand:DI 2 "general_operand" "r,on,r,on")))
1124    (clobber (reg:CC CC_REGNUM))]
1125   "reload_completed"  
1126   "*
1128   rtx inops[2];
1129   rtx exops[4][2];
1130   
1131   inops[0] = operands[0];
1132   inops[1] = operands[2];
1133   pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
1134   
1135   if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1136     output_asm_insn (\"add\t%1,%0\", exops[0]);
1137   if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1138   {
1139     output_asm_insn (\"add\t%1,%0\", exops[1]);
1140     output_asm_insn (\"adc\t%0\", exops[0]);
1141   }
1142   if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1143   {
1144     output_asm_insn (\"add\t%1,%0\", exops[2]);
1145     output_asm_insn (\"adc\t%0\", exops[1]);
1146     output_asm_insn (\"adc\t%0\", exops[0]);
1147   }
1148   if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1149   {
1150     output_asm_insn (\"add\t%1,%0\", exops[3]);
1151     output_asm_insn (\"adc\t%0\", exops[2]);
1152     output_asm_insn (\"adc\t%0\", exops[1]);
1153     output_asm_insn (\"adc\t%0\", exops[0]);
1154   }
1156   return \"\";
1158   [(set_attr "length" "20,28,40,48")
1159    (set_attr "base_cost" "0")])
1161 ;; Note that the register operand is not marked earlyclobber.
1162 ;; The reason is that SI values go in register pairs, so they
1163 ;; can't partially overlap.  They can be either disjoint, or
1164 ;; source and destination can be equal.  The latter case is 
1165 ;; handled properly because of the ordering of the individual
1166 ;; instructions used.  Specifically, carry from the low to the
1167 ;; high word is added at the end, so the adding of the high parts
1168 ;; will always used the original high part and not a high part
1169 ;; modified by carry (which would amount to double carry).
1170 (define_insn_and_split "addsi3"
1171   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1172         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1173                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1174   ""
1175   "#"
1176   "reload_completed"
1177   [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
1178               (clobber (reg:CC CC_REGNUM))])]
1179   ""
1180   [(set_attr "length" "6,10,12,16")])
1182 (define_insn "*addsi3_nocc"
1183   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1184         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1185               (match_operand:SI 2 "general_operand" "r,on,r,on")))
1186    (clobber (reg:CC CC_REGNUM))]
1187   "reload_completed"
1188   "*
1190   rtx inops[2];
1191   rtx exops[2][2];
1192   
1193   inops[0] = operands[0];
1194   inops[1] = operands[2];
1195   pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
1196   
1197   if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1198     output_asm_insn (\"add\t%1,%0\", exops[0]);
1199   if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1200   {
1201     output_asm_insn (\"add\t%1,%0\", exops[1]);
1202     output_asm_insn (\"adc\t%0\", exops[0]);
1203   }
1205   return \"\";
1207   [(set_attr "length" "6,10,12,16")
1208    (set_attr "base_cost" "0")])
1210 (define_insn_and_split "addhi3"
1211   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1212         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1213                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1214   ""
1215   "#"
1216   "reload_completed"
1217   [(parallel [(set (match_dup 0)
1218                    (plus:HI (match_dup 1) (match_dup 2)))
1219               (clobber (reg:CC CC_REGNUM))])]
1220   ""
1221   [(set_attr "length" "2,4,4,6")])
1223 ;; Add sets V if overflow from the add
1224 (define_insn "*addhi3<cc_ccnz>"
1225   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1226         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1227                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1228    (clobber (reg:CC CC_REGNUM))]
1229   "reload_completed"
1230   "*
1232   if (GET_CODE (operands[2]) == CONST_INT)
1233     {
1234       if (INTVAL(operands[2]) == 1)
1235         return \"inc\t%0\";
1236       else if (INTVAL(operands[2]) == -1)
1237         return \"dec\t%0\";
1238     }
1240   return \"add\t%2,%0\";
1242   [(set_attr "length" "2,4,4,6")])
1244 (define_insn_and_split "addqi3"
1245   [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1246         (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1247                  (match_operand:QI 2 "incdec_operand" "LM,LM")))]
1248   ""
1249   "#"
1250   "reload_completed"
1251   [(parallel [(set (match_dup 0)
1252                    (plus:QI (match_dup 1) (match_dup 2)))
1253               (clobber (reg:CC CC_REGNUM))])]
1254   ""
1255   [(set_attr "length" "2,4")])
1257 ;; Inc/dec sets V if overflow from the operation
1258 (define_insn "*addqi3<cc_ccnz>"
1259   [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1260         (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1261                  (match_operand:QI 2 "incdec_operand" "LM,LM")))
1262    (clobber (reg:CC CC_REGNUM))]
1263   "reload_completed"
1264   "*
1266   if (INTVAL(operands[2]) == 1)
1267     return \"incb\t%0\";
1268   else
1269     return \"decb\t%0\";
1271   [(set_attr "length" "2,4")])
1274 ;;- subtract instructions
1275 ;; we don't have to care for constant second 
1276 ;; args, since they are canonical plus:xx now!
1277 ;; also for minus:DF ??
1279 (define_insn_and_split "subdf3"
1280   [(set (match_operand:DF 0 "register_operand" "=a,a")
1281         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1282                   (match_operand:DF 2 "general_operand" "fR,Q")))]
1283   "TARGET_FPU"
1284   "#"
1285   "&& reload_completed"
1286   [(parallel [(set (match_dup 0)
1287                    (minus:DF (match_dup 1) (match_dup 2)))
1288               (clobber (reg:CC FCC_REGNUM))])]
1289   ""
1290   [(set_attr "length" "2,4")])
1292 (define_insn "*subdf3<fcc_ccnz>"
1293   [(set (match_operand:DF 0 "register_operand" "=a,a")
1294         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1295                   (match_operand:DF 2 "general_operand" "fR,QF")))
1296    (clobber (reg:CC FCC_REGNUM))]
1297   "TARGET_FPU && reload_completed"
1298   "{subd|subf}\t%2,%0"
1299   [(set_attr "length" "2,4")
1300    (set_attr "base_cost" "6")])
1302 (define_insn_and_split "subdi3"
1303   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1304         (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1305                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1306   ""
1307   "#"
1308   "reload_completed"
1309   [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
1310               (clobber (reg:CC CC_REGNUM))])]
1311   ""
1312   [(set_attr "length" "20,28,40,48")])
1314 (define_insn "*subdi3_nocc"
1315   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1316         (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1317               (match_operand:DI 2 "general_operand" "r,on,r,on")))
1318    (clobber (reg:CC CC_REGNUM))]
1319   "reload_completed"
1320   "*
1322   rtx inops[2];
1323   rtx exops[4][2];
1324   
1325   inops[0] = operands[0];
1326   inops[1] = operands[2];
1327   pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
1328   
1329   if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1330     output_asm_insn (\"sub\t%1,%0\", exops[0]);
1331   if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1332   {
1333     output_asm_insn (\"sub\t%1,%0\", exops[1]);
1334     output_asm_insn (\"sbc\t%0\", exops[0]);
1335   }
1336   if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1337   {
1338     output_asm_insn (\"sub\t%1,%0\", exops[2]);
1339     output_asm_insn (\"sbc\t%0\", exops[1]);
1340     output_asm_insn (\"sbc\t%0\", exops[0]);
1341   }
1342   if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1343   {
1344     output_asm_insn (\"sub\t%1,%0\", exops[3]);
1345     output_asm_insn (\"sbc\t%0\", exops[2]);
1346     output_asm_insn (\"sbc\t%0\", exops[1]);
1347     output_asm_insn (\"sbc\t%0\", exops[0]);
1348   }
1350   return \"\";
1352   [(set_attr "length" "20,28,40,48")
1353    (set_attr "base_cost" "0")])
1355 (define_insn_and_split "subsi3"
1356   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1357         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1358                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1359   ""
1360   "#"
1361   "reload_completed"
1362   [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1363               (clobber (reg:CC CC_REGNUM))])]
1364   ""
1365   [(set_attr "length" "6,10,12,16")])
1367 (define_insn "*subsi3_nocc"
1368   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1369         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1370               (match_operand:SI 2 "general_operand" "r,on,r,on")))
1371    (clobber (reg:CC CC_REGNUM))]
1372   "reload_completed"
1373   "*
1375   rtx inops[2];
1376   rtx exops[2][2];
1377   
1378   inops[0] = operands[0];
1379   inops[1] = operands[2];
1380   pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
1381   
1382   if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1383     output_asm_insn (\"sub\t%1,%0\", exops[0]);
1384   if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1385   {
1386     output_asm_insn (\"sub\t%1,%0\", exops[1]);
1387     output_asm_insn (\"sbc\t%0\", exops[0]);
1388   }
1390   return \"\";
1392   [(set_attr "length" "6,10,12,16")
1393    (set_attr "base_cost" "0")])
1395 (define_insn_and_split "subhi3"
1396   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1397         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1398                   (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1399   ""
1400   "#"
1401   "reload_completed"
1402   [(parallel [(set (match_dup 0)
1403                    (minus:HI (match_dup 1) (match_dup 2)))
1404               (clobber (reg:CC CC_REGNUM))])]
1405   ""
1406   [(set_attr "length" "2,4,4,6")])
1408 ;; Note: the manual says that (minus m (const_int n)) is converted
1409 ;; to (plus m (const_int -n)) but that does not appear to be
1410 ;; the case when it's wrapped in a PARALLEL.  So instead we handle
1411 ;; that case here, which is easy enough.
1412 (define_insn "*subhi3<cc_ccnz>"
1413   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1414         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1415                   (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1416    (clobber (reg:CC CC_REGNUM))]
1417   "reload_completed"
1418   "*
1420   if (GET_CODE (operands[2]) == CONST_INT)
1421     {
1422       if (INTVAL(operands[2]) == 1)
1423         return \"dec\t%0\";
1424       else if (INTVAL(operands[2]) == -1)
1425         return \"inc\t%0\";
1426     }
1428   return \"sub\t%2,%0\";
1430   [(set_attr "length" "2,4,4,6")])
1432 (define_insn_and_split "subqi3"
1433   [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1434         (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1435                  (match_operand:QI 2 "incdec_operand" "LM,LM")))]
1436   ""
1437   "#"
1438   "reload_completed"
1439   [(parallel [(set (match_dup 0)
1440                    (plus:QI (match_dup 1) (match_dup 2)))
1441               (clobber (reg:CC CC_REGNUM))])]
1442   ""
1443   [(set_attr "length" "2,4")])
1445 ;; Inc/dec sets V if overflow from the operation
1446 (define_insn "*subqi3<cc_ccnz>"
1447   [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1448         (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1449                  (match_operand:QI 2 "incdec_operand" "LM,LM")))
1450    (clobber (reg:CC CC_REGNUM))]
1451   "reload_completed"
1452   "*
1454   if (INTVAL(operands[2]) == -1)
1455     return \"incb\t%0\";
1456   else
1457     return \"decb\t%0\";
1459   [(set_attr "length" "2,4")])
1461 ;;;;- and instructions
1462 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1464 (define_expand "and<mode>3"
1465   [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
1466         (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
1467                    (match_operand:PDPint 2 "general_operand" "")))]
1468   ""
1469   "
1471   rtx op1 = operands[1];
1473   /* If there is a constant argument, complement that one.
1474      Similarly, if one of the inputs is the same as the output,
1475      complement the other input.  */
1476   if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
1477       rtx_equal_p (operands[0], operands[1]))
1478     {
1479       operands[1] = operands[2];
1480       operands[2] = op1;
1481       op1 = operands[1];
1482     }
1484   if (CONST_INT_P (op1))
1485     operands[1] = GEN_INT (~INTVAL (op1));
1486   else
1487     operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
1489   [(set_attr "length" "2,4,4,6")])
1491 (define_insn_and_split "*bic<mode>"
1492   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1493         (and:PDPint
1494              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1495              (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
1496   ""
1497   "#"
1498   "reload_completed"
1499   [(parallel [(set (match_dup 0)
1500                    (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2)))
1501               (clobber (reg:CC CC_REGNUM))])]
1502   "")
1504 (define_insn "*bic<mode><cc_cc>"
1505   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1506         (and:PDPint
1507              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1508                           (match_operand:PDPint 2 "general_operand" "0,0,0,0")))
1509    (clobber (reg:CC CC_REGNUM))]
1510   "reload_completed"
1511   "bic<PDPint:isfx>\t%1,%0"
1512   [(set_attr "length" "2,4,4,6")])
1514 ;;- Bit set (inclusive or) instructions
1515 (define_insn_and_split "ior<mode>3"
1516   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1517         (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1518                     (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
1519   ""
1520   "#"
1521   "reload_completed"
1522   [(parallel [(set (match_dup 0)
1523                    (ior:PDPint (match_dup 1) (match_dup 2)))
1524               (clobber (reg:CC CC_REGNUM))])]
1525   ""
1526   [(set_attr "length" "2,4,4,6")])
1528 (define_insn "ior<mode>3<cc_cc>"
1529   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1530         (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1531              (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))
1532    (clobber (reg:CC CC_REGNUM))]
1533   "reload_completed"
1534   "bis<PDPint:isfx>\t%2,%0"
1535   [(set_attr "length" "2,4,4,6")])
1537 ;;- xor instructions
1538 (define_insn_and_split "xorhi3"
1539   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1540         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1541                 (match_operand:HI 2 "register_operand" "r,r")))]
1542   "TARGET_40_PLUS"
1543   "#"
1544   "&& reload_completed"
1545   [(parallel [(set (match_dup 0)
1546                    (xor:HI (match_dup 1) (match_dup 2)))
1547               (clobber (reg:CC CC_REGNUM))])]
1548   ""
1549   [(set_attr "length" "2,4")])
1551 (define_insn "*xorhi3<cc_cc>"
1552   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1553         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1554              (match_operand:HI 2 "register_operand" "r,r")))
1555    (clobber (reg:CC CC_REGNUM))]
1556   "TARGET_40_PLUS && reload_completed"
1557   "xor\t%2,%0"
1558   [(set_attr "length" "2,4")])
1560 ;;- one complement instructions
1562 (define_insn_and_split "one_cmpl<mode>2"
1563   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1564         (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1565   ""
1566   "#"
1567   "reload_completed"
1568   [(parallel [(set (match_dup 0)
1569                    (not:PDPint (match_dup 1)))
1570               (clobber (reg:CC CC_REGNUM))])]
1571   ""
1572   [(set_attr "length" "2,4")])
1574 (define_insn "*one_cmpl<mode>2<cc_cc>"
1575   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1576         (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1577    (clobber (reg:CC CC_REGNUM))]
1578   "reload_completed"
1579   "com<PDPint:isfx>\t%0"
1580   [(set_attr "length" "2,4")])
1582 ;;- arithmetic shift instructions
1584 ;; There is a fair amount of complexity here because with -m10
1585 ;; (pdp-11/10, /20) we only have shift by one bit.  Iterators are
1586 ;; used to reduce the amount of very similar code.
1588 ;; First the insns used for small constant shifts.
1589 (define_insn_and_split "<code><mode>_sc"
1590   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1591         (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1592                     (match_operand:HI 2 "expand_shift_operand" "O,O")))]
1593   ""
1594   "#"
1595   "reload_completed"
1596   [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1597               (clobber (reg:CC CC_REGNUM))])]
1598   ""
1599   [(set (attr "length")
1600         (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
1601                                          <CODE>, which_alternative == 0)"))
1602    (set_attr "base_cost" "0")])
1604 (define_insn "<code><mode>_sc<cc_ccnz>"
1605   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rD,Q")
1606         (SHF:PDPint (match_operand:PDPint 1 "general_operand" "0,0")
1607              (match_operand:HI 2 "expand_shift_operand" "O,O")))
1608    (clobber (reg:CC CC_REGNUM))]
1609   "reload_completed"
1610   "* return pdp11_assemble_shift (operands, <PDPint:mname>, <CODE>);"
1611   [(set (attr "length")
1612         (symbol_ref "pdp11_shift_length (operands, <PDPint:mname>, 
1613                                          <CODE>, which_alternative == 0)"))
1614    (set_attr "base_cost" "0")])
1616 ;; This one comes only in clobber flavor.
1617 (define_insn "<code>si_sc_nocc"
1618   [(set (match_operand:SI 0 "nonimmediate_operand" "=rD,Q")
1619         (SHF:SI (match_operand:SI 1 "general_operand" "0,0")
1620              (match_operand:HI 2 "expand_shift_operand" "O,O")))
1621    (clobber (reg:CC CC_REGNUM))]
1622   "reload_completed"
1623   "* return pdp11_assemble_shift (operands, SImode, <CODE>);"
1624   [(set (attr "length")
1625         (symbol_ref "pdp11_shift_length (operands, SImode, 
1626                                          <CODE>, which_alternative == 0)"))
1627    (set_attr "base_cost" "0")])
1629 ;; Next, shifts that are done as a loop on base (11/10 class) machines.
1630 ;; This applies to shift counts too large to unroll, or variable shift
1631 ;; counts.  The check for count <= 0 is done before we get here.
1632 (define_insn_and_split "<code><mode>_base"
1633   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1634         (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1635              (match_operand:HI 2 "register_operand" "r,r")))
1636    (clobber (match_dup 2))]
1637   ""
1638   "#"
1639   "reload_completed"
1640   [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1641               (clobber (match_dup 2))
1642               (clobber (reg:CC CC_REGNUM))])]
1643   ""
1644   [(set (attr "length")
1645         (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
1646                                          <CODE>, which_alternative == 0)"))
1647    (set_attr "base_cost" "0")])
1649 (define_insn "<code><mode>_base_nocc"
1650   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1651         (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1652              (match_operand:HI 2 "register_operand" "r,r")))
1653    (clobber (match_dup 2))
1654    (clobber (reg:CC CC_REGNUM))]
1655   "reload_completed"
1656   "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1657   [(set (attr "length")
1658         (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
1659                                          <CODE>, which_alternative == 0)"))
1660    (set_attr "base_cost" "0")])
1662 ;; Next the insns that use the extended instructions ash and ashc.
1663 ;; Note that these are just left shifts, and HI/SI only.  (Right shifts
1664 ;; are done by shifting by a negative amount.)
1665 (define_insn_and_split "aslhi_op"
1666   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1667         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1668                        (match_operand:HI 2 "general_operand" "rR,Qi")))]
1669   "TARGET_40_PLUS"
1670   "#"
1671   "&& reload_completed"
1672   [(parallel [(set (match_dup 0)
1673                    (ashift:HI (match_dup 1) (match_dup 2)))
1674               (clobber (reg:CC CC_REGNUM))])]
1675   ""
1676   [(set_attr "length" "2,4")
1677    (set_attr "base_cost" "8")])
1679 (define_insn "aslhi_op<cc_ccnz>"
1680   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1681         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1682                 (match_operand:HI 2 "general_operand" "rR,Qi")))
1683    (clobber (reg:CC CC_REGNUM))]
1684   "TARGET_40_PLUS && reload_completed"
1685   "ash\t%2,%0"
1686   [(set_attr "length" "2,4")
1687    (set_attr "base_cost" "8")])
1689 (define_insn_and_split "aslsi_op"
1690   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1691         (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1692                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
1693   "TARGET_40_PLUS"
1694   "#"
1695   "&& reload_completed"
1696   [(parallel [(set (match_dup 0)
1697                    (ashift:SI (match_dup 1) (match_dup 2)))
1698               (clobber (reg:CC CC_REGNUM))])]
1699   ""
1700   [(set_attr "length" "2,4")
1701    (set_attr "base_cost" "8")])
1703 (define_insn "aslsi_op_<cc_ccnz>"
1704   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1705         (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1706                 (match_operand:HI 2 "general_operand" "rR,Qi")))
1707    (clobber (reg:CC CC_REGNUM))]
1708   "TARGET_40_PLUS && reload_completed"
1709   "ashc\t%2,%0"
1710   [(set_attr "length" "2,4")
1711    (set_attr "base_cost" "8")])
1713 ;; Now the expanders that produce the insns defined above. 
1714 (define_expand "ashl<mode>3"
1715   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1716    (match_operand:QHSint 1 "general_operand" "")
1717    (match_operand:HI 2 "general_operand" "")]
1718   ""
1719   "
1721   rtx r;
1723   if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base))
1724     {
1725       if (<QHSint:e_mname> == E_QImode)
1726         {
1727           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1728           emit_insn (gen_aslhi_op (r, r, operands[2]));
1729           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1730         }
1731       else
1732         {
1733           emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1734         }
1735     }
1736   DONE;
1739 (define_expand "ashr<mode>3"
1740   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1741    (match_operand:QHSint 1 "general_operand" "")
1742    (match_operand:HI 2 "general_operand" "")]
1743   ""
1744   "
1746   rtx r;
1748   if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base))
1749     {
1750       operands[2] = negate_rtx (HImode, operands[2]);
1751       if (<QHSint:e_mname> == E_QImode)
1752         {
1753           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1754           emit_insn (gen_aslhi_op (r, r, operands[2]));
1755           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1756         }
1757       else
1758         {
1759           emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1760         }
1761     }
1762   DONE;
1765 (define_expand "lshr<mode>3"
1766   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1767    (match_operand:QHSint 1 "general_operand" "")
1768    (match_operand:HI 2 "general_operand" "")]
1769   ""
1770   "
1772   rtx r, n;
1774   if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base))
1775     {
1776       if (<QHSint:e_mname> == E_QImode)
1777         {
1778           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1779           emit_insn (gen_aslhi_op (r, r, operands[2]));
1780           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1781         }
1782       else
1783         {
1784           r = gen_reg_rtx (<QHSint:mname>);
1785           emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx));
1786           if (GET_CODE (operands[2]) != CONST_INT)
1787             {
1788               n = gen_reg_rtx (HImode);
1789               emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1)));
1790               emit_insn (gen_ashr<mode>3 (operands[0], r, n));
1791             }
1792           else
1793             emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r,
1794                                   GEN_INT (1 - INTVAL (operands[2]))));
1795         }
1796     }
1797   DONE;
1800 ;; absolute 
1802 (define_insn_and_split "absdf2"
1803   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1804         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1805   "TARGET_FPU"
1806   "#"
1807   "&& reload_completed"
1808   [(parallel [(set (match_dup 0) (abs:DF (match_dup 1)))
1809               (clobber (reg:CC FCC_REGNUM))])]
1810    ""
1811   [(set_attr "length" "2,4")])
1813 (define_insn "absdf2<fcc_cc>"
1814   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1815         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))
1816    (clobber (reg:CC FCC_REGNUM))]
1817   "TARGET_FPU && reload_completed"
1818   "{absd|absf}\t%0"
1819   [(set_attr "length" "2,4")])
1821 ;; negate insns
1823 (define_insn_and_split "negdf2"
1824   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1825         (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
1826   "TARGET_FPU"
1827   "#"
1828   "&& reload_completed"
1829   [(parallel [(set (match_dup 0) (neg:DF (match_dup 1)))
1830               (clobber (reg:CC FCC_REGNUM))])]
1831    ""
1832   [(set_attr "length" "2,4")])
1834 (define_insn "negdf2<fcc_cc>"
1835   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1836         (neg:DF (match_operand:DF 1 "general_operand" "0,0")))
1837    (clobber (reg:CC FCC_REGNUM))]
1838   "TARGET_FPU && reload_completed"
1839   "{negd|negf}\t%0"
1840   [(set_attr "length" "2,4")])
1842 (define_insn_and_split "negdi2"
1843   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1844         (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1845   ""
1846   "#"
1847   "reload_completed"
1848   [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
1849               (clobber (reg:CC CC_REGNUM))])]
1850   ""
1851   [(set_attr "length" "18,34")])
1852   
1853 ;; TODO: this can be neg/adc/neg/adc... I believe.  Check.  Saves one word.
1854 (define_insn "negdi2_nocc"
1855   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1856         (neg:DI (match_operand:DI 1 "general_operand" "0,0")))
1857    (clobber (reg:CC CC_REGNUM))]
1858   "reload_completed"
1859   {
1860     rtx inops[2];
1861     rtx exops[4][2];
1863     inops[0] = operands[0];
1864     pdp11_expand_operands (inops, exops, 1, 4, NULL, big);
1865   
1866     output_asm_insn (\"com\t%0\", exops[3]);
1867     output_asm_insn (\"com\t%0\", exops[2]);
1868     output_asm_insn (\"com\t%0\", exops[1]);
1869     output_asm_insn (\"com\t%0\", exops[0]);
1870     output_asm_insn (\"add\t%#1,%0\", exops[3]);
1871     output_asm_insn (\"adc\t%0\", exops[2]);
1872     output_asm_insn (\"adc\t%0\", exops[1]);
1873     output_asm_insn (\"adc\t%0\", exops[0]);
1874   
1875     return \"\";
1876   }
1877   [(set_attr "length" "18,34")
1878    (set_attr "base_cost" "0")])
1880 (define_insn_and_split "negsi2"
1881   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1882         (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1883   ""
1884   "#"
1885   "reload_completed"
1886   [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
1887               (clobber (reg:CC CC_REGNUM))])]
1888   ""
1889   [(set_attr "length" "10,18")])
1890   
1891 ;; TODO: this can be neg/adc/neg/adc... I believe.  Check.  Saves one word.
1892 (define_insn "negsi2_nocc"
1893   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1894         (neg:SI (match_operand:SI 1 "general_operand" "0,0")))
1895    (clobber (reg:CC CC_REGNUM))]
1896   "reload_completed"
1897   {
1898     rtx inops[2];
1899     rtx exops[4][2];
1901     inops[0] = operands[0];
1902     pdp11_expand_operands (inops, exops, 1, 2, NULL, big);
1903   
1904     output_asm_insn (\"com\t%0\", exops[1]);
1905     output_asm_insn (\"com\t%0\", exops[0]);
1906     output_asm_insn (\"add\t%#1,%0\", exops[1]);
1907     output_asm_insn (\"adc\t%0\", exops[0]);
1908   
1909     return \"\";
1910   }
1911   [(set_attr "length" "10,18")
1912    (set_attr "base_cost" "0")])
1914 (define_insn_and_split "neg<mode>2"
1915   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1916         (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1917   ""
1918   "#"
1919   "reload_completed"
1920   [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1)))
1921               (clobber (reg:CC CC_REGNUM))])]
1922   ""
1923   [(set_attr "length" "2,4")])
1924   
1925 (define_insn "neg<mode>2<cc_ccnz>"
1926   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1927         (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1928    (clobber (reg:CC CC_REGNUM))]
1929   ""
1930   "neg<PDPint:isfx>\t%0"
1931   [(set_attr "length" "2,4")])
1934 ;; Unconditional and other jump instructions
1935 (define_insn "jump"
1936   [(set (pc)
1937         (label_ref (match_operand 0 "" "")))]
1938   ""
1939   "*
1941   if (get_attr_length (insn) == 2)
1942     return \"br\t%l0\";
1943   return \"jmp\t%l0\";
1945   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1946                                                       (pc))
1947                                                (const_int MIN_BRANCH))
1948                                            (gt (minus (match_dup 0)
1949                                                       (pc))
1950                                                (const_int MAX_BRANCH)))
1951                                       (const_int 4)
1952                                       (const_int 2)))])
1954 (define_insn "tablejump"
1955   [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1956    (use (label_ref (match_operand 1 "" "")))]
1957   ""
1958   "@
1959   jmp\t(%0)
1960   jmp\t%@%0
1961   jmp\t%@%0"
1962   [(set_attr "length" "2,2,4")])
1964 ;; indirect jump.  TODO: this needs a constraint that allows memory
1965 ;; references but not indirection, since we add a level of indirection
1966 ;; in the generated code.
1967 (define_insn "indirect_jump"
1968   [(set (pc) (match_operand:HI 0 "general_operand" "r"))]
1969   ""
1970   "jmp\t@%0"
1971   [(set_attr "length" "2")])
1973 ;;- jump to subroutine
1975 (define_insn "call"
1976   [(call (match_operand:HI 0 "general_operand" "rR,Q")
1977          (match_operand:HI 1 "general_operand" "g,g"))]
1978   ;;- Don't use operand 1 for most machines.
1979   ""
1980   "jsr\tpc,%0"
1981   [(set_attr "length" "2,4")])
1983 ;;- jump to subroutine
1984 (define_insn "call_value"
1985   [(set (match_operand 0 "" "")
1986         (call (match_operand:HI 1 "general_operand" "rR,Q")
1987               (match_operand:HI 2 "general_operand" "g,g")))]
1988   ;;- Don't use operand 2 for most machines.
1989   ""
1990   "jsr\tpc,%1"
1991   [(set_attr "length" "2,4")])
1993 (define_expand "untyped_call"
1994   [(parallel [(call (match_operand 0 "" "")
1995                     (const_int 0))
1996               (match_operand 1 "" "")
1997               (match_operand 2 "" "")])]
1998   ""
2000   int i;
2002   emit_call_insn (gen_call (operands[0], const0_rtx));
2004   for (i = 0; i < XVECLEN (operands[2], 0); i++)
2005     {
2006       rtx set = XVECEXP (operands[2], 0, i);
2007       emit_move_insn (SET_DEST (set), SET_SRC (set));
2008     }
2010   /* The optimizer does not know that the call sets the function value
2011      registers we stored in the result block.  We avoid problems by
2012      claiming that all hard registers are used and clobbered at this
2013      point.  */
2014   emit_insn (gen_blockage ());
2016   DONE;
2019 ;;- nop instruction
2020 (define_insn "nop"
2021   [(const_int 0)]
2022   ""
2023   "nop")
2026 ;;- multiply 
2028 (define_insn_and_split "muldf3"
2029   [(set (match_operand:DF 0 "register_operand" "=a,a")
2030         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
2031                  (match_operand:DF 2 "float_operand" "fR,QF")))]
2032   "TARGET_FPU"
2033   "#"
2034   "&& reload_completed"
2035   [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2)))
2036               (clobber (reg:CC FCC_REGNUM))])]
2037   ""
2038   [(set_attr "length" "2,4")])
2040 (define_insn "muldf3<fcc_ccnz>"
2041   [(set (match_operand:DF 0 "register_operand" "=a,a")
2042         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
2043               (match_operand:DF 2 "float_operand" "fR,QF")))
2044    (clobber (reg:CC FCC_REGNUM))]
2045   "TARGET_FPU && reload_completed"
2046   "{muld|mulf}\t%2,%0"
2047   [(set_attr "length" "2,4")
2048    (set_attr "base_cost" "20")])
2050 ;; 16 bit result multiply.  This uses odd numbered registers.
2052 (define_insn_and_split "mulhi3"
2053   [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
2054         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2055                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
2056   "TARGET_40_PLUS"
2057   "#"
2058   "&& reload_completed"
2059   [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2)))
2060               (clobber (reg:CC CC_REGNUM))])]
2061   ""
2062   [(set_attr "length" "2,4")])
2064 (define_insn "mulhi3<cc_cc>"
2065   [(set (match_operand:HI 0 "register_operand" "=d,d")
2066         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2067               (match_operand:HI 2 "general_operand" "rR,Qi")))
2068    (clobber (reg:CC CC_REGNUM))]
2069   "TARGET_40_PLUS && reload_completed"
2070   "mul\t%2,%0"
2071   [(set_attr "length" "2,4")
2072    (set_attr "base_cost" "20")])
2074 ;; 32 bit result from 16 bit operands
2075 (define_insn_and_split "mulhisi3"
2076   [(set (match_operand:SI 0 "register_operand" "=r,r")
2077         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
2078                  (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))]
2079   "TARGET_40_PLUS"
2080   "#"
2081   "&& reload_completed"
2082   [(parallel [(set (match_dup 0)
2083                    (mult:SI (sign_extend:SI (match_dup 1))
2084                          (sign_extend:SI (match_dup 2))))
2085               (clobber (reg:CC CC_REGNUM))])]
2086   ""
2087   [(set_attr "length" "2,4")])
2089 (define_insn "mulhisi3<cc_cc>"
2090   [(set (match_operand:SI 0 "register_operand" "=r,r")
2091         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
2092               (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))
2093    (clobber (reg:CC CC_REGNUM))]
2094   "TARGET_40_PLUS && reload_completed"
2095   "mul\t%2,%0"
2096   [(set_attr "length" "2,4")
2097    (set_attr "base_cost" "20")])
2099 ;;- divide
2100 (define_insn_and_split "divdf3"
2101   [(set (match_operand:DF 0 "register_operand" "=a,a")
2102         (div:DF (match_operand:DF 1 "register_operand" "0,0")
2103                 (match_operand:DF 2 "general_operand" "fR,QF")))]
2104   "TARGET_FPU"
2105   "#"
2106   "&& reload_completed"
2107   [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2)))
2108               (clobber (reg:CC FCC_REGNUM))])]
2109    ""
2110   [(set_attr "length" "2,4")])
2111   
2112 (define_insn "divdf3<fcc_ccnz>"
2113   [(set (match_operand:DF 0 "register_operand" "=a,a")
2114         (div:DF (match_operand:DF 1 "register_operand" "0,0")
2115              (match_operand:DF 2 "general_operand" "fR,QF")))
2116    (clobber (reg:CC FCC_REGNUM))]
2117   "TARGET_FPU && reload_completed"
2118   "{divd|divf}\t%2,%0"
2119   [(set_attr "length" "2,4")
2120    (set_attr "base_cost" "20")])
2122 (define_expand "divmodhi4"
2123   [(parallel
2124     [(set (subreg:HI (match_dup 1) 0)
2125         (div:HI (match_operand:SI 1 "register_operand" "0")
2126                 (match_operand:HI 2 "general_operand" "g")))
2127      (set (subreg:HI (match_dup 1) 2)
2128         (mod:HI (match_dup 1) (match_dup 2)))])
2129    (set (match_operand:HI 0 "register_operand" "=r")
2130         (subreg:HI (match_dup 1) 0))
2131    (set (match_operand:HI 3 "register_operand" "=r")
2132         (subreg:HI (match_dup 1) 2))]
2133   "TARGET_40_PLUS"
2134   "")
2136 (define_insn_and_split "*divmodhi4"
2137   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
2138         (div:HI (match_operand:SI 1 "register_operand" "0,0")
2139              (match_operand:HI 2 "general_operand" "rR,Qi")))
2140    (set (subreg:HI (match_dup 1) 2)
2141         (mod:HI (match_dup 1) (match_dup 2)))]
2142   "TARGET_40_PLUS"
2143   "#"
2144   "&& reload_completed"
2145   [(parallel [(set (subreg:HI (match_dup 0) 0)
2146                    (div:HI (match_dup 1) (match_dup 2)))
2147               (set (subreg:HI (match_dup 1) 2)
2148                    (mod:HI (match_dup 1) (match_dup 2)))
2149               (clobber (reg:CC CC_REGNUM))])]
2150   ""
2151   [(set_attr "length" "2,4")])
2153 ;; Note that there is no corresponding CC setter pattern.
2154 ;; The reason is that it won't be generated, because
2155 ;; compare-elim.c only does the transformation on input
2156 ;; insns that have a two-element PARALLEL, as opposed to
2157 ;; the three-element one we have here.     
2158 (define_insn "divmodhi4_nocc"
2159   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
2160         (div:HI (match_operand:SI 1 "register_operand" "0,0")
2161                 (match_operand:HI 2 "general_operand" "rR,Qi")))
2162    (set (subreg:HI (match_dup 1) 2)
2163         (mod:HI (match_dup 1) (match_dup 2)))
2164    (clobber (reg:CC CC_REGNUM))]
2165   "TARGET_40_PLUS"
2166    "div\t%2,%0"
2167   [(set_attr "length" "2,4")
2168    (set_attr "base_cost" "40")])
2170 ;; Byte swap
2171 (define_insn_and_split "bswaphi2"
2172   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2173         (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))]
2174   ""
2175   "#"
2176   "reload_completed"
2177   [(parallel [(set (match_dup 0) (bswap:HI (match_dup 1)))
2178               (clobber (reg:CC CC_REGNUM))])]
2179   ""
2180   [(set_attr "length" "2,4")])
2182 (define_insn "bswaphi2<cc_ccnz>"
2183   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2184         (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))
2185    (clobber (reg:CC CC_REGNUM))]
2186   ""
2187   "swab\t%0"
2188   [(set_attr "length" "2,4")])
2190 (define_insn_and_split "bswapsi2"
2191   [(set (match_operand:SI 0 "register_operand" "=&r")
2192         (bswap:SI (match_operand:SI 1 "general_operand" "g")))]
2193   ""
2194   "#"
2195   "reload_completed"
2196   [(parallel [(set (match_dup 0)
2197                    (bswap:SI (match_dup 1)))
2198               (clobber (reg:CC CC_REGNUM))])]
2199   ""
2200   [(set_attr "length" "10")])
2202 (define_insn "bswapsi2_nocc"
2203   [(set (match_operand:SI 0 "register_operand" "=&r,&r,&r")
2204         (bswap:SI (match_operand:SI 1 "general_operand" "r,D,Q")))
2205    (clobber (reg:CC CC_REGNUM))]
2206   ""
2207   {
2208     rtx inops[2];
2209     rtx exops[2][2];
2210     rtx t;
2212     inops[0] = operands[0];
2213     inops[1] = operands[1];
2214     pdp11_expand_operands (inops, exops, 2, 2, NULL, either);
2216     t = exops[0][0];
2217     exops[0][0] = exops[1][0];
2218     exops[1][0] = t;
2220     output_asm_insn ("mov\t%0,%1", exops[0]);
2221     output_asm_insn ("mov\t%0,%1", exops[1]);
2222     output_asm_insn ("swab\t%0", exops[0]);
2223     output_asm_insn ("swab\t%0", exops[1]);
2224     return "";
2225   }
2226   [(set_attr "length" "8,10,12")])
2228 (define_expand "rotrhi3"
2229   [(match_operand:HI 0 "register_operand" "")
2230    (match_operand:HI 1 "register_operand" "")
2231    (match_operand:HI 2 "general_operand" "")]
2232   "TARGET_40_PLUS"
2233   "
2235   operands[2] = negate_rtx (HImode, operands[2]);
2236   emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2]));
2237   DONE;
2240 (define_insn_and_split "rotlhi3"
2241   [(set (match_operand:HI 0 "register_operand" "=d,d")
2242         (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2243                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
2244   "TARGET_40_PLUS"
2245   "#"
2246   "&& reload_completed"
2247   [(parallel [(set (match_dup 0)
2248                    (rotate:HI (match_dup 1) (match_dup 2)))
2249               (clobber (reg:CC CC_REGNUM))])]
2250   ""
2251   [(set_attr "length" "2,4")
2252    (set_attr "base_cost" "8")])
2254 (define_insn "rotlhi3<cc_ccnz>"
2255   [(set (match_operand:HI 0 "register_operand" "=d,d")
2256         (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2257                    (match_operand:HI 2 "general_operand" "rR,Qi")))
2258    (clobber (reg:CC CC_REGNUM))]
2259   "TARGET_40_PLUS && reload_completed"
2260   "ashc\t%2,%0"
2261   [(set_attr "length" "2,4")
2262    (set_attr "base_cost" "8")])
2265   
2266 ;; Some peephole optimizations
2268 ;; Move then conditional branch on the result of the move is handled
2269 ;; by compare elimination, but an earlier pass sometimes changes the
2270 ;; compare operand to the move input, and then the compare is not
2271 ;; eliminated.  Do so here.
2272 (define_peephole2
2273   [(parallel [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
2274                    (match_operand:PDPint 1 "general_operand" ""))
2275               (clobber (reg:CC CC_REGNUM))])
2276    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))]
2277   ""
2278   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
2279               (set (match_dup 0) (match_dup 1))])]
2280   "")