]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/pdp11/pdp11.md
Fix ICE on block move when using LRA.
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.md
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).
4
5 ;; This file is part of GCC.
6
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
20
21 (include "predicates.md")
22 (include "constraints.md")
23
24 (define_c_enum "unspecv"
25 [
26 UNSPECV_BLOCKAGE
27 UNSPECV_SETD
28 UNSPECV_SETI
29 ])
30
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)])
63
64 ;; DF is 64 bit
65 ;; SF is 32 bit
66 ;; SI is 32 bit
67 ;; HI is 16 bit
68 ;; QI is 8 bit
69
70 ;; Integer modes supported on the PDP11, with a mapping from machine mode
71 ;; to mnemonic suffix. SImode and DImode are usually special cases.
72 (define_mode_iterator PDPint [QI HI])
73 (define_mode_attr isfx [(QI "b") (HI "")])
74 (define_mode_attr mname [(QI "QImode") (HI "HImode") (SI "SImode") (DI "DImode")])
75 (define_mode_attr e_mname [(QI "E_QImode") (HI "E_HImode") (SI "E_SImode") (DI "E_DImode")])
76 (define_mode_attr hmode [(QI "hi") (HI "hi") (SI "si") (DI "di")])
77
78 ;; These are analogous for use in splitters and expanders.
79 (define_mode_iterator HSint [HI SI])
80 (define_mode_iterator QHSint [QI HI SI])
81 (define_mode_iterator QHSDint [QI HI SI DI])
82
83 (define_code_iterator SHF [ashift ashiftrt lshiftrt])
84
85 ;; Substitution to turn a CC clobber into a CC setter. We have four of
86 ;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
87 (define_subst "cc_cc"
88 [(set (match_operand 0 "") (match_operand 1 ""))
89 (clobber (reg CC_REGNUM))]
90 ""
91 [(set (reg:CC CC_REGNUM)
92 (compare:CC (match_dup 1) (const_int 0)))
93 (set (match_dup 0) (match_dup 1))])
94
95 (define_subst "cc_ccnz"
96 [(set (match_operand 0 "") (match_operand 1 ""))
97 (clobber (reg CC_REGNUM))]
98 ""
99 [(set (reg:CCNZ CC_REGNUM)
100 (compare:CCNZ (match_dup 1) (const_int 0)))
101 (set (match_dup 0) (match_dup 1))])
102
103 (define_subst "fcc_cc"
104 [(set (match_operand 0 "") (match_operand 1 ""))
105 (clobber (reg FCC_REGNUM))]
106 ""
107 [(set (reg:CC FCC_REGNUM)
108 (compare:CC (match_dup 1) (const_int 0)))
109 (set (match_dup 0) (match_dup 1))])
110
111 (define_subst "fcc_ccnz"
112 [(set (match_operand 0 "") (match_operand 1 ""))
113 (clobber (reg FCC_REGNUM))]
114 ""
115 [(set (reg:CCNZ FCC_REGNUM)
116 (compare:CCNZ (match_dup 1) (const_int 0)))
117 (set (match_dup 0) (match_dup 1))])
118
119 (define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
120 (define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc")
121 (define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc")
122 (define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc")
123
124 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
125
126 ;; Compare instructions.
127
128 ;; currently we only support df floats, which saves us quite some
129 ;; hassle switching the FP mode!
130 ;; we assume that CPU is always in long float mode, and
131 ;; 16 bit integer mode - currently, the prologue for main does this,
132 ;; but maybe we should just set up a NEW crt0 properly,
133 ;; -- and what about signal handling code?
134 ;; (we don't even let sf floats in the register file, so
135 ;; we only should have to worry about truncating and widening
136 ;; when going to memory)
137
138 ;; abort() call by g++ - must define libfunc for cmp_optab
139 ;; and ucmp_optab for mode SImode, because we don't have that!!!
140 ;; - yet since no libfunc is there, we abort ()
141
142 ;; define attributes
143 ;; currently type is only fpu or arith or unknown, maybe branch later ?
144 ;; default is arith
145 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
146
147 ;; length default is 2 bytes each
148 (define_attr "length" "" (const_int 2))
149
150 ;; instruction base cost (not counting operands)
151 (define_attr "base_cost" "" (const_int 2))
152
153 ;; a user's asm statement
154 (define_asm_attributes
155 [(set_attr "type" "unknown")
156 ; length for asm is the max length per statement. That would be
157 ; 3 words, for a two-operand instruction with extra word addressing
158 ; modes for both operands.
159 (set_attr "length" "6")])
160
161 ;; define function units
162
163 ;; Prologue and epilogue support.
164
165 (define_expand "prologue"
166 [(const_int 0)]
167 ""
168 {
169 pdp11_expand_prologue ();
170 DONE;
171 })
172
173 (define_expand "epilogue"
174 [(const_int 0)]
175 ""
176 {
177 pdp11_expand_epilogue ();
178 DONE;
179 })
180
181 (define_expand "return"
182 [(return)]
183 "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
184 "")
185
186 (define_insn "*rts"
187 [(return)]
188 ""
189 "rts\tpc")
190
191 (define_insn "blockage"
192 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
193 ""
194 ""
195 [(set_attr "length" "0")])
196
197 (define_insn "setd"
198 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
199 ""
200 "setd")
201
202 (define_insn "seti"
203 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
204 ""
205 "seti")
206
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)
210
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)
213
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 "*
221 {
222 if (which_alternative == 0 || which_alternative == 2)
223 return \"{tstd|tstf}\t%0\";
224 else
225 return \"{cmpd|cmpf}\t%0,%1\";
226 }"
227 [(set_attr "length" "2,2,4,4")
228 (set_attr "base_cost" "4")
229 (set_attr "type" "fp")])
230
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")
237
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")])
251
252 ;; sob instruction
253 ;;
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 "")
279
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 "*
297 {
298 rtx lb[1];
299
300 if (get_attr_length (insn) == 2)
301 return \"sob\t%0,%l1\";
302
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);
308
309 output_asm_label (lb[0]);
310 fputs (\":\\n\", asm_out_file);
311
312 return \"\";
313 }"
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))))])
323
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 "")
348
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 "")
367
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 "")
384
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)))])
401
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)))])
418
419 \f
420 ;; Move instructions
421
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")])
432
433
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")])
441
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")])
448
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")])
456
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")])
463
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 "*
482 {
483 if (operands[1] == const0_rtx)
484 return \"clr<PDPint:isfx>\t%0\";
485
486 return \"mov<PDPint:isfx>\t%1,%0\";
487 }"
488 [(set_attr "length" "2,4,4,6")])
489
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.
493 ;;
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.
498
499 (define_expand "movdf"
500 [(set (match_operand:DF 0 "float_nonimm_operand" "")
501 (match_operand:DF 1 "float_operand" ""))]
502 "TARGET_FPU"
503 "")
504
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")])
526
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")])
538
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")])
572
573 ;; Expand a block move. We turn this into a move loop.
574 (define_expand "movmemhi"
575 [(match_operand:BLK 0 "general_operand" "=g")
576 (match_operand:BLK 1 "general_operand" "g")
577 (match_operand:HI 2 "immediate_operand" "i")
578 (match_operand:HI 3 "immediate_operand" "i")]
579 ""
580 "
581 {
582 if (INTVAL (operands[2]) != 0)
583 expand_block_move (operands);
584 DONE;
585 }")
586
587 \f
588 ;;- truncation instructions
589
590 ;; We sometimes end up doing a register to register truncate,
591 ;; which isn't right because we actually load registers always
592 ;; with a DFmode value. But even with PROMOTE the compiler
593 ;; doesn't always get that (so we don't use it). That means
594 ;; a register to register truncate is a NOP.
595 (define_insn_and_split "truncdfsf2"
596 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
597 (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))]
598 "TARGET_FPU"
599 {
600 gcc_assert (which_alternative == 0);
601 return "";
602 }
603 "&& reload_completed"
604 [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1)))
605 (clobber (reg:CC FCC_REGNUM))])]
606 "{
607 if (GET_CODE (operands[0]) == REG &&
608 GET_CODE (operands[1]) == REG &&
609 REGNO (operands[0]) == REGNO (operands[1]))
610 FAIL;
611 }"
612 [(set_attr "length" "0,0,0")])
613
614 (define_insn "*truncdfsf2_<fcc_cc>"
615 [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q")
616 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a")))
617 (clobber (reg:CC FCC_REGNUM))]
618 "TARGET_FPU && reload_completed"
619 "{stcdf|movfo}\t%1,%0"
620 [(set_attr "length" "2,4")])
621
622 \f
623 ;;- zero extension instruction
624
625 (define_insn_and_split "zero_extendqihi2"
626 [(set (match_operand:HI 0 "nonimmediate_operand" "=rD,Q,&r,&r")
627 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0,rR,Q")))]
628 ""
629 "#"
630 "reload_completed"
631 [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
632 (clobber (reg:CC CC_REGNUM))])]
633 "{
634 rtx r;
635
636 if (!REG_P (operands[0]))
637 {
638 r = gen_rtx_MEM (QImode, operands[0]);
639 adjust_address (r, QImode, 1);
640 emit_move_insn (r, const0_rtx);
641 DONE;
642 }
643 else if (!rtx_equal_p (operands[0], operands[1]))
644 {
645 /* Alternatives 2 and 3 */
646 emit_move_insn (operands[0], const0_rtx);
647 r = gen_rtx_REG (QImode, REGNO (operands[0]));
648 emit_insn (gen_iorqi3_nocc (r, r, operands[1]));
649 DONE;
650 }
651 }"
652 [(set_attr "length" "4,4,4,6")])
653
654 (define_insn "*zero_extendqihi2<cc_cc>"
655 [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
656 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))
657 (clobber (reg:CC CC_REGNUM))])]
658 "reload_completed"
659 "bic\t%#0177400,%0"
660 [(set_attr "length" "4,6")])
661
662 ;;- sign extension instructions
663
664 ;; We sometimes end up doing a register to register extend,
665 ;; which isn't right because we actually load registers always
666 ;; with a DFmode value. But even with PROMOTE the compiler
667 ;; doesn't always get that (so we don't use it). That means
668 ;; a register to register truncate is a NOP.
669 (define_insn_and_split "extendsfdf2"
670 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
671 (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))]
672 "TARGET_FPU"
673 {
674 gcc_assert (which_alternative == 0);
675 return "";
676 }
677 "&& reload_completed"
678 [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1)))
679 (clobber (reg:CC FCC_REGNUM))])]
680 "{
681 if (GET_CODE (operands[0]) == REG &&
682 GET_CODE (operands[1]) == REG &&
683 REGNO (operands[0]) == REGNO (operands[1]))
684 FAIL;
685 }"
686 [(set_attr "length" "0,0,0")])
687
688 (define_insn "*extendsfdf2_<fcc_cc>"
689 [(set (match_operand:DF 0 "register_operand" "=a,a")
690 (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q")))
691 (clobber (reg:CC FCC_REGNUM))]
692 "TARGET_FPU && reload_completed"
693 "{ldcfd|movof}\t%1,%0"
694 [(set_attr "length" "2,4")
695 (set_attr "base_cost" "6")])
696
697 ;; movb sign extends if destination is a register
698 (define_insn_and_split "extendqihi2"
699 [(set (match_operand:HI 0 "register_operand" "=r,r")
700 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
701 ""
702 "#"
703 "reload_completed"
704 [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
705 (clobber (reg:CC CC_REGNUM))])]
706 ""
707 [(set_attr "length" "2,4")])
708
709 ;; MOVB clears V
710 (define_insn "*extendqihi2<cc_cc>"
711 [(set (match_operand:HI 0 "register_operand" "=r,r")
712 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))
713 (clobber (reg:CC CC_REGNUM))]
714 "reload_completed"
715 "movb\t%1,%0"
716 [(set_attr "length" "2,4")])
717
718 (define_insn_and_split "extendhisi2"
719 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
720 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
721 "TARGET_40_PLUS"
722 "#"
723 "&& reload_completed"
724 [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
725 (clobber (reg:CC CC_REGNUM))])]
726 ""
727 [(set_attr "length" "10,6,6")])
728
729 (define_insn "*extendhisi2_nocc"
730 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
731 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))
732 (clobber (reg:CC CC_REGNUM))]
733 "TARGET_40_PLUS && reload_completed"
734 "*
735 {
736 rtx latehalf[2];
737
738 /* we don't want to mess with auto increment */
739
740 switch (which_alternative)
741 {
742 case 0:
743
744 latehalf[0] = operands[0];
745 operands[0] = adjust_address(operands[0], HImode, 2);
746
747 output_asm_insn(\"mov\t%1,%0\", operands);
748 output_asm_insn(\"sxt\t%0\", latehalf);
749
750 return \"\";
751
752 case 1:
753
754 /* - auto-decrement - right direction ;-) */
755 output_asm_insn(\"mov\t%1,%0\", operands);
756 output_asm_insn(\"sxt\t%0\", operands);
757
758 return \"\";
759
760 case 2:
761
762 /* make register pair available */
763 latehalf[0] = operands[0];
764 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
765
766 output_asm_insn(\"mov\t%1,%0\", operands);
767 output_asm_insn(\"sxt\t%0\", latehalf);
768
769 return \"\";
770
771 default:
772
773 gcc_unreachable ();
774 }
775 }"
776 [(set_attr "length" "10,6,6")])
777
778 ;; make float to int and vice versa
779 ;; assume that we are normally in double and integer mode -
780 ;; what do pdp library routines do to fpu mode ?
781
782 ;; Note: the hardware treats register source as
783 ;; a 16-bit (high order only) source, which isn't
784 ;; what we want. But we do need to support register
785 ;; dest because gcc asks for it.
786 (define_insn_and_split "floatsidf2"
787 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
788 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
789 "TARGET_FPU"
790 "#"
791 "&& reload_completed"
792 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
793 (clobber (reg:CC FCC_REGNUM))])]
794 ""
795 [(set_attr "length" "10,6,8")])
796
797 (define_insn "*floatsidf2<fcc_cc>"
798 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
799 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))
800 (clobber (reg:CC FCC_REGNUM))]
801 "TARGET_FPU && reload_completed"
802 "* if (which_alternative ==0)
803 {
804 rtx latehalf[2];
805
806 latehalf[0] = NULL;
807 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
808 output_asm_insn(\"mov\t%1,-(sp)\", latehalf);
809 output_asm_insn(\"mov\t%1,-(sp)\", operands);
810
811 output_asm_insn(\"setl\", operands);
812 output_asm_insn(\"{ldcld|movif}\t(sp)+,%0\", operands);
813 output_asm_insn(\"seti\", operands);
814 return \"\";
815 }
816 else
817 return \"setl\;{ldcld|movif}\t%1,%0\;seti\";
818 "
819 [(set_attr "length" "10,6,8")
820 (set_attr "base_cost" "12")])
821
822 (define_insn_and_split "floathidf2"
823 [(set (match_operand:DF 0 "register_operand" "=a,a")
824 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
825 "TARGET_FPU"
826 "#"
827 "&& reload_completed"
828 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
829 (clobber (reg:CC FCC_REGNUM))])]
830 ""
831 [(set_attr "length" "2,4")])
832
833 (define_insn "*floathidf2<fcc_cc>"
834 [(set (match_operand:DF 0 "register_operand" "=a,a")
835 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))
836 (clobber (reg:CC FCC_REGNUM))]
837 "TARGET_FPU && reload_completed"
838 "{ldcid|movif}\t%1,%0"
839 [(set_attr "length" "2,4")
840 (set_attr "base_cost" "12")])
841
842 ;; cut float to int
843
844 ;; Note: the hardware treats register destination as
845 ;; a 16-bit (high order only) destination, which isn't
846 ;; what we want. But we do need to support register
847 ;; dest because gcc asks for it.
848 (define_insn_and_split "fix_truncdfsi2"
849 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
850 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
851 "TARGET_FPU"
852 "#"
853 "&& reload_completed"
854 [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1))))
855 (clobber (reg:CC CC_REGNUM))
856 (clobber (reg:CC FCC_REGNUM))])]
857 ""
858 [(set_attr "length" "10,6,8")])
859
860 ;; Note: this clobbers both sets of condition codes!
861 (define_insn "*fix_truncdfsi2_nocc"
862 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
863 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))
864 (clobber (reg:CC CC_REGNUM))
865 (clobber (reg:CC FCC_REGNUM))]
866 "TARGET_FPU && reload_completed"
867 "* if (which_alternative ==0)
868 {
869 output_asm_insn(\"setl\", operands);
870 output_asm_insn(\"{stcdl|movfi}\t%1,-(sp)\", operands);
871 output_asm_insn(\"seti\", operands);
872 output_asm_insn(\"mov\t(sp)+,%0\", operands);
873 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
874 output_asm_insn(\"mov\t(sp)+,%0\", operands);
875 return \"\";
876 }
877 else
878 return \"setl\;{stcdl|movfi}\t%1,%0\;seti\";
879 "
880 [(set_attr "length" "10,6,8")
881 (set_attr "base_cost" "12")])
882
883 (define_insn_and_split "fix_truncdfhi2"
884 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
885 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
886 "TARGET_FPU"
887 "#"
888 "&& reload_completed"
889 [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1))))
890 (clobber (reg:CC CC_REGNUM))
891 (clobber (reg:CC FCC_REGNUM))])]
892 ""
893 [(set_attr "length" "2,4")])
894
895 ;; Note: this clobbers both sets of condition codes!
896 (define_insn "*fix_truncdfhi2_nocc"
897 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
898 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))
899 (clobber (reg:CC CC_REGNUM))
900 (clobber (reg:CC FCC_REGNUM))]
901 "TARGET_FPU && reload_completed"
902 "{stcdi|movfi}\t%1,%0"
903 [(set_attr "length" "2,4")
904 (set_attr "base_cost" "12")])
905
906 \f
907 ;;- arithmetic instructions
908 ;;- add instructions
909
910 (define_insn_and_split "adddf3"
911 [(set (match_operand:DF 0 "register_operand" "=a,a")
912 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
913 (match_operand:DF 2 "general_operand" "fR,QF")))]
914 "TARGET_FPU"
915 "#"
916 "&& reload_completed"
917 [(parallel [(set (match_dup 0)
918 (plus:DF (match_dup 1) (match_dup 2)))
919 (clobber (reg:CC FCC_REGNUM))])]
920 ""
921 [(set_attr "length" "2,4")])
922
923 ;; Float add sets V if overflow from add
924 (define_insn "*adddf3<fcc_ccnz>"
925 [(set (match_operand:DF 0 "register_operand" "=a,a")
926 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
927 (match_operand:DF 2 "general_operand" "fR,QF")))
928 (clobber (reg:CC FCC_REGNUM))]
929 "TARGET_FPU && reload_completed"
930 "{addd|addf}\t%2,%0"
931 [(set_attr "length" "2,4")
932 (set_attr "base_cost" "6")])
933
934 (define_insn_and_split "adddi3"
935 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
936 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
937 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
938 ""
939 "#"
940 "reload_completed"
941 [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
942 (clobber (reg:CC CC_REGNUM))])]
943 ""
944 [(set_attr "length" "20,28,40,48")])
945
946 (define_insn "*adddi3_nocc"
947 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
948 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
949 (match_operand:DI 2 "general_operand" "r,on,r,on")))
950 (clobber (reg:CC CC_REGNUM))]
951 "reload_completed"
952 "*
953 {
954 rtx inops[2];
955 rtx exops[4][2];
956
957 inops[0] = operands[0];
958 inops[1] = operands[2];
959 pdp11_expand_operands (inops, exops, 2, NULL, either);
960
961 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
962 output_asm_insn (\"add\t%1,%0\", exops[0]);
963 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
964 {
965 output_asm_insn (\"add\t%1,%0\", exops[1]);
966 output_asm_insn (\"adc\t%0\", exops[0]);
967 }
968 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
969 {
970 output_asm_insn (\"add\t%1,%0\", exops[2]);
971 output_asm_insn (\"adc\t%0\", exops[1]);
972 output_asm_insn (\"adc\t%0\", exops[0]);
973 }
974 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
975 {
976 output_asm_insn (\"add\t%1,%0\", exops[3]);
977 output_asm_insn (\"adc\t%0\", exops[2]);
978 output_asm_insn (\"adc\t%0\", exops[1]);
979 output_asm_insn (\"adc\t%0\", exops[0]);
980 }
981
982 return \"\";
983 }"
984 [(set_attr "length" "20,28,40,48")
985 (set_attr "base_cost" "0")])
986
987 ;; Note that the register operand is not marked earlyclobber.
988 ;; The reason is that SI values go in register pairs, so they
989 ;; can't partially overlap. They can be either disjoint, or
990 ;; source and destination can be equal. The latter case is
991 ;; handled properly because of the ordering of the individual
992 ;; instructions used. Specifically, carry from the low to the
993 ;; high word is added at the end, so the adding of the high parts
994 ;; will always used the original high part and not a high part
995 ;; modified by carry (which would amount to double carry).
996 (define_insn_and_split "addsi3"
997 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
998 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
999 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1000 ""
1001 "#"
1002 "reload_completed"
1003 [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
1004 (clobber (reg:CC CC_REGNUM))])]
1005 ""
1006 [(set_attr "length" "6,10,12,16")])
1007
1008 (define_insn "*addsi3_nocc"
1009 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1010 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1011 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1012 (clobber (reg:CC CC_REGNUM))]
1013 "reload_completed"
1014 "*
1015 {
1016 rtx inops[2];
1017 rtx exops[2][2];
1018
1019 inops[0] = operands[0];
1020 inops[1] = operands[2];
1021 pdp11_expand_operands (inops, exops, 2, NULL, either);
1022
1023 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1024 output_asm_insn (\"add\t%1,%0\", exops[0]);
1025 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1026 {
1027 output_asm_insn (\"add\t%1,%0\", exops[1]);
1028 output_asm_insn (\"adc\t%0\", exops[0]);
1029 }
1030
1031 return \"\";
1032 }"
1033 [(set_attr "length" "6,10,12,16")
1034 (set_attr "base_cost" "0")])
1035
1036 (define_insn_and_split "addhi3"
1037 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1038 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1039 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1040 ""
1041 "#"
1042 "reload_completed"
1043 [(parallel [(set (match_dup 0)
1044 (plus:HI (match_dup 1) (match_dup 2)))
1045 (clobber (reg:CC CC_REGNUM))])]
1046 ""
1047 [(set_attr "length" "2,4,4,6")])
1048
1049 ;; Add sets V if overflow from the add
1050 (define_insn "*addhi3<cc_ccnz>"
1051 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1052 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1053 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1054 (clobber (reg:CC CC_REGNUM))]
1055 "reload_completed"
1056 "*
1057 {
1058 if (GET_CODE (operands[2]) == CONST_INT)
1059 {
1060 if (INTVAL(operands[2]) == 1)
1061 return \"inc\t%0\";
1062 else if (INTVAL(operands[2]) == -1)
1063 return \"dec\t%0\";
1064 }
1065
1066 return \"add\t%2,%0\";
1067 }"
1068 [(set_attr "length" "2,4,4,6")])
1069
1070 \f
1071 ;;- subtract instructions
1072 ;; we don't have to care for constant second
1073 ;; args, since they are canonical plus:xx now!
1074 ;; also for minus:DF ??
1075
1076 (define_insn_and_split "subdf3"
1077 [(set (match_operand:DF 0 "register_operand" "=a,a")
1078 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1079 (match_operand:DF 2 "general_operand" "fR,Q")))]
1080 "TARGET_FPU"
1081 "#"
1082 "&& reload_completed"
1083 [(parallel [(set (match_dup 0)
1084 (minus:DF (match_dup 1) (match_dup 2)))
1085 (clobber (reg:CC FCC_REGNUM))])]
1086 ""
1087 [(set_attr "length" "2,4")])
1088
1089 (define_insn "*subdf3<fcc_ccnz>"
1090 [(set (match_operand:DF 0 "register_operand" "=a,a")
1091 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1092 (match_operand:DF 2 "general_operand" "fR,QF")))
1093 (clobber (reg:CC FCC_REGNUM))]
1094 "TARGET_FPU && reload_completed"
1095 "{subd|subf}\t%2,%0"
1096 [(set_attr "length" "2,4")
1097 (set_attr "base_cost" "6")])
1098
1099 (define_insn_and_split "subdi3"
1100 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1101 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1102 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
1103 ""
1104 "#"
1105 "reload_completed"
1106 [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
1107 (clobber (reg:CC CC_REGNUM))])]
1108 ""
1109 [(set_attr "length" "20,28,40,48")])
1110
1111 (define_insn "*subdi3_nocc"
1112 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1113 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1114 (match_operand:DI 2 "general_operand" "r,on,r,on")))
1115 (clobber (reg:CC CC_REGNUM))]
1116 "reload_completed"
1117 "*
1118 {
1119 rtx inops[2];
1120 rtx exops[4][2];
1121
1122 inops[0] = operands[0];
1123 inops[1] = operands[2];
1124 pdp11_expand_operands (inops, exops, 2, NULL, either);
1125
1126 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1127 output_asm_insn (\"sub\t%1,%0\", exops[0]);
1128 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1129 {
1130 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1131 output_asm_insn (\"sbc\t%0\", exops[0]);
1132 }
1133 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
1134 {
1135 output_asm_insn (\"sub\t%1,%0\", exops[2]);
1136 output_asm_insn (\"sbc\t%0\", exops[1]);
1137 output_asm_insn (\"sbc\t%0\", exops[0]);
1138 }
1139 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
1140 {
1141 output_asm_insn (\"sub\t%1,%0\", exops[3]);
1142 output_asm_insn (\"sbc\t%0\", exops[2]);
1143 output_asm_insn (\"sbc\t%0\", exops[1]);
1144 output_asm_insn (\"sbc\t%0\", exops[0]);
1145 }
1146
1147 return \"\";
1148 }"
1149 [(set_attr "length" "20,28,40,48")
1150 (set_attr "base_cost" "0")])
1151
1152 (define_insn_and_split "subsi3"
1153 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1154 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1155 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1156 ""
1157 "#"
1158 "reload_completed"
1159 [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1160 (clobber (reg:CC CC_REGNUM))])]
1161 ""
1162 [(set_attr "length" "6,10,12,16")])
1163
1164 (define_insn "*subsi3_nocc"
1165 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1166 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1167 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1168 (clobber (reg:CC CC_REGNUM))]
1169 "reload_completed"
1170 "*
1171 {
1172 rtx inops[2];
1173 rtx exops[2][2];
1174
1175 inops[0] = operands[0];
1176 inops[1] = operands[2];
1177 pdp11_expand_operands (inops, exops, 2, NULL, either);
1178
1179 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
1180 output_asm_insn (\"sub\t%1,%0\", exops[0]);
1181 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
1182 {
1183 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1184 output_asm_insn (\"sbc\t%0\", exops[0]);
1185 }
1186
1187 return \"\";
1188 }"
1189 [(set_attr "length" "6,10,12,16")
1190 (set_attr "base_cost" "0")])
1191
1192 (define_insn_and_split "subhi3"
1193 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1194 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1195 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1196 ""
1197 "#"
1198 "reload_completed"
1199 [(parallel [(set (match_dup 0)
1200 (minus:HI (match_dup 1) (match_dup 2)))
1201 (clobber (reg:CC CC_REGNUM))])]
1202 ""
1203 [(set_attr "length" "2,4,4,6")])
1204
1205 ;; Note: the manual says that (minus m (const_int n)) is converted
1206 ;; to (plus m (const_int -n)) but that does not appear to be
1207 ;; the case when it's wrapped in a PARALLEL. So instead we handle
1208 ;; that case here, which is easy enough.
1209 (define_insn "*subhi3<cc_ccnz>"
1210 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1211 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1212 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1213 (clobber (reg:CC CC_REGNUM))]
1214 "reload_completed"
1215 "*
1216 {
1217 if (GET_CODE (operands[2]) == CONST_INT)
1218 {
1219 if (INTVAL(operands[2]) == 1)
1220 return \"dec\t%0\";
1221 else if (INTVAL(operands[2]) == -1)
1222 return \"inc\t%0\";
1223 }
1224
1225 return \"sub\t%2,%0\";
1226 }"
1227 [(set_attr "length" "2,4,4,6")])
1228
1229 ;;;;- and instructions
1230 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1231
1232 (define_expand "and<mode>3"
1233 [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
1234 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
1235 (match_operand:PDPint 2 "general_operand" "")))]
1236 ""
1237 "
1238 {
1239 rtx op1 = operands[1];
1240
1241 /* If there is a constant argument, complement that one.
1242 Similarly, if one of the inputs is the same as the output,
1243 complement the other input. */
1244 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
1245 rtx_equal_p (operands[0], operands[1]))
1246 {
1247 operands[1] = operands[2];
1248 operands[2] = op1;
1249 op1 = operands[1];
1250 }
1251
1252 if (CONST_INT_P (op1))
1253 operands[1] = GEN_INT (~INTVAL (op1));
1254 else
1255 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
1256 }"
1257 [(set_attr "length" "2,4,4,6")])
1258
1259 (define_insn_and_split "*bic<mode>"
1260 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1261 (and:PDPint
1262 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1263 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
1264 ""
1265 "#"
1266 "reload_completed"
1267 [(parallel [(set (match_dup 0)
1268 (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2)))
1269 (clobber (reg:CC CC_REGNUM))])]
1270 "")
1271
1272 (define_insn "*bic<mode><cc_cc>"
1273 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1274 (and:PDPint
1275 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1276 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))
1277 (clobber (reg:CC CC_REGNUM))]
1278 "reload_completed"
1279 "bic<PDPint:isfx>\t%1,%0"
1280 [(set_attr "length" "2,4,4,6")])
1281
1282 ;;- Bit set (inclusive or) instructions
1283 (define_insn_and_split "ior<mode>3"
1284 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1285 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1286 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
1287 ""
1288 "#"
1289 "reload_completed"
1290 [(parallel [(set (match_dup 0)
1291 (ior:PDPint (match_dup 1) (match_dup 2)))
1292 (clobber (reg:CC CC_REGNUM))])]
1293 ""
1294 [(set_attr "length" "2,4,4,6")])
1295
1296 (define_insn "ior<mode>3<cc_cc>"
1297 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1298 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1299 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))
1300 (clobber (reg:CC CC_REGNUM))]
1301 "reload_completed"
1302 "bis<PDPint:isfx>\t%2,%0"
1303 [(set_attr "length" "2,4,4,6")])
1304
1305 ;;- xor instructions
1306 (define_insn_and_split "xorhi3"
1307 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1308 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1309 (match_operand:HI 2 "register_operand" "r,r")))]
1310 "TARGET_40_PLUS"
1311 "#"
1312 "&& reload_completed"
1313 [(parallel [(set (match_dup 0)
1314 (xor:HI (match_dup 1) (match_dup 2)))
1315 (clobber (reg:CC CC_REGNUM))])]
1316 ""
1317 [(set_attr "length" "2,4")])
1318
1319 (define_insn "*xorhi3<cc_cc>"
1320 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1321 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1322 (match_operand:HI 2 "register_operand" "r,r")))
1323 (clobber (reg:CC CC_REGNUM))]
1324 "TARGET_40_PLUS && reload_completed"
1325 "xor\t%2,%0"
1326 [(set_attr "length" "2,4")])
1327
1328 ;;- one complement instructions
1329
1330 (define_insn_and_split "one_cmpl<mode>2"
1331 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1332 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1333 ""
1334 "#"
1335 "reload_completed"
1336 [(parallel [(set (match_dup 0)
1337 (not:PDPint (match_dup 1)))
1338 (clobber (reg:CC CC_REGNUM))])]
1339 ""
1340 [(set_attr "length" "2,4")])
1341
1342 (define_insn "*one_cmpl<mode>2<cc_cc>"
1343 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1344 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1345 (clobber (reg:CC CC_REGNUM))]
1346 "reload_completed"
1347 "com<PDPint:isfx>\t%0"
1348 [(set_attr "length" "2,4")])
1349
1350 ;;- arithmetic shift instructions
1351 ;;
1352 ;; There is a fair amount of complexity here because with -m10
1353 ;; (pdp-11/10, /20) we only have shift by one bit. Iterators are
1354 ;; used to reduce the amount of very similar code.
1355 ;;
1356 ;; First the insns used for small constant shifts.
1357 (define_insn_and_split "<code><mode>_sc"
1358 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1359 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1360 (match_operand:HI 2 "expand_shift_operand" "O,O")))]
1361 ""
1362 "#"
1363 "reload_completed"
1364 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1365 (clobber (reg:CC CC_REGNUM))])]
1366 ""
1367 [(set (attr "length")
1368 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1369 <CODE>, which_alternative == 0)"))
1370 (set_attr "base_cost" "0")])
1371
1372 (define_insn "<code><mode>_sc<cc_ccnz>"
1373 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rD,Q")
1374 (SHF:PDPint (match_operand:PDPint 1 "general_operand" "0,0")
1375 (match_operand:HI 2 "expand_shift_operand" "O,O")))
1376 (clobber (reg:CC CC_REGNUM))]
1377 "reload_completed"
1378 "* return pdp11_assemble_shift (operands, <PDPint:mname>, <CODE>);"
1379 [(set (attr "length")
1380 (symbol_ref "pdp11_shift_length (operands, <PDPint:mname>,
1381 <CODE>, which_alternative == 0)"))
1382 (set_attr "base_cost" "0")])
1383
1384 ;; This one comes only in clobber flavor.
1385 (define_insn "<code>si_sc_nocc"
1386 [(set (match_operand:SI 0 "nonimmediate_operand" "=rD,Q")
1387 (SHF:SI (match_operand:SI 1 "general_operand" "0,0")
1388 (match_operand:HI 2 "expand_shift_operand" "O,O")))
1389 (clobber (reg:CC CC_REGNUM))]
1390 "reload_completed"
1391 "* return pdp11_assemble_shift (operands, SImode, <CODE>);"
1392 [(set (attr "length")
1393 (symbol_ref "pdp11_shift_length (operands, SImode,
1394 <CODE>, which_alternative == 0)"))
1395 (set_attr "base_cost" "0")])
1396
1397 ;; Next, shifts that are done as a loop on base (11/10 class) machines.
1398 ;; This applies to shift counts too large to unroll, or variable shift
1399 ;; counts. The check for count <= 0 is done before we get here.
1400 (define_insn_and_split "<code><mode>_base"
1401 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1402 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1403 (match_operand:HI 2 "register_operand" "r,r")))
1404 (clobber (match_dup 2))]
1405 ""
1406 "#"
1407 "reload_completed"
1408 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1409 (clobber (match_dup 2))
1410 (clobber (reg:CC CC_REGNUM))])]
1411 ""
1412 [(set (attr "length")
1413 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1414 <CODE>, which_alternative == 0)"))
1415 (set_attr "base_cost" "0")])
1416
1417 (define_insn "<code><mode>_base_nocc"
1418 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1419 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1420 (match_operand:HI 2 "register_operand" "r,r")))
1421 (clobber (match_dup 2))
1422 (clobber (reg:CC CC_REGNUM))]
1423 "reload_completed"
1424 "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
1425 [(set (attr "length")
1426 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1427 <CODE>, which_alternative == 0)"))
1428 (set_attr "base_cost" "0")])
1429
1430 ;; Next the insns that use the extended instructions ash and ashc.
1431 ;; Note that these are just left shifts, and HI/SI only. (Right shifts
1432 ;; are done by shifting by a negative amount.)
1433 (define_insn_and_split "aslhi_op"
1434 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1435 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1436 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1437 "TARGET_40_PLUS"
1438 "#"
1439 "&& reload_completed"
1440 [(parallel [(set (match_dup 0)
1441 (ashift:HI (match_dup 1) (match_dup 2)))
1442 (clobber (reg:CC CC_REGNUM))])]
1443 ""
1444 [(set_attr "length" "2,4")
1445 (set_attr "base_cost" "8")])
1446
1447 (define_insn "aslhi_op<cc_ccnz>"
1448 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1449 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1450 (match_operand:HI 2 "general_operand" "rR,Qi")))
1451 (clobber (reg:CC CC_REGNUM))]
1452 "TARGET_40_PLUS && reload_completed"
1453 "ash\t%2,%0"
1454 [(set_attr "length" "2,4")
1455 (set_attr "base_cost" "8")])
1456
1457 (define_insn_and_split "aslsi_op"
1458 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1459 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1460 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1461 "TARGET_40_PLUS"
1462 "#"
1463 "&& reload_completed"
1464 [(parallel [(set (match_dup 0)
1465 (ashift:SI (match_dup 1) (match_dup 2)))
1466 (clobber (reg:CC CC_REGNUM))])]
1467 ""
1468 [(set_attr "length" "2,4")
1469 (set_attr "base_cost" "8")])
1470
1471 (define_insn "aslsi_op_<cc_ccnz>"
1472 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1473 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1474 (match_operand:HI 2 "general_operand" "rR,Qi")))
1475 (clobber (reg:CC CC_REGNUM))]
1476 "TARGET_40_PLUS && reload_completed"
1477 "ashc\t%2,%0"
1478 [(set_attr "length" "2,4")
1479 (set_attr "base_cost" "8")])
1480
1481 ;; Now the expanders that produce the insns defined above.
1482 (define_expand "ashl<mode>3"
1483 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1484 (match_operand:QHSint 1 "general_operand" "")
1485 (match_operand:HI 2 "general_operand" "")]
1486 ""
1487 "
1488 {
1489 rtx r;
1490
1491 if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base))
1492 {
1493 if (<QHSint:e_mname> == E_QImode)
1494 {
1495 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1496 emit_insn (gen_aslhi_op (r, r, operands[2]));
1497 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1498 }
1499 else
1500 {
1501 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1502 }
1503 }
1504 DONE;
1505 }")
1506
1507 (define_expand "ashr<mode>3"
1508 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1509 (match_operand:QHSint 1 "general_operand" "")
1510 (match_operand:HI 2 "general_operand" "")]
1511 ""
1512 "
1513 {
1514 rtx r;
1515
1516 if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base))
1517 {
1518 operands[2] = negate_rtx (HImode, operands[2]);
1519 if (<QHSint:e_mname> == E_QImode)
1520 {
1521 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1522 emit_insn (gen_aslhi_op (r, r, operands[2]));
1523 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1524 }
1525 else
1526 {
1527 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1528 }
1529 }
1530 DONE;
1531 }")
1532
1533 (define_expand "lshr<mode>3"
1534 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1535 (match_operand:QHSint 1 "general_operand" "")
1536 (match_operand:HI 2 "general_operand" "")]
1537 ""
1538 "
1539 {
1540 rtx r, n;
1541
1542 if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base))
1543 {
1544 if (<QHSint:e_mname> == E_QImode)
1545 {
1546 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1547 emit_insn (gen_aslhi_op (r, r, operands[2]));
1548 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1549 }
1550 else
1551 {
1552 r = gen_reg_rtx (<QHSint:mname>);
1553 emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx));
1554 if (GET_CODE (operands[2]) != CONST_INT)
1555 {
1556 n = gen_reg_rtx (HImode);
1557 emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1)));
1558 emit_insn (gen_ashr<mode>3 (operands[0], r, n));
1559 }
1560 else
1561 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r,
1562 GEN_INT (1 - INTVAL (operands[2]))));
1563 }
1564 }
1565 DONE;
1566 }")
1567
1568 ;; absolute
1569
1570 (define_insn_and_split "absdf2"
1571 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1572 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1573 "TARGET_FPU"
1574 "#"
1575 "&& reload_completed"
1576 [(parallel [(set (match_dup 0) (abs:DF (match_dup 1)))
1577 (clobber (reg:CC FCC_REGNUM))])]
1578 ""
1579 [(set_attr "length" "2,4")])
1580
1581 (define_insn "absdf2<fcc_cc>"
1582 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1583 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))
1584 (clobber (reg:CC FCC_REGNUM))]
1585 "TARGET_FPU && reload_completed"
1586 "{absd|absf}\t%0"
1587 [(set_attr "length" "2,4")])
1588
1589 ;; negate insns
1590
1591 (define_insn_and_split "negdf2"
1592 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1593 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
1594 "TARGET_FPU"
1595 "#"
1596 "&& reload_completed"
1597 [(parallel [(set (match_dup 0) (neg:DF (match_dup 1)))
1598 (clobber (reg:CC FCC_REGNUM))])]
1599 ""
1600 [(set_attr "length" "2,4")])
1601
1602 (define_insn "negdf2<fcc_cc>"
1603 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1604 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))
1605 (clobber (reg:CC FCC_REGNUM))]
1606 "TARGET_FPU && reload_completed"
1607 "{negd|negf}\t%0"
1608 [(set_attr "length" "2,4")])
1609
1610 (define_insn_and_split "negdi2"
1611 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1612 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
1613 ""
1614 "#"
1615 "reload_completed"
1616 [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
1617 (clobber (reg:CC CC_REGNUM))])]
1618 ""
1619 [(set_attr "length" "18,34")])
1620
1621 ;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1622 (define_insn "negdi2_nocc"
1623 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1624 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))
1625 (clobber (reg:CC CC_REGNUM))]
1626 "reload_completed"
1627 {
1628 rtx exops[4][2];
1629
1630 pdp11_expand_operands (operands, exops, 1, NULL, either);
1631
1632 output_asm_insn (\"com\t%0\", exops[3]);
1633 output_asm_insn (\"com\t%0\", exops[2]);
1634 output_asm_insn (\"com\t%0\", exops[1]);
1635 output_asm_insn (\"com\t%0\", exops[0]);
1636 output_asm_insn (\"add\t%#1,%0\", exops[3]);
1637 output_asm_insn (\"adc\t%0\", exops[2]);
1638 output_asm_insn (\"adc\t%0\", exops[1]);
1639 output_asm_insn (\"adc\t%0\", exops[0]);
1640
1641 return \"\";
1642 }
1643 [(set_attr "length" "18,34")
1644 (set_attr "base_cost" "0")])
1645
1646 (define_insn_and_split "negsi2"
1647 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1648 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1649 ""
1650 "#"
1651 "reload_completed"
1652 [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
1653 (clobber (reg:CC CC_REGNUM))])]
1654 ""
1655 [(set_attr "length" "10,18")])
1656
1657 ;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1658 (define_insn "negsi2_nocc"
1659 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1660 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))
1661 (clobber (reg:CC CC_REGNUM))]
1662 "reload_completed"
1663 {
1664 rtx exops[2][2];
1665
1666 pdp11_expand_operands (operands, exops, 1, NULL, either);
1667
1668 output_asm_insn (\"com\t%0\", exops[1]);
1669 output_asm_insn (\"com\t%0\", exops[0]);
1670 output_asm_insn (\"add\t%#1,%0\", exops[1]);
1671 output_asm_insn (\"adc\t%0\", exops[0]);
1672
1673 return \"\";
1674 }
1675 [(set_attr "length" "10,18")
1676 (set_attr "base_cost" "0")])
1677
1678 (define_insn_and_split "neg<mode>2"
1679 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1680 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
1681 ""
1682 "#"
1683 "reload_completed"
1684 [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1)))
1685 (clobber (reg:CC CC_REGNUM))])]
1686 ""
1687 [(set_attr "length" "2,4")])
1688
1689 (define_insn "neg<mode>2<cc_ccnz>"
1690 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1691 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1692 (clobber (reg:CC CC_REGNUM))]
1693 ""
1694 "neg<PDPint:isfx>\t%0"
1695 [(set_attr "length" "2,4")])
1696
1697
1698 ;; Unconditional and other jump instructions
1699 (define_insn "jump"
1700 [(set (pc)
1701 (label_ref (match_operand 0 "" "")))]
1702 ""
1703 "*
1704 {
1705 if (get_attr_length (insn) == 2)
1706 return \"br\t%l0\";
1707 return \"jmp\t%l0\";
1708 }"
1709 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
1710 (pc))
1711 (const_int MIN_BRANCH))
1712 (gt (minus (match_dup 0)
1713 (pc))
1714 (const_int MAX_BRANCH)))
1715 (const_int 4)
1716 (const_int 2)))])
1717
1718 (define_insn "tablejump"
1719 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
1720 (use (label_ref (match_operand 1 "" "")))]
1721 ""
1722 "@
1723 jmp\t(%0)
1724 jmp\t%@%0
1725 jmp\t%@%0"
1726 [(set_attr "length" "2,2,4")])
1727
1728 ;; indirect jump. TODO: this needs a constraint that allows memory
1729 ;; references but not indirection, since we add a level of indirection
1730 ;; in the generated code.
1731 (define_insn "indirect_jump"
1732 [(set (pc) (match_operand:HI 0 "general_operand" "r"))]
1733 ""
1734 "jmp\t@%0"
1735 [(set_attr "length" "2")])
1736
1737 ;;- jump to subroutine
1738
1739 (define_insn "call"
1740 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1741 (match_operand:HI 1 "general_operand" "g,g"))]
1742 ;;- Don't use operand 1 for most machines.
1743 ""
1744 "jsr\tpc,%0"
1745 [(set_attr "length" "2,4")])
1746
1747 ;;- jump to subroutine
1748 (define_insn "call_value"
1749 [(set (match_operand 0 "" "")
1750 (call (match_operand:HI 1 "general_operand" "rR,Q")
1751 (match_operand:HI 2 "general_operand" "g,g")))]
1752 ;;- Don't use operand 2 for most machines.
1753 ""
1754 "jsr\tpc,%1"
1755 [(set_attr "length" "2,4")])
1756
1757 (define_expand "untyped_call"
1758 [(parallel [(call (match_operand 0 "" "")
1759 (const_int 0))
1760 (match_operand 1 "" "")
1761 (match_operand 2 "" "")])]
1762 ""
1763 {
1764 int i;
1765
1766 emit_call_insn (gen_call (operands[0], const0_rtx));
1767
1768 for (i = 0; i < XVECLEN (operands[2], 0); i++)
1769 {
1770 rtx set = XVECEXP (operands[2], 0, i);
1771 emit_move_insn (SET_DEST (set), SET_SRC (set));
1772 }
1773
1774 /* The optimizer does not know that the call sets the function value
1775 registers we stored in the result block. We avoid problems by
1776 claiming that all hard registers are used and clobbered at this
1777 point. */
1778 emit_insn (gen_blockage ());
1779
1780 DONE;
1781 })
1782
1783 ;;- nop instruction
1784 (define_insn "nop"
1785 [(const_int 0)]
1786 ""
1787 "nop")
1788 \f
1789
1790 ;;- multiply
1791
1792 (define_insn_and_split "muldf3"
1793 [(set (match_operand:DF 0 "register_operand" "=a,a")
1794 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1795 (match_operand:DF 2 "float_operand" "fR,QF")))]
1796 "TARGET_FPU"
1797 "#"
1798 "&& reload_completed"
1799 [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2)))
1800 (clobber (reg:CC FCC_REGNUM))])]
1801 ""
1802 [(set_attr "length" "2,4")])
1803
1804 (define_insn "muldf3<fcc_ccnz>"
1805 [(set (match_operand:DF 0 "register_operand" "=a,a")
1806 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1807 (match_operand:DF 2 "float_operand" "fR,QF")))
1808 (clobber (reg:CC FCC_REGNUM))]
1809 "TARGET_FPU && reload_completed"
1810 "{muld|mulf}\t%2,%0"
1811 [(set_attr "length" "2,4")
1812 (set_attr "base_cost" "20")])
1813
1814 ;; 16 bit result multiply. This uses odd numbered registers.
1815
1816 (define_insn_and_split "mulhi3"
1817 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1818 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1819 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1820 "TARGET_40_PLUS"
1821 "#"
1822 "&& reload_completed"
1823 [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2)))
1824 (clobber (reg:CC CC_REGNUM))])]
1825 ""
1826 [(set_attr "length" "2,4")])
1827
1828 (define_insn "mulhi3<cc_cc>"
1829 [(set (match_operand:HI 0 "register_operand" "=d,d")
1830 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1831 (match_operand:HI 2 "general_operand" "rR,Qi")))
1832 (clobber (reg:CC CC_REGNUM))]
1833 "TARGET_40_PLUS && reload_completed"
1834 "mul\t%2,%0"
1835 [(set_attr "length" "2,4")
1836 (set_attr "base_cost" "20")])
1837
1838 ;; 32 bit result from 16 bit operands
1839 (define_insn_and_split "mulhisi3"
1840 [(set (match_operand:SI 0 "register_operand" "=r,r")
1841 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
1842 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))]
1843 "TARGET_40_PLUS"
1844 "#"
1845 "&& reload_completed"
1846 [(parallel [(set (match_dup 0)
1847 (mult:SI (sign_extend:SI (match_dup 1))
1848 (sign_extend:SI (match_dup 2))))
1849 (clobber (reg:CC CC_REGNUM))])]
1850 ""
1851 [(set_attr "length" "2,4")])
1852
1853 (define_insn "mulhisi3<cc_cc>"
1854 [(set (match_operand:SI 0 "register_operand" "=r,r")
1855 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
1856 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))
1857 (clobber (reg:CC CC_REGNUM))]
1858 "TARGET_40_PLUS && reload_completed"
1859 "mul\t%2,%0"
1860 [(set_attr "length" "2,4")
1861 (set_attr "base_cost" "20")])
1862
1863 ;;- divide
1864 (define_insn_and_split "divdf3"
1865 [(set (match_operand:DF 0 "register_operand" "=a,a")
1866 (div:DF (match_operand:DF 1 "register_operand" "0,0")
1867 (match_operand:DF 2 "general_operand" "fR,QF")))]
1868 "TARGET_FPU"
1869 "#"
1870 "&& reload_completed"
1871 [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2)))
1872 (clobber (reg:CC FCC_REGNUM))])]
1873 ""
1874 [(set_attr "length" "2,4")])
1875
1876 (define_insn "divdf3<fcc_ccnz>"
1877 [(set (match_operand:DF 0 "register_operand" "=a,a")
1878 (div:DF (match_operand:DF 1 "register_operand" "0,0")
1879 (match_operand:DF 2 "general_operand" "fR,QF")))
1880 (clobber (reg:CC FCC_REGNUM))]
1881 "TARGET_FPU && reload_completed"
1882 "{divd|divf}\t%2,%0"
1883 [(set_attr "length" "2,4")
1884 (set_attr "base_cost" "20")])
1885
1886 (define_expand "divmodhi4"
1887 [(parallel
1888 [(set (subreg:HI (match_dup 1) 0)
1889 (div:HI (match_operand:SI 1 "register_operand" "0")
1890 (match_operand:HI 2 "general_operand" "g")))
1891 (set (subreg:HI (match_dup 1) 2)
1892 (mod:HI (match_dup 1) (match_dup 2)))])
1893 (set (match_operand:HI 0 "register_operand" "=r")
1894 (subreg:HI (match_dup 1) 0))
1895 (set (match_operand:HI 3 "register_operand" "=r")
1896 (subreg:HI (match_dup 1) 2))]
1897 "TARGET_40_PLUS"
1898 "")
1899
1900 (define_insn_and_split "*divmodhi4"
1901 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
1902 (div:HI (match_operand:SI 1 "register_operand" "0,0")
1903 (match_operand:HI 2 "general_operand" "rR,Qi")))
1904 (set (subreg:HI (match_dup 1) 2)
1905 (mod:HI (match_dup 1) (match_dup 2)))]
1906 "TARGET_40_PLUS"
1907 "#"
1908 "&& reload_completed"
1909 [(parallel [(set (subreg:HI (match_dup 0) 0)
1910 (div:HI (match_dup 1) (match_dup 2)))
1911 (set (subreg:HI (match_dup 1) 2)
1912 (mod:HI (match_dup 1) (match_dup 2)))
1913 (clobber (reg:CC CC_REGNUM))])]
1914 ""
1915 [(set_attr "length" "2,4")])
1916
1917 ;; Note that there is no corresponding CC setter pattern.
1918 ;; The reason is that it won't be generated, because
1919 ;; compare-elim.c only does the transformation on input
1920 ;; insns that have a two-element PARALLEL, as opposed to
1921 ;; the three-element one we have here.
1922 (define_insn "divmodhi4_nocc"
1923 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
1924 (div:HI (match_operand:SI 1 "register_operand" "0,0")
1925 (match_operand:HI 2 "general_operand" "rR,Qi")))
1926 (set (subreg:HI (match_dup 1) 2)
1927 (mod:HI (match_dup 1) (match_dup 2)))
1928 (clobber (reg:CC CC_REGNUM))]
1929 "TARGET_40_PLUS"
1930 "div\t%2,%0"
1931 [(set_attr "length" "2,4")
1932 (set_attr "base_cost" "40")])
1933
1934 ;; Byte swap
1935 (define_insn_and_split "bswaphi2"
1936 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1937 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))]
1938 ""
1939 "#"
1940 "reload_completed"
1941 [(parallel [(set (match_dup 0) (bswap:HI (match_dup 1)))
1942 (clobber (reg:CC CC_REGNUM))])]
1943 ""
1944 [(set_attr "length" "2,4")])
1945
1946 (define_insn "bswaphi2<cc_ccnz>"
1947 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1948 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))
1949 (clobber (reg:CC CC_REGNUM))]
1950 ""
1951 "swab\t%0"
1952 [(set_attr "length" "2,4")])
1953
1954 (define_insn_and_split "bswapsi2"
1955 [(set (match_operand:SI 0 "register_operand" "=&r")
1956 (bswap:SI (match_operand:SI 1 "general_operand" "g")))]
1957 ""
1958 "#"
1959 "reload_completed"
1960 [(parallel [(set (match_dup 0)
1961 (bswap:SI (match_dup 1)))
1962 (clobber (reg:CC CC_REGNUM))])]
1963 ""
1964 [(set_attr "length" "10")])
1965
1966 (define_insn "bswapsi2_nocc"
1967 [(set (match_operand:SI 0 "register_operand" "=&r,&r,&r")
1968 (bswap:SI (match_operand:SI 1 "general_operand" "r,D,Q")))
1969 (clobber (reg:CC CC_REGNUM))]
1970 ""
1971 {
1972 rtx exops[2][2];
1973 rtx t;
1974
1975 pdp11_expand_operands (operands, exops, 2, NULL, either);
1976
1977 t = exops[0][0];
1978 exops[0][0] = exops[1][0];
1979 exops[1][0] = t;
1980
1981 output_asm_insn ("mov\t%0,%1", exops[0]);
1982 output_asm_insn ("mov\t%0,%1", exops[1]);
1983 output_asm_insn ("swab\t%0", exops[0]);
1984 output_asm_insn ("swab\t%0", exops[1]);
1985 return "";
1986 }
1987 [(set_attr "length" "8,10,12")])
1988
1989 (define_expand "rotrhi3"
1990 [(match_operand:HI 0 "register_operand" "")
1991 (match_operand:HI 1 "register_operand" "")
1992 (match_operand:HI 2 "general_operand" "")]
1993 "TARGET_40_PLUS"
1994 "
1995 {
1996 operands[2] = negate_rtx (HImode, operands[2]);
1997 emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2]));
1998 DONE;
1999 }")
2000
2001 (define_insn_and_split "rotlhi3"
2002 [(set (match_operand:HI 0 "register_operand" "=d,d")
2003 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2004 (match_operand:HI 2 "general_operand" "rR,Qi")))]
2005 "TARGET_40_PLUS"
2006 "#"
2007 "&& reload_completed"
2008 [(parallel [(set (match_dup 0)
2009 (rotate:HI (match_dup 1) (match_dup 2)))
2010 (clobber (reg:CC CC_REGNUM))])]
2011 ""
2012 [(set_attr "length" "2,4")
2013 (set_attr "base_cost" "8")])
2014
2015 (define_insn "rotlhi3<cc_ccnz>"
2016 [(set (match_operand:HI 0 "register_operand" "=d,d")
2017 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2018 (match_operand:HI 2 "general_operand" "rR,Qi")))
2019 (clobber (reg:CC CC_REGNUM))]
2020 "TARGET_40_PLUS && reload_completed"
2021 "ashc\t%2,%0"
2022 [(set_attr "length" "2,4")
2023 (set_attr "base_cost" "8")])
2024
2025
2026
2027 ;; Some peephole optimizations
2028
2029 ;; Move then conditional branch on the result of the move is handled
2030 ;; by compare elimination, but an earlier pass sometimes changes the
2031 ;; compare operand to the move input, and then the compare is not
2032 ;; eliminated. Do so here.
2033 (define_peephole2
2034 [(parallel [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
2035 (match_operand:PDPint 1 "general_operand" ""))
2036 (clobber (reg:CC CC_REGNUM))])
2037 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))]
2038 ""
2039 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
2040 (set (match_dup 0) (match_dup 1))])]
2041 "")