Fix insn length for pdp11 shift patterns.
[official-gcc.git] / gcc / config / pdp11 / pdp11.md
blob6592a2cb806a0f8bc96a16d29ca9ee049e8c8562
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   ])
31 (define_constants
32   [
33    ;; Register numbers
34    (R0_REGNUM             0)
35    (RETVAL_REGNUM         0)
36    (HARD_FRAME_POINTER_REGNUM  5)
37    (STACK_POINTER_REGNUM  6)
38    (PC_REGNUM             7)
39    (AC0_REGNUM            8)
40    (AC3_REGNUM            11)
41    (AC4_REGNUM            12)
42    (AC5_REGNUM            13)
43    ;; The next two are not physical registers but are used for addressing
44    ;; arguments.
45    (FRAME_POINTER_REGNUM  14)
46    (ARG_POINTER_REGNUM    15)
47    ;; Condition code registers
48    (CC_REGNUM             16)
49    (FCC_REGNUM            17)
50    ;; End of hard registers
51    (FIRST_PSEUDO_REGISTER 18)
52    
53    ;; Branch offset limits, as byte offsets from instruction address
54    (MIN_BRANCH            -254)
55    (MAX_BRANCH            256)
56    (MIN_SOB               -126)
57    (MAX_SOB               0)])
59 ;; DF is 64 bit
60 ;; SF is 32 bit
61 ;; SI is 32 bit
62 ;; HI is 16 bit
63 ;; QI is 8 bit 
65 ;; Integer modes supported on the PDP11, with a mapping from machine mode
66 ;; to mnemonic suffix.  SImode and DImode are usually special cases.
67 (define_mode_iterator PDPint [QI HI])
68 (define_mode_attr  isfx [(QI "b") (HI "")])
69 (define_mode_attr  mname [(QI "QImode") (HI "HImode") (SI "SImode") (DI "DImode")])
70 (define_mode_attr  e_mname [(QI "E_QImode") (HI "E_HImode") (SI "E_SImode") (DI "E_DImode")])
71 (define_mode_attr  hmode [(QI "hi") (HI "hi") (SI "si") (DI "di")])
73 ;; These are analogous for use in splitters and expanders.
74 (define_mode_iterator HSint [HI SI])
75 (define_mode_iterator QHSint [QI HI SI])
76 (define_mode_iterator QHSDint [QI HI SI DI])
78 (define_code_iterator SHF [ashift ashiftrt lshiftrt])
80 ;; Substitution to turn a CC clobber into a CC setter.  We have four of
81 ;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
82 (define_subst "cc_cc"
83   [(set (match_operand 0 "") (match_operand 1 ""))
84    (clobber (reg CC_REGNUM))]
85   ""
86   [(set (reg:CC CC_REGNUM)
87         (compare:CC (match_dup 1) (const_int 0)))
88    (set (match_dup 0) (match_dup 1))])
90 (define_subst "cc_ccnz"
91   [(set (match_operand 0 "") (match_operand 1 ""))
92    (clobber (reg CC_REGNUM))]
93   ""
94   [(set (reg:CCNZ CC_REGNUM)
95         (compare:CCNZ (match_dup 1) (const_int 0)))
96    (set (match_dup 0) (match_dup 1))])
98 (define_subst "fcc_cc"
99   [(set (match_operand 0 "") (match_operand 1 ""))
100    (clobber (reg FCC_REGNUM))]
101   ""
102   [(set (reg:CC FCC_REGNUM)
103         (compare:CC (match_dup 1) (const_int 0)))
104    (set (match_dup 0) (match_dup 1))])
106 (define_subst "fcc_ccnz"
107   [(set (match_operand 0 "") (match_operand 1 ""))
108    (clobber (reg FCC_REGNUM))]
109   ""
110   [(set (reg:CCNZ FCC_REGNUM)
111         (compare:CCNZ (match_dup 1) (const_int 0)))
112    (set (match_dup 0) (match_dup 1))])
114 (define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
115 (define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc")
116 (define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc")
117 (define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc")
119 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
121 ;; Compare instructions.
123 ;; currently we only support df floats, which saves us quite some
124 ;; hassle switching the FP mode! 
125 ;; we assume that CPU is always in long float mode, and 
126 ;; 16 bit integer mode - currently, the prologue for main does this,
127 ;; but maybe we should just set up a NEW crt0 properly, 
128 ;; -- and what about signal handling code?
129 ;; (we don't even let sf floats in the register file, so
130 ;; we only should have to worry about truncating and widening 
131 ;; when going to memory)
133 ;; abort() call by g++ - must define libfunc for cmp_optab
134 ;; and ucmp_optab for mode SImode, because we don't have that!!!
135 ;; - yet since no libfunc is there, we abort ()
137 ;; define attributes
138 ;; currently type is only fpu or arith or unknown, maybe branch later ?
139 ;; default is arith
140 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
142 ;; length default is 2 bytes each
143 (define_attr "length" "" (const_int 2))
145 ;; a user's asm statement
146 (define_asm_attributes
147   [(set_attr "type" "unknown")
148 ; length for asm is the max length per statement.  That would be
149 ; 3 words, for a two-operand instruction with extra word addressing
150 ; modes for both operands.
151    (set_attr "length" "6")])
153 ;; define function units
155 ;; Prologue and epilogue support.
157 (define_expand "prologue"
158   [(const_int 0)]
159   ""
161   pdp11_expand_prologue ();
162   DONE;
165 (define_expand "epilogue"
166   [(const_int 0)]
167   ""
169   pdp11_expand_epilogue ();
170   DONE;
173 (define_expand "return"
174   [(return)]
175   "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
176   "")
178 (define_insn "*rts"
179   [(return)]
180   ""
181   "rts pc")
183 (define_insn "blockage"
184   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
185   ""
186   ""
187   [(set_attr "length" "0")])
189 (define_insn "setd"
190   [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
191   ""
192   "setd")
194 (define_insn "seti"
195   [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
196   ""
197   "seti")
199 ;; arithmetic - values here immediately when next insn issued
200 ;; or does it mean the number of cycles after this insn was issued?
201 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
203 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
204 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
206 ;; compare
207 (define_insn "*cmpdf"
208   [(set (reg:CC FCC_REGNUM)
209         (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
210                     (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
211   "TARGET_FPU && reload_completed"
212   "*
214   if (which_alternative == 0 || which_alternative == 2)
215     return \"{tstd|tstf} %0\";
216   else
217     return \"{cmpd|cmpf} %0, %1\";
219   [(set_attr "length" "2,2,4,4")
220    (set_attr "type" "fp")]) 
222 ;; Copy floating point processor condition code register to main CPU
223 ;; condition code register.
224 (define_insn "*cfcc"
225   [(set (reg CC_REGNUM) (reg FCC_REGNUM))]
226   "TARGET_FPU && reload_completed"
227   "cfcc")
229 (define_insn "cmp<mode>"
230   [(set (reg:CC CC_REGNUM)
231         (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
232                     (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
233   ""
234   "@
235    tst<PDPint:isfx> %0
236    cmp<PDPint:isfx> %0,%1
237    cmp<PDPint:isfx> %0,%1
238    tst<PDPint:isfx> %0
239    cmp<PDPint:isfx> %0,%1
240    cmp<PDPint:isfx> %0,%1"
241   [(set_attr "length" "2,2,4,4,4,6")])
243 ;; sob instruction - FIXME: this doesn't do anything, need to use doloop_end.
245 (define_insn ""
246   [(set (pc)
247         (if_then_else
248          (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
249                       (const_int -1))
250              (const_int 0))
251          (label_ref (match_operand 1 "" ""))
252          (pc)))
253    (set (match_dup 0)
254         (plus:HI (match_dup 0)
255                  (const_int -1)))]
256   "TARGET_40_PLUS"
257   "*
259  if (get_attr_length (insn) == 2)
260     return \"sob %0, %l1\";
262  /* emulate sob */
263  operands[2] = gen_label_rtx ();
264  output_asm_insn (\"dec %0\", operands);
265  output_asm_insn (\"beq %l2\", operands);
266  output_asm_insn (\"jmp %l1\", operands);
268  output_asm_label (operands[2]);
269  fputs (\":\\n\", asm_out_file);
271  return \"\";
273   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
274                                                        (pc))
275                                                 (const_int MIN_SOB))
276                                            (gt (minus (match_dup 0)
277                                                        (pc))
278                                                 (const_int MAX_SOB)))
279                                       (const_int 8)
280                                       (const_int 2)))])
282 ;; These control RTL generation for conditional jump insns
283 ;; and match them for register allocation.
284 ;; Post reload these get expanded into insns that actually
285 ;; manipulate the condition code registers.  We can't do that before
286 ;; because instructions generated by reload clobber condition codes (new
287 ;; CC design, type #2).
288 (define_insn_and_split "cbranchdf4"
289   [(set (pc)
290         (if_then_else (match_operator 0 "ordered_comparison_operator"
291                        [(match_operand:DF 1 "general_operand" "fg")
292                         (match_operand:DF 2 "general_operand" "a")])
293                       (label_ref (match_operand 3 "" ""))
294                       (pc)))]
295   "TARGET_FPU"
296   "#"
297   "&& reload_completed"
298   [(set (reg:CC FCC_REGNUM)
299         (compare:CC (match_dup 1) (match_dup 2)))
300    (set (pc)
301         (if_then_else (match_op_dup 0
302                       [(reg:CC FCC_REGNUM) (const_int 0)])
303                       (label_ref (match_dup 3))
304                       (pc)))]
305   "")
307 (define_insn_and_split "cbranch<mode>4"
308   [(set (pc)
309         (if_then_else (match_operator 0 "ordered_comparison_operator"
310                        [(match_operand:PDPint 1 "general_operand" "g")
311                         (match_operand:PDPint 2 "general_operand" "g")])
312                       (label_ref (match_operand 3 "" ""))
313                       (pc)))]
314   ""
315   "#"
316   "reload_completed"
317   [(set (reg:CC CC_REGNUM)
318         (compare:CC (match_dup 1) (match_dup 2)))
319    (set (pc)
320         (if_then_else (match_op_dup 0
321                       [(reg:CC CC_REGNUM) (const_int 0)])
322                       (label_ref (match_dup 3))
323                       (pc)))]
324   "")
326 ;; This splitter turns a branch on float condition into a branch on
327 ;; CPU condition, by adding a CFCC.
328 (define_split
329   [(set (pc)
330         (if_then_else (match_operator 0 "ordered_comparison_operator"
331                       [(reg:CC FCC_REGNUM) (const_int 0)])
332                       (label_ref (match_operand 1 "" ""))
333                       (pc)))]
334   "TARGET_FPU && reload_completed"
335   [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM))
336    (set (pc)
337         (if_then_else (match_op_dup 0
338                       [(reg:CC CC_REGNUM) (const_int 0)])
339                       (label_ref (match_dup 1))
340                       (pc)))]
341   "")
343 (define_insn "cond_branch"
344   [(set (pc)
345         (if_then_else (match_operator 0 "ordered_comparison_operator"
346                        [(reg:CC CC_REGNUM) (const_int 0)])
347                       (label_ref (match_operand 1 "" ""))
348                       (pc)))]
349   "reload_completed"
350   "* return output_jump (operands, 0, get_attr_length (insn));"
351   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
352                                                       (pc))
353                                                (const_int MIN_BRANCH))
354                                            (gt (minus (match_dup 1)
355                                                       (pc))
356                                                (const_int MAX_BRANCH)))
357                                       (const_int 6)
358                                       (const_int 2)))])
360 (define_insn "*branch"
361   [(set (pc)
362         (if_then_else (match_operator 0 "ccnz_operator"
363                        [(reg:CCNZ CC_REGNUM) (const_int 0)])
364                       (label_ref (match_operand 1 "" ""))
365                       (pc)))]
366   "reload_completed"
367   "* return output_jump (operands, 1, get_attr_length (insn));"
368   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
369                                                       (pc))
370                                                (const_int MIN_BRANCH))
371                                            (gt (minus (match_dup 1)
372                                                       (pc))
373                                                (const_int MAX_BRANCH)))
374                                       (const_int 6)
375                                       (const_int 2)))])
378 ;; Move instructions
380 (define_insn "movdi"
381   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
382         (match_operand:DI 1 "general_operand" "rN,g"))]
383   ""
384   "")
387 (define_insn "*movdi_nocc"
388   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
389         (match_operand:DI 1 "general_operand" "rN,g"))
390    (clobber (reg:CC CC_REGNUM))]
391   ""
392   "* return output_move_multiple (operands);"
393   [(set_attr "length" "16,32")])
395 (define_insn "movsi"
396   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
397         (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
398   ""
399   "")
401 (define_insn "*movsi_nocc"
402   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
403         (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))
404    (clobber (reg:CC CC_REGNUM))]
405   ""
406   "* return output_move_multiple (operands);"
407   [(set_attr "length" "4,6,8,16")])
409 (define_insn "mov<mode>"
410   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
411         (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
412   ""
413   "")
415 ;; This splits all the integer moves: DI and SI modes as well as
416 ;; the simple machine operations.
417 (define_split 
418   [(set (match_operand:QHSDint 0 "nonimmediate_operand" "")
419         (match_operand:QHSDint 1 "general_operand" ""))]
420   "reload_completed"
421   [(parallel [(set (match_dup 0)
422                    (match_dup 1))
423               (clobber (reg:CC CC_REGNUM))])]
424   "")
425   
426 ;; MOV clears V
427 (define_insn "*mov<mode>_<cc_cc>"
428   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
429         (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))
430    (clobber (reg:CC CC_REGNUM))]
431   "reload_completed"
432   "*
434   if (operands[1] == const0_rtx)
435     return \"clr<PDPint:isfx> %0\";
437   return \"mov<PDPint:isfx> %1, %0\";
439   [(set_attr "length" "2,4,4,6")])
441 ;; movdf has unusually complicated condition code handling, because
442 ;; load (into float register) updates the FCC, while store (from
443 ;; float register) leaves it untouched.
445 ;; 1. Loads are:  ac4, ac5, or non-register into load-register
446 ;; 2. Stores are: load-register to non-register, ac4, or ac5
447 ;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled
448 ;;    either as loads or as stores.
450 (define_expand "movdf"
451   [(set (match_operand:DF 0 "float_nonimm_operand" "")
452         (match_operand:DF 1 "float_operand" ""))]
453   "TARGET_FPU"
454   "")
456 ;; Splitter for all these cases.  Store is the first two
457 ;; alternatives, which are not split.  Note that case 3
458 ;; is treated as a store, i.e., not split.
459 (define_insn_and_split "movdf_split"
460   [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,FQ,a,a,a")
461         (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))]
462   "TARGET_FPU"
463   "*
464   gcc_assert (which_alternative < 2);
465   return \"std %1, %0\";
466   "
467   "&& reload_completed"
468   [(parallel [(set (match_dup 0)
469                    (match_dup 1))
470               (clobber (reg:CC FCC_REGNUM))])]
471   "{
472   if (GET_CODE (operands[1]) == REG && 
473       REGNO_REG_CLASS (REGNO (operands[1])) == LOAD_FPU_REGS)
474     FAIL;
475   }"
476   [(set_attr "length" "2,4,0,0,0")])
478 ;; Loads (case 1).  
479 (define_insn "*ldd<fcc_cc>"
480   [(set (match_operand:DF 0 "float_nonimm_operand" "=a,a,a")
481         (match_operand:DF 1 "float_operand" "hR,FQ,G"))
482    (clobber (reg:CC FCC_REGNUM))]
483   "TARGET_FPU && reload_completed"
484   "@
485   ldd %1, %0
486   ldd %1, %0
487   clrd %0"
488   [(set_attr "length" "2,4,2")])
490 ;; SFmode is easier because that uses convert load/store, which
491 ;; always change condition codes.
492 ;; Note that these insns are cheating a bit.  We actually have
493 ;; DFmode operands in the FPU registers, which is why the
494 ;; ldcfd and stcdf instructions appear.  But GCC likes to think
495 ;; of these as SFmode loads and does the conversion once in the
496 ;; register, at least in many cases.  So we pretend to do this,
497 ;; but then extend and truncate register-to-register are NOP and
498 ;; generate no code.
499 (define_insn_and_split "movsf"
500   [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q")
501         (match_operand:SF 1 "float_operand" "fRG,a,FQ,a"))]
502   "TARGET_FPU"
503   "#"
504   "&& reload_completed"
505   [(parallel [(set (match_dup 0)
506                    (match_dup 1))
507               (clobber (reg:CC FCC_REGNUM))])]
508   "")
509   
510 (define_insn "*movsf<fcc_ccnz>"
511   [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
512         (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G"))
513    (clobber (reg:CC FCC_REGNUM))]
514   "TARGET_FPU && reload_completed"
515   "@
516   {ldcfd|movof} %1, %0
517   {stcdf|movfo} %1, %0
518   {ldcfd|movof} %1, %0
519   {stcdf|movfo} %1, %0
520   clrf %0"
521   [(set_attr "length" "2,2,4,4,2")])
523 ;; maybe fiddle a bit with move_ratio, then 
524 ;; let constraints only accept a register ...
526 (define_expand "movmemhi"
527   [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
528                    (match_operand:BLK 1 "general_operand" "g,g"))
529               (use (match_operand:HI 2 "general_operand" "n,mr"))
530               (use (match_operand:HI 3 "immediate_operand" "i,i"))
531               (clobber (match_scratch:HI 6 "=&r,X"))
532               (clobber (match_dup 4))
533               (clobber (match_dup 5))
534               (clobber (match_dup 2))])]
535   ""
536   "
538   operands[0]
539     = replace_equiv_address (operands[0],
540                              copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
541   operands[1]
542     = replace_equiv_address (operands[1],
543                              copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
545   operands[4] = XEXP (operands[0], 0);
546   operands[5] = XEXP (operands[1], 0);
550 (define_insn "*movmemhi1"
551   [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
552         (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
553    (use (match_operand:HI 2 "general_operand" "n,r"))
554    (use (match_operand:HI 3 "immediate_operand" "i,i"))
555    (clobber (match_scratch:HI 4 "=&r,X"))
556    (clobber (match_dup 0))
557    (clobber (match_dup 1))
558    (clobber (match_dup 2))]
559   ""
560   "* return output_block_move (operands);"
561 ;;; just a guess
562   [(set_attr "length" "80")])
563    
566 ;;- truncation instructions
568 ;; We sometimes end up doing a register to register truncate,
569 ;; which isn't right because we actually load registers always
570 ;; with a DFmode value.  But even with PROMOTE the compiler
571 ;; doesn't always get that (so we don't use it).  That means
572 ;; a register to register truncate is a NOP.
573 (define_insn_and_split  "truncdfsf2"
574   [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
575         (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))]
576   "TARGET_FPU"
577   {
578     gcc_assert (which_alternative == 0);
579     return "";
580   }           
581   "&& reload_completed"
582   [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1)))
583               (clobber (reg:CC FCC_REGNUM))])]
584   "{
585   if (GET_CODE (operands[0]) == REG && 
586       GET_CODE (operands[1]) == REG && 
587       REGNO (operands[0]) == REGNO (operands[1]))
588     FAIL;
589   }"
590   [(set_attr "length" "0,0,0")])
592 (define_insn "*truncdfsf2_<fcc_cc>"
593   [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q")
594         (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a")))
595    (clobber (reg:CC FCC_REGNUM))]
596   "TARGET_FPU && reload_completed"
597    "{stcdf|movfo} %1, %0"
598   [(set_attr "length" "2,4")])
601 ;;- zero extension instructions
603 (define_insn_and_split "zero_extendqihi2"
604   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
605         (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
606   ""
607   "#"
608   "reload_completed"
609   [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
610               (clobber (reg:CC CC_REGNUM))])]
611   "")
613 (define_insn "*zero_extendqihi2<cc_cc>"
614   [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
615                    (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))
616               (clobber (reg:CC CC_REGNUM))])]
617   "reload_completed"
618   "bic $0177400, %0"
619   [(set_attr "length" "4,6")])
620                          
621 (define_expand "zero_extendhisi2"
622   [(set (subreg:HI 
623           (match_dup 0)
624           2)
625         (match_operand:HI 1 "register_operand" "r"))
626    (set (subreg:HI 
627           (match_operand:SI 0 "register_operand" "=r")
628           0)
629         (const_int 0))]
630   ""
631   "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
634 ;;- sign extension instructions
636 ;; We sometimes end up doing a register to register extend,
637 ;; which isn't right because we actually load registers always
638 ;; with a DFmode value.  But even with PROMOTE the compiler
639 ;; doesn't always get that (so we don't use it).  That means
640 ;; a register to register truncate is a NOP.
641 (define_insn_and_split "extendsfdf2"
642   [(set (match_operand:DF 0 "register_operand" "=f,a,a")
643         (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))]
644   "TARGET_FPU"
645   {
646     gcc_assert (which_alternative == 0);
647     return "";
648   }           
649   "&& reload_completed"
650   [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1)))
651               (clobber (reg:CC FCC_REGNUM))])]
652   "{
653   if (GET_CODE (operands[0]) == REG && 
654       GET_CODE (operands[1]) == REG && 
655       REGNO (operands[0]) == REGNO (operands[1]))
656     FAIL;
657   }"
658   [(set_attr "length" "0,0,0")])
660 (define_insn "*extendsfdf2_<fcc_cc>"
661   [(set (match_operand:DF 0 "register_operand" "=a,a")
662         (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q")))
663    (clobber (reg:CC FCC_REGNUM))]
664   "TARGET_FPU && reload_completed"
665   "{ldcfd|movof} %1, %0"
666   [(set_attr "length" "2,4")])
668 ;; movb sign extends if destination is a register
669 (define_insn_and_split "extendqihi2"
670   [(set (match_operand:HI 0 "register_operand" "=r,r")
671         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
672   ""
673   "#"
674   "reload_completed"
675   [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
676               (clobber (reg:CC CC_REGNUM))])]
677   "")
679 ;; MOVB clears V
680 (define_insn "*extendqihi2<cc_cc>"
681   [(set (match_operand:HI 0 "register_operand" "=r,r")
682         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))
683    (clobber (reg:CC CC_REGNUM))]
684   "reload_completed"
685   "movb %1, %0"
686   [(set_attr "length" "2,4")])
688 (define_insn_and_split "extendhisi2"
689   [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
690         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
691   "TARGET_40_PLUS"
692   "#"
693   "&& reload_completed"
694   [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
695               (clobber (reg:CC CC_REGNUM))])]
696   "")
698 (define_insn "*extendhisi2_nocc"
699   [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
700         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))
701    (clobber (reg:CC CC_REGNUM))]
702   "TARGET_40_PLUS && reload_completed"
703   "*
705   rtx latehalf[2];
707   /* we don't want to mess with auto increment */
708   
709   switch (which_alternative)
710   {
711     case 0:
713       latehalf[0] = operands[0];
714       operands[0] = adjust_address(operands[0], HImode, 2);
715   
716       output_asm_insn(\"mov %1, %0\", operands);
717       output_asm_insn(\"sxt %0\", latehalf);
719       return \"\";
721     case 1:
723       /* - auto-decrement - right direction ;-) */
724       output_asm_insn(\"mov %1, %0\", operands);
725       output_asm_insn(\"sxt %0\", operands);
727       return \"\";
729     case 2:
731       /* make register pair available */
732       latehalf[0] = operands[0];
733       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
735       output_asm_insn(\"mov %1, %0\", operands);
736       output_asm_insn(\"sxt %0\", latehalf);
738       return \"\";
740     default:
742       gcc_unreachable ();
743   }
745   [(set_attr "length" "10,6,6")])
747 ;; make float to int and vice versa 
748 ;; assume that we are normally in double and integer mode -
749 ;; what do pdp library routines do to fpu mode ?
751 ;; Note: the hardware treats register source as
752 ;; a 16-bit (high order only) source, which isn't
753 ;; what we want.  But we do need to support register
754 ;; dest because gcc asks for it.
755 (define_insn_and_split "floatsidf2"
756   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
757         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
758   "TARGET_FPU"
759   "#"
760   "&& reload_completed"
761   [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
762               (clobber (reg:CC FCC_REGNUM))])]
763   "")
765 (define_insn "*floatsidf2<fcc_cc>"
766   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
767         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))
768    (clobber (reg:CC FCC_REGNUM))]
769   "TARGET_FPU && reload_completed"
770   "* if (which_alternative ==0)
771      {
772        rtx latehalf[2];
774        latehalf[0] = NULL; 
775        latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
776        output_asm_insn(\"mov %1, -(sp)\", latehalf);
777        output_asm_insn(\"mov %1, -(sp)\", operands);
778        
779        output_asm_insn(\"setl\", operands);
780        output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
781        output_asm_insn(\"seti\", operands);
782        return \"\";
783      }
784      else 
785        return \"setl\;{ldcld|movif} %1, %0\;seti\";
786   "
787   [(set_attr "length" "10,6,8")])
789 (define_insn_and_split "floathidf2"
790   [(set (match_operand:DF 0 "register_operand" "=a,a")
791         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
792   "TARGET_FPU"
793   "#"
794   "&& reload_completed"
795   [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
796               (clobber (reg:CC FCC_REGNUM))])]
797   "")
799 (define_insn "*floathidf2<fcc_cc>"
800   [(set (match_operand:DF 0 "register_operand" "=a,a")
801         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))
802    (clobber (reg:CC FCC_REGNUM))]
803   "TARGET_FPU && reload_completed"
804   "{ldcid|movif} %1, %0"
805   [(set_attr "length" "2,4")])
806         
807 ;; cut float to int
809 ;; Note: the hardware treats register destination as
810 ;; a 16-bit (high order only) destination, which isn't
811 ;; what we want.  But we do need to support register
812 ;; dest because gcc asks for it.
813 (define_insn_and_split "fix_truncdfsi2"
814   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
815         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
816   "TARGET_FPU"
817   "#"
818   "&& reload_completed"
819   [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1))))
820               (clobber (reg:CC CC_REGNUM))
821               (clobber (reg:CC FCC_REGNUM))])]
822   "")
824 ;; Note: this clobbers both sets of condition codes!
825 (define_insn "*fix_truncdfsi2_nocc"
826   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
827         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))
828    (clobber (reg:CC CC_REGNUM))
829    (clobber (reg:CC FCC_REGNUM))]
830   "TARGET_FPU && reload_completed"
831   "* if (which_alternative ==0)
832      {
833        output_asm_insn(\"setl\", operands);
834        output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
835        output_asm_insn(\"seti\", operands);
836        output_asm_insn(\"mov (sp)+, %0\", operands);
837        operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
838        output_asm_insn(\"mov (sp)+, %0\", operands);
839        return \"\";
840      }
841      else 
842        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
843   "
844   [(set_attr "length" "10,6,8")])
846 (define_insn_and_split "fix_truncdfhi2"
847   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
848         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
849   "TARGET_FPU"
850   "#"
851   "&& reload_completed"
852   [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1))))
853               (clobber (reg:CC CC_REGNUM))
854               (clobber (reg:CC FCC_REGNUM))])]
855   "")
857 ;; Note: this clobbers both sets of condition codes!
858 (define_insn "*fix_truncdfhi2_nocc"
859   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
860         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))
861    (clobber (reg:CC CC_REGNUM))
862    (clobber (reg:CC FCC_REGNUM))]
863   "TARGET_FPU && reload_completed"
864   "{stcdi|movfi} %1, %0"
865   [(set_attr "length" "2,4")])
868 ;;- arithmetic instructions
869 ;;- add instructions
871 (define_insn_and_split "adddf3"
872   [(set (match_operand:DF 0 "register_operand" "=a,a")
873         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
874                  (match_operand:DF 2 "general_operand" "fR,QF")))]
875   "TARGET_FPU"
876   "#"
877   "&& reload_completed"
878   [(parallel [(set (match_dup 0)
879                    (plus:DF (match_dup 1) (match_dup 2)))
880               (clobber (reg:CC FCC_REGNUM))])]
881   "")
883 ;; Float add sets V if overflow from add
884 (define_insn "*adddf3<fcc_ccnz>"
885   [(set (match_operand:DF 0 "register_operand" "=a,a")
886         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
887               (match_operand:DF 2 "general_operand" "fR,QF")))
888    (clobber (reg:CC FCC_REGNUM))]
889   "TARGET_FPU && reload_completed"
890   "{addd|addf} %2, %0"
891   [(set_attr "length" "2,4")])
893 (define_insn_and_split "adddi3"
894   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
895         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
896                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
897   ""
898   "#"
899   "reload_completed"
900   [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
901               (clobber (reg:CC CC_REGNUM))])]
902   "")
904 (define_insn "*adddi3_nocc"
905   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
906         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
907               (match_operand:DI 2 "general_operand" "r,on,r,on")))
908    (clobber (reg:CC CC_REGNUM))]
909   "reload_completed"  
910   "*
912   rtx inops[2];
913   rtx exops[4][2];
914   
915   inops[0] = operands[0];
916   inops[1] = operands[2];
917   pdp11_expand_operands (inops, exops, 2, NULL, either);
918   
919   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
920     output_asm_insn (\"add %1, %0\", exops[0]);
921   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
922   {
923     output_asm_insn (\"add %1, %0\", exops[1]);
924     output_asm_insn (\"adc %0\", exops[0]);
925   }
926   if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
927   {
928     output_asm_insn (\"add %1, %0\", exops[2]);
929     output_asm_insn (\"adc %0\", exops[1]);
930     output_asm_insn (\"adc %0\", exops[0]);
931   }
932   if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
933   {
934     output_asm_insn (\"add %1, %0\", exops[3]);
935     output_asm_insn (\"adc %0\", exops[2]);
936     output_asm_insn (\"adc %0\", exops[1]);
937     output_asm_insn (\"adc %0\", exops[0]);
938   }
940   return \"\";
942   [(set_attr "length" "20,28,40,48")])
944 ;; Note that the register operand is not marked earlyclobber.
945 ;; The reason is that SI values go in register pairs, so they
946 ;; can't partially overlap.  They can be either disjoint, or
947 ;; source and destination can be equal.  The latter case is 
948 ;; handled properly because of the ordering of the individual
949 ;; instructions used.  Specifically, carry from the low to the
950 ;; high word is added at the end, so the adding of the high parts
951 ;; will always used the original high part and not a high part
952 ;; modified by carry (which would amount to double carry).
953 (define_insn_and_split "addsi3"
954   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
955         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
956                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
957   ""
958   "#"
959   "reload_completed"
960   [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
961               (clobber (reg:CC CC_REGNUM))])]
962   "")
964 (define_insn "*addsi3_nocc"
965   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
966         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
967               (match_operand:SI 2 "general_operand" "r,on,r,on")))
968    (clobber (reg:CC CC_REGNUM))]
969   "reload_completed"
970   "*
972   rtx inops[2];
973   rtx exops[2][2];
974   
975   inops[0] = operands[0];
976   inops[1] = operands[2];
977   pdp11_expand_operands (inops, exops, 2, NULL, either);
978   
979   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
980     output_asm_insn (\"add %1, %0\", exops[0]);
981   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
982   {
983     output_asm_insn (\"add %1, %0\", exops[1]);
984     output_asm_insn (\"adc %0\", exops[0]);
985   }
987   return \"\";
989   [(set_attr "length" "6,10,12,16")])
991 (define_insn_and_split "addhi3"
992   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
993         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
994                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
995   ""
996   "#"
997   "reload_completed"
998   [(parallel [(set (match_dup 0)
999                    (plus:HI (match_dup 1) (match_dup 2)))
1000               (clobber (reg:CC CC_REGNUM))])]
1001   "")
1003 ;; Add sets V if overflow from the add
1004 (define_insn "*addhi3<cc_ccnz>"
1005   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1006         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1007                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1008    (clobber (reg:CC CC_REGNUM))]
1009   "reload_completed"
1010   "*
1012   if (GET_CODE (operands[2]) == CONST_INT)
1013     {
1014       if (INTVAL(operands[2]) == 1)
1015         return \"inc %0\";
1016       else if (INTVAL(operands[2]) == -1)
1017         return \"dec %0\";
1018     }
1020   return \"add %2, %0\";
1022   [(set_attr "length" "2,4,4,6")])
1025 ;;- subtract instructions
1026 ;; we don't have to care for constant second 
1027 ;; args, since they are canonical plus:xx now!
1028 ;; also for minus:DF ??
1030 (define_insn_and_split "subdf3"
1031   [(set (match_operand:DF 0 "register_operand" "=a,a")
1032         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1033                   (match_operand:DF 2 "general_operand" "fR,Q")))]
1034   "TARGET_FPU"
1035   "#"
1036   "&& reload_completed"
1037   [(parallel [(set (match_dup 0)
1038                    (minus:DF (match_dup 1) (match_dup 2)))
1039               (clobber (reg:CC FCC_REGNUM))])]
1040   "")
1042 (define_insn "*subdf3<fcc_ccnz>"
1043   [(set (match_operand:DF 0 "register_operand" "=a,a")
1044         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1045                   (match_operand:DF 2 "general_operand" "fR,QF")))
1046    (clobber (reg:CC FCC_REGNUM))]
1047   "TARGET_FPU && reload_completed"
1048   "{subd|subf} %2, %0"
1049   [(set_attr "length" "2,4")])
1051 (define_insn_and_split "subdi3"
1052   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1053         (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1054                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1055   ""
1056   "#"
1057   "reload_completed"
1058   [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
1059               (clobber (reg:CC CC_REGNUM))])]
1060   "")
1062 (define_insn "*subdi3_nocc"
1063   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1064         (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1065               (match_operand:DI 2 "general_operand" "r,on,r,on")))
1066    (clobber (reg:CC CC_REGNUM))]
1067   "reload_completed"
1068   "*
1070   rtx inops[2];
1071   rtx exops[4][2];
1072   
1073   inops[0] = operands[0];
1074   inops[1] = operands[2];
1075   pdp11_expand_operands (inops, exops, 2, NULL, either);
1076   
1077   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1078     output_asm_insn (\"sub %1, %0\", exops[0]);
1079   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1080   {
1081     output_asm_insn (\"sub %1, %0\", exops[1]);
1082     output_asm_insn (\"sbc %0\", exops[0]);
1083   }
1084   if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1085   {
1086     output_asm_insn (\"sub %1, %0\", exops[2]);
1087     output_asm_insn (\"sbc %0\", exops[1]);
1088     output_asm_insn (\"sbc %0\", exops[0]);
1089   }
1090   if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1091   {
1092     output_asm_insn (\"sub %1, %0\", exops[3]);
1093     output_asm_insn (\"sbc %0\", exops[2]);
1094     output_asm_insn (\"sbc %0\", exops[1]);
1095     output_asm_insn (\"sbc %0\", exops[0]);
1096   }
1098   return \"\";
1100   [(set_attr "length" "20,28,40,48")])
1102 (define_insn_and_split "subsi3"
1103   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1104         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1105                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1106   ""
1107   "#"
1108   "reload_completed"
1109   [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1110               (clobber (reg:CC CC_REGNUM))])]
1111   "")
1113 (define_insn "*subsi3_nocc"
1114   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1115         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1116               (match_operand:SI 2 "general_operand" "r,on,r,on")))
1117    (clobber (reg:CC CC_REGNUM))]
1118   "reload_completed"
1119   "*
1121   rtx inops[2];
1122   rtx exops[2][2];
1123   
1124   inops[0] = operands[0];
1125   inops[1] = operands[2];
1126   pdp11_expand_operands (inops, exops, 2, NULL, either);
1127   
1128   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1129     output_asm_insn (\"sub %1, %0\", exops[0]);
1130   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1131   {
1132     output_asm_insn (\"sub %1, %0\", exops[1]);
1133     output_asm_insn (\"sbc %0\", exops[0]);
1134   }
1136   return \"\";
1138   [(set_attr "length" "6,10,12,16")])
1140 (define_insn_and_split "subhi3"
1141   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1142         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1143                   (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1144   ""
1145   "#"
1146   "reload_completed"
1147   [(parallel [(set (match_dup 0)
1148                    (minus:HI (match_dup 1) (match_dup 2)))
1149               (clobber (reg:CC CC_REGNUM))])]
1150   "")
1152 ;; Note: the manual says that (minus m (const_int n)) is converted
1153 ;; to (plus m (const_int -n)) but that does not appear to be
1154 ;; the case when it's wrapped in a PARALLEL.  So instead we handle
1155 ;; that case here, which is easy enough.
1156 (define_insn "*subhi3<cc_ccnz>"
1157   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1158         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1159                   (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1160    (clobber (reg:CC CC_REGNUM))]
1161   "reload_completed"
1162   "*
1164   if (GET_CODE (operands[2]) == CONST_INT)
1165     {
1166       if (INTVAL(operands[2]) == 1)
1167         return \"dec %0\";
1168       else if (INTVAL(operands[2]) == -1)
1169         return \"inc %0\";
1170     }
1172   return \"sub %2, %0\";
1174   [(set_attr "length" "2,4,4,6")])
1176 ;;;;- and instructions
1177 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1179 (define_expand "and<mode>3"
1180   [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
1181         (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
1182                    (match_operand:PDPint 2 "general_operand" "")))]
1183   ""
1184   "
1186   rtx op1 = operands[1];
1188   /* If there is a constant argument, complement that one.
1189      Similarly, if one of the inputs is the same as the output,
1190      complement the other input.  */
1191   if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
1192       rtx_equal_p (operands[0], operands[1]))
1193     {
1194       operands[1] = operands[2];
1195       operands[2] = op1;
1196       op1 = operands[1];
1197     }
1199   if (CONST_INT_P (op1))
1200     operands[1] = GEN_INT (~INTVAL (op1));
1201   else
1202     operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
1205 (define_insn_and_split "*bic<mode>"
1206   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1207         (and:PDPint
1208              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1209              (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
1210   ""
1211   "#"
1212   "reload_completed"
1213   [(parallel [(set (match_dup 0)
1214                    (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2)))
1215               (clobber (reg:CC CC_REGNUM))])]
1216   "")
1218 (define_insn "*bic<mode><cc_cc>"
1219   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1220         (and:PDPint
1221              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1222                           (match_operand:PDPint 2 "general_operand" "0,0,0,0")))
1223    (clobber (reg:CC CC_REGNUM))]
1224   "reload_completed"
1225   "bic<PDPint:isfx> %1, %0"
1226   [(set_attr "length" "2,4,4,6")])
1228 ;;- Bit set (inclusive or) instructions
1229 (define_insn_and_split "ior<mode>3"
1230   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1231         (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1232                     (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
1233   ""
1234   "#"
1235   "reload_completed"
1236   [(parallel [(set (match_dup 0)
1237                    (ior:PDPint (match_dup 1) (match_dup 2)))
1238               (clobber (reg:CC CC_REGNUM))])]
1239   "")
1241 (define_insn "ior<mode>3<cc_cc>"
1242   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1243         (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1244              (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))
1245    (clobber (reg:CC CC_REGNUM))]
1246   "reload_completed"
1247   "bis<PDPint:isfx> %2, %0"
1248   [(set_attr "length" "2,4,4,6")])
1250 ;;- xor instructions
1251 (define_insn_and_split "xorhi3"
1252   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1253         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1254                 (match_operand:HI 2 "register_operand" "r,r")))]
1255   "TARGET_40_PLUS"
1256   "#"
1257   "&& reload_completed"
1258   [(parallel [(set (match_dup 0)
1259                    (xor:HI (match_dup 1) (match_dup 2)))
1260               (clobber (reg:CC CC_REGNUM))])]
1261   "")
1263 (define_insn "*xorhi3<cc_cc>"
1264   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1265         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1266              (match_operand:HI 2 "register_operand" "r,r")))
1267    (clobber (reg:CC CC_REGNUM))]
1268   "TARGET_40_PLUS && reload_completed"
1269   "xor %2, %0"
1270   [(set_attr "length" "2,4")])
1272 ;;- one complement instructions
1274 (define_insn_and_split "one_cmpl<mode>2"
1275   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1276         (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1277   ""
1278   "#"
1279   "reload_completed"
1280   [(parallel [(set (match_dup 0)
1281                    (not:PDPint (match_dup 1)))
1282               (clobber (reg:CC CC_REGNUM))])]
1283   "")
1285 (define_insn "*one_cmpl<mode>2<cc_cc>"
1286   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1287         (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1288    (clobber (reg:CC CC_REGNUM))]
1289   "reload_completed"
1290   "com<PDPint:isfx> %0"
1291   [(set_attr "length" "2,4")])
1293 ;;- arithmetic shift instructions
1295 ;; There is a fair amount of complexity here because with -m10
1296 ;; (pdp-11/10, /20) we only have shift by one bit.  Iterators are
1297 ;; used to reduce the amount of very similar code.
1299 ;; First the insns used for small constant shifts.
1300 (define_insn "<code><mode>_sc"
1301   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1302         (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1303                     (match_operand:HI 2 "expand_shift_operand" "O,O")))]
1304   ""
1305   "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1306   [(set (attr "length")
1307         (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
1308                                          <CODE>, which_alternative == 0)"))])
1310 ;; Next, shifts that are done as a loop on base (11/10 class) machines.
1311 ;; This applies to shift counts too large to unroll, or variable shift
1312 ;; counts.  The check for count <= 0 is done before we get here.
1313 (define_insn "<code><mode>_base"
1314   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1315         (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1316              (match_operand:HI 2 "register_operand" "r,r")))
1317    (clobber (match_dup 2))]
1318   ""
1319   "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1320   [(set (attr "length")
1321         (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
1322                                          <CODE>, which_alternative == 0)"))])
1324 ;; Next the insns that use the extended instructions ash and ashc.
1325 ;; Note that these are just left shifts, and HI/SI only.  (Right shifts
1326 ;; are done by shifting by a negative amount.)
1327 (define_insn "aslhi_op"
1328   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1329         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1330                        (match_operand:HI 2 "general_operand" "rR,Q")))]
1331   "TARGET_40_PLUS"
1332   "ash %2, %0"
1333   [(set_attr "length" "2,4")])
1335 (define_insn "aslsi_op"
1336   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1337         (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1338                    (match_operand:HI 2 "general_operand" "rR,Q")))]
1339   "TARGET_40_PLUS"
1340   "ashc %2, %0"
1341   [(set_attr "length" "2,4")])
1343 ;; Now the expanders that produce the insns defined above. 
1344 (define_expand "ashl<mode>3"
1345   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1346    (match_operand:QHSint 1 "general_operand" "")
1347    (match_operand:HI 2 "general_operand" "")]
1348   ""
1349   "
1351   rtx r;
1353   if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base))
1354     {
1355       if (<QHSint:e_mname> == E_QImode)
1356         {
1357           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1358           emit_insn (gen_aslhi_op (r, r, operands[2]));
1359           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1360         }
1361       else
1362         {
1363           emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1364         }
1365     }
1366   DONE;
1369 (define_expand "ashr<mode>3"
1370   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1371    (match_operand:QHSint 1 "general_operand" "")
1372    (match_operand:HI 2 "general_operand" "")]
1373   ""
1374   "
1376   rtx r;
1378   if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base))
1379     {
1380       operands[2] = negate_rtx (HImode, operands[2]);
1381       if (<QHSint:e_mname> == E_QImode)
1382         {
1383           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1384           emit_insn (gen_aslhi_op (r, r, operands[2]));
1385           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1386         }
1387       else
1388         {
1389           emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1390         }
1391     }
1392   DONE;
1395 (define_expand "lshr<mode>3"
1396   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1397    (match_operand:QHSint 1 "general_operand" "")
1398    (match_operand:HI 2 "general_operand" "")]
1399   ""
1400   "
1402   rtx r, n;
1404   if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base))
1405     {
1406       if (<QHSint:e_mname> == E_QImode)
1407         {
1408           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1409           emit_insn (gen_aslhi_op (r, r, operands[2]));
1410           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1411         }
1412       else
1413         {
1414           r = gen_reg_rtx (<QHSint:mname>);
1415           emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx));
1416           if (GET_CODE (operands[2]) != CONST_INT)
1417             {
1418               n = gen_reg_rtx (HImode);
1419               emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1)));
1420               emit_insn (gen_ashr<mode>3 (operands[0], r, n));
1421             }
1422           else
1423             emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r,
1424                                   GEN_INT (1 - INTVAL (operands[2]))));
1425         }
1426     }
1427   DONE;
1430 ;; absolute 
1432 (define_insn_and_split "absdf2"
1433   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1434         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1435   "TARGET_FPU"
1436   "#"
1437   "&& reload_completed"
1438   [(parallel [(set (match_dup 0) (abs:DF (match_dup 1)))
1439               (clobber (reg:CC FCC_REGNUM))])]
1440    "")
1442 (define_insn "absdf2<fcc_cc>"
1443   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1444         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))
1445    (clobber (reg:CC FCC_REGNUM))]
1446   "TARGET_FPU && reload_completed"
1447   "{absd|absf} %0"
1448   [(set_attr "length" "2,4")])
1450 ;; negate insns
1452 (define_insn_and_split "negdf2"
1453   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1454         (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
1455   "TARGET_FPU"
1456   "#"
1457   "&& reload_completed"
1458   [(parallel [(set (match_dup 0) (neg:DF (match_dup 1)))
1459               (clobber (reg:CC FCC_REGNUM))])]
1460    "")
1462 (define_insn "negdf2<fcc_cc>"
1463   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1464         (neg:DF (match_operand:DF 1 "general_operand" "0,0")))
1465    (clobber (reg:CC FCC_REGNUM))]
1466   "TARGET_FPU && reload_completed"
1467   "{negd|negf} %0"
1468   [(set_attr "length" "2,4")])
1470 (define_insn_and_split "negdi2"
1471   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1472         (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1473   ""
1474   "#"
1475   "reload_completed"
1476   [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
1477               (clobber (reg:CC CC_REGNUM))])]
1478   "")
1479   
1480 ;; TODO: this can be neg/adc/neg/adc... I believe.  Check.  Saves one word.
1481 (define_insn "negdi2_nocc"
1482   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1483         (neg:DI (match_operand:DI 1 "general_operand" "0,0")))
1484    (clobber (reg:CC CC_REGNUM))]
1485   "reload_completed"
1487   rtx exops[4][2];
1488   
1489   pdp11_expand_operands (operands, exops, 1, NULL, either);
1491   output_asm_insn (\"com %0\", exops[3]);
1492   output_asm_insn (\"com %0\", exops[2]);
1493   output_asm_insn (\"com %0\", exops[1]);
1494   output_asm_insn (\"com %0\", exops[0]);
1495   output_asm_insn (\"add $1, %0\", exops[3]);
1496   output_asm_insn (\"adc %0\", exops[2]);
1497   output_asm_insn (\"adc %0\", exops[1]);
1498   output_asm_insn (\"adc %0\", exops[0]);
1500   return \"\";
1502 [(set_attr "length" "18,34")])
1504 (define_insn_and_split "negsi2"
1505   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1506         (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1507   ""
1508   "#"
1509   "reload_completed"
1510   [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
1511               (clobber (reg:CC CC_REGNUM))])]
1512   "")
1513   
1514 ;; TODO: this can be neg/adc/neg/adc... I believe.  Check.  Saves one word.
1515 (define_insn "negsi2_nocc"
1516   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1517         (neg:SI (match_operand:SI 1 "general_operand" "0,0")))
1518    (clobber (reg:CC CC_REGNUM))]
1519   "reload_completed"
1521   rtx exops[2][2];
1522   
1523   pdp11_expand_operands (operands, exops, 1, NULL, either);
1525   output_asm_insn (\"com %0\", exops[1]);
1526   output_asm_insn (\"com %0\", exops[0]);
1527   output_asm_insn (\"add $1, %0\", exops[1]);
1528   output_asm_insn (\"adc %0\", exops[0]);
1530   return \"\";
1532 [(set_attr "length" "10,18")])
1534 (define_insn_and_split "neg<mode>2"
1535   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1536         (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1537   ""
1538   "#"
1539   "reload_completed"
1540   [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1)))
1541               (clobber (reg:CC CC_REGNUM))])]
1542   "")
1543   
1544 (define_insn "neg<mode>2<cc_ccnz>"
1545   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1546         (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1547    (clobber (reg:CC CC_REGNUM))]
1548   ""
1549   "neg<PDPint:isfx> %0"
1550   [(set_attr "length" "2,4")])
1553 ;; Unconditional and other jump instructions
1554 (define_insn "jump"
1555   [(set (pc)
1556         (label_ref (match_operand 0 "" "")))]
1557   ""
1558   "*
1560   if (get_attr_length (insn) == 2)
1561     return \"br %l0\";
1562   return \"jmp %l0\";
1564   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1565                                                       (pc))
1566                                                (const_int MIN_BRANCH))
1567                                            (gt (minus (match_dup 0)
1568                                                       (pc))
1569                                                (const_int MAX_BRANCH)))
1570                                       (const_int 4)
1571                                       (const_int 2)))])
1573 (define_insn "tablejump"
1574   [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1575    (use (label_ref (match_operand 1 "" "")))]
1576   ""
1577   "@
1578   jmp (%0)
1579   jmp %@%0
1580   jmp %@%0"
1581   [(set_attr "length" "2,2,4")])
1583 ;; indirect jump.  TODO: this needs a constraint that allows memory
1584 ;; references but not indirection, since we add a level of indirection
1585 ;; in the generated code.
1586 (define_insn "indirect_jump"
1587   [(set (pc) (match_operand:HI 0 "general_operand" "r"))]
1588   ""
1589   "jmp @%0"
1590   [(set_attr "length" "2")])
1592 ;;- jump to subroutine
1594 (define_insn "call"
1595   [(call (match_operand:HI 0 "general_operand" "rR,Q")
1596          (match_operand:HI 1 "general_operand" "g,g"))]
1597   ;;- Don't use operand 1 for most machines.
1598   ""
1599   "jsr pc, %0"
1600   [(set_attr "length" "2,4")])
1602 ;;- jump to subroutine
1603 (define_insn "call_value"
1604   [(set (match_operand 0 "" "")
1605         (call (match_operand:HI 1 "general_operand" "rR,Q")
1606               (match_operand:HI 2 "general_operand" "g,g")))]
1607   ;;- Don't use operand 2 for most machines.
1608   ""
1609   "jsr pc, %1"
1610   [(set_attr "length" "2,4")])
1612 (define_expand "untyped_call"
1613   [(parallel [(call (match_operand 0 "" "")
1614                     (const_int 0))
1615               (match_operand 1 "" "")
1616               (match_operand 2 "" "")])]
1617   ""
1619   int i;
1621   emit_call_insn (gen_call (operands[0], const0_rtx));
1623   for (i = 0; i < XVECLEN (operands[2], 0); i++)
1624     {
1625       rtx set = XVECEXP (operands[2], 0, i);
1626       emit_move_insn (SET_DEST (set), SET_SRC (set));
1627     }
1629   /* The optimizer does not know that the call sets the function value
1630      registers we stored in the result block.  We avoid problems by
1631      claiming that all hard registers are used and clobbered at this
1632      point.  */
1633   emit_insn (gen_blockage ());
1635   DONE;
1638 ;;- nop instruction
1639 (define_insn "nop"
1640   [(const_int 0)]
1641   ""
1642   "nop")
1645 ;;- multiply 
1647 (define_insn_and_split "muldf3"
1648   [(set (match_operand:DF 0 "register_operand" "=a,a")
1649         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1650                  (match_operand:DF 2 "float_operand" "fR,QF")))]
1651   "TARGET_FPU"
1652   "#"
1653   "&& reload_completed"
1654   [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2)))
1655               (clobber (reg:CC FCC_REGNUM))])]
1656   "")
1658 (define_insn "muldf3<fcc_ccnz>"
1659   [(set (match_operand:DF 0 "register_operand" "=a,a")
1660         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1661               (match_operand:DF 2 "float_operand" "fR,QF")))
1662    (clobber (reg:CC FCC_REGNUM))]
1663   "TARGET_FPU && reload_completed"
1664   "{muld|mulf} %2, %0"
1665   [(set_attr "length" "2,4")])
1667 ;; 16 bit result multiply.  This uses odd numbered registers.
1669 (define_insn_and_split "mulhi3"
1670   [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1671         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1672                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1673   "TARGET_40_PLUS"
1674   "#"
1675   "&& reload_completed"
1676   [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2)))
1677               (clobber (reg:CC CC_REGNUM))])]
1678   "")
1680 (define_insn "mulhi3<cc_cc>"
1681   [(set (match_operand:HI 0 "register_operand" "=d,d")
1682         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1683               (match_operand:HI 2 "general_operand" "rR,Qi")))
1684    (clobber (reg:CC CC_REGNUM))]
1685   "TARGET_40_PLUS && reload_completed"
1686   "mul %2, %0"
1687   [(set_attr "length" "2,4")])
1689 ;; 32 bit result from 16 bit operands
1690 (define_insn_and_split "mulhisi3"
1691   [(set (match_operand:SI 0 "register_operand" "=r,r")
1692         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
1693                  (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))]
1694   "TARGET_40_PLUS"
1695   "#"
1696   "&& reload_completed"
1697   [(parallel [(set (match_dup 0)
1698                    (mult:SI (sign_extend:SI (match_dup 1))
1699                          (sign_extend:SI (match_dup 2))))
1700               (clobber (reg:CC CC_REGNUM))])]
1701   "")
1703 (define_insn "mulhisi3<cc_cc>"
1704   [(set (match_operand:SI 0 "register_operand" "=r,r")
1705         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
1706               (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))
1707    (clobber (reg:CC CC_REGNUM))]
1708   "TARGET_40_PLUS && reload_completed"
1709   "mul %2, %0"
1710   [(set_attr "length" "2,4")])
1712 ;;- divide
1713 (define_insn_and_split "divdf3"
1714   [(set (match_operand:DF 0 "register_operand" "=a,a")
1715         (div:DF (match_operand:DF 1 "register_operand" "0,0")
1716                 (match_operand:DF 2 "general_operand" "fR,QF")))]
1717   "TARGET_FPU"
1718   "#"
1719   "&& reload_completed"
1720   [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2)))
1721               (clobber (reg:CC FCC_REGNUM))])]
1722    "")
1723   
1724 (define_insn "divdf3<fcc_ccnz>"
1725   [(set (match_operand:DF 0 "register_operand" "=a,a")
1726         (div:DF (match_operand:DF 1 "register_operand" "0,0")
1727              (match_operand:DF 2 "general_operand" "fR,QF")))
1728    (clobber (reg:CC FCC_REGNUM))]
1729   "TARGET_FPU && reload_completed"
1730   "{divd|divf} %2, %0"
1731   [(set_attr "length" "2,4")])
1733 (define_expand "divmodhi4"
1734   [(parallel
1735     [(set (subreg:HI (match_dup 1) 0)
1736         (div:HI (match_operand:SI 1 "register_operand" "0")
1737                 (match_operand:HI 2 "general_operand" "g")))
1738      (set (subreg:HI (match_dup 1) 2)
1739         (mod:HI (match_dup 1) (match_dup 2)))])
1740    (set (match_operand:HI 0 "register_operand" "=r")
1741         (subreg:HI (match_dup 1) 0))
1742    (set (match_operand:HI 3 "register_operand" "=r")
1743         (subreg:HI (match_dup 1) 2))]
1744   "TARGET_40_PLUS"
1745   "")
1747 (define_insn_and_split "*divmodhi4"
1748   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
1749         (div:HI (match_operand:SI 1 "register_operand" "0,0")
1750              (match_operand:HI 2 "general_operand" "rR,Qi")))
1751    (set (subreg:HI (match_dup 1) 2)
1752         (mod:HI (match_dup 1) (match_dup 2)))]
1753   "TARGET_40_PLUS"
1754   "#"
1755   "&& reload_completed"
1756   [(parallel [(set (subreg:HI (match_dup 0) 0)
1757                    (div:HI (match_dup 1) (match_dup 2)))
1758               (set (subreg:HI (match_dup 1) 2)
1759                    (mod:HI (match_dup 1) (match_dup 2)))
1760               (clobber (reg:CC CC_REGNUM))])]
1761   "")
1763 ;; Note that there is no corresponding CC setter pattern.
1764 ;; The reason is that it won't be generated, because
1765 ;; compare-elim.c only does the transformation on input
1766 ;; insns that have a two-element PARALLEL, as opposed to
1767 ;; the three-element one we have here.     
1768 (define_insn "divmodhi4_nocc"
1769   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
1770         (div:HI (match_operand:SI 1 "register_operand" "0,0")
1771                 (match_operand:HI 2 "general_operand" "rR,Qi")))
1772    (set (subreg:HI (match_dup 1) 2)
1773         (mod:HI (match_dup 1) (match_dup 2)))
1774    (clobber (reg:CC CC_REGNUM))]
1775   "TARGET_40_PLUS"
1776    "div %2,%0"
1777   [(set_attr "length" "2,4")])