Improve code generation for pdp11 target.
[official-gcc.git] / gcc / config / pdp11 / pdp11.md
blobe51f5381967e1a76e9e5eac42fc922832b53084d
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 (pc).  That is NOT
54    ;; the same thing as "instruction address" -- it is for backward
55    ;; branches, but for forward branches it refers to the address
56    ;; following the instruction.  So the max forward distance
57    ;; matches what the processor handbook says, while the max
58    ;; backward branch is 2 less than the book.
59    (MIN_BRANCH            -254)
60    (MAX_BRANCH            254)
61    (MIN_SOB               -124)
62    (MAX_SOB               0)])
64 ;; DF is 64 bit
65 ;; SF is 32 bit
66 ;; SI is 32 bit
67 ;; HI is 16 bit
68 ;; QI is 8 bit 
70 ;; Integer modes supported on the PDP11, with a mapping from machine mode
71 ;; to mnemonic suffix.  SImode and DImode are usually special cases.
72 (define_mode_iterator PDPint [QI HI])
73 (define_mode_attr  isfx [(QI "b") (HI "")])
74 (define_mode_attr  mname [(QI "QImode") (HI "HImode") (SI "SImode") (DI "DImode")])
75 (define_mode_attr  e_mname [(QI "E_QImode") (HI "E_HImode") (SI "E_SImode") (DI "E_DImode")])
76 (define_mode_attr  hmode [(QI "hi") (HI "hi") (SI "si") (DI "di")])
78 ;; These are analogous for use in splitters and expanders.
79 (define_mode_iterator HSint [HI SI])
80 (define_mode_iterator QHSint [QI HI SI])
81 (define_mode_iterator QHSDint [QI HI SI DI])
83 (define_code_iterator SHF [ashift ashiftrt lshiftrt])
85 ;; Substitution to turn a CC clobber into a CC setter.  We have four of
86 ;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
87 (define_subst "cc_cc"
88   [(set (match_operand 0 "") (match_operand 1 ""))
89    (clobber (reg CC_REGNUM))]
90   ""
91   [(set (reg:CC CC_REGNUM)
92         (compare:CC (match_dup 1) (const_int 0)))
93    (set (match_dup 0) (match_dup 1))])
95 (define_subst "cc_ccnz"
96   [(set (match_operand 0 "") (match_operand 1 ""))
97    (clobber (reg CC_REGNUM))]
98   ""
99   [(set (reg:CCNZ CC_REGNUM)
100         (compare:CCNZ (match_dup 1) (const_int 0)))
101    (set (match_dup 0) (match_dup 1))])
103 (define_subst "fcc_cc"
104   [(set (match_operand 0 "") (match_operand 1 ""))
105    (clobber (reg FCC_REGNUM))]
106   ""
107   [(set (reg:CC FCC_REGNUM)
108         (compare:CC (match_dup 1) (const_int 0)))
109    (set (match_dup 0) (match_dup 1))])
111 (define_subst "fcc_ccnz"
112   [(set (match_operand 0 "") (match_operand 1 ""))
113    (clobber (reg FCC_REGNUM))]
114   ""
115   [(set (reg:CCNZ FCC_REGNUM)
116         (compare:CCNZ (match_dup 1) (const_int 0)))
117    (set (match_dup 0) (match_dup 1))])
119 (define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
120 (define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc")
121 (define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc")
122 (define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc")
124 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
126 ;; Compare instructions.
128 ;; currently we only support df floats, which saves us quite some
129 ;; hassle switching the FP mode! 
130 ;; we assume that CPU is always in long float mode, and 
131 ;; 16 bit integer mode - currently, the prologue for main does this,
132 ;; but maybe we should just set up a NEW crt0 properly, 
133 ;; -- and what about signal handling code?
134 ;; (we don't even let sf floats in the register file, so
135 ;; we only should have to worry about truncating and widening 
136 ;; when going to memory)
138 ;; abort() call by g++ - must define libfunc for cmp_optab
139 ;; and ucmp_optab for mode SImode, because we don't have that!!!
140 ;; - yet since no libfunc is there, we abort ()
142 ;; define attributes
143 ;; currently type is only fpu or arith or unknown, maybe branch later ?
144 ;; default is arith
145 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
147 ;; length default is 2 bytes each
148 (define_attr "length" "" (const_int 2))
150 ;; instruction base cost (not counting operands)
151 (define_attr "base_cost" "" (const_int 2))
153 ;; a user's asm statement
154 (define_asm_attributes
155   [(set_attr "type" "unknown")
156 ; length for asm is the max length per statement.  That would be
157 ; 3 words, for a two-operand instruction with extra word addressing
158 ; modes for both operands.
159    (set_attr "length" "6")])
161 ;; define function units
163 ;; Prologue and epilogue support.
165 (define_expand "prologue"
166   [(const_int 0)]
167   ""
169   pdp11_expand_prologue ();
170   DONE;
173 (define_expand "epilogue"
174   [(const_int 0)]
175   ""
177   pdp11_expand_epilogue ();
178   DONE;
181 (define_expand "return"
182   [(return)]
183   "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
184   "")
186 (define_insn "*rts"
187   [(return)]
188   ""
189   "rts\tpc")
191 (define_insn "blockage"
192   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
193   ""
194   ""
195   [(set_attr "length" "0")])
197 (define_insn "setd"
198   [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
199   ""
200   "setd")
202 (define_insn "seti"
203   [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
204   ""
205   "seti")
207 ;; arithmetic - values here immediately when next insn issued
208 ;; or does it mean the number of cycles after this insn was issued?
209 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
211 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
212 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
214 ;; compare
215 (define_insn "*cmpdf"
216   [(set (reg:CC FCC_REGNUM)
217         (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
218                     (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
219   "TARGET_FPU && reload_completed"
220   "*
222   if (which_alternative == 0 || which_alternative == 2)
223     return \"{tstd|tstf}\t%0\";
224   else
225     return \"{cmpd|cmpf}\t%0,%1\";
227   [(set_attr "length" "2,2,4,4")
228    (set_attr "base_cost" "4")
229    (set_attr "type" "fp")]) 
231 ;; Copy floating point processor condition code register to main CPU
232 ;; condition code register.
233 (define_insn "*cfcc"
234   [(set (reg CC_REGNUM) (reg FCC_REGNUM))]
235   "TARGET_FPU && reload_completed"
236   "cfcc")
238 (define_insn "cmp<mode>"
239   [(set (reg:CC CC_REGNUM)
240         (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
241                     (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
242   ""
243   "@
244    tst<PDPint:isfx>\t%0
245    cmp<PDPint:isfx>\t%0,%1
246    cmp<PDPint:isfx>\t%0,%1
247    tst<PDPint:isfx>\t%0
248    cmp<PDPint:isfx>\t%0,%1
249    cmp<PDPint:isfx>\t%0,%1"
250   [(set_attr "length" "2,2,4,4,4,6")])
252 ;; sob instruction
254 ;; Do a define_expand because some alternatives clobber CC.
255 ;; Some don't, but it isn't all that interesting to cover that case.
256 (define_insn_and_split "doloop_end"
257   [(set (pc)
258         (if_then_else
259          (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
260              (const_int 1))
261          (label_ref (match_operand 1 "" ""))
262          (pc)))
263    (set (match_dup 0)
264         (plus:HI (match_dup 0)
265                  (const_int -1)))]
266   "TARGET_40_PLUS"
267   "#"
268   "&& reload_completed"
269   [(parallel [(set (pc)
270                    (if_then_else
271                     (ne (match_dup 0) (const_int 1))
272                     (label_ref (match_dup 1))
273                     (pc)))
274               (set (match_dup 0)
275                    (plus:HI (match_dup 0)
276                          (const_int -1)))
277               (clobber (reg:CC CC_REGNUM))])]
278   "")
280 ;; Note that there is a memory alternative here.  This is as documented
281 ;; in gccint, which says that doloop_end, since it has both a jump and
282 ;; an output interrupt "must handle its own reloads".  That translates
283 ;; to: must accept memory operands as valid though they may be deprecated.
284 (define_insn "doloop_end_nocc"
285   [(set (pc)
286         (if_then_else
287          (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
288              (const_int 1))
289          (label_ref (match_operand 1 "" ""))
290          (pc)))
291    (set (match_dup 0)
292         (plus:HI (match_dup 0)
293               (const_int -1)))
294    (clobber (reg:CC CC_REGNUM))]
295   "TARGET_40_PLUS && reload_completed"
296   "*
298  rtx lb[1];
300  if (get_attr_length (insn) == 2)
301     return \"sob\t%0,%l1\";
303  /* emulate sob */
304  lb[0] = gen_label_rtx ();
305  output_asm_insn (\"dec\t%0\", operands);
306  output_asm_insn (\"beq\t%l0\", lb);
307  output_asm_insn (\"jmp\t%l1\", operands);
309  output_asm_label (lb[0]);
310  fputs (\":\\n\", asm_out_file);
312  return \"\";
314   [(set (attr "length")
315         (if_then_else (eq (symbol_ref ("which_alternative")) (const_int 1))
316                           (const_int 10)
317                           (if_then_else (ior (lt (minus (match_dup 1) (pc))
318                                                  (const_int MIN_SOB))
319                                              (gt (minus (match_dup 1) (pc))
320                                                  (const_int MAX_SOB)))
321                                         (const_int 8)
322                                         (const_int 2))))])
324 ;; These control RTL generation for conditional jump insns
325 ;; and match them for register allocation.
326 ;; Post reload these get expanded into insns that actually
327 ;; manipulate the condition code registers.  We can't do that before
328 ;; because instructions generated by reload clobber condition codes (new
329 ;; CC design, type #2).
330 (define_insn_and_split "cbranchdf4"
331   [(set (pc)
332         (if_then_else (match_operator 0 "ordered_comparison_operator"
333                        [(match_operand:DF 1 "general_operand" "fg")
334                         (match_operand:DF 2 "general_operand" "a")])
335                       (label_ref (match_operand 3 "" ""))
336                       (pc)))]
337   "TARGET_FPU"
338   "#"
339   "&& reload_completed"
340   [(set (reg:CC FCC_REGNUM)
341         (compare:CC (match_dup 1) (match_dup 2)))
342    (set (pc)
343         (if_then_else (match_op_dup 0
344                       [(reg:CC FCC_REGNUM) (const_int 0)])
345                       (label_ref (match_dup 3))
346                       (pc)))]
347   "")
349 (define_insn_and_split "cbranch<mode>4"
350   [(set (pc)
351         (if_then_else (match_operator 0 "ordered_comparison_operator"
352                        [(match_operand:PDPint 1 "general_operand" "g")
353                         (match_operand:PDPint 2 "general_operand" "g")])
354                       (label_ref (match_operand 3 "" ""))
355                       (pc)))]
356   ""
357   "#"
358   "reload_completed"
359   [(set (reg:CC CC_REGNUM)
360         (compare:CC (match_dup 1) (match_dup 2)))
361    (set (pc)
362         (if_then_else (match_op_dup 0
363                       [(reg:CC CC_REGNUM) (const_int 0)])
364                       (label_ref (match_dup 3))
365                       (pc)))]
366   "")
368 ;; This splitter turns a branch on float condition into a branch on
369 ;; CPU condition, by adding a CFCC.
370 (define_split
371   [(set (pc)
372         (if_then_else (match_operator 0 "ordered_comparison_operator"
373                       [(reg:CC FCC_REGNUM) (const_int 0)])
374                       (label_ref (match_operand 1 "" ""))
375                       (pc)))]
376   "TARGET_FPU && reload_completed"
377   [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM))
378    (set (pc)
379         (if_then_else (match_op_dup 0
380                       [(reg:CC CC_REGNUM) (const_int 0)])
381                       (label_ref (match_dup 1))
382                       (pc)))]
383   "")
385 (define_insn "cond_branch"
386   [(set (pc)
387         (if_then_else (match_operator 0 "ordered_comparison_operator"
388                        [(reg:CC CC_REGNUM) (const_int 0)])
389                       (label_ref (match_operand 1 "" ""))
390                       (pc)))]
391   "reload_completed"
392   "* return output_jump (operands, 0, get_attr_length (insn));"
393   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
394                                                       (pc))
395                                                (const_int MIN_BRANCH))
396                                            (gt (minus (match_dup 1)
397                                                       (pc))
398                                                (const_int MAX_BRANCH)))
399                                       (const_int 6)
400                                       (const_int 2)))])
402 (define_insn "*branch"
403   [(set (pc)
404         (if_then_else (match_operator 0 "ccnz_operator"
405                        [(reg:CCNZ CC_REGNUM) (const_int 0)])
406                       (label_ref (match_operand 1 "" ""))
407                       (pc)))]
408   "reload_completed"
409   "* return output_jump (operands, 1, get_attr_length (insn));"
410   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
411                                                       (pc))
412                                                (const_int MIN_BRANCH))
413                                            (gt (minus (match_dup 1)
414                                                       (pc))
415                                                (const_int MAX_BRANCH)))
416                                       (const_int 6)
417                                       (const_int 2)))])
420 ;; Move instructions
422 ;; "length" is defined even though this pattern won't appear at
423 ;; assembly language output time.  But the length is used by
424 ;; pdp11_insn_cost, before the post-reload splitter adds the
425 ;; CC clobber to the insn.
426 (define_insn "movdi"
427   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
428         (match_operand:DI 1 "general_operand" "rN,g"))]
429   ""
430   ""
431   [(set_attr "length" "16,32")])
434 (define_insn "*movdi_nocc"
435   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
436         (match_operand:DI 1 "general_operand" "rN,g"))
437    (clobber (reg:CC CC_REGNUM))]
438   ""
439   "* return output_move_multiple (operands);"
440   [(set_attr "length" "16,32")])
442 (define_insn "movsi"
443   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
444         (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
445   ""
446   ""
447   [(set_attr "length" "4,6,8,16")])
449 (define_insn "*movsi_nocc"
450   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
451         (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))
452    (clobber (reg:CC CC_REGNUM))]
453   ""
454   "* return output_move_multiple (operands);"
455   [(set_attr "length" "4,6,8,16")])
457 (define_insn "mov<mode>"
458   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
459         (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
460   ""
461   ""
462   [(set_attr "length" "2,4,4,6")])
464 ;; This splits all the integer moves: DI and SI modes as well as
465 ;; the simple machine operations.
466 (define_split 
467   [(set (match_operand:QHSDint 0 "nonimmediate_operand" "")
468         (match_operand:QHSDint 1 "general_operand" ""))]
469   "reload_completed"
470   [(parallel [(set (match_dup 0)
471                    (match_dup 1))
472               (clobber (reg:CC CC_REGNUM))])]
473   "")
474   
475 ;; MOV clears V
476 (define_insn "*mov<mode>_<cc_cc>"
477   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
478         (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))
479    (clobber (reg:CC CC_REGNUM))]
480   "reload_completed"
481   "*
483   if (operands[1] == const0_rtx)
484     return \"clr<PDPint:isfx>\t%0\";
486   return \"mov<PDPint:isfx>\t%1,%0\";
488   [(set_attr "length" "2,4,4,6")])
490 ;; movdf has unusually complicated condition code handling, because
491 ;; load (into float register) updates the FCC, while store (from
492 ;; float register) leaves it untouched.
494 ;; 1. Loads are:  ac4, ac5, or non-register into load-register
495 ;; 2. Stores are: load-register to non-register, ac4, or ac5
496 ;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled
497 ;;    either as loads or as stores.
499 (define_expand "movdf"
500   [(set (match_operand:DF 0 "float_nonimm_operand" "")
501         (match_operand:DF 1 "float_operand" ""))]
502   "TARGET_FPU"
503   "")
505 ;; Splitter for all these cases.  Store is the first two
506 ;; alternatives, which are not split.  Note that case 3
507 ;; is treated as a store, i.e., not split.
508 (define_insn_and_split "movdf_split"
509   [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,FQ,a,a,a")
510         (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))]
511   "TARGET_FPU"
512   "*
513   gcc_assert (which_alternative < 2);
514   return \"std\t%1,%0\";
515   "
516   "&& reload_completed"
517   [(parallel [(set (match_dup 0)
518                    (match_dup 1))
519               (clobber (reg:CC FCC_REGNUM))])]
520   "{
521   if (GET_CODE (operands[1]) == REG && 
522       REGNO_REG_CLASS (REGNO (operands[1])) == LOAD_FPU_REGS)
523     FAIL;
524   }"
525   [(set_attr "length" "2,4,0,0,0")])
527 ;; Loads (case 1).  
528 (define_insn "*ldd<fcc_cc>"
529   [(set (match_operand:DF 0 "float_nonimm_operand" "=a,a,a")
530         (match_operand:DF 1 "float_operand" "hR,FQ,G"))
531    (clobber (reg:CC FCC_REGNUM))]
532   "TARGET_FPU && reload_completed"
533   "@
534   ldd\t%1,%0
535   ldd\t%1,%0
536   clrd\t%0"
537   [(set_attr "length" "2,4,2")])
539 ;; SFmode is easier because that uses convert load/store, which
540 ;; always change condition codes.
541 ;; Note that these insns are cheating a bit.  We actually have
542 ;; DFmode operands in the FPU registers, which is why the
543 ;; ldcfd and stcdf instructions appear.  But GCC likes to think
544 ;; of these as SFmode loads and does the conversion once in the
545 ;; register, at least in many cases.  So we pretend to do this,
546 ;; but then extend and truncate register-to-register are NOP and
547 ;; generate no code.
548 (define_insn_and_split "movsf"
549   [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
550         (match_operand:SF 1 "float_operand" "fRG,a,FQ,a,G"))]
551   "TARGET_FPU"
552   "#"
553   "&& reload_completed"
554   [(parallel [(set (match_dup 0)
555                    (match_dup 1))
556               (clobber (reg:CC FCC_REGNUM))])]
557   ""
558   [(set_attr "length" "2,2,4,4,2")])
559   
560 (define_insn "*movsf<fcc_ccnz>"
561   [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
562         (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G"))
563    (clobber (reg:CC FCC_REGNUM))]
564   "TARGET_FPU && reload_completed"
565   "@
566   {ldcfd|movof}\t%1,%0
567   {stcdf|movfo}\t%1,%0
568   {ldcfd|movof}\t%1,%0
569   {stcdf|movfo}\t%1,%0
570   clrf\t%0"
571   [(set_attr "length" "2,2,4,4,2")])
573 ;; maybe fiddle a bit with move_ratio, then 
574 ;; let constraints only accept a register ...
576 (define_expand "movmemhi"
577   [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
578                    (match_operand:BLK 1 "general_operand" "g,g"))
579               (use (match_operand:HI 2 "general_operand" "n,mr"))
580               (use (match_operand:HI 3 "immediate_operand" "i,i"))
581               (clobber (match_scratch:HI 6 "=&r,X"))
582               (clobber (match_dup 4))
583               (clobber (match_dup 5))
584               (clobber (match_dup 2))])]
585   ""
586   "
588   operands[0]
589     = replace_equiv_address (operands[0],
590                              copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
591   operands[1]
592     = replace_equiv_address (operands[1],
593                              copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
595   operands[4] = XEXP (operands[0], 0);
596   operands[5] = XEXP (operands[1], 0);
600 (define_insn "*movmemhi1"
601   [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
602         (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
603    (use (match_operand:HI 2 "general_operand" "n,r"))
604    (use (match_operand:HI 3 "immediate_operand" "i,i"))
605    (clobber (match_scratch:HI 4 "=&r,X"))
606    (clobber (match_dup 0))
607    (clobber (match_dup 1))
608    (clobber (match_dup 2))]
609   ""
610   "* return output_block_move (operands);"
611 ;;; just a guess
612   [(set_attr "length" "80")])
613    
616 ;;- truncation instructions
618 ;; We sometimes end up doing a register to register truncate,
619 ;; which isn't right because we actually load registers always
620 ;; with a DFmode value.  But even with PROMOTE the compiler
621 ;; doesn't always get that (so we don't use it).  That means
622 ;; a register to register truncate is a NOP.
623 (define_insn_and_split  "truncdfsf2"
624   [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
625         (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))]
626   "TARGET_FPU"
627   {
628     gcc_assert (which_alternative == 0);
629     return "";
630   }           
631   "&& reload_completed"
632   [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1)))
633               (clobber (reg:CC FCC_REGNUM))])]
634   "{
635   if (GET_CODE (operands[0]) == REG && 
636       GET_CODE (operands[1]) == REG && 
637       REGNO (operands[0]) == REGNO (operands[1]))
638     FAIL;
639   }"
640   [(set_attr "length" "0,0,0")])
642 (define_insn "*truncdfsf2_<fcc_cc>"
643   [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q")
644         (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a")))
645    (clobber (reg:CC FCC_REGNUM))]
646   "TARGET_FPU && reload_completed"
647    "{stcdf|movfo}\t%1,%0"
648   [(set_attr "length" "2,4")])
651 ;;- zero extension instruction
653 (define_insn_and_split "zero_extendqihi2"
654   [(set (match_operand:HI 0 "nonimmediate_operand" "=rD,Q,&r,&r")
655         (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0,rR,Q")))]
656   ""
657   "#"
658   "reload_completed"
659   [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
660               (clobber (reg:CC CC_REGNUM))])]
661   "{
662     rtx r;
664     if (!REG_P (operands[0]))
665       {
666         r = gen_rtx_MEM (QImode, operands[0]);
667         adjust_address (r, QImode, 1);
668         emit_move_insn (r, const0_rtx);
669         DONE;
670       }
671     else if (!rtx_equal_p (operands[0], operands[1]))
672       {
673         /* Alternatives 2 and 3 */
674         emit_move_insn (operands[0], const0_rtx);
675         r = gen_rtx_REG (QImode, REGNO (operands[0]));
676         emit_insn (gen_iorqi3_nocc (r, r, operands[1]));
677         DONE;
678       }
679   }"
680   [(set_attr "length" "4,4,4,6")])
682 (define_insn "*zero_extendqihi2<cc_cc>"
683   [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
684                    (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))
685               (clobber (reg:CC CC_REGNUM))])]
686   "reload_completed"
687   "bic\t%#0177400,%0"
688   [(set_attr "length" "4,6")])
689                          
690 ;;- sign extension instructions
692 ;; We sometimes end up doing a register to register extend,
693 ;; which isn't right because we actually load registers always
694 ;; with a DFmode value.  But even with PROMOTE the compiler
695 ;; doesn't always get that (so we don't use it).  That means
696 ;; a register to register truncate is a NOP.
697 (define_insn_and_split "extendsfdf2"
698   [(set (match_operand:DF 0 "register_operand" "=f,a,a")
699         (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))]
700   "TARGET_FPU"
701   {
702     gcc_assert (which_alternative == 0);
703     return "";
704   }           
705   "&& reload_completed"
706   [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1)))
707               (clobber (reg:CC FCC_REGNUM))])]
708   "{
709   if (GET_CODE (operands[0]) == REG && 
710       GET_CODE (operands[1]) == REG && 
711       REGNO (operands[0]) == REGNO (operands[1]))
712     FAIL;
713   }"
714   [(set_attr "length" "0,0,0")])
716 (define_insn "*extendsfdf2_<fcc_cc>"
717   [(set (match_operand:DF 0 "register_operand" "=a,a")
718         (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q")))
719    (clobber (reg:CC FCC_REGNUM))]
720   "TARGET_FPU && reload_completed"
721   "{ldcfd|movof}\t%1,%0"
722   [(set_attr "length" "2,4")
723    (set_attr "base_cost" "6")])
725 ;; movb sign extends if destination is a register
726 (define_insn_and_split "extendqihi2"
727   [(set (match_operand:HI 0 "register_operand" "=r,r")
728         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
729   ""
730   "#"
731   "reload_completed"
732   [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
733               (clobber (reg:CC CC_REGNUM))])]
734   ""
735   [(set_attr "length" "2,4")])
737 ;; MOVB clears V
738 (define_insn "*extendqihi2<cc_cc>"
739   [(set (match_operand:HI 0 "register_operand" "=r,r")
740         (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))
741    (clobber (reg:CC CC_REGNUM))]
742   "reload_completed"
743   "movb\t%1,%0"
744   [(set_attr "length" "2,4")])
746 (define_insn_and_split "extendhisi2"
747   [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
748         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
749   "TARGET_40_PLUS"
750   "#"
751   "&& reload_completed"
752   [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
753               (clobber (reg:CC CC_REGNUM))])]
754   ""
755   [(set_attr "length" "10,6,6")])
757 (define_insn "*extendhisi2_nocc"
758   [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
759         (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))
760    (clobber (reg:CC CC_REGNUM))]
761   "TARGET_40_PLUS && reload_completed"
762   "*
764   rtx latehalf[2];
766   /* we don't want to mess with auto increment */
767   
768   switch (which_alternative)
769   {
770     case 0:
772       latehalf[0] = operands[0];
773       operands[0] = adjust_address(operands[0], HImode, 2);
774   
775       output_asm_insn(\"mov\t%1,%0\", operands);
776       output_asm_insn(\"sxt\t%0\", latehalf);
778       return \"\";
780     case 1:
782       /* - auto-decrement - right direction ;-) */
783       output_asm_insn(\"mov\t%1,%0\", operands);
784       output_asm_insn(\"sxt\t%0\", operands);
786       return \"\";
788     case 2:
790       /* make register pair available */
791       latehalf[0] = operands[0];
792       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
794       output_asm_insn(\"mov\t%1,%0\", operands);
795       output_asm_insn(\"sxt\t%0\", latehalf);
797       return \"\";
799     default:
801       gcc_unreachable ();
802   }
804   [(set_attr "length" "10,6,6")])
806 ;; make float to int and vice versa 
807 ;; assume that we are normally in double and integer mode -
808 ;; what do pdp library routines do to fpu mode ?
810 ;; Note: the hardware treats register source as
811 ;; a 16-bit (high order only) source, which isn't
812 ;; what we want.  But we do need to support register
813 ;; dest because gcc asks for it.
814 (define_insn_and_split "floatsidf2"
815   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
816         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
817   "TARGET_FPU"
818   "#"
819   "&& reload_completed"
820   [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
821               (clobber (reg:CC FCC_REGNUM))])]
822   ""
823   [(set_attr "length" "10,6,8")])
825 (define_insn "*floatsidf2<fcc_cc>"
826   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
827         (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))
828    (clobber (reg:CC FCC_REGNUM))]
829   "TARGET_FPU && reload_completed"
830   "* if (which_alternative ==0)
831      {
832        rtx latehalf[2];
834        latehalf[0] = NULL; 
835        latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
836        output_asm_insn(\"mov\t%1,-(sp)\", latehalf);
837        output_asm_insn(\"mov\t%1,-(sp)\", operands);
838        
839        output_asm_insn(\"setl\", operands);
840        output_asm_insn(\"{ldcld|movif}\t(sp)+,%0\", operands);
841        output_asm_insn(\"seti\", operands);
842        return \"\";
843      }
844      else 
845        return \"setl\;{ldcld|movif}\t%1,%0\;seti\";
846   "
847   [(set_attr "length" "10,6,8")
848    (set_attr "base_cost" "12")])
850 (define_insn_and_split "floathidf2"
851   [(set (match_operand:DF 0 "register_operand" "=a,a")
852         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
853   "TARGET_FPU"
854   "#"
855   "&& reload_completed"
856   [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
857               (clobber (reg:CC FCC_REGNUM))])]
858   ""
859   [(set_attr "length" "2,4")])
861 (define_insn "*floathidf2<fcc_cc>"
862   [(set (match_operand:DF 0 "register_operand" "=a,a")
863         (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))
864    (clobber (reg:CC FCC_REGNUM))]
865   "TARGET_FPU && reload_completed"
866   "{ldcid|movif}\t%1,%0"
867   [(set_attr "length" "2,4")
868    (set_attr "base_cost" "12")])
870 ;; cut float to int
872 ;; Note: the hardware treats register destination as
873 ;; a 16-bit (high order only) destination, which isn't
874 ;; what we want.  But we do need to support register
875 ;; dest because gcc asks for it.
876 (define_insn_and_split "fix_truncdfsi2"
877   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
878         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
879   "TARGET_FPU"
880   "#"
881   "&& reload_completed"
882   [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1))))
883               (clobber (reg:CC CC_REGNUM))
884               (clobber (reg:CC FCC_REGNUM))])]
885   ""
886   [(set_attr "length" "10,6,8")])
888 ;; Note: this clobbers both sets of condition codes!
889 (define_insn "*fix_truncdfsi2_nocc"
890   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
891         (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))
892    (clobber (reg:CC CC_REGNUM))
893    (clobber (reg:CC FCC_REGNUM))]
894   "TARGET_FPU && reload_completed"
895   "* if (which_alternative ==0)
896      {
897        output_asm_insn(\"setl\", operands);
898        output_asm_insn(\"{stcdl|movfi}\t%1,-(sp)\", operands);
899        output_asm_insn(\"seti\", operands);
900        output_asm_insn(\"mov\t(sp)+,%0\", operands);
901        operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
902        output_asm_insn(\"mov\t(sp)+,%0\", operands);
903        return \"\";
904      }
905      else 
906        return \"setl\;{stcdl|movfi}\t%1,%0\;seti\";
907   "
908   [(set_attr "length" "10,6,8")
909    (set_attr "base_cost" "12")])
911 (define_insn_and_split "fix_truncdfhi2"
912   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
913         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
914   "TARGET_FPU"
915   "#"
916   "&& reload_completed"
917   [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1))))
918               (clobber (reg:CC CC_REGNUM))
919               (clobber (reg:CC FCC_REGNUM))])]
920   ""
921   [(set_attr "length" "2,4")])
923 ;; Note: this clobbers both sets of condition codes!
924 (define_insn "*fix_truncdfhi2_nocc"
925   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
926         (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))
927    (clobber (reg:CC CC_REGNUM))
928    (clobber (reg:CC FCC_REGNUM))]
929   "TARGET_FPU && reload_completed"
930   "{stcdi|movfi}\t%1,%0"
931   [(set_attr "length" "2,4")
932    (set_attr "base_cost" "12")])
935 ;;- arithmetic instructions
936 ;;- add instructions
938 (define_insn_and_split "adddf3"
939   [(set (match_operand:DF 0 "register_operand" "=a,a")
940         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
941                  (match_operand:DF 2 "general_operand" "fR,QF")))]
942   "TARGET_FPU"
943   "#"
944   "&& reload_completed"
945   [(parallel [(set (match_dup 0)
946                    (plus:DF (match_dup 1) (match_dup 2)))
947               (clobber (reg:CC FCC_REGNUM))])]
948   ""
949   [(set_attr "length" "2,4")])
951 ;; Float add sets V if overflow from add
952 (define_insn "*adddf3<fcc_ccnz>"
953   [(set (match_operand:DF 0 "register_operand" "=a,a")
954         (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
955               (match_operand:DF 2 "general_operand" "fR,QF")))
956    (clobber (reg:CC FCC_REGNUM))]
957   "TARGET_FPU && reload_completed"
958   "{addd|addf}\t%2,%0"
959   [(set_attr "length" "2,4")
960    (set_attr "base_cost" "6")])
962 (define_insn_and_split "adddi3"
963   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
964         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
965                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
966   ""
967   "#"
968   "reload_completed"
969   [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
970               (clobber (reg:CC CC_REGNUM))])]
971   ""
972   [(set_attr "length" "20,28,40,48")])
974 (define_insn "*adddi3_nocc"
975   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
976         (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
977               (match_operand:DI 2 "general_operand" "r,on,r,on")))
978    (clobber (reg:CC CC_REGNUM))]
979   "reload_completed"  
980   "*
982   rtx inops[2];
983   rtx exops[4][2];
984   
985   inops[0] = operands[0];
986   inops[1] = operands[2];
987   pdp11_expand_operands (inops, exops, 2, NULL, either);
988   
989   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
990     output_asm_insn (\"add\t%1,%0\", exops[0]);
991   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
992   {
993     output_asm_insn (\"add\t%1,%0\", exops[1]);
994     output_asm_insn (\"adc\t%0\", exops[0]);
995   }
996   if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
997   {
998     output_asm_insn (\"add\t%1,%0\", exops[2]);
999     output_asm_insn (\"adc\t%0\", exops[1]);
1000     output_asm_insn (\"adc\t%0\", exops[0]);
1001   }
1002   if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1003   {
1004     output_asm_insn (\"add\t%1,%0\", exops[3]);
1005     output_asm_insn (\"adc\t%0\", exops[2]);
1006     output_asm_insn (\"adc\t%0\", exops[1]);
1007     output_asm_insn (\"adc\t%0\", exops[0]);
1008   }
1010   return \"\";
1012   [(set_attr "length" "20,28,40,48")
1013    (set_attr "base_cost" "0")])
1015 ;; Note that the register operand is not marked earlyclobber.
1016 ;; The reason is that SI values go in register pairs, so they
1017 ;; can't partially overlap.  They can be either disjoint, or
1018 ;; source and destination can be equal.  The latter case is 
1019 ;; handled properly because of the ordering of the individual
1020 ;; instructions used.  Specifically, carry from the low to the
1021 ;; high word is added at the end, so the adding of the high parts
1022 ;; will always used the original high part and not a high part
1023 ;; modified by carry (which would amount to double carry).
1024 (define_insn_and_split "addsi3"
1025   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1026         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1027                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1028   ""
1029   "#"
1030   "reload_completed"
1031   [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
1032               (clobber (reg:CC CC_REGNUM))])]
1033   ""
1034   [(set_attr "length" "6,10,12,16")])
1036 (define_insn "*addsi3_nocc"
1037   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1038         (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1039               (match_operand:SI 2 "general_operand" "r,on,r,on")))
1040    (clobber (reg:CC CC_REGNUM))]
1041   "reload_completed"
1042   "*
1044   rtx inops[2];
1045   rtx exops[2][2];
1046   
1047   inops[0] = operands[0];
1048   inops[1] = operands[2];
1049   pdp11_expand_operands (inops, exops, 2, NULL, either);
1050   
1051   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1052     output_asm_insn (\"add\t%1,%0\", exops[0]);
1053   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1054   {
1055     output_asm_insn (\"add\t%1,%0\", exops[1]);
1056     output_asm_insn (\"adc\t%0\", exops[0]);
1057   }
1059   return \"\";
1061   [(set_attr "length" "6,10,12,16")
1062    (set_attr "base_cost" "0")])
1064 (define_insn_and_split "addhi3"
1065   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1066         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1067                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1068   ""
1069   "#"
1070   "reload_completed"
1071   [(parallel [(set (match_dup 0)
1072                    (plus:HI (match_dup 1) (match_dup 2)))
1073               (clobber (reg:CC CC_REGNUM))])]
1074   ""
1075   [(set_attr "length" "2,4,4,6")])
1077 ;; Add sets V if overflow from the add
1078 (define_insn "*addhi3<cc_ccnz>"
1079   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1080         (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1081                  (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1082    (clobber (reg:CC CC_REGNUM))]
1083   "reload_completed"
1084   "*
1086   if (GET_CODE (operands[2]) == CONST_INT)
1087     {
1088       if (INTVAL(operands[2]) == 1)
1089         return \"inc\t%0\";
1090       else if (INTVAL(operands[2]) == -1)
1091         return \"dec\t%0\";
1092     }
1094   return \"add\t%2,%0\";
1096   [(set_attr "length" "2,4,4,6")])
1099 ;;- subtract instructions
1100 ;; we don't have to care for constant second 
1101 ;; args, since they are canonical plus:xx now!
1102 ;; also for minus:DF ??
1104 (define_insn_and_split "subdf3"
1105   [(set (match_operand:DF 0 "register_operand" "=a,a")
1106         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1107                   (match_operand:DF 2 "general_operand" "fR,Q")))]
1108   "TARGET_FPU"
1109   "#"
1110   "&& reload_completed"
1111   [(parallel [(set (match_dup 0)
1112                    (minus:DF (match_dup 1) (match_dup 2)))
1113               (clobber (reg:CC FCC_REGNUM))])]
1114   ""
1115   [(set_attr "length" "2,4")])
1117 (define_insn "*subdf3<fcc_ccnz>"
1118   [(set (match_operand:DF 0 "register_operand" "=a,a")
1119         (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1120                   (match_operand:DF 2 "general_operand" "fR,QF")))
1121    (clobber (reg:CC FCC_REGNUM))]
1122   "TARGET_FPU && reload_completed"
1123   "{subd|subf}\t%2,%0"
1124   [(set_attr "length" "2,4")
1125    (set_attr "base_cost" "6")])
1127 (define_insn_and_split "subdi3"
1128   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1129         (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1130                  (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1131   ""
1132   "#"
1133   "reload_completed"
1134   [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
1135               (clobber (reg:CC CC_REGNUM))])]
1136   ""
1137   [(set_attr "length" "20,28,40,48")])
1139 (define_insn "*subdi3_nocc"
1140   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1141         (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1142               (match_operand:DI 2 "general_operand" "r,on,r,on")))
1143    (clobber (reg:CC CC_REGNUM))]
1144   "reload_completed"
1145   "*
1147   rtx inops[2];
1148   rtx exops[4][2];
1149   
1150   inops[0] = operands[0];
1151   inops[1] = operands[2];
1152   pdp11_expand_operands (inops, exops, 2, NULL, either);
1153   
1154   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1155     output_asm_insn (\"sub\t%1,%0\", exops[0]);
1156   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1157   {
1158     output_asm_insn (\"sub\t%1,%0\", exops[1]);
1159     output_asm_insn (\"sbc\t%0\", exops[0]);
1160   }
1161   if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1162   {
1163     output_asm_insn (\"sub\t%1,%0\", exops[2]);
1164     output_asm_insn (\"sbc\t%0\", exops[1]);
1165     output_asm_insn (\"sbc\t%0\", exops[0]);
1166   }
1167   if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1168   {
1169     output_asm_insn (\"sub\t%1,%0\", exops[3]);
1170     output_asm_insn (\"sbc\t%0\", exops[2]);
1171     output_asm_insn (\"sbc\t%0\", exops[1]);
1172     output_asm_insn (\"sbc\t%0\", exops[0]);
1173   }
1175   return \"\";
1177   [(set_attr "length" "20,28,40,48")
1178    (set_attr "base_cost" "0")])
1180 (define_insn_and_split "subsi3"
1181   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1182         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1183                  (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1184   ""
1185   "#"
1186   "reload_completed"
1187   [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1188               (clobber (reg:CC CC_REGNUM))])]
1189   ""
1190   [(set_attr "length" "6,10,12,16")])
1192 (define_insn "*subsi3_nocc"
1193   [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1194         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1195               (match_operand:SI 2 "general_operand" "r,on,r,on")))
1196    (clobber (reg:CC CC_REGNUM))]
1197   "reload_completed"
1198   "*
1200   rtx inops[2];
1201   rtx exops[2][2];
1202   
1203   inops[0] = operands[0];
1204   inops[1] = operands[2];
1205   pdp11_expand_operands (inops, exops, 2, NULL, either);
1206   
1207   if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1208     output_asm_insn (\"sub\t%1,%0\", exops[0]);
1209   if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1210   {
1211     output_asm_insn (\"sub\t%1,%0\", exops[1]);
1212     output_asm_insn (\"sbc\t%0\", exops[0]);
1213   }
1215   return \"\";
1217   [(set_attr "length" "6,10,12,16")
1218    (set_attr "base_cost" "0")])
1220 (define_insn_and_split "subhi3"
1221   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1222         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1223                   (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1224   ""
1225   "#"
1226   "reload_completed"
1227   [(parallel [(set (match_dup 0)
1228                    (minus:HI (match_dup 1) (match_dup 2)))
1229               (clobber (reg:CC CC_REGNUM))])]
1230   ""
1231   [(set_attr "length" "2,4,4,6")])
1233 ;; Note: the manual says that (minus m (const_int n)) is converted
1234 ;; to (plus m (const_int -n)) but that does not appear to be
1235 ;; the case when it's wrapped in a PARALLEL.  So instead we handle
1236 ;; that case here, which is easy enough.
1237 (define_insn "*subhi3<cc_ccnz>"
1238   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1239         (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1240                   (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1241    (clobber (reg:CC CC_REGNUM))]
1242   "reload_completed"
1243   "*
1245   if (GET_CODE (operands[2]) == CONST_INT)
1246     {
1247       if (INTVAL(operands[2]) == 1)
1248         return \"dec\t%0\";
1249       else if (INTVAL(operands[2]) == -1)
1250         return \"inc\t%0\";
1251     }
1253   return \"sub\t%2,%0\";
1255   [(set_attr "length" "2,4,4,6")])
1257 ;;;;- and instructions
1258 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1260 (define_expand "and<mode>3"
1261   [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
1262         (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
1263                    (match_operand:PDPint 2 "general_operand" "")))]
1264   ""
1265   "
1267   rtx op1 = operands[1];
1269   /* If there is a constant argument, complement that one.
1270      Similarly, if one of the inputs is the same as the output,
1271      complement the other input.  */
1272   if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
1273       rtx_equal_p (operands[0], operands[1]))
1274     {
1275       operands[1] = operands[2];
1276       operands[2] = op1;
1277       op1 = operands[1];
1278     }
1280   if (CONST_INT_P (op1))
1281     operands[1] = GEN_INT (~INTVAL (op1));
1282   else
1283     operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
1285   [(set_attr "length" "2,4,4,6")])
1287 (define_insn_and_split "*bic<mode>"
1288   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1289         (and:PDPint
1290              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1291              (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
1292   ""
1293   "#"
1294   "reload_completed"
1295   [(parallel [(set (match_dup 0)
1296                    (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2)))
1297               (clobber (reg:CC CC_REGNUM))])]
1298   "")
1300 (define_insn "*bic<mode><cc_cc>"
1301   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1302         (and:PDPint
1303              (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1304                           (match_operand:PDPint 2 "general_operand" "0,0,0,0")))
1305    (clobber (reg:CC CC_REGNUM))]
1306   "reload_completed"
1307   "bic<PDPint:isfx>\t%1,%0"
1308   [(set_attr "length" "2,4,4,6")])
1310 ;;- Bit set (inclusive or) instructions
1311 (define_insn_and_split "ior<mode>3"
1312   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1313         (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1314                     (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
1315   ""
1316   "#"
1317   "reload_completed"
1318   [(parallel [(set (match_dup 0)
1319                    (ior:PDPint (match_dup 1) (match_dup 2)))
1320               (clobber (reg:CC CC_REGNUM))])]
1321   ""
1322   [(set_attr "length" "2,4,4,6")])
1324 (define_insn "ior<mode>3<cc_cc>"
1325   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1326         (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1327              (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))
1328    (clobber (reg:CC CC_REGNUM))]
1329   "reload_completed"
1330   "bis<PDPint:isfx>\t%2,%0"
1331   [(set_attr "length" "2,4,4,6")])
1333 ;;- xor instructions
1334 (define_insn_and_split "xorhi3"
1335   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1336         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1337                 (match_operand:HI 2 "register_operand" "r,r")))]
1338   "TARGET_40_PLUS"
1339   "#"
1340   "&& reload_completed"
1341   [(parallel [(set (match_dup 0)
1342                    (xor:HI (match_dup 1) (match_dup 2)))
1343               (clobber (reg:CC CC_REGNUM))])]
1344   ""
1345   [(set_attr "length" "2,4")])
1347 (define_insn "*xorhi3<cc_cc>"
1348   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1349         (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1350              (match_operand:HI 2 "register_operand" "r,r")))
1351    (clobber (reg:CC CC_REGNUM))]
1352   "TARGET_40_PLUS && reload_completed"
1353   "xor\t%2,%0"
1354   [(set_attr "length" "2,4")])
1356 ;;- one complement instructions
1358 (define_insn_and_split "one_cmpl<mode>2"
1359   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1360         (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1361   ""
1362   "#"
1363   "reload_completed"
1364   [(parallel [(set (match_dup 0)
1365                    (not:PDPint (match_dup 1)))
1366               (clobber (reg:CC CC_REGNUM))])]
1367   ""
1368   [(set_attr "length" "2,4")])
1370 (define_insn "*one_cmpl<mode>2<cc_cc>"
1371   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1372         (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1373    (clobber (reg:CC CC_REGNUM))]
1374   "reload_completed"
1375   "com<PDPint:isfx>\t%0"
1376   [(set_attr "length" "2,4")])
1378 ;;- arithmetic shift instructions
1380 ;; There is a fair amount of complexity here because with -m10
1381 ;; (pdp-11/10, /20) we only have shift by one bit.  Iterators are
1382 ;; used to reduce the amount of very similar code.
1384 ;; First the insns used for small constant shifts.
1385 (define_insn_and_split "<code><mode>_sc"
1386   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1387         (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1388                     (match_operand:HI 2 "expand_shift_operand" "O,O")))]
1389   ""
1390   "#"
1391   "reload_completed"
1392   [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1393               (clobber (reg:CC CC_REGNUM))])]
1394   ""
1395   [(set (attr "length")
1396         (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
1397                                          <CODE>, which_alternative == 0)"))
1398    (set_attr "base_cost" "0")])
1400 (define_insn "<code><mode>_sc<cc_ccnz>"
1401   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rD,Q")
1402         (SHF:PDPint (match_operand:PDPint 1 "general_operand" "0,0")
1403              (match_operand:HI 2 "expand_shift_operand" "O,O")))
1404    (clobber (reg:CC CC_REGNUM))]
1405   "reload_completed"
1406   "* return pdp11_assemble_shift (operands, <PDPint:mname>, <CODE>);"
1407   [(set (attr "length")
1408         (symbol_ref "pdp11_shift_length (operands, <PDPint:mname>, 
1409                                          <CODE>, which_alternative == 0)"))
1410    (set_attr "base_cost" "0")])
1412 ;; This one comes only in clobber flavor.
1413 (define_insn "<code>si_sc_nocc"
1414   [(set (match_operand:SI 0 "nonimmediate_operand" "=rD,Q")
1415         (SHF:SI (match_operand:SI 1 "general_operand" "0,0")
1416              (match_operand:HI 2 "expand_shift_operand" "O,O")))
1417    (clobber (reg:CC CC_REGNUM))]
1418   "reload_completed"
1419   "* return pdp11_assemble_shift (operands, SImode, <CODE>);"
1420   [(set (attr "length")
1421         (symbol_ref "pdp11_shift_length (operands, SImode, 
1422                                          <CODE>, which_alternative == 0)"))
1423    (set_attr "base_cost" "0")])
1425 ;; Next, shifts that are done as a loop on base (11/10 class) machines.
1426 ;; This applies to shift counts too large to unroll, or variable shift
1427 ;; counts.  The check for count <= 0 is done before we get here.
1428 (define_insn_and_split "<code><mode>_base"
1429   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1430         (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1431              (match_operand:HI 2 "register_operand" "r,r")))
1432    (clobber (match_dup 2))]
1433   ""
1434   "#"
1435   "reload_completed"
1436   [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1437               (clobber (match_dup 2))
1438               (clobber (reg:CC CC_REGNUM))])]
1439   ""
1440   [(set (attr "length")
1441         (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
1442                                          <CODE>, which_alternative == 0)"))
1443    (set_attr "base_cost" "0")])
1445 (define_insn "<code><mode>_base_nocc"
1446   [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1447         (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1448              (match_operand:HI 2 "register_operand" "r,r")))
1449    (clobber (match_dup 2))
1450    (clobber (reg:CC CC_REGNUM))]
1451   "reload_completed"
1452   "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1453   [(set (attr "length")
1454         (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>, 
1455                                          <CODE>, which_alternative == 0)"))
1456    (set_attr "base_cost" "0")])
1458 ;; Next the insns that use the extended instructions ash and ashc.
1459 ;; Note that these are just left shifts, and HI/SI only.  (Right shifts
1460 ;; are done by shifting by a negative amount.)
1461 (define_insn_and_split "aslhi_op"
1462   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1463         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1464                        (match_operand:HI 2 "general_operand" "rR,Qi")))]
1465   "TARGET_40_PLUS"
1466   "#"
1467   "&& reload_completed"
1468   [(parallel [(set (match_dup 0)
1469                    (ashift:HI (match_dup 1) (match_dup 2)))
1470               (clobber (reg:CC CC_REGNUM))])]
1471   ""
1472   [(set_attr "length" "2,4")
1473    (set_attr "base_cost" "8")])
1475 (define_insn "aslhi_op<cc_ccnz>"
1476   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1477         (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1478                 (match_operand:HI 2 "general_operand" "rR,Qi")))
1479    (clobber (reg:CC CC_REGNUM))]
1480   "TARGET_40_PLUS && reload_completed"
1481   "ash\t%2,%0"
1482   [(set_attr "length" "2,4")
1483    (set_attr "base_cost" "8")])
1485 (define_insn_and_split "aslsi_op"
1486   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1487         (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1488                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
1489   "TARGET_40_PLUS"
1490   "#"
1491   "&& reload_completed"
1492   [(parallel [(set (match_dup 0)
1493                    (ashift:SI (match_dup 1) (match_dup 2)))
1494               (clobber (reg:CC CC_REGNUM))])]
1495   ""
1496   [(set_attr "length" "2,4")
1497    (set_attr "base_cost" "8")])
1499 (define_insn "aslsi_op_<cc_ccnz>"
1500   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1501         (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1502                 (match_operand:HI 2 "general_operand" "rR,Qi")))
1503    (clobber (reg:CC CC_REGNUM))]
1504   "TARGET_40_PLUS && reload_completed"
1505   "ashc\t%2,%0"
1506   [(set_attr "length" "2,4")
1507    (set_attr "base_cost" "8")])
1509 ;; Now the expanders that produce the insns defined above. 
1510 (define_expand "ashl<mode>3"
1511   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1512    (match_operand:QHSint 1 "general_operand" "")
1513    (match_operand:HI 2 "general_operand" "")]
1514   ""
1515   "
1517   rtx r;
1519   if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base))
1520     {
1521       if (<QHSint:e_mname> == E_QImode)
1522         {
1523           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1524           emit_insn (gen_aslhi_op (r, r, operands[2]));
1525           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1526         }
1527       else
1528         {
1529           emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1530         }
1531     }
1532   DONE;
1535 (define_expand "ashr<mode>3"
1536   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1537    (match_operand:QHSint 1 "general_operand" "")
1538    (match_operand:HI 2 "general_operand" "")]
1539   ""
1540   "
1542   rtx r;
1544   if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base))
1545     {
1546       operands[2] = negate_rtx (HImode, operands[2]);
1547       if (<QHSint:e_mname> == E_QImode)
1548         {
1549           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1550           emit_insn (gen_aslhi_op (r, r, operands[2]));
1551           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1552         }
1553       else
1554         {
1555           emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1556         }
1557     }
1558   DONE;
1561 (define_expand "lshr<mode>3"
1562   [(match_operand:QHSint 0 "nonimmediate_operand" "")
1563    (match_operand:QHSint 1 "general_operand" "")
1564    (match_operand:HI 2 "general_operand" "")]
1565   ""
1566   "
1568   rtx r, n;
1570   if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base))
1571     {
1572       if (<QHSint:e_mname> == E_QImode)
1573         {
1574           r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1575           emit_insn (gen_aslhi_op (r, r, operands[2]));
1576           emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1577         }
1578       else
1579         {
1580           r = gen_reg_rtx (<QHSint:mname>);
1581           emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx));
1582           if (GET_CODE (operands[2]) != CONST_INT)
1583             {
1584               n = gen_reg_rtx (HImode);
1585               emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1)));
1586               emit_insn (gen_ashr<mode>3 (operands[0], r, n));
1587             }
1588           else
1589             emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r,
1590                                   GEN_INT (1 - INTVAL (operands[2]))));
1591         }
1592     }
1593   DONE;
1596 ;; absolute 
1598 (define_insn_and_split "absdf2"
1599   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1600         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1601   "TARGET_FPU"
1602   "#"
1603   "&& reload_completed"
1604   [(parallel [(set (match_dup 0) (abs:DF (match_dup 1)))
1605               (clobber (reg:CC FCC_REGNUM))])]
1606    ""
1607   [(set_attr "length" "2,4")])
1609 (define_insn "absdf2<fcc_cc>"
1610   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1611         (abs:DF (match_operand:DF 1 "general_operand" "0,0")))
1612    (clobber (reg:CC FCC_REGNUM))]
1613   "TARGET_FPU && reload_completed"
1614   "{absd|absf}\t%0"
1615   [(set_attr "length" "2,4")])
1617 ;; negate insns
1619 (define_insn_and_split "negdf2"
1620   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1621         (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
1622   "TARGET_FPU"
1623   "#"
1624   "&& reload_completed"
1625   [(parallel [(set (match_dup 0) (neg:DF (match_dup 1)))
1626               (clobber (reg:CC FCC_REGNUM))])]
1627    ""
1628   [(set_attr "length" "2,4")])
1630 (define_insn "negdf2<fcc_cc>"
1631   [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1632         (neg:DF (match_operand:DF 1 "general_operand" "0,0")))
1633    (clobber (reg:CC FCC_REGNUM))]
1634   "TARGET_FPU && reload_completed"
1635   "{negd|negf}\t%0"
1636   [(set_attr "length" "2,4")])
1638 (define_insn_and_split "negdi2"
1639   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1640         (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1641   ""
1642   "#"
1643   "reload_completed"
1644   [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
1645               (clobber (reg:CC CC_REGNUM))])]
1646   ""
1647   [(set_attr "length" "18,34")])
1648   
1649 ;; TODO: this can be neg/adc/neg/adc... I believe.  Check.  Saves one word.
1650 (define_insn "negdi2_nocc"
1651   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1652         (neg:DI (match_operand:DI 1 "general_operand" "0,0")))
1653    (clobber (reg:CC CC_REGNUM))]
1654   "reload_completed"
1655   {
1656     rtx exops[4][2];
1657     
1658     pdp11_expand_operands (operands, exops, 1, NULL, either);
1659   
1660     output_asm_insn (\"com\t%0\", exops[3]);
1661     output_asm_insn (\"com\t%0\", exops[2]);
1662     output_asm_insn (\"com\t%0\", exops[1]);
1663     output_asm_insn (\"com\t%0\", exops[0]);
1664     output_asm_insn (\"add\t%#1,%0\", exops[3]);
1665     output_asm_insn (\"adc\t%0\", exops[2]);
1666     output_asm_insn (\"adc\t%0\", exops[1]);
1667     output_asm_insn (\"adc\t%0\", exops[0]);
1668   
1669     return \"\";
1670   }
1671   [(set_attr "length" "18,34")
1672    (set_attr "base_cost" "0")])
1674 (define_insn_and_split "negsi2"
1675   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1676         (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1677   ""
1678   "#"
1679   "reload_completed"
1680   [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
1681               (clobber (reg:CC CC_REGNUM))])]
1682   ""
1683   [(set_attr "length" "10,18")])
1684   
1685 ;; TODO: this can be neg/adc/neg/adc... I believe.  Check.  Saves one word.
1686 (define_insn "negsi2_nocc"
1687   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1688         (neg:SI (match_operand:SI 1 "general_operand" "0,0")))
1689    (clobber (reg:CC CC_REGNUM))]
1690   "reload_completed"
1691   {
1692     rtx exops[2][2];
1693     
1694     pdp11_expand_operands (operands, exops, 1, NULL, either);
1695   
1696     output_asm_insn (\"com\t%0\", exops[1]);
1697     output_asm_insn (\"com\t%0\", exops[0]);
1698     output_asm_insn (\"add\t%#1,%0\", exops[1]);
1699     output_asm_insn (\"adc\t%0\", exops[0]);
1700   
1701     return \"\";
1702   }
1703   [(set_attr "length" "10,18")
1704    (set_attr "base_cost" "0")])
1706 (define_insn_and_split "neg<mode>2"
1707   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1708         (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1709   ""
1710   "#"
1711   "reload_completed"
1712   [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1)))
1713               (clobber (reg:CC CC_REGNUM))])]
1714   ""
1715   [(set_attr "length" "2,4")])
1716   
1717 (define_insn "neg<mode>2<cc_ccnz>"
1718   [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1719         (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1720    (clobber (reg:CC CC_REGNUM))]
1721   ""
1722   "neg<PDPint:isfx>\t%0"
1723   [(set_attr "length" "2,4")])
1726 ;; Unconditional and other jump instructions
1727 (define_insn "jump"
1728   [(set (pc)
1729         (label_ref (match_operand 0 "" "")))]
1730   ""
1731   "*
1733   if (get_attr_length (insn) == 2)
1734     return \"br\t%l0\";
1735   return \"jmp\t%l0\";
1737   [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1738                                                       (pc))
1739                                                (const_int MIN_BRANCH))
1740                                            (gt (minus (match_dup 0)
1741                                                       (pc))
1742                                                (const_int MAX_BRANCH)))
1743                                       (const_int 4)
1744                                       (const_int 2)))])
1746 (define_insn "tablejump"
1747   [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1748    (use (label_ref (match_operand 1 "" "")))]
1749   ""
1750   "@
1751   jmp\t(%0)
1752   jmp\t%@%0
1753   jmp\t%@%0"
1754   [(set_attr "length" "2,2,4")])
1756 ;; indirect jump.  TODO: this needs a constraint that allows memory
1757 ;; references but not indirection, since we add a level of indirection
1758 ;; in the generated code.
1759 (define_insn "indirect_jump"
1760   [(set (pc) (match_operand:HI 0 "general_operand" "r"))]
1761   ""
1762   "jmp\t@%0"
1763   [(set_attr "length" "2")])
1765 ;;- jump to subroutine
1767 (define_insn "call"
1768   [(call (match_operand:HI 0 "general_operand" "rR,Q")
1769          (match_operand:HI 1 "general_operand" "g,g"))]
1770   ;;- Don't use operand 1 for most machines.
1771   ""
1772   "jsr\tpc,%0"
1773   [(set_attr "length" "2,4")])
1775 ;;- jump to subroutine
1776 (define_insn "call_value"
1777   [(set (match_operand 0 "" "")
1778         (call (match_operand:HI 1 "general_operand" "rR,Q")
1779               (match_operand:HI 2 "general_operand" "g,g")))]
1780   ;;- Don't use operand 2 for most machines.
1781   ""
1782   "jsr\tpc,%1"
1783   [(set_attr "length" "2,4")])
1785 (define_expand "untyped_call"
1786   [(parallel [(call (match_operand 0 "" "")
1787                     (const_int 0))
1788               (match_operand 1 "" "")
1789               (match_operand 2 "" "")])]
1790   ""
1792   int i;
1794   emit_call_insn (gen_call (operands[0], const0_rtx));
1796   for (i = 0; i < XVECLEN (operands[2], 0); i++)
1797     {
1798       rtx set = XVECEXP (operands[2], 0, i);
1799       emit_move_insn (SET_DEST (set), SET_SRC (set));
1800     }
1802   /* The optimizer does not know that the call sets the function value
1803      registers we stored in the result block.  We avoid problems by
1804      claiming that all hard registers are used and clobbered at this
1805      point.  */
1806   emit_insn (gen_blockage ());
1808   DONE;
1811 ;;- nop instruction
1812 (define_insn "nop"
1813   [(const_int 0)]
1814   ""
1815   "nop")
1818 ;;- multiply 
1820 (define_insn_and_split "muldf3"
1821   [(set (match_operand:DF 0 "register_operand" "=a,a")
1822         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1823                  (match_operand:DF 2 "float_operand" "fR,QF")))]
1824   "TARGET_FPU"
1825   "#"
1826   "&& reload_completed"
1827   [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2)))
1828               (clobber (reg:CC FCC_REGNUM))])]
1829   ""
1830   [(set_attr "length" "2,4")])
1832 (define_insn "muldf3<fcc_ccnz>"
1833   [(set (match_operand:DF 0 "register_operand" "=a,a")
1834         (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1835               (match_operand:DF 2 "float_operand" "fR,QF")))
1836    (clobber (reg:CC FCC_REGNUM))]
1837   "TARGET_FPU && reload_completed"
1838   "{muld|mulf}\t%2,%0"
1839   [(set_attr "length" "2,4")
1840    (set_attr "base_cost" "20")])
1842 ;; 16 bit result multiply.  This uses odd numbered registers.
1844 (define_insn_and_split "mulhi3"
1845   [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1846         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1847                  (match_operand:HI 2 "general_operand" "rR,Qi")))]
1848   "TARGET_40_PLUS"
1849   "#"
1850   "&& reload_completed"
1851   [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2)))
1852               (clobber (reg:CC CC_REGNUM))])]
1853   ""
1854   [(set_attr "length" "2,4")])
1856 (define_insn "mulhi3<cc_cc>"
1857   [(set (match_operand:HI 0 "register_operand" "=d,d")
1858         (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1859               (match_operand:HI 2 "general_operand" "rR,Qi")))
1860    (clobber (reg:CC CC_REGNUM))]
1861   "TARGET_40_PLUS && reload_completed"
1862   "mul\t%2,%0"
1863   [(set_attr "length" "2,4")
1864    (set_attr "base_cost" "20")])
1866 ;; 32 bit result from 16 bit operands
1867 (define_insn_and_split "mulhisi3"
1868   [(set (match_operand:SI 0 "register_operand" "=r,r")
1869         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
1870                  (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))]
1871   "TARGET_40_PLUS"
1872   "#"
1873   "&& reload_completed"
1874   [(parallel [(set (match_dup 0)
1875                    (mult:SI (sign_extend:SI (match_dup 1))
1876                          (sign_extend:SI (match_dup 2))))
1877               (clobber (reg:CC CC_REGNUM))])]
1878   ""
1879   [(set_attr "length" "2,4")])
1881 (define_insn "mulhisi3<cc_cc>"
1882   [(set (match_operand:SI 0 "register_operand" "=r,r")
1883         (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
1884               (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))
1885    (clobber (reg:CC CC_REGNUM))]
1886   "TARGET_40_PLUS && reload_completed"
1887   "mul\t%2,%0"
1888   [(set_attr "length" "2,4")
1889    (set_attr "base_cost" "20")])
1891 ;;- divide
1892 (define_insn_and_split "divdf3"
1893   [(set (match_operand:DF 0 "register_operand" "=a,a")
1894         (div:DF (match_operand:DF 1 "register_operand" "0,0")
1895                 (match_operand:DF 2 "general_operand" "fR,QF")))]
1896   "TARGET_FPU"
1897   "#"
1898   "&& reload_completed"
1899   [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2)))
1900               (clobber (reg:CC FCC_REGNUM))])]
1901    ""
1902   [(set_attr "length" "2,4")])
1903   
1904 (define_insn "divdf3<fcc_ccnz>"
1905   [(set (match_operand:DF 0 "register_operand" "=a,a")
1906         (div:DF (match_operand:DF 1 "register_operand" "0,0")
1907              (match_operand:DF 2 "general_operand" "fR,QF")))
1908    (clobber (reg:CC FCC_REGNUM))]
1909   "TARGET_FPU && reload_completed"
1910   "{divd|divf}\t%2,%0"
1911   [(set_attr "length" "2,4")
1912    (set_attr "base_cost" "20")])
1914 (define_expand "divmodhi4"
1915   [(parallel
1916     [(set (subreg:HI (match_dup 1) 0)
1917         (div:HI (match_operand:SI 1 "register_operand" "0")
1918                 (match_operand:HI 2 "general_operand" "g")))
1919      (set (subreg:HI (match_dup 1) 2)
1920         (mod:HI (match_dup 1) (match_dup 2)))])
1921    (set (match_operand:HI 0 "register_operand" "=r")
1922         (subreg:HI (match_dup 1) 0))
1923    (set (match_operand:HI 3 "register_operand" "=r")
1924         (subreg:HI (match_dup 1) 2))]
1925   "TARGET_40_PLUS"
1926   "")
1928 (define_insn_and_split "*divmodhi4"
1929   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
1930         (div:HI (match_operand:SI 1 "register_operand" "0,0")
1931              (match_operand:HI 2 "general_operand" "rR,Qi")))
1932    (set (subreg:HI (match_dup 1) 2)
1933         (mod:HI (match_dup 1) (match_dup 2)))]
1934   "TARGET_40_PLUS"
1935   "#"
1936   "&& reload_completed"
1937   [(parallel [(set (subreg:HI (match_dup 0) 0)
1938                    (div:HI (match_dup 1) (match_dup 2)))
1939               (set (subreg:HI (match_dup 1) 2)
1940                    (mod:HI (match_dup 1) (match_dup 2)))
1941               (clobber (reg:CC CC_REGNUM))])]
1942   ""
1943   [(set_attr "length" "2,4")])
1945 ;; Note that there is no corresponding CC setter pattern.
1946 ;; The reason is that it won't be generated, because
1947 ;; compare-elim.c only does the transformation on input
1948 ;; insns that have a two-element PARALLEL, as opposed to
1949 ;; the three-element one we have here.     
1950 (define_insn "divmodhi4_nocc"
1951   [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
1952         (div:HI (match_operand:SI 1 "register_operand" "0,0")
1953                 (match_operand:HI 2 "general_operand" "rR,Qi")))
1954    (set (subreg:HI (match_dup 1) 2)
1955         (mod:HI (match_dup 1) (match_dup 2)))
1956    (clobber (reg:CC CC_REGNUM))]
1957   "TARGET_40_PLUS"
1958    "div\t%2,%0"
1959   [(set_attr "length" "2,4")
1960    (set_attr "base_cost" "40")])
1962 ;; Byte swap
1963 (define_insn_and_split "bswaphi2"
1964   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1965         (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))]
1966   ""
1967   "#"
1968   "reload_completed"
1969   [(parallel [(set (match_dup 0) (bswap:HI (match_dup 1)))
1970               (clobber (reg:CC CC_REGNUM))])]
1971   ""
1972   [(set_attr "length" "2,4")])
1974 (define_insn "bswaphi2<cc_ccnz>"
1975   [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1976         (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))
1977    (clobber (reg:CC CC_REGNUM))]
1978   ""
1979   "swab\t%0"
1980   [(set_attr "length" "2,4")])
1982 (define_insn_and_split "bswapsi2"
1983   [(set (match_operand:SI 0 "register_operand" "=&r")
1984         (bswap:SI (match_operand:SI 1 "general_operand" "g")))]
1985   ""
1986   "#"
1987   "reload_completed"
1988   [(parallel [(set (match_dup 0)
1989                    (bswap:SI (match_dup 1)))
1990               (clobber (reg:CC CC_REGNUM))])]
1991   ""
1992   [(set_attr "length" "10")])
1994 (define_insn "bswapsi2_nocc"
1995   [(set (match_operand:SI 0 "register_operand" "=&r,&r,&r")
1996         (bswap:SI (match_operand:SI 1 "general_operand" "r,D,Q")))
1997    (clobber (reg:CC CC_REGNUM))]
1998   ""
1999   {
2000     rtx exops[2][2];
2001     rtx t;
2002   
2003     pdp11_expand_operands (operands, exops, 2, NULL, either);
2005     t = exops[0][0];
2006     exops[0][0] = exops[1][0];
2007     exops[1][0] = t;
2009     output_asm_insn ("mov\t%0,%1", exops[0]);
2010     output_asm_insn ("mov\t%0,%1", exops[1]);
2011     output_asm_insn ("swab\t%0", exops[0]);
2012     output_asm_insn ("swab\t%0", exops[1]);
2013     return "";
2014   }
2015   [(set_attr "length" "8,10,12")])
2017 (define_expand "rotrhi3"
2018   [(match_operand:HI 0 "register_operand" "")
2019    (match_operand:HI 1 "register_operand" "")
2020    (match_operand:HI 2 "general_operand" "")]
2021   "TARGET_40_PLUS"
2022   "
2024   operands[2] = negate_rtx (HImode, operands[2]);
2025   emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2]));
2026   DONE;
2029 (define_insn_and_split "rotlhi3"
2030   [(set (match_operand:HI 0 "register_operand" "=d,d")
2031         (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2032                    (match_operand:HI 2 "general_operand" "rR,Qi")))]
2033   "TARGET_40_PLUS"
2034   "#"
2035   "&& reload_completed"
2036   [(parallel [(set (match_dup 0)
2037                    (rotate:HI (match_dup 1) (match_dup 2)))
2038               (clobber (reg:CC CC_REGNUM))])]
2039   ""
2040   [(set_attr "length" "2,4")
2041    (set_attr "base_cost" "8")])
2043 (define_insn "rotlhi3<cc_ccnz>"
2044   [(set (match_operand:HI 0 "register_operand" "=d,d")
2045         (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2046                    (match_operand:HI 2 "general_operand" "rR,Qi")))
2047    (clobber (reg:CC CC_REGNUM))]
2048   "TARGET_40_PLUS && reload_completed"
2049   "ashc\t%2,%0"
2050   [(set_attr "length" "2,4")
2051    (set_attr "base_cost" "8")])
2054   
2055 ;; Some peephole optimizations
2057 ;; Move then conditional branch on the result of the move is handled
2058 ;; by compare elimination, but an earlier pass sometimes changes the
2059 ;; compare operand to the move input, and then the compare is not
2060 ;; eliminated.  Do so here.
2061 (define_peephole2
2062   [(parallel [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
2063                    (match_operand:PDPint 1 "general_operand" ""))
2064               (clobber (reg:CC CC_REGNUM))])
2065    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))]
2066   ""
2067   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
2068               (set (match_dup 0) (match_dup 1))])]
2069   "")