xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/pdp11/pdp11.md (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1;;- Machine description for the pdp11 for GNU C compiler
2;; Copyright (C) 1994-2020 Free Software Foundation, Inc.
3;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
4
5;; This file is part of GCC.
6
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.
11
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.
16
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/>.
20
21(include "predicates.md")
22(include "constraints.md")
23
24(define_c_enum "unspecv"
25  [
26    UNSPECV_BLOCKAGE
27    UNSPECV_SETD
28    UNSPECV_SETI
29    UNSPECV_CPYMEM
30  ])
31
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)])
63
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
69
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")])
77
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])
82
83(define_code_iterator SHF [ashift ashiftrt lshiftrt])
84
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))])
94
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))])
102
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))])
110
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))])
118
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")
123
124;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
125
126;; Compare instructions.
127
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)
137
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 ()
141
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"))
146
147;; length default is 2 bytes each
148(define_attr "length" "" (const_int 2))
149
150;; instruction base cost (not counting operands)
151(define_attr "base_cost" "" (const_int 2))
152
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")])
160
161;; define function units
162
163;; Prologue and epilogue support.
164
165(define_expand "prologue"
166  [(const_int 0)]
167  ""
168{
169  pdp11_expand_prologue ();
170  DONE;
171})
172
173(define_expand "epilogue"
174  [(const_int 0)]
175  ""
176{
177  pdp11_expand_epilogue ();
178  DONE;
179})
180
181(define_insn "rtspc"
182  [(return)]
183  ""
184  "rts\tpc")
185
186(define_insn "blockage"
187  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
188  ""
189  ""
190  [(set_attr "length" "0")])
191
192(define_insn "setd"
193  [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
194  ""
195  "setd")
196
197(define_insn "seti"
198  [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
199  ""
200  "seti")
201
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)
205
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)
208
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  "*
216{
217  if (which_alternative == 0 || which_alternative == 2)
218    return \"{tstd|tstf}\t%0\";
219  else
220    return \"{cmpd|cmpf}\t%0,%1\";
221}"
222  [(set_attr "length" "2,2,4,4")
223   (set_attr "base_cost" "4")
224   (set_attr "type" "fp")])
225
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")
232
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")])
246
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  ""
253{
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);
274
275  return "";
276}
277  [(set (attr "length")
278	(symbol_ref "pdp11_cmp_length (operands, 2)"))
279   (set_attr "base_cost" "0")])
280
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  ""
287{
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 ();
297
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);
312
313  return "";
314}
315  [(set (attr "length")
316	(symbol_ref "pdp11_cmp_length (operands, 2)"))
317   (set_attr "base_cost" "0")])
318
319;; sob instruction
320;;
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  }")
339
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  "")
365
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  "*
383{
384 rtx lb[1];
385
386 if (get_attr_length (insn) == 2)
387    return \"sob\t%0,%l1\";
388
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);
394
395 output_asm_label (lb[0]);
396 fputs (\":\\n\", asm_out_file);
397
398 return \"\";
399}"
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))))])
409
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  "")
434
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  "")
453
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  "")
470
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)))])
487
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)))])
504
505
506;; Move instructions
507
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")])
518
519
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")])
527
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")])
534
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")])
542
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")])
556
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  "*
575{
576  if (operands[1] == const0_rtx)
577    return \"clr<PDPint:isfx>\t%0\";
578
579  return \"mov<PDPint:isfx>\t%1,%0\";
580}"
581  [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
582
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.
586;;
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.
591
592(define_expand "movdf"
593  [(set (match_operand:DF 0 "float_nonimm_operand" "")
594        (match_operand:DF 1 "float_operand" ""))]
595  "TARGET_FPU"
596  "")
597
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")])
619
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")])
631
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")])
665
666;; Expand a block move.  We turn this into a move loop.
667(define_expand "cpymemhi"
668  [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
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  "
679{
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));
690
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));
694}")
695
696;; Expand a block move.  We turn this into a move loop.
697(define_insn_and_split "cpymemhi1"
698  [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
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_CPYMEM)
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  "")
721
722(define_insn "cpymemhi_nocc"
723  [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
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  "*
735{
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 \"\";
755}"
756  [(set (attr "length")
757	(if_then_else (match_test "TARGET_40_PLUS")
758		      (const_int 4)
759		      (const_int 6)))])
760
761;;- truncation instructions
762
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")])
786
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")])
794
795
796;;- zero extension instruction
797
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;
808
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")])
827
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
837
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")])
861
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")])
870
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")])
882
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")])
891
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")])
902
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  "*
909{
910  rtx latehalf[2];
911
912  /* we don't want to mess with auto increment */
913
914  switch (which_alternative)
915  {
916    case 0:
917
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);
923
924      return \"\";
925
926    case 1:
927
928      /* - auto-decrement - right direction ;-) */
929      output_asm_insn(\"mov\t%1,%0\", operands);
930      output_asm_insn(\"sxt\t%0\", operands);
931
932      return \"\";
933
934    case 2:
935
936      /* make register pair available */
937      latehalf[0] = operands[0];
938      operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
939
940      output_asm_insn(\"mov\t%1,%0\", operands);
941      output_asm_insn(\"sxt\t%0\", latehalf);
942
943      return \"\";
944
945    default:
946
947      gcc_unreachable ();
948  }
949}"
950  [(set_attr "length" "10,6,6")])
951
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 ?
955
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")])
970
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];
979
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")])
995
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")])
1006
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")])
1015
1016;; cut float to int
1017
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")])
1033
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")])
1056
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")])
1068
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")])
1079
1080
1081;;- arithmetic instructions
1082;;- add instructions
1083
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")])
1096
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")])
1107
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")])
1119
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  "*
1127{
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  }
1155
1156  return \"\";
1157}"
1158  [(set_attr "length" "20,28,40,48")
1159   (set_attr "base_cost" "0")])
1160
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")])
1181
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  "*
1189{
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  }
1204
1205  return \"\";
1206}"
1207  [(set_attr "length" "6,10,12,16")
1208   (set_attr "base_cost" "0")])
1209
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")])
1222
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  "*
1231{
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    }
1239
1240  return \"add\t%2,%0\";
1241}"
1242  [(set_attr "length" "2,4,4,6")])
1243
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")])
1256
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  "*
1265{
1266  if (INTVAL(operands[2]) == 1)
1267    return \"incb\t%0\";
1268  else
1269    return \"decb\t%0\";
1270}"
1271  [(set_attr "length" "2,4")])
1272
1273
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 ??
1278
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")])
1291
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")])
1301
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")])
1313
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  "*
1321{
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  }
1349
1350  return \"\";
1351}"
1352  [(set_attr "length" "20,28,40,48")
1353   (set_attr "base_cost" "0")])
1354
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")])
1366
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  "*
1374{
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  }
1389
1390  return \"\";
1391}"
1392  [(set_attr "length" "6,10,12,16")
1393   (set_attr "base_cost" "0")])
1394
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")])
1407
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  "*
1419{
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    }
1427
1428  return \"sub\t%2,%0\";
1429}"
1430  [(set_attr "length" "2,4,4,6")])
1431
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")])
1444
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  "*
1453{
1454  if (INTVAL(operands[2]) == -1)
1455    return \"incb\t%0\";
1456  else
1457    return \"decb\t%0\";
1458}"
1459  [(set_attr "length" "2,4")])
1460
1461;;;;- and instructions
1462;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1463
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  "
1470{
1471  rtx op1 = operands[1];
1472
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    }
1483
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);
1488}"
1489  [(set_attr "length" "2,4,4,6")])
1490
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  "")
1503
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")])
1513
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")])
1527
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")])
1536
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")])
1550
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")])
1559
1560;;- one complement instructions
1561
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")])
1573
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")])
1581
1582;;- arithmetic shift instructions
1583;;
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.
1587;;
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")])
1603
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")])
1615
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")])
1628
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")])
1648
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")])
1661
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")])
1678
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")])
1688
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")])
1702
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")])
1712
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  "
1720{
1721  rtx r;
1722
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;
1737}")
1738
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  "
1745{
1746  rtx r;
1747
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;
1763}")
1764
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  "
1771{
1772  rtx r, n;
1773
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;
1798}")
1799
1800;; absolute
1801
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")])
1812
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")])
1820
1821;; negate insns
1822
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")])
1833
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")])
1841
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];
1862
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")])
1879
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];
1900
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")])
1913
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")])
1932
1933
1934;; Unconditional and other jump instructions
1935(define_insn "jump"
1936  [(set (pc)
1937	(label_ref (match_operand 0 "" "")))]
1938  ""
1939  "*
1940{
1941  if (get_attr_length (insn) == 2)
1942    return \"br\t%l0\";
1943  return \"jmp\t%l0\";
1944}"
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)))])
1953
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")])
1963
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")])
1972
1973;;- jump to subroutine
1974
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")])
1982
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")])
1992
1993(define_expand "untyped_call"
1994  [(parallel [(call (match_operand 0 "" "")
1995		    (const_int 0))
1996	      (match_operand 1 "" "")
1997	      (match_operand 2 "" "")])]
1998  ""
1999{
2000  int i;
2001
2002  emit_call_insn (gen_call (operands[0], const0_rtx));
2003
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    }
2009
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 ());
2015
2016  DONE;
2017})
2018
2019;;- nop instruction
2020(define_insn "nop"
2021  [(const_int 0)]
2022  ""
2023  "nop")
2024
2025
2026;;- multiply
2027
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")])
2039
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")])
2049
2050;; 16 bit result multiply.  This uses odd numbered registers.
2051
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")])
2063
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")])
2073
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")])
2088
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")])
2098
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")])
2121
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  "")
2135
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")])
2152
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")])
2169
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")])
2181
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")])
2189
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")])
2201
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;
2211
2212    inops[0] = operands[0];
2213    inops[1] = operands[1];
2214    pdp11_expand_operands (inops, exops, 2, 2, NULL, either);
2215
2216    t = exops[0][0];
2217    exops[0][0] = exops[1][0];
2218    exops[1][0] = t;
2219
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")])
2227
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  "
2234{
2235  operands[2] = negate_rtx (HImode, operands[2]);
2236  emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2]));
2237  DONE;
2238}")
2239
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")])
2253
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")])
2263
2264
2265
2266;; Some peephole optimizations
2267
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  "")
2281