]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/pdp11/pdp11.md
Improve code generation for pdp11 target.
[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 ;; maybe fiddle a bit with move_ratio, then
574 ;; let constraints only accept a register ...
575
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 "
587 {
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)));
594
595 operands[4] = XEXP (operands[0], 0);
596 operands[5] = XEXP (operands[1], 0);
597 }")
598
599
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
614
615 \f
616 ;;- truncation instructions
617
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")])
641
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")])
649
650 \f
651 ;;- zero extension instruction
652
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;
663
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")])
681
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
691
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")])
715
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")])
724
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")])
736
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")])
745
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")])
756
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 "*
763 {
764 rtx latehalf[2];
765
766 /* we don't want to mess with auto increment */
767
768 switch (which_alternative)
769 {
770 case 0:
771
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);
777
778 return \"\";
779
780 case 1:
781
782 /* - auto-decrement - right direction ;-) */
783 output_asm_insn(\"mov\t%1,%0\", operands);
784 output_asm_insn(\"sxt\t%0\", operands);
785
786 return \"\";
787
788 case 2:
789
790 /* make register pair available */
791 latehalf[0] = operands[0];
792 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
793
794 output_asm_insn(\"mov\t%1,%0\", operands);
795 output_asm_insn(\"sxt\t%0\", latehalf);
796
797 return \"\";
798
799 default:
800
801 gcc_unreachable ();
802 }
803 }"
804 [(set_attr "length" "10,6,6")])
805
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 ?
809
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")])
824
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];
833
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")])
849
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")])
860
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")])
869
870 ;; cut float to int
871
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")])
887
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")])
910
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")])
922
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")])
933
934 \f
935 ;;- arithmetic instructions
936 ;;- add instructions
937
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")])
950
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")])
961
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")])
973
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 "*
981 {
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 }
1009
1010 return \"\";
1011 }"
1012 [(set_attr "length" "20,28,40,48")
1013 (set_attr "base_cost" "0")])
1014
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")])
1035
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 "*
1043 {
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 }
1058
1059 return \"\";
1060 }"
1061 [(set_attr "length" "6,10,12,16")
1062 (set_attr "base_cost" "0")])
1063
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")])
1076
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 "*
1085 {
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 }
1093
1094 return \"add\t%2,%0\";
1095 }"
1096 [(set_attr "length" "2,4,4,6")])
1097
1098 \f
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 ??
1103
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")])
1116
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")])
1126
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")])
1138
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 "*
1146 {
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 }
1174
1175 return \"\";
1176 }"
1177 [(set_attr "length" "20,28,40,48")
1178 (set_attr "base_cost" "0")])
1179
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")])
1191
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 "*
1199 {
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 }
1214
1215 return \"\";
1216 }"
1217 [(set_attr "length" "6,10,12,16")
1218 (set_attr "base_cost" "0")])
1219
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")])
1232
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 "*
1244 {
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 }
1252
1253 return \"sub\t%2,%0\";
1254 }"
1255 [(set_attr "length" "2,4,4,6")])
1256
1257 ;;;;- and instructions
1258 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1259
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 "
1266 {
1267 rtx op1 = operands[1];
1268
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 }
1279
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);
1284 }"
1285 [(set_attr "length" "2,4,4,6")])
1286
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 "")
1299
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")])
1309
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")])
1323
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")])
1332
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")])
1346
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")])
1355
1356 ;;- one complement instructions
1357
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")])
1369
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")])
1377
1378 ;;- arithmetic shift instructions
1379 ;;
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.
1383 ;;
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")])
1399
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")])
1411
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")])
1424
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")])
1444
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")])
1457
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")])
1474
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")])
1484
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")])
1498
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")])
1508
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 "
1516 {
1517 rtx r;
1518
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;
1533 }")
1534
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 "
1541 {
1542 rtx r;
1543
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;
1559 }")
1560
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 "
1567 {
1568 rtx r, n;
1569
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;
1594 }")
1595
1596 ;; absolute
1597
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")])
1608
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")])
1616
1617 ;; negate insns
1618
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")])
1629
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")])
1637
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")])
1673
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")])
1705
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")])
1724
1725
1726 ;; Unconditional and other jump instructions
1727 (define_insn "jump"
1728 [(set (pc)
1729 (label_ref (match_operand 0 "" "")))]
1730 ""
1731 "*
1732 {
1733 if (get_attr_length (insn) == 2)
1734 return \"br\t%l0\";
1735 return \"jmp\t%l0\";
1736 }"
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)))])
1745
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")])
1755
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")])
1764
1765 ;;- jump to subroutine
1766
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")])
1774
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")])
1784
1785 (define_expand "untyped_call"
1786 [(parallel [(call (match_operand 0 "" "")
1787 (const_int 0))
1788 (match_operand 1 "" "")
1789 (match_operand 2 "" "")])]
1790 ""
1791 {
1792 int i;
1793
1794 emit_call_insn (gen_call (operands[0], const0_rtx));
1795
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 }
1801
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 ());
1807
1808 DONE;
1809 })
1810
1811 ;;- nop instruction
1812 (define_insn "nop"
1813 [(const_int 0)]
1814 ""
1815 "nop")
1816 \f
1817
1818 ;;- multiply
1819
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")])
1831
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")])
1841
1842 ;; 16 bit result multiply. This uses odd numbered registers.
1843
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")])
1855
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")])
1865
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")])
1880
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")])
1890
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")])
1913
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 "")
1927
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")])
1944
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")])
1961
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")])
1973
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")])
1981
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")])
1993
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);
2004
2005 t = exops[0][0];
2006 exops[0][0] = exops[1][0];
2007 exops[1][0] = t;
2008
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")])
2016
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 "
2023 {
2024 operands[2] = negate_rtx (HImode, operands[2]);
2025 emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2]));
2026 DONE;
2027 }")
2028
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")])
2042
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")])
2052
2053
2054
2055 ;; Some peephole optimizations
2056
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 "")