]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/pdp11/pdp11.md
Change references of .c files to .cc files
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.md
CommitLineData
2c9c2489 1;;- Machine description for the pdp11 for GNU C compiler
7adcbafe 2;; Copyright (C) 1994-2022 Free Software Foundation, Inc.
2c9c2489
RK
3;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
4
7ec022b2 5;; This file is part of GCC.
2c9c2489 6
7ec022b2 7;; GCC is free software; you can redistribute it and/or modify
2c9c2489 8;; it under the terms of the GNU General Public License as published by
2f83c7d6 9;; the Free Software Foundation; either version 3, or (at your option)
2c9c2489
RK
10;; any later version.
11
7ec022b2 12;; GCC is distributed in the hope that it will be useful,
2c9c2489
RK
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
2f83c7d6
NC
18;; along with GCC; see the file COPYING3. If not see
19;; <http://www.gnu.org/licenses/>.
2c9c2489 20
19ce9cf1
PK
21(include "predicates.md")
22(include "constraints.md")
f90b7a5a 23
8662b2ba
RH
24(define_c_enum "unspecv"
25 [
26 UNSPECV_BLOCKAGE
27 UNSPECV_SETD
28 UNSPECV_SETI
76715c32 29 UNSPECV_CPYMEM
8662b2ba
RH
30 ])
31
7021d5df
PK
32(define_constants
33 [
34 ;; Register numbers
58dd8e86 35 (R0_REGNUM 0)
a01c666c 36 (RETVAL_REGNUM 0)
442fcea7 37 (FRAME_POINTER_REGNUM 5)
7021d5df
PK
38 (STACK_POINTER_REGNUM 6)
39 (PC_REGNUM 7)
40 (AC0_REGNUM 8)
41 (AC3_REGNUM 11)
42 (AC4_REGNUM 12)
43 (AC5_REGNUM 13)
442fcea7
PK
44 ;; The next one is not a physical register but is used for
45 ;; addressing arguments.
46 (ARG_POINTER_REGNUM 14)
b4324a14 47 ;; Condition code registers
442fcea7
PK
48 (CC_REGNUM 15)
49 (FCC_REGNUM 16)
b4324a14 50 ;; End of hard registers
442fcea7 51 (FIRST_PSEUDO_REGISTER 17)
b4324a14 52
aad2444d
PK
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.
7021d5df 59 (MIN_BRANCH -254)
aad2444d
PK
60 (MAX_BRANCH 254)
61 (MIN_SOB -124)
7021d5df 62 (MAX_SOB 0)])
2c9c2489 63
b4324a14
PK
64;; DF is 64 bit
65;; SF is 32 bit
66;; SI is 32 bit
2c9c2489
RK
67;; HI is 16 bit
68;; QI is 8 bit
69
9546fe6a 70;; Integer modes supported on the PDP11, with a mapping from machine mode
b4324a14 71;; to mnemonic suffix. SImode and DImode are usually special cases.
9546fe6a
PK
72(define_mode_iterator PDPint [QI HI])
73(define_mode_attr isfx [(QI "b") (HI "")])
b4324a14
PK
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
be7e8072
MR
85(define_mode_iterator PDPfp [SF DF])
86
b4324a14
PK
87;; Substitution to turn a CC clobber into a CC setter. We have four of
88;; these: for CCmode vs. CCNZmode, and for CC_REGNUM vs. FCC_REGNUM.
89(define_subst "cc_cc"
90 [(set (match_operand 0 "") (match_operand 1 ""))
91 (clobber (reg CC_REGNUM))]
92 ""
93 [(set (reg:CC CC_REGNUM)
94 (compare:CC (match_dup 1) (const_int 0)))
95 (set (match_dup 0) (match_dup 1))])
9546fe6a 96
b4324a14
PK
97(define_subst "cc_ccnz"
98 [(set (match_operand 0 "") (match_operand 1 ""))
99 (clobber (reg CC_REGNUM))]
100 ""
101 [(set (reg:CCNZ CC_REGNUM)
102 (compare:CCNZ (match_dup 1) (const_int 0)))
103 (set (match_dup 0) (match_dup 1))])
2c9c2489 104
b4324a14 105(define_subst "fcc_cc"
be7e8072 106 [(set (match_operand:PDPfp 0 "") (match_operand:PDPfp 1 ""))
b4324a14
PK
107 (clobber (reg FCC_REGNUM))]
108 ""
109 [(set (reg:CC FCC_REGNUM)
be7e8072 110 (compare:CC (match_dup 1) (const_double_zero:PDPfp)))
b4324a14
PK
111 (set (match_dup 0) (match_dup 1))])
112
113(define_subst "fcc_ccnz"
be7e8072 114 [(set (match_operand:PDPfp 0 "") (match_operand:PDPfp 1 ""))
b4324a14
PK
115 (clobber (reg FCC_REGNUM))]
116 ""
117 [(set (reg:CCNZ FCC_REGNUM)
be7e8072 118 (compare:CCNZ (match_dup 1) (const_double_zero:PDPfp)))
b4324a14
PK
119 (set (match_dup 0) (match_dup 1))])
120
121(define_subst_attr "cc_cc" "cc_cc" "_nocc" "_cc")
122(define_subst_attr "fcc_cc" "fcc_cc" "_nocc" "_cc")
123(define_subst_attr "cc_ccnz" "cc_ccnz" "_nocc" "_cc")
124(define_subst_attr "fcc_ccnz" "fcc_ccnz" "_nocc" "_cc")
125
126;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
2c9c2489 127
2c9c2489
RK
128;; Compare instructions.
129
130;; currently we only support df floats, which saves us quite some
131;; hassle switching the FP mode!
132;; we assume that CPU is always in long float mode, and
133;; 16 bit integer mode - currently, the prologue for main does this,
134;; but maybe we should just set up a NEW crt0 properly,
135;; -- and what about signal handling code?
136;; (we don't even let sf floats in the register file, so
137;; we only should have to worry about truncating and widening
138;; when going to memory)
139
140;; abort() call by g++ - must define libfunc for cmp_optab
141;; and ucmp_optab for mode SImode, because we don't have that!!!
142;; - yet since no libfunc is there, we abort ()
143
2c9c2489
RK
144;; define attributes
145;; currently type is only fpu or arith or unknown, maybe branch later ?
146;; default is arith
147(define_attr "type" "unknown,arith,fp" (const_string "arith"))
148
0f237806
PK
149;; length default is 2 bytes each
150(define_attr "length" "" (const_int 2))
2c9c2489 151
aad2444d
PK
152;; instruction base cost (not counting operands)
153(define_attr "base_cost" "" (const_int 2))
154
ddd5a7c1 155;; a user's asm statement
2c9c2489
RK
156(define_asm_attributes
157 [(set_attr "type" "unknown")
0f237806 158; length for asm is the max length per statement. That would be
c67b2d4e
PK
159; 3 words, for a two-operand instruction with extra word addressing
160; modes for both operands.
161 (set_attr "length" "6")])
2c9c2489
RK
162
163;; define function units
164
8662b2ba
RH
165;; Prologue and epilogue support.
166
167(define_expand "prologue"
168 [(const_int 0)]
169 ""
170{
171 pdp11_expand_prologue ();
172 DONE;
173})
174
175(define_expand "epilogue"
176 [(const_int 0)]
177 ""
178{
179 pdp11_expand_epilogue ();
180 DONE;
181})
182
442fcea7 183(define_insn "rtspc"
8662b2ba
RH
184 [(return)]
185 ""
aad2444d 186 "rts\tpc")
8662b2ba
RH
187
188(define_insn "blockage"
189 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
190 ""
191 ""
192 [(set_attr "length" "0")])
193
194(define_insn "setd"
195 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
196 ""
197 "setd")
198
199(define_insn "seti"
200 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
201 ""
202 "seti")
203
2c9c2489
RK
204;; arithmetic - values here immediately when next insn issued
205;; or does it mean the number of cycles after this insn was issued?
206;; how do I say that fpu insns use cpu also? (pre-interaction phase)
207
208;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
209;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
210
211;; compare
f90b7a5a 212(define_insn "*cmpdf"
b4324a14
PK
213 [(set (reg:CC FCC_REGNUM)
214 (compare:CC (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
215 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
216 "TARGET_FPU && reload_completed"
2c9c2489
RK
217 "*
218{
f90b7a5a 219 if (which_alternative == 0 || which_alternative == 2)
4aef57c9 220 return \"{tstd|tstf}\t%0\";
f90b7a5a 221 else
4aef57c9 222 return \"{cmpd|cmpf}\t%0,%1\";
2c9c2489 223}"
b4324a14 224 [(set_attr "length" "2,2,4,4")
aad2444d 225 (set_attr "base_cost" "4")
b4324a14
PK
226 (set_attr "type" "fp")])
227
228;; Copy floating point processor condition code register to main CPU
229;; condition code register.
230(define_insn "*cfcc"
231 [(set (reg CC_REGNUM) (reg FCC_REGNUM))]
232 "TARGET_FPU && reload_completed"
233 "cfcc")
234
235(define_insn "cmp<mode>"
236 [(set (reg:CC CC_REGNUM)
237 (compare:CC (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
238 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
2c9c2489 239 ""
f90b7a5a 240 "@
4aef57c9
PK
241 tst<PDPint:isfx>\t%0
242 cmp<PDPint:isfx>\t%0,%1
243 cmp<PDPint:isfx>\t%0,%1
244 tst<PDPint:isfx>\t%0
245 cmp<PDPint:isfx>\t%0,%1
246 cmp<PDPint:isfx>\t%0,%1"
0f237806 247 [(set_attr "length" "2,2,4,4,4,6")])
f90b7a5a 248
442fcea7
PK
249;; Two word compare
250(define_insn "cmpsi"
251 [(set (reg:CC CC_REGNUM)
252 (compare:CC (match_operand:SI 0 "general_operand" "rDQi")
253 (match_operand:SI 1 "general_operand" "rDQi")))]
254 ""
255{
256 rtx inops[2];
257 rtx exops[2][2];
258 rtx lb[1];
259
260 inops[0] = operands[0];
261 inops[1] = operands[1];
262 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
263 lb[0] = gen_label_rtx ();
264
265 if (CONST_INT_P (exops[0][1]) && INTVAL (exops[0][1]) == 0)
266 output_asm_insn ("tst\t%0", exops[0]);
267 else
268 output_asm_insn ("cmp\t%0,%1", exops[0]);
269 output_asm_insn ("bne\t%l0", lb);
270 if (CONST_INT_P (exops[1][1]) && INTVAL (exops[1][1]) == 0)
271 output_asm_insn ("tst\t%0", exops[1]);
272 else
273 output_asm_insn ("cmp\t%0,%1", exops[1]);
274 output_asm_label (lb[0]);
275 fputs (":\n", asm_out_file);
276
277 return "";
278}
279 [(set (attr "length")
280 (symbol_ref "pdp11_cmp_length (operands, 2)"))
281 (set_attr "base_cost" "0")])
282
283;; Four word compare
284(define_insn "cmpdi"
285 [(set (reg:CC CC_REGNUM)
286 (compare:CC (match_operand:DI 0 "general_operand" "rDQi")
287 (match_operand:DI 1 "general_operand" "rDQi")))]
288 ""
289{
290 rtx inops[4];
291 rtx exops[4][2];
292 rtx lb[1];
293 int i;
294
295 inops[0] = operands[0];
296 inops[1] = operands[1];
297 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
298 lb[0] = gen_label_rtx ();
299
300 for (i = 0; i < 3; i++)
301 {
302 if (CONST_INT_P (exops[i][1]) && INTVAL (exops[i][1]) == 0)
303 output_asm_insn ("tst\t%0", exops[i]);
304 else
305 output_asm_insn ("cmp\t%0,%1", exops[i]);
306 output_asm_insn ("bne\t%l0", lb);
307 }
308 if (CONST_INT_P (exops[3][1]) && INTVAL (exops[3][1]) == 0)
309 output_asm_insn ("tst\t%0", exops[3]);
310 else
311 output_asm_insn ("cmp\t%0,%1", exops[3]);
312 output_asm_label (lb[0]);
313 fputs (":\n", asm_out_file);
314
315 return "";
316}
317 [(set (attr "length")
318 (symbol_ref "pdp11_cmp_length (operands, 2)"))
319 (set_attr "base_cost" "0")])
320
aad2444d
PK
321;; sob instruction
322;;
fe65151b
PK
323;; This expander has to check for mode match because the doloop pass
324;; in gcc that invokes it does not do so, i.e., it may attempt to apply
325;; this pattern even if the count operand is QI or SI mode.
326(define_expand "doloop_end"
327 [(parallel [(set (pc)
328 (if_then_else
329 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
330 (const_int 1))
331 (label_ref (match_operand 1 "" ""))
332 (pc)))
333 (set (match_dup 0)
334 (plus:HI (match_dup 0)
335 (const_int -1)))])]
336 "TARGET_40_PLUS"
337 "{
338 if (GET_MODE (operands[0]) != HImode)
339 FAIL;
340 }")
341
342;; Do a define_split because some alternatives clobber CC.
aad2444d 343;; Some don't, but it isn't all that interesting to cover that case.
fe65151b 344(define_insn_and_split "doloop_end_insn"
2c9c2489
RK
345 [(set (pc)
346 (if_then_else
aad2444d
PK
347 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
348 (const_int 1))
2c9c2489
RK
349 (label_ref (match_operand 1 "" ""))
350 (pc)))
351 (set (match_dup 0)
352 (plus:HI (match_dup 0)
353 (const_int -1)))]
354 "TARGET_40_PLUS"
aad2444d
PK
355 "#"
356 "&& reload_completed"
357 [(parallel [(set (pc)
358 (if_then_else
359 (ne (match_dup 0) (const_int 1))
360 (label_ref (match_dup 1))
361 (pc)))
362 (set (match_dup 0)
363 (plus:HI (match_dup 0)
364 (const_int -1)))
365 (clobber (reg:CC CC_REGNUM))])]
366 "")
367
368;; Note that there is a memory alternative here. This is as documented
369;; in gccint, which says that doloop_end, since it has both a jump and
370;; an output interrupt "must handle its own reloads". That translates
371;; to: must accept memory operands as valid though they may be deprecated.
372(define_insn "doloop_end_nocc"
373 [(set (pc)
374 (if_then_else
375 (ne (match_operand:HI 0 "nonimmediate_operand" "+r,!m")
376 (const_int 1))
377 (label_ref (match_operand 1 "" ""))
378 (pc)))
379 (set (match_dup 0)
380 (plus:HI (match_dup 0)
381 (const_int -1)))
382 (clobber (reg:CC CC_REGNUM))]
383 "TARGET_40_PLUS && reload_completed"
2c9c2489
RK
384 "*
385{
aad2444d
PK
386 rtx lb[1];
387
0f237806 388 if (get_attr_length (insn) == 2)
4aef57c9 389 return \"sob\t%0,%l1\";
2c9c2489
RK
390
391 /* emulate sob */
aad2444d 392 lb[0] = gen_label_rtx ();
4aef57c9 393 output_asm_insn (\"dec\t%0\", operands);
aad2444d 394 output_asm_insn (\"beq\t%l0\", lb);
4aef57c9 395 output_asm_insn (\"jmp\t%l1\", operands);
2c9c2489 396
aad2444d 397 output_asm_label (lb[0]);
b4324a14 398 fputs (\":\\n\", asm_out_file);
2c9c2489
RK
399
400 return \"\";
401}"
aad2444d
PK
402 [(set (attr "length")
403 (if_then_else (eq (symbol_ref ("which_alternative")) (const_int 1))
404 (const_int 10)
405 (if_then_else (ior (lt (minus (match_dup 1) (pc))
406 (const_int MIN_SOB))
407 (gt (minus (match_dup 1) (pc))
408 (const_int MAX_SOB)))
409 (const_int 8)
410 (const_int 2))))])
2c9c2489
RK
411
412;; These control RTL generation for conditional jump insns
413;; and match them for register allocation.
b4324a14
PK
414;; Post reload these get expanded into insns that actually
415;; manipulate the condition code registers. We can't do that before
416;; because instructions generated by reload clobber condition codes (new
417;; CC design, type #2).
418(define_insn_and_split "cbranchdf4"
419 [(set (pc)
f90b7a5a 420 (if_then_else (match_operator 0 "ordered_comparison_operator"
b4324a14
PK
421 [(match_operand:DF 1 "general_operand" "fg")
422 (match_operand:DF 2 "general_operand" "a")])
f90b7a5a 423 (label_ref (match_operand 3 "" ""))
2c9c2489 424 (pc)))]
825cb171 425 "TARGET_FPU"
b4324a14
PK
426 "#"
427 "&& reload_completed"
428 [(set (reg:CC FCC_REGNUM)
429 (compare:CC (match_dup 1) (match_dup 2)))
430 (set (pc)
431 (if_then_else (match_op_dup 0
432 [(reg:CC FCC_REGNUM) (const_int 0)])
433 (label_ref (match_dup 3))
434 (pc)))]
f90b7a5a 435 "")
2c9c2489 436
b4324a14
PK
437(define_insn_and_split "cbranch<mode>4"
438 [(set (pc)
f90b7a5a 439 (if_then_else (match_operator 0 "ordered_comparison_operator"
442fcea7
PK
440 [(match_operand:QHSDint 1 "general_operand" "g")
441 (match_operand:QHSDint 2 "general_operand" "g")])
f90b7a5a 442 (label_ref (match_operand 3 "" ""))
2c9c2489
RK
443 (pc)))]
444 ""
b4324a14
PK
445 "#"
446 "reload_completed"
447 [(set (reg:CC CC_REGNUM)
448 (compare:CC (match_dup 1) (match_dup 2)))
449 (set (pc)
450 (if_then_else (match_op_dup 0
451 [(reg:CC CC_REGNUM) (const_int 0)])
452 (label_ref (match_dup 3))
453 (pc)))]
f90b7a5a 454 "")
2c9c2489 455
b4324a14
PK
456;; This splitter turns a branch on float condition into a branch on
457;; CPU condition, by adding a CFCC.
458(define_split
459 [(set (pc)
460 (if_then_else (match_operator 0 "ordered_comparison_operator"
461 [(reg:CC FCC_REGNUM) (const_int 0)])
462 (label_ref (match_operand 1 "" ""))
463 (pc)))]
464 "TARGET_FPU && reload_completed"
465 [(set (reg:CC CC_REGNUM) (reg:CC FCC_REGNUM))
466 (set (pc)
467 (if_then_else (match_op_dup 0
468 [(reg:CC CC_REGNUM) (const_int 0)])
469 (label_ref (match_dup 1))
470 (pc)))]
471 "")
2c9c2489 472
b4324a14 473(define_insn "cond_branch"
2c9c2489 474 [(set (pc)
f90b7a5a 475 (if_then_else (match_operator 0 "ordered_comparison_operator"
b4324a14 476 [(reg:CC CC_REGNUM) (const_int 0)])
f90b7a5a 477 (label_ref (match_operand 1 "" ""))
2c9c2489 478 (pc)))]
b4324a14
PK
479 "reload_completed"
480 "* return output_jump (operands, 0, get_attr_length (insn));"
7021d5df 481 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
2c9c2489 482 (pc))
7021d5df
PK
483 (const_int MIN_BRANCH))
484 (gt (minus (match_dup 1)
2c9c2489 485 (pc))
7021d5df 486 (const_int MAX_BRANCH)))
0f237806
PK
487 (const_int 6)
488 (const_int 2)))])
2c9c2489 489
b4324a14 490(define_insn "*branch"
2c9c2489 491 [(set (pc)
b4324a14
PK
492 (if_then_else (match_operator 0 "ccnz_operator"
493 [(reg:CCNZ CC_REGNUM) (const_int 0)])
494 (label_ref (match_operand 1 "" ""))
495 (pc)))]
496 "reload_completed"
497 "* return output_jump (operands, 1, get_attr_length (insn));"
7021d5df 498 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
2c9c2489 499 (pc))
7021d5df
PK
500 (const_int MIN_BRANCH))
501 (gt (minus (match_dup 1)
2c9c2489 502 (pc))
7021d5df 503 (const_int MAX_BRANCH)))
0f237806
PK
504 (const_int 6)
505 (const_int 2)))])
b4324a14 506
2c9c2489
RK
507\f
508;; Move instructions
509
aad2444d
PK
510;; "length" is defined even though this pattern won't appear at
511;; assembly language output time. But the length is used by
512;; pdp11_insn_cost, before the post-reload splitter adds the
513;; CC clobber to the insn.
2c9c2489 514(define_insn "movdi"
30442c59
PK
515 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
516 (match_operand:DI 1 "general_operand" "rN,g"))]
2c9c2489 517 ""
aad2444d
PK
518 ""
519 [(set_attr "length" "16,32")])
b4324a14
PK
520
521
522(define_insn "*movdi_nocc"
523 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
524 (match_operand:DI 1 "general_operand" "rN,g"))
525 (clobber (reg:CC CC_REGNUM))]
526 ""
30442c59 527 "* return output_move_multiple (operands);"
30442c59 528 [(set_attr "length" "16,32")])
2c9c2489
RK
529
530(define_insn "movsi"
30442c59
PK
531 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
532 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
2c9c2489 533 ""
aad2444d
PK
534 ""
535 [(set_attr "length" "4,6,8,16")])
b4324a14
PK
536
537(define_insn "*movsi_nocc"
538 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
539 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))
540 (clobber (reg:CC CC_REGNUM))]
541 ""
30442c59 542 "* return output_move_multiple (operands);"
30442c59 543 [(set_attr "length" "4,6,8,16")])
2c9c2489 544
442fcea7
PK
545;; That long string of "Z" constraints enforces the restriction that
546;; a register source and auto increment or decrement destination must
547;; not use the same register, because that case is not consistently
548;; implemented across the PDP11 models.
549;; TODO: the same should be applied to insn like add, but this is not
550;; necessary yet because the incdec optimization pass does not apply
551;; that optimization to 3-operand insns at the moment.
63caf8bb 552(define_insn "mov<mode>"
442fcea7
PK
553 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
554 (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))]
2c9c2489 555 ""
aad2444d 556 ""
442fcea7 557 [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
b4324a14
PK
558
559;; This splits all the integer moves: DI and SI modes as well as
560;; the simple machine operations.
561(define_split
562 [(set (match_operand:QHSDint 0 "nonimmediate_operand" "")
563 (match_operand:QHSDint 1 "general_operand" ""))]
564 "reload_completed"
565 [(parallel [(set (match_dup 0)
566 (match_dup 1))
567 (clobber (reg:CC CC_REGNUM))])]
568 "")
569
570;; MOV clears V
571(define_insn "*mov<mode>_<cc_cc>"
442fcea7
PK
572 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Za,Zb,Zc,Zd,Ze,Zf,Zg,rD,rR,Q,Q")
573 (match_operand:PDPint 1 "general_operand" "RN,Z0,Z1,Z2,Z3,Z4,Z5,Z6,r,Qi,rRN,Qi"))
b4324a14
PK
574 (clobber (reg:CC CC_REGNUM))]
575 "reload_completed"
2c9c2489
RK
576 "*
577{
578 if (operands[1] == const0_rtx)
4aef57c9 579 return \"clr<PDPint:isfx>\t%0\";
2c9c2489 580
4aef57c9 581 return \"mov<PDPint:isfx>\t%1,%0\";
2c9c2489 582}"
442fcea7 583 [(set_attr "length" "2,2,2,2,2,2,2,2,2,4,4,6")])
2c9c2489 584
b4324a14
PK
585;; movdf has unusually complicated condition code handling, because
586;; load (into float register) updates the FCC, while store (from
587;; float register) leaves it untouched.
588;;
589;; 1. Loads are: ac4, ac5, or non-register into load-register
590;; 2. Stores are: load-register to non-register, ac4, or ac5
591;; 3. Moves from ac0-ac3 to another ac0-ac3 can be handled
592;; either as loads or as stores.
593
594(define_expand "movdf"
595 [(set (match_operand:DF 0 "float_nonimm_operand" "")
596 (match_operand:DF 1 "float_operand" ""))]
825cb171 597 "TARGET_FPU"
b4324a14 598 "")
2c9c2489 599
b4324a14
PK
600;; Splitter for all these cases. Store is the first two
601;; alternatives, which are not split. Note that case 3
602;; is treated as a store, i.e., not split.
603(define_insn_and_split "movdf_split"
604 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,FQ,a,a,a")
605 (match_operand:DF 1 "float_operand" "a,a,hR,FQ,G"))]
2c9c2489 606 "TARGET_FPU"
b4324a14
PK
607 "*
608 gcc_assert (which_alternative < 2);
4aef57c9 609 return \"std\t%1,%0\";
b4324a14
PK
610 "
611 "&& reload_completed"
612 [(parallel [(set (match_dup 0)
613 (match_dup 1))
614 (clobber (reg:CC FCC_REGNUM))])]
615 "{
616 if (GET_CODE (operands[1]) == REG &&
617 REGNO_REG_CLASS (REGNO (operands[1])) == LOAD_FPU_REGS)
618 FAIL;
619 }"
620 [(set_attr "length" "2,4,0,0,0")])
621
622;; Loads (case 1).
623(define_insn "*ldd<fcc_cc>"
624 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,a,a")
625 (match_operand:DF 1 "float_operand" "hR,FQ,G"))
626 (clobber (reg:CC FCC_REGNUM))]
627 "TARGET_FPU && reload_completed"
628 "@
4aef57c9
PK
629 ldd\t%1,%0
630 ldd\t%1,%0
631 clrd\t%0"
b4324a14
PK
632 [(set_attr "length" "2,4,2")])
633
634;; SFmode is easier because that uses convert load/store, which
635;; always change condition codes.
636;; Note that these insns are cheating a bit. We actually have
637;; DFmode operands in the FPU registers, which is why the
638;; ldcfd and stcdf instructions appear. But GCC likes to think
639;; of these as SFmode loads and does the conversion once in the
640;; register, at least in many cases. So we pretend to do this,
641;; but then extend and truncate register-to-register are NOP and
642;; generate no code.
643(define_insn_and_split "movsf"
aad2444d
PK
644 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
645 (match_operand:SF 1 "float_operand" "fRG,a,FQ,a,G"))]
b4324a14
PK
646 "TARGET_FPU"
647 "#"
648 "&& reload_completed"
649 [(parallel [(set (match_dup 0)
650 (match_dup 1))
651 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
652 ""
653 [(set_attr "length" "2,2,4,4,2")])
b4324a14
PK
654
655(define_insn "*movsf<fcc_ccnz>"
656 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,a")
657 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,G"))
658 (clobber (reg:CC FCC_REGNUM))]
659 "TARGET_FPU && reload_completed"
660 "@
4aef57c9
PK
661 {ldcfd|movof}\t%1,%0
662 {stcdf|movfo}\t%1,%0
663 {ldcfd|movof}\t%1,%0
664 {stcdf|movfo}\t%1,%0
665 clrf\t%0"
b4324a14 666 [(set_attr "length" "2,2,4,4,2")])
2c9c2489 667
a3368b8e 668;; Expand a block move. We turn this into a move loop.
76715c32
AS
669(define_expand "cpymemhi"
670 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
442fcea7
PK
671 (match_operand:BLK 0 "general_operand" "=g")
672 (match_operand:BLK 1 "general_operand" "g")
673 (match_operand:HI 2 "immediate_operand" "i")
674 (match_operand:HI 3 "immediate_operand" "i")
675 (clobber (mem:BLK (scratch)))
676 (clobber (match_dup 0))
677 (clobber (match_dup 1))
678 (clobber (match_dup 2))])]
b4324a14 679 ""
2c9c2489
RK
680 "
681{
442fcea7
PK
682 int count;
683 count = INTVAL (operands[2]);
684 if (count == 0)
685 DONE;
686 if (INTVAL (operands [3]) >= 2 && (count & 1) == 0)
687 count >>= 1;
688 else
689 operands[3] = const1_rtx;
690 operands[2] = copy_to_mode_reg (HImode,
691 gen_rtx_CONST_INT (HImode, count));
692
693 /* Load BLKmode MEM addresses into scratch registers. */
694 operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
695 operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
2c9c2489
RK
696}")
697
442fcea7 698;; Expand a block move. We turn this into a move loop.
76715c32
AS
699(define_insn_and_split "cpymemhi1"
700 [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
442fcea7
PK
701 (match_operand:HI 0 "register_operand" "+r")
702 (match_operand:HI 1 "register_operand" "+r")
703 (match_operand:HI 2 "register_operand" "+r")
704 (match_operand:HI 3 "immediate_operand" "i")
705 (clobber (mem:BLK (scratch)))
706 (clobber (match_dup 0))
707 (clobber (match_dup 1))
708 (clobber (match_dup 2))]
709 ""
710 "#"
711 "reload_completed"
76715c32 712 [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
442fcea7
PK
713 (match_dup 0)
714 (match_dup 1)
715 (match_dup 2)
716 (match_dup 3)
717 (clobber (mem:BLK (scratch)))
718 (clobber (match_dup 0))
719 (clobber (match_dup 1))
720 (clobber (match_dup 2))
721 (clobber (reg:CC CC_REGNUM))])]
722 "")
723
76715c32
AS
724(define_insn "cpymemhi_nocc"
725 [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
442fcea7
PK
726 (match_operand:HI 0 "register_operand" "+r")
727 (match_operand:HI 1 "register_operand" "+r")
728 (match_operand:HI 2 "register_operand" "+r")
729 (match_operand:HI 3 "immediate_operand" "i")
730 (clobber (mem:BLK (scratch)))
731 (clobber (match_dup 0))
732 (clobber (match_dup 1))
733 (clobber (match_dup 2))
734 (clobber (reg:CC CC_REGNUM))]
735 "reload_completed"
736 "*
737{
738 rtx lb[2];
739
740 lb[0] = operands[2];
741 lb[1] = gen_label_rtx ();
742
743 output_asm_label (lb[1]);
744 fputs (\":\n\", asm_out_file);
745 if (INTVAL (operands[3]) > 1)
746 output_asm_insn (\"mov\t(%1)+,(%0)+\", operands);
747 else
748 output_asm_insn (\"movb\t(%1)+,(%0)+\", operands);
749 if (TARGET_40_PLUS)
750 output_asm_insn (\"sob\t%0,%l1\", lb);
751 else
752 {
753 output_asm_insn (\"dec\t%0\", lb);
754 output_asm_insn (\"bne\t%l1\", lb);
755 }
756 return \"\";
757}"
758 [(set (attr "length")
759 (if_then_else (match_test "TARGET_40_PLUS")
760 (const_int 4)
761 (const_int 6)))])
2c9c2489
RK
762\f
763;;- truncation instructions
764
b4324a14
PK
765;; We sometimes end up doing a register to register truncate,
766;; which isn't right because we actually load registers always
767;; with a DFmode value. But even with PROMOTE the compiler
768;; doesn't always get that (so we don't use it). That means
769;; a register to register truncate is a NOP.
770(define_insn_and_split "truncdfsf2"
166208c2 771 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
b4324a14 772 (float_truncate:SF (match_operand:DF 1 "register_operand" "0,a,a")))]
2c9c2489 773 "TARGET_FPU"
b4324a14
PK
774 {
775 gcc_assert (which_alternative == 0);
776 return "";
777 }
778 "&& reload_completed"
779 [(parallel [(set (match_dup 0) (float_truncate:SF (match_dup 1)))
780 (clobber (reg:CC FCC_REGNUM))])]
781 "{
782 if (GET_CODE (operands[0]) == REG &&
783 GET_CODE (operands[1]) == REG &&
784 REGNO (operands[0]) == REGNO (operands[1]))
785 FAIL;
786 }"
787 [(set_attr "length" "0,0,0")])
788
789(define_insn "*truncdfsf2_<fcc_cc>"
790 [(set (match_operand:SF 0 "float_nonimm_operand" "=R,Q")
791 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a")))
792 (clobber (reg:CC FCC_REGNUM))]
793 "TARGET_FPU && reload_completed"
4aef57c9 794 "{stcdf|movfo}\t%1,%0"
b4324a14 795 [(set_attr "length" "2,4")])
2c9c2489 796
2c9c2489 797\f
aad2444d 798;;- zero extension instruction
2c9c2489 799
b4324a14 800(define_insn_and_split "zero_extendqihi2"
aad2444d
PK
801 [(set (match_operand:HI 0 "nonimmediate_operand" "=rD,Q,&r,&r")
802 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0,rR,Q")))]
2c9c2489 803 ""
b4324a14
PK
804 "#"
805 "reload_completed"
806 [(parallel [(set (match_dup 0) (zero_extend:HI (match_dup 1)))
807 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
808 "{
809 rtx r;
810
811 if (!REG_P (operands[0]))
812 {
813 r = gen_rtx_MEM (QImode, operands[0]);
814 adjust_address (r, QImode, 1);
815 emit_move_insn (r, const0_rtx);
816 DONE;
817 }
442fcea7
PK
818 else if (!REG_P (operands[1]) ||
819 REGNO (operands[0]) != REGNO (operands[1]))
aad2444d
PK
820 {
821 /* Alternatives 2 and 3 */
822 emit_move_insn (operands[0], const0_rtx);
823 r = gen_rtx_REG (QImode, REGNO (operands[0]));
824 emit_insn (gen_iorqi3_nocc (r, r, operands[1]));
825 DONE;
826 }
827 }"
828 [(set_attr "length" "4,4,4,6")])
b4324a14
PK
829
830(define_insn "*zero_extendqihi2<cc_cc>"
831 [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
832 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))
833 (clobber (reg:CC CC_REGNUM))])]
834 "reload_completed"
4aef57c9 835 "bic\t%#0177400,%0"
0f237806 836 [(set_attr "length" "4,6")])
2c9c2489 837
2c9c2489
RK
838;;- sign extension instructions
839
b4324a14
PK
840;; We sometimes end up doing a register to register extend,
841;; which isn't right because we actually load registers always
842;; with a DFmode value. But even with PROMOTE the compiler
843;; doesn't always get that (so we don't use it). That means
844;; a register to register truncate is a NOP.
845(define_insn_and_split "extendsfdf2"
a01c666c 846 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
b4324a14 847 (float_extend:DF (match_operand:SF 1 "float_operand" "0,R,Q")))]
2c9c2489 848 "TARGET_FPU"
b4324a14
PK
849 {
850 gcc_assert (which_alternative == 0);
851 return "";
852 }
853 "&& reload_completed"
854 [(parallel [(set (match_dup 0) (float_extend:DF (match_dup 1)))
855 (clobber (reg:CC FCC_REGNUM))])]
856 "{
857 if (GET_CODE (operands[0]) == REG &&
858 GET_CODE (operands[1]) == REG &&
859 REGNO (operands[0]) == REGNO (operands[1]))
860 FAIL;
861 }"
862 [(set_attr "length" "0,0,0")])
863
864(define_insn "*extendsfdf2_<fcc_cc>"
865 [(set (match_operand:DF 0 "register_operand" "=a,a")
866 (float_extend:DF (match_operand:SF 1 "float_operand" "R,Q")))
867 (clobber (reg:CC FCC_REGNUM))]
868 "TARGET_FPU && reload_completed"
4aef57c9 869 "{ldcfd|movof}\t%1,%0"
aad2444d
PK
870 [(set_attr "length" "2,4")
871 (set_attr "base_cost" "6")])
2c9c2489 872
b4324a14
PK
873;; movb sign extends if destination is a register
874(define_insn_and_split "extendqihi2"
2c9c2489
RK
875 [(set (match_operand:HI 0 "register_operand" "=r,r")
876 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
877 ""
b4324a14
PK
878 "#"
879 "reload_completed"
880 [(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
881 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
882 ""
883 [(set_attr "length" "2,4")])
b4324a14
PK
884
885;; MOVB clears V
886(define_insn "*extendqihi2<cc_cc>"
887 [(set (match_operand:HI 0 "register_operand" "=r,r")
888 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))
889 (clobber (reg:CC CC_REGNUM))]
890 "reload_completed"
4aef57c9 891 "movb\t%1,%0"
0f237806 892 [(set_attr "length" "2,4")])
2c9c2489 893
b4324a14 894(define_insn_and_split "extendhisi2"
166208c2 895 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
2c9c2489
RK
896 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
897 "TARGET_40_PLUS"
b4324a14
PK
898 "#"
899 "&& reload_completed"
900 [(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
901 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
902 ""
903 [(set_attr "length" "10,6,6")])
b4324a14
PK
904
905(define_insn "*extendhisi2_nocc"
906 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
907 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))
908 (clobber (reg:CC CC_REGNUM))]
909 "TARGET_40_PLUS && reload_completed"
2c9c2489
RK
910 "*
911{
912 rtx latehalf[2];
913
914 /* we don't want to mess with auto increment */
915
b72f00af 916 switch (which_alternative)
2c9c2489
RK
917 {
918 case 0:
919
920 latehalf[0] = operands[0];
b72f00af 921 operands[0] = adjust_address(operands[0], HImode, 2);
2c9c2489 922
4aef57c9
PK
923 output_asm_insn(\"mov\t%1,%0\", operands);
924 output_asm_insn(\"sxt\t%0\", latehalf);
2c9c2489
RK
925
926 return \"\";
927
928 case 1:
929
930 /* - auto-decrement - right direction ;-) */
4aef57c9
PK
931 output_asm_insn(\"mov\t%1,%0\", operands);
932 output_asm_insn(\"sxt\t%0\", operands);
2c9c2489
RK
933
934 return \"\";
935
936 case 2:
937
938 /* make register pair available */
939 latehalf[0] = operands[0];
c5c76735 940 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
2c9c2489 941
4aef57c9
PK
942 output_asm_insn(\"mov\t%1,%0\", operands);
943 output_asm_insn(\"sxt\t%0\", latehalf);
2c9c2489
RK
944
945 return \"\";
946
947 default:
948
d35d9223 949 gcc_unreachable ();
2c9c2489
RK
950 }
951}"
0f237806 952 [(set_attr "length" "10,6,6")])
2c9c2489 953
2c9c2489 954;; make float to int and vice versa
2c9c2489
RK
955;; assume that we are normally in double and integer mode -
956;; what do pdp library routines do to fpu mode ?
957
b4324a14
PK
958;; Note: the hardware treats register source as
959;; a 16-bit (high order only) source, which isn't
960;; what we want. But we do need to support register
961;; dest because gcc asks for it.
962(define_insn_and_split "floatsidf2"
e3be1b32
RK
963 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
964 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
2c9c2489 965 "TARGET_FPU"
b4324a14
PK
966 "#"
967 "&& reload_completed"
968 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
969 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
970 ""
971 [(set_attr "length" "10,6,8")])
b4324a14
PK
972
973(define_insn "*floatsidf2<fcc_cc>"
974 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
975 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))
976 (clobber (reg:CC FCC_REGNUM))]
977 "TARGET_FPU && reload_completed"
e3be1b32
RK
978 "* if (which_alternative ==0)
979 {
980 rtx latehalf[2];
b4324a14 981
e3be1b32 982 latehalf[0] = NULL;
e7f9979a 983 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
4aef57c9
PK
984 output_asm_insn(\"mov\t%1,-(sp)\", latehalf);
985 output_asm_insn(\"mov\t%1,-(sp)\", operands);
e3be1b32
RK
986
987 output_asm_insn(\"setl\", operands);
4aef57c9 988 output_asm_insn(\"{ldcld|movif}\t(sp)+,%0\", operands);
e3be1b32
RK
989 output_asm_insn(\"seti\", operands);
990 return \"\";
991 }
e3be1b32 992 else
4aef57c9 993 return \"setl\;{ldcld|movif}\t%1,%0\;seti\";
e3be1b32 994 "
aad2444d
PK
995 [(set_attr "length" "10,6,8")
996 (set_attr "base_cost" "12")])
2c9c2489 997
b4324a14 998(define_insn_and_split "floathidf2"
2c9c2489
RK
999 [(set (match_operand:DF 0 "register_operand" "=a,a")
1000 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
1001 "TARGET_FPU"
b4324a14
PK
1002 "#"
1003 "&& reload_completed"
1004 [(parallel [(set (match_dup 0) (float:DF (match_dup 1)))
1005 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
1006 ""
1007 [(set_attr "length" "2,4")])
b4324a14
PK
1008
1009(define_insn "*floathidf2<fcc_cc>"
1010 [(set (match_operand:DF 0 "register_operand" "=a,a")
1011 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))
1012 (clobber (reg:CC FCC_REGNUM))]
1013 "TARGET_FPU && reload_completed"
4aef57c9 1014 "{ldcid|movif}\t%1,%0"
aad2444d
PK
1015 [(set_attr "length" "2,4")
1016 (set_attr "base_cost" "12")])
1017
2c9c2489 1018;; cut float to int
b4324a14
PK
1019
1020;; Note: the hardware treats register destination as
1021;; a 16-bit (high order only) destination, which isn't
1022;; what we want. But we do need to support register
1023;; dest because gcc asks for it.
1024(define_insn_and_split "fix_truncdfsi2"
166208c2 1025 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
e3be1b32 1026 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
2c9c2489 1027 "TARGET_FPU"
b4324a14
PK
1028 "#"
1029 "&& reload_completed"
1030 [(parallel [(set (match_dup 0) (fix:SI (fix:DF (match_dup 1))))
1031 (clobber (reg:CC CC_REGNUM))
1032 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
1033 ""
1034 [(set_attr "length" "10,6,8")])
b4324a14
PK
1035
1036;; Note: this clobbers both sets of condition codes!
1037(define_insn "*fix_truncdfsi2_nocc"
1038 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
1039 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))
1040 (clobber (reg:CC CC_REGNUM))
1041 (clobber (reg:CC FCC_REGNUM))]
1042 "TARGET_FPU && reload_completed"
e3be1b32
RK
1043 "* if (which_alternative ==0)
1044 {
1045 output_asm_insn(\"setl\", operands);
4aef57c9 1046 output_asm_insn(\"{stcdl|movfi}\t%1,-(sp)\", operands);
e3be1b32 1047 output_asm_insn(\"seti\", operands);
4aef57c9 1048 output_asm_insn(\"mov\t(sp)+,%0\", operands);
c5c76735 1049 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
4aef57c9 1050 output_asm_insn(\"mov\t(sp)+,%0\", operands);
e3be1b32
RK
1051 return \"\";
1052 }
e3be1b32 1053 else
4aef57c9 1054 return \"setl\;{stcdl|movfi}\t%1,%0\;seti\";
e3be1b32 1055 "
aad2444d
PK
1056 [(set_attr "length" "10,6,8")
1057 (set_attr "base_cost" "12")])
2c9c2489 1058
b4324a14 1059(define_insn_and_split "fix_truncdfhi2"
166208c2 1060 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2c9c2489
RK
1061 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
1062 "TARGET_FPU"
b4324a14
PK
1063 "#"
1064 "&& reload_completed"
1065 [(parallel [(set (match_dup 0) (fix:HI (fix:DF (match_dup 1))))
1066 (clobber (reg:CC CC_REGNUM))
1067 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
1068 ""
1069 [(set_attr "length" "2,4")])
b4324a14
PK
1070
1071;; Note: this clobbers both sets of condition codes!
1072(define_insn "*fix_truncdfhi2_nocc"
1073 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1074 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))
1075 (clobber (reg:CC CC_REGNUM))
1076 (clobber (reg:CC FCC_REGNUM))]
1077 "TARGET_FPU && reload_completed"
4aef57c9 1078 "{stcdi|movfi}\t%1,%0"
aad2444d
PK
1079 [(set_attr "length" "2,4")
1080 (set_attr "base_cost" "12")])
2c9c2489
RK
1081
1082\f
1083;;- arithmetic instructions
1084;;- add instructions
1085
b4324a14 1086(define_insn_and_split "adddf3"
c67b2d4e
PK
1087 [(set (match_operand:DF 0 "register_operand" "=a,a")
1088 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
1089 (match_operand:DF 2 "general_operand" "fR,QF")))]
2c9c2489 1090 "TARGET_FPU"
b4324a14
PK
1091 "#"
1092 "&& reload_completed"
1093 [(parallel [(set (match_dup 0)
1094 (plus:DF (match_dup 1) (match_dup 2)))
1095 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
1096 ""
1097 [(set_attr "length" "2,4")])
b4324a14
PK
1098
1099;; Float add sets V if overflow from add
1100(define_insn "*adddf3<fcc_ccnz>"
1101 [(set (match_operand:DF 0 "register_operand" "=a,a")
1102 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
1103 (match_operand:DF 2 "general_operand" "fR,QF")))
1104 (clobber (reg:CC FCC_REGNUM))]
1105 "TARGET_FPU && reload_completed"
4aef57c9 1106 "{addd|addf}\t%2,%0"
aad2444d
PK
1107 [(set_attr "length" "2,4")
1108 (set_attr "base_cost" "6")])
2c9c2489 1109
b4324a14 1110(define_insn_and_split "adddi3"
30442c59
PK
1111 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1112 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
1113 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
2c9c2489 1114 ""
b4324a14
PK
1115 "#"
1116 "reload_completed"
1117 [(parallel [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
1118 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1119 ""
1120 [(set_attr "length" "20,28,40,48")])
b4324a14
PK
1121
1122(define_insn "*adddi3_nocc"
1123 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1124 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
1125 (match_operand:DI 2 "general_operand" "r,on,r,on")))
1126 (clobber (reg:CC CC_REGNUM))]
1127 "reload_completed"
2c9c2489 1128 "*
30442c59
PK
1129{
1130 rtx inops[2];
1131 rtx exops[4][2];
2c9c2489 1132
30442c59
PK
1133 inops[0] = operands[0];
1134 inops[1] = operands[2];
442fcea7 1135 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
2c9c2489 1136
442fcea7 1137 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
4aef57c9 1138 output_asm_insn (\"add\t%1,%0\", exops[0]);
442fcea7 1139 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
2c9c2489 1140 {
4aef57c9
PK
1141 output_asm_insn (\"add\t%1,%0\", exops[1]);
1142 output_asm_insn (\"adc\t%0\", exops[0]);
30442c59 1143 }
442fcea7 1144 if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
30442c59 1145 {
4aef57c9
PK
1146 output_asm_insn (\"add\t%1,%0\", exops[2]);
1147 output_asm_insn (\"adc\t%0\", exops[1]);
1148 output_asm_insn (\"adc\t%0\", exops[0]);
30442c59 1149 }
442fcea7 1150 if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
30442c59 1151 {
4aef57c9
PK
1152 output_asm_insn (\"add\t%1,%0\", exops[3]);
1153 output_asm_insn (\"adc\t%0\", exops[2]);
1154 output_asm_insn (\"adc\t%0\", exops[1]);
1155 output_asm_insn (\"adc\t%0\", exops[0]);
2c9c2489
RK
1156 }
1157
30442c59
PK
1158 return \"\";
1159}"
aad2444d
PK
1160 [(set_attr "length" "20,28,40,48")
1161 (set_attr "base_cost" "0")])
30442c59
PK
1162
1163;; Note that the register operand is not marked earlyclobber.
1164;; The reason is that SI values go in register pairs, so they
1165;; can't partially overlap. They can be either disjoint, or
1166;; source and destination can be equal. The latter case is
1167;; handled properly because of the ordering of the individual
1168;; instructions used. Specifically, carry from the low to the
1169;; high word is added at the end, so the adding of the high parts
1170;; will always used the original high part and not a high part
1171;; modified by carry (which would amount to double carry).
b4324a14
PK
1172(define_insn_and_split "addsi3"
1173 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
30442c59
PK
1174 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1175 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1176 ""
b4324a14
PK
1177 "#"
1178 "reload_completed"
1179 [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
1180 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1181 ""
1182 [(set_attr "length" "6,10,12,16")])
b4324a14
PK
1183
1184(define_insn "*addsi3_nocc"
1185 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1186 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
1187 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1188 (clobber (reg:CC CC_REGNUM))]
1189 "reload_completed"
30442c59
PK
1190 "*
1191{
1192 rtx inops[2];
1193 rtx exops[2][2];
2c9c2489 1194
30442c59
PK
1195 inops[0] = operands[0];
1196 inops[1] = operands[2];
442fcea7 1197 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
30442c59 1198
442fcea7 1199 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
4aef57c9 1200 output_asm_insn (\"add\t%1,%0\", exops[0]);
442fcea7 1201 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
30442c59 1202 {
4aef57c9
PK
1203 output_asm_insn (\"add\t%1,%0\", exops[1]);
1204 output_asm_insn (\"adc\t%0\", exops[0]);
2c9c2489
RK
1205 }
1206
2c9c2489
RK
1207 return \"\";
1208}"
aad2444d
PK
1209 [(set_attr "length" "6,10,12,16")
1210 (set_attr "base_cost" "0")])
2c9c2489 1211
b4324a14 1212(define_insn_and_split "addhi3"
166208c2 1213 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
2c9c2489
RK
1214 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1215 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1216 ""
b4324a14
PK
1217 "#"
1218 "reload_completed"
1219 [(parallel [(set (match_dup 0)
1220 (plus:HI (match_dup 1) (match_dup 2)))
1221 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1222 ""
1223 [(set_attr "length" "2,4,4,6")])
b4324a14
PK
1224
1225;; Add sets V if overflow from the add
1226(define_insn "*addhi3<cc_ccnz>"
1227 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1228 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1229 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1230 (clobber (reg:CC CC_REGNUM))]
1231 "reload_completed"
2c9c2489
RK
1232 "*
1233{
1234 if (GET_CODE (operands[2]) == CONST_INT)
09b893bb
JM
1235 {
1236 if (INTVAL(operands[2]) == 1)
4aef57c9 1237 return \"inc\t%0\";
09b893bb 1238 else if (INTVAL(operands[2]) == -1)
4aef57c9 1239 return \"dec\t%0\";
09b893bb 1240 }
2c9c2489 1241
4aef57c9 1242 return \"add\t%2,%0\";
2c9c2489 1243}"
0f237806 1244 [(set_attr "length" "2,4,4,6")])
2c9c2489 1245
fe65151b
PK
1246(define_insn_and_split "addqi3"
1247 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1248 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1249 (match_operand:QI 2 "incdec_operand" "LM,LM")))]
1250 ""
1251 "#"
1252 "reload_completed"
1253 [(parallel [(set (match_dup 0)
1254 (plus:QI (match_dup 1) (match_dup 2)))
1255 (clobber (reg:CC CC_REGNUM))])]
1256 ""
1257 [(set_attr "length" "2,4")])
1258
1259;; Inc/dec sets V if overflow from the operation
1260(define_insn "*addqi3<cc_ccnz>"
1261 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1262 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1263 (match_operand:QI 2 "incdec_operand" "LM,LM")))
1264 (clobber (reg:CC CC_REGNUM))]
1265 "reload_completed"
1266 "*
1267{
1268 if (INTVAL(operands[2]) == 1)
1269 return \"incb\t%0\";
1270 else
1271 return \"decb\t%0\";
1272}"
1273 [(set_attr "length" "2,4")])
1274
2c9c2489
RK
1275\f
1276;;- subtract instructions
1277;; we don't have to care for constant second
ddd5a7c1 1278;; args, since they are canonical plus:xx now!
2c9c2489
RK
1279;; also for minus:DF ??
1280
b4324a14 1281(define_insn_and_split "subdf3"
2c9c2489
RK
1282 [(set (match_operand:DF 0 "register_operand" "=a,a")
1283 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1284 (match_operand:DF 2 "general_operand" "fR,Q")))]
1285 "TARGET_FPU"
b4324a14
PK
1286 "#"
1287 "&& reload_completed"
1288 [(parallel [(set (match_dup 0)
1289 (minus:DF (match_dup 1) (match_dup 2)))
1290 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
1291 ""
1292 [(set_attr "length" "2,4")])
b4324a14
PK
1293
1294(define_insn "*subdf3<fcc_ccnz>"
1295 [(set (match_operand:DF 0 "register_operand" "=a,a")
1296 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1297 (match_operand:DF 2 "general_operand" "fR,QF")))
1298 (clobber (reg:CC FCC_REGNUM))]
1299 "TARGET_FPU && reload_completed"
4aef57c9 1300 "{subd|subf}\t%2,%0"
aad2444d
PK
1301 [(set_attr "length" "2,4")
1302 (set_attr "base_cost" "6")])
2c9c2489 1303
b4324a14 1304(define_insn_and_split "subdi3"
30442c59
PK
1305 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1306 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1307 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
2c9c2489 1308 ""
b4324a14
PK
1309 "#"
1310 "reload_completed"
1311 [(parallel [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
1312 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1313 ""
1314 [(set_attr "length" "20,28,40,48")])
b4324a14
PK
1315
1316(define_insn "*subdi3_nocc"
1317 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
1318 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
1319 (match_operand:DI 2 "general_operand" "r,on,r,on")))
1320 (clobber (reg:CC CC_REGNUM))]
1321 "reload_completed"
2c9c2489 1322 "*
30442c59
PK
1323{
1324 rtx inops[2];
1325 rtx exops[4][2];
1326
1327 inops[0] = operands[0];
1328 inops[1] = operands[2];
442fcea7 1329 pdp11_expand_operands (inops, exops, 2, 4, NULL, big);
30442c59 1330
442fcea7 1331 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
4aef57c9 1332 output_asm_insn (\"sub\t%1,%0\", exops[0]);
442fcea7 1333 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
30442c59 1334 {
4aef57c9
PK
1335 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1336 output_asm_insn (\"sbc\t%0\", exops[0]);
30442c59 1337 }
442fcea7 1338 if (!CONST_INT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
30442c59 1339 {
4aef57c9
PK
1340 output_asm_insn (\"sub\t%1,%0\", exops[2]);
1341 output_asm_insn (\"sbc\t%0\", exops[1]);
1342 output_asm_insn (\"sbc\t%0\", exops[0]);
30442c59 1343 }
442fcea7 1344 if (!CONST_INT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
30442c59 1345 {
4aef57c9
PK
1346 output_asm_insn (\"sub\t%1,%0\", exops[3]);
1347 output_asm_insn (\"sbc\t%0\", exops[2]);
1348 output_asm_insn (\"sbc\t%0\", exops[1]);
1349 output_asm_insn (\"sbc\t%0\", exops[0]);
30442c59 1350 }
2c9c2489 1351
30442c59
PK
1352 return \"\";
1353}"
aad2444d
PK
1354 [(set_attr "length" "20,28,40,48")
1355 (set_attr "base_cost" "0")])
2c9c2489 1356
b4324a14
PK
1357(define_insn_and_split "subsi3"
1358 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
30442c59
PK
1359 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1360 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
1361 ""
b4324a14
PK
1362 "#"
1363 "reload_completed"
1364 [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
1365 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1366 ""
1367 [(set_attr "length" "6,10,12,16")])
b4324a14
PK
1368
1369(define_insn "*subsi3_nocc"
1370 [(set (match_operand:SI 0 "nonimmediate_operand" "=&r,r,o,o")
1371 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1372 (match_operand:SI 2 "general_operand" "r,on,r,on")))
1373 (clobber (reg:CC CC_REGNUM))]
1374 "reload_completed"
30442c59
PK
1375 "*
1376{
1377 rtx inops[2];
1378 rtx exops[2][2];
2c9c2489 1379
30442c59
PK
1380 inops[0] = operands[0];
1381 inops[1] = operands[2];
442fcea7 1382 pdp11_expand_operands (inops, exops, 2, 2, NULL, big);
2c9c2489 1383
442fcea7 1384 if (!CONST_INT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
4aef57c9 1385 output_asm_insn (\"sub\t%1,%0\", exops[0]);
442fcea7 1386 if (!CONST_INT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
30442c59 1387 {
4aef57c9
PK
1388 output_asm_insn (\"sub\t%1,%0\", exops[1]);
1389 output_asm_insn (\"sbc\t%0\", exops[0]);
30442c59 1390 }
2c9c2489 1391
2c9c2489
RK
1392 return \"\";
1393}"
aad2444d
PK
1394 [(set_attr "length" "6,10,12,16")
1395 (set_attr "base_cost" "0")])
2c9c2489 1396
b4324a14 1397(define_insn_and_split "subhi3"
166208c2 1398 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
2c9c2489 1399 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
b4324a14 1400 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
2c9c2489 1401 ""
b4324a14
PK
1402 "#"
1403 "reload_completed"
1404 [(parallel [(set (match_dup 0)
1405 (minus:HI (match_dup 1) (match_dup 2)))
1406 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1407 ""
1408 [(set_attr "length" "2,4,4,6")])
b4324a14
PK
1409
1410;; Note: the manual says that (minus m (const_int n)) is converted
1411;; to (plus m (const_int -n)) but that does not appear to be
1412;; the case when it's wrapped in a PARALLEL. So instead we handle
1413;; that case here, which is easy enough.
1414(define_insn "*subhi3<cc_ccnz>"
1415 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1416 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1417 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))
1418 (clobber (reg:CC CC_REGNUM))]
1419 "reload_completed"
2c9c2489
RK
1420 "*
1421{
b4324a14
PK
1422 if (GET_CODE (operands[2]) == CONST_INT)
1423 {
1424 if (INTVAL(operands[2]) == 1)
4aef57c9 1425 return \"dec\t%0\";
b4324a14 1426 else if (INTVAL(operands[2]) == -1)
4aef57c9 1427 return \"inc\t%0\";
b4324a14 1428 }
2c9c2489 1429
4aef57c9 1430 return \"sub\t%2,%0\";
2c9c2489 1431}"
0f237806 1432 [(set_attr "length" "2,4,4,6")])
2c9c2489 1433
fe65151b
PK
1434(define_insn_and_split "subqi3"
1435 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1436 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1437 (match_operand:QI 2 "incdec_operand" "LM,LM")))]
1438 ""
1439 "#"
1440 "reload_completed"
1441 [(parallel [(set (match_dup 0)
1442 (plus:QI (match_dup 1) (match_dup 2)))
1443 (clobber (reg:CC CC_REGNUM))])]
1444 ""
1445 [(set_attr "length" "2,4")])
1446
1447;; Inc/dec sets V if overflow from the operation
1448(define_insn "*subqi3<cc_ccnz>"
1449 [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
1450 (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
1451 (match_operand:QI 2 "incdec_operand" "LM,LM")))
1452 (clobber (reg:CC CC_REGNUM))]
1453 "reload_completed"
1454 "*
1455{
1456 if (INTVAL(operands[2]) == -1)
1457 return \"incb\t%0\";
1458 else
1459 return \"decb\t%0\";
1460}"
1461 [(set_attr "length" "2,4")])
1462
2c9c2489 1463;;;;- and instructions
8aeea6e6 1464;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
2c9c2489 1465
9546fe6a 1466(define_expand "and<mode>3"
166208c2 1467 [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
9546fe6a
PK
1468 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
1469 (match_operand:PDPint 2 "general_operand" "")))]
2c9c2489 1470 ""
9546fe6a
PK
1471 "
1472{
1473 rtx op1 = operands[1];
2c9c2489 1474
9546fe6a
PK
1475 /* If there is a constant argument, complement that one.
1476 Similarly, if one of the inputs is the same as the output,
1477 complement the other input. */
1478 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
1479 rtx_equal_p (operands[0], operands[1]))
1480 {
1481 operands[1] = operands[2];
1482 operands[2] = op1;
1483 op1 = operands[1];
1484 }
2c9c2489 1485
9546fe6a
PK
1486 if (CONST_INT_P (op1))
1487 operands[1] = GEN_INT (~INTVAL (op1));
2c9c2489 1488 else
9546fe6a 1489 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
aad2444d
PK
1490}"
1491 [(set_attr "length" "2,4,4,6")])
2c9c2489 1492
b4324a14 1493(define_insn_and_split "*bic<mode>"
166208c2 1494 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
9546fe6a
PK
1495 (and:PDPint
1496 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1497 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
2c9c2489 1498 ""
b4324a14
PK
1499 "#"
1500 "reload_completed"
1501 [(parallel [(set (match_dup 0)
1502 (and:PDPint (not:PDPint (match_dup 1)) (match_dup 2)))
1503 (clobber (reg:CC CC_REGNUM))])]
1504 "")
1505
1506(define_insn "*bic<mode><cc_cc>"
1507 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1508 (and:PDPint
1509 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
1510 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))
1511 (clobber (reg:CC CC_REGNUM))]
1512 "reload_completed"
4aef57c9 1513 "bic<PDPint:isfx>\t%1,%0"
0f237806 1514 [(set_attr "length" "2,4,4,6")])
2c9c2489
RK
1515
1516;;- Bit set (inclusive or) instructions
b4324a14 1517(define_insn_and_split "ior<mode>3"
63caf8bb
PK
1518 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1519 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
b4324a14 1520 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
2c9c2489 1521 ""
b4324a14
PK
1522 "#"
1523 "reload_completed"
1524 [(parallel [(set (match_dup 0)
1525 (ior:PDPint (match_dup 1) (match_dup 2)))
1526 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1527 ""
1528 [(set_attr "length" "2,4,4,6")])
b4324a14
PK
1529
1530(define_insn "ior<mode>3<cc_cc>"
1531 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
1532 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
1533 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))
1534 (clobber (reg:CC CC_REGNUM))]
1535 "reload_completed"
4aef57c9 1536 "bis<PDPint:isfx>\t%2,%0"
0f237806 1537 [(set_attr "length" "2,4,4,6")])
2c9c2489 1538
2c9c2489 1539;;- xor instructions
b4324a14 1540(define_insn_and_split "xorhi3"
166208c2 1541 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2c9c2489
RK
1542 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1543 (match_operand:HI 2 "register_operand" "r,r")))]
1544 "TARGET_40_PLUS"
b4324a14
PK
1545 "#"
1546 "&& reload_completed"
1547 [(parallel [(set (match_dup 0)
1548 (xor:HI (match_dup 1) (match_dup 2)))
1549 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1550 ""
1551 [(set_attr "length" "2,4")])
b4324a14
PK
1552
1553(define_insn "*xorhi3<cc_cc>"
1554 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
1555 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1556 (match_operand:HI 2 "register_operand" "r,r")))
1557 (clobber (reg:CC CC_REGNUM))]
1558 "TARGET_40_PLUS && reload_completed"
4aef57c9 1559 "xor\t%2,%0"
0f237806 1560 [(set_attr "length" "2,4")])
2c9c2489
RK
1561
1562;;- one complement instructions
1563
b4324a14 1564(define_insn_and_split "one_cmpl<mode>2"
63caf8bb
PK
1565 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1566 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
2c9c2489 1567 ""
b4324a14
PK
1568 "#"
1569 "reload_completed"
1570 [(parallel [(set (match_dup 0)
1571 (not:PDPint (match_dup 1)))
1572 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1573 ""
1574 [(set_attr "length" "2,4")])
b4324a14
PK
1575
1576(define_insn "*one_cmpl<mode>2<cc_cc>"
1577 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1578 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1579 (clobber (reg:CC CC_REGNUM))]
1580 "reload_completed"
4aef57c9 1581 "com<PDPint:isfx>\t%0"
0f237806 1582 [(set_attr "length" "2,4")])
2c9c2489
RK
1583
1584;;- arithmetic shift instructions
b4324a14
PK
1585;;
1586;; There is a fair amount of complexity here because with -m10
1587;; (pdp-11/10, /20) we only have shift by one bit. Iterators are
1588;; used to reduce the amount of very similar code.
1589;;
1590;; First the insns used for small constant shifts.
aad2444d 1591(define_insn_and_split "<code><mode>_sc"
b4324a14
PK
1592 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1593 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1594 (match_operand:HI 2 "expand_shift_operand" "O,O")))]
2c9c2489 1595 ""
aad2444d
PK
1596 "#"
1597 "reload_completed"
1598 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1599 (clobber (reg:CC CC_REGNUM))])]
1600 ""
9cd1665b
PK
1601 [(set (attr "length")
1602 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
aad2444d
PK
1603 <CODE>, which_alternative == 0)"))
1604 (set_attr "base_cost" "0")])
1605
1606(define_insn "<code><mode>_sc<cc_ccnz>"
1607 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rD,Q")
1608 (SHF:PDPint (match_operand:PDPint 1 "general_operand" "0,0")
1609 (match_operand:HI 2 "expand_shift_operand" "O,O")))
1610 (clobber (reg:CC CC_REGNUM))]
1611 "reload_completed"
1612 "* return pdp11_assemble_shift (operands, <PDPint:mname>, <CODE>);"
1613 [(set (attr "length")
1614 (symbol_ref "pdp11_shift_length (operands, <PDPint:mname>,
1615 <CODE>, which_alternative == 0)"))
1616 (set_attr "base_cost" "0")])
1617
1618;; This one comes only in clobber flavor.
1619(define_insn "<code>si_sc_nocc"
1620 [(set (match_operand:SI 0 "nonimmediate_operand" "=rD,Q")
1621 (SHF:SI (match_operand:SI 1 "general_operand" "0,0")
1622 (match_operand:HI 2 "expand_shift_operand" "O,O")))
1623 (clobber (reg:CC CC_REGNUM))]
1624 "reload_completed"
1625 "* return pdp11_assemble_shift (operands, SImode, <CODE>);"
1626 [(set (attr "length")
1627 (symbol_ref "pdp11_shift_length (operands, SImode,
1628 <CODE>, which_alternative == 0)"))
1629 (set_attr "base_cost" "0")])
2c9c2489 1630
b4324a14
PK
1631;; Next, shifts that are done as a loop on base (11/10 class) machines.
1632;; This applies to shift counts too large to unroll, or variable shift
1633;; counts. The check for count <= 0 is done before we get here.
aad2444d 1634(define_insn_and_split "<code><mode>_base"
b4324a14
PK
1635 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1636 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1637 (match_operand:HI 2 "register_operand" "r,r")))
1638 (clobber (match_dup 2))]
2c9c2489 1639 ""
aad2444d
PK
1640 "#"
1641 "reload_completed"
1642 [(parallel [(set (match_dup 0) (SHF:QHSint (match_dup 1) (match_dup 2)))
1643 (clobber (match_dup 2))
1644 (clobber (reg:CC CC_REGNUM))])]
1645 ""
1646 [(set (attr "length")
1647 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
1648 <CODE>, which_alternative == 0)"))
1649 (set_attr "base_cost" "0")])
1650
1651(define_insn "<code><mode>_base_nocc"
1652 [(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
1653 (SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
1654 (match_operand:HI 2 "register_operand" "r,r")))
1655 (clobber (match_dup 2))
1656 (clobber (reg:CC CC_REGNUM))]
1657 "reload_completed"
b4324a14 1658 "* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
9cd1665b
PK
1659 [(set (attr "length")
1660 (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
aad2444d
PK
1661 <CODE>, which_alternative == 0)"))
1662 (set_attr "base_cost" "0")])
2c9c2489 1663
b4324a14
PK
1664;; Next the insns that use the extended instructions ash and ashc.
1665;; Note that these are just left shifts, and HI/SI only. (Right shifts
1666;; are done by shifting by a negative amount.)
aad2444d 1667(define_insn_and_split "aslhi_op"
b4324a14 1668 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
2c9c2489 1669 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
aad2444d 1670 (match_operand:HI 2 "general_operand" "rR,Qi")))]
b4324a14 1671 "TARGET_40_PLUS"
aad2444d
PK
1672 "#"
1673 "&& reload_completed"
1674 [(parallel [(set (match_dup 0)
1675 (ashift:HI (match_dup 1) (match_dup 2)))
1676 (clobber (reg:CC CC_REGNUM))])]
1677 ""
1678 [(set_attr "length" "2,4")
1679 (set_attr "base_cost" "8")])
1680
1681(define_insn "aslhi_op<cc_ccnz>"
1682 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
1683 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1684 (match_operand:HI 2 "general_operand" "rR,Qi")))
1685 (clobber (reg:CC CC_REGNUM))]
1686 "TARGET_40_PLUS && reload_completed"
4aef57c9 1687 "ash\t%2,%0"
aad2444d
PK
1688 [(set_attr "length" "2,4")
1689 (set_attr "base_cost" "8")])
2c9c2489 1690
aad2444d 1691(define_insn_and_split "aslsi_op"
b4324a14
PK
1692 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1693 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
aad2444d 1694 (match_operand:HI 2 "general_operand" "rR,Qi")))]
b4324a14 1695 "TARGET_40_PLUS"
aad2444d
PK
1696 "#"
1697 "&& reload_completed"
1698 [(parallel [(set (match_dup 0)
1699 (ashift:SI (match_dup 1) (match_dup 2)))
1700 (clobber (reg:CC CC_REGNUM))])]
1701 ""
1702 [(set_attr "length" "2,4")
1703 (set_attr "base_cost" "8")])
1704
1705(define_insn "aslsi_op_<cc_ccnz>"
1706 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
1707 (ashift:SI (match_operand:SI 1 "general_operand" "0,0")
1708 (match_operand:HI 2 "general_operand" "rR,Qi")))
1709 (clobber (reg:CC CC_REGNUM))]
1710 "TARGET_40_PLUS && reload_completed"
4aef57c9 1711 "ashc\t%2,%0"
aad2444d
PK
1712 [(set_attr "length" "2,4")
1713 (set_attr "base_cost" "8")])
e7f9979a 1714
b4324a14
PK
1715;; Now the expanders that produce the insns defined above.
1716(define_expand "ashl<mode>3"
1717 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1718 (match_operand:QHSint 1 "general_operand" "")
d5214afa
PK
1719 (match_operand:HI 2 "general_operand" "")]
1720 ""
1721 "
1722{
1723 rtx r;
1724
b4324a14 1725 if (!pdp11_expand_shift (operands, gen_ashift<mode>_sc, gen_ashift<mode>_base))
d5214afa 1726 {
b4324a14
PK
1727 if (<QHSint:e_mname> == E_QImode)
1728 {
1729 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1730 emit_insn (gen_aslhi_op (r, r, operands[2]));
1731 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1732 }
1733 else
1734 {
1735 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1736 }
d5214afa
PK
1737 }
1738 DONE;
b4324a14 1739}")
2c9c2489 1740
b4324a14
PK
1741(define_expand "ashr<mode>3"
1742 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1743 (match_operand:QHSint 1 "general_operand" "")
1744 (match_operand:HI 2 "general_operand" "")]
2c9c2489 1745 ""
b4324a14 1746 "
2c9c2489 1747{
b4324a14
PK
1748 rtx r;
1749
1750 if (!pdp11_expand_shift (operands, gen_ashiftrt<mode>_sc, gen_ashiftrt<mode>_base))
09b893bb 1751 {
b4324a14
PK
1752 operands[2] = negate_rtx (HImode, operands[2]);
1753 if (<QHSint:e_mname> == E_QImode)
1754 {
1755 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1756 emit_insn (gen_aslhi_op (r, r, operands[2]));
1757 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1758 }
1759 else
1760 {
1761 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], operands[1], operands[2]));
1762 }
09b893bb 1763 }
b4324a14 1764 DONE;
2c9c2489
RK
1765}")
1766
b4324a14
PK
1767(define_expand "lshr<mode>3"
1768 [(match_operand:QHSint 0 "nonimmediate_operand" "")
1769 (match_operand:QHSint 1 "general_operand" "")
d5214afa
PK
1770 (match_operand:HI 2 "general_operand" "")]
1771 ""
1772 "
1773{
b4324a14 1774 rtx r, n;
d5214afa 1775
b4324a14 1776 if (!pdp11_expand_shift (operands, gen_lshiftrt<mode>_sc, gen_lshiftrt<mode>_base))
d5214afa 1777 {
b4324a14
PK
1778 if (<QHSint:e_mname> == E_QImode)
1779 {
1780 r = copy_to_mode_reg (HImode, gen_rtx_ZERO_EXTEND (HImode, operands[1]));
1781 emit_insn (gen_aslhi_op (r, r, operands[2]));
1782 emit_insn (gen_movqi (operands[0], gen_rtx_SUBREG (QImode, r, 0)));
1783 }
1784 else
1785 {
1786 r = gen_reg_rtx (<QHSint:mname>);
1787 emit_insn (gen_lshiftrt<mode>_sc (r, operands[1], const1_rtx));
1788 if (GET_CODE (operands[2]) != CONST_INT)
1789 {
1790 n = gen_reg_rtx (HImode);
1791 emit_insn (gen_addhi3 (n, operands [2], GEN_INT (-1)));
1792 emit_insn (gen_ashr<mode>3 (operands[0], r, n));
1793 }
1794 else
1795 emit_insn (gen_asl<QHSint:hmode>_op (operands[0], r,
1796 GEN_INT (1 - INTVAL (operands[2]))));
1797 }
d5214afa
PK
1798 }
1799 DONE;
b4324a14 1800}")
2c9c2489
RK
1801
1802;; absolute
1803
b4324a14 1804(define_insn_and_split "absdf2"
166208c2 1805 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
2c9c2489
RK
1806 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1807 "TARGET_FPU"
b4324a14
PK
1808 "#"
1809 "&& reload_completed"
1810 [(parallel [(set (match_dup 0) (abs:DF (match_dup 1)))
1811 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
1812 ""
1813 [(set_attr "length" "2,4")])
b4324a14
PK
1814
1815(define_insn "absdf2<fcc_cc>"
1816 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1817 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))
1818 (clobber (reg:CC FCC_REGNUM))]
1819 "TARGET_FPU && reload_completed"
4aef57c9 1820 "{absd|absf}\t%0"
0f237806 1821 [(set_attr "length" "2,4")])
2c9c2489 1822
2c9c2489
RK
1823;; negate insns
1824
b4324a14
PK
1825(define_insn_and_split "negdf2"
1826 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1827 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
2c9c2489 1828 "TARGET_FPU"
b4324a14
PK
1829 "#"
1830 "&& reload_completed"
1831 [(parallel [(set (match_dup 0) (neg:DF (match_dup 1)))
1832 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
1833 ""
1834 [(set_attr "length" "2,4")])
b4324a14
PK
1835
1836(define_insn "negdf2<fcc_cc>"
1837 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
1838 (neg:DF (match_operand:DF 1 "general_operand" "0,0")))
1839 (clobber (reg:CC FCC_REGNUM))]
1840 "TARGET_FPU && reload_completed"
4aef57c9 1841 "{negd|negf}\t%0"
0f237806 1842 [(set_attr "length" "2,4")])
2c9c2489 1843
b4324a14 1844(define_insn_and_split "negdi2"
30442c59
PK
1845 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1846 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
e7f9979a 1847 ""
b4324a14
PK
1848 "#"
1849 "reload_completed"
1850 [(parallel [(set (match_dup 0) (neg:DI (match_dup 1)))
1851 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1852 ""
1853 [(set_attr "length" "18,34")])
b4324a14
PK
1854
1855;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1856(define_insn "negdi2_nocc"
1857 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1858 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))
1859 (clobber (reg:CC CC_REGNUM))]
1860 "reload_completed"
aad2444d 1861 {
442fcea7 1862 rtx inops[2];
aad2444d 1863 rtx exops[4][2];
442fcea7
PK
1864
1865 inops[0] = operands[0];
1866 pdp11_expand_operands (inops, exops, 1, 4, NULL, big);
30442c59 1867
aad2444d
PK
1868 output_asm_insn (\"com\t%0\", exops[3]);
1869 output_asm_insn (\"com\t%0\", exops[2]);
1870 output_asm_insn (\"com\t%0\", exops[1]);
1871 output_asm_insn (\"com\t%0\", exops[0]);
1872 output_asm_insn (\"add\t%#1,%0\", exops[3]);
1873 output_asm_insn (\"adc\t%0\", exops[2]);
1874 output_asm_insn (\"adc\t%0\", exops[1]);
1875 output_asm_insn (\"adc\t%0\", exops[0]);
1876
1877 return \"\";
1878 }
1879 [(set_attr "length" "18,34")
1880 (set_attr "base_cost" "0")])
e7f9979a 1881
b4324a14 1882(define_insn_and_split "negsi2"
30442c59
PK
1883 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1884 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1885 ""
b4324a14
PK
1886 "#"
1887 "reload_completed"
1888 [(parallel [(set (match_dup 0) (neg:SI (match_dup 1)))
1889 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1890 ""
1891 [(set_attr "length" "10,18")])
b4324a14
PK
1892
1893;; TODO: this can be neg/adc/neg/adc... I believe. Check. Saves one word.
1894(define_insn "negsi2_nocc"
1895 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1896 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))
1897 (clobber (reg:CC CC_REGNUM))]
1898 "reload_completed"
aad2444d 1899 {
442fcea7
PK
1900 rtx inops[2];
1901 rtx exops[4][2];
1902
1903 inops[0] = operands[0];
1904 pdp11_expand_operands (inops, exops, 1, 2, NULL, big);
30442c59 1905
aad2444d
PK
1906 output_asm_insn (\"com\t%0\", exops[1]);
1907 output_asm_insn (\"com\t%0\", exops[0]);
1908 output_asm_insn (\"add\t%#1,%0\", exops[1]);
1909 output_asm_insn (\"adc\t%0\", exops[0]);
1910
1911 return \"\";
1912 }
1913 [(set_attr "length" "10,18")
1914 (set_attr "base_cost" "0")])
e7f9979a 1915
b4324a14 1916(define_insn_and_split "neg<mode>2"
30442c59
PK
1917 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1918 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
2c9c2489 1919 ""
b4324a14
PK
1920 "#"
1921 "reload_completed"
1922 [(parallel [(set (match_dup 0) (neg:PDPint (match_dup 1)))
1923 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
1924 ""
1925 [(set_attr "length" "2,4")])
b4324a14
PK
1926
1927(define_insn "neg<mode>2<cc_ccnz>"
1928 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1929 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))
1930 (clobber (reg:CC CC_REGNUM))]
1931 ""
4aef57c9 1932 "neg<PDPint:isfx>\t%0"
0f237806 1933 [(set_attr "length" "2,4")])
2c9c2489
RK
1934
1935
1936;; Unconditional and other jump instructions
1937(define_insn "jump"
1938 [(set (pc)
1939 (label_ref (match_operand 0 "" "")))]
1940 ""
0f237806
PK
1941 "*
1942{
b4324a14 1943 if (get_attr_length (insn) == 2)
4aef57c9
PK
1944 return \"br\t%l0\";
1945 return \"jmp\t%l0\";
0f237806 1946}"
7021d5df 1947 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
0f237806 1948 (pc))
7021d5df
PK
1949 (const_int MIN_BRANCH))
1950 (gt (minus (match_dup 0)
0f237806 1951 (pc))
7021d5df 1952 (const_int MAX_BRANCH)))
0f237806
PK
1953 (const_int 4)
1954 (const_int 2)))])
2c9c2489 1955
2c9c2489 1956(define_insn "tablejump"
12eb6ed3 1957 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
2c9c2489
RK
1958 (use (label_ref (match_operand 1 "" "")))]
1959 ""
12eb6ed3 1960 "@
4aef57c9
PK
1961 jmp\t(%0)
1962 jmp\t%@%0
1963 jmp\t%@%0"
12eb6ed3 1964 [(set_attr "length" "2,2,4")])
2c9c2489 1965
b4324a14
PK
1966;; indirect jump. TODO: this needs a constraint that allows memory
1967;; references but not indirection, since we add a level of indirection
1968;; in the generated code.
2c9c2489 1969(define_insn "indirect_jump"
b4324a14 1970 [(set (pc) (match_operand:HI 0 "general_operand" "r"))]
2c9c2489 1971 ""
aad2444d 1972 "jmp\t@%0"
b4324a14 1973 [(set_attr "length" "2")])
2c9c2489
RK
1974
1975;;- jump to subroutine
1976
1977(define_insn "call"
e7f9979a 1978 [(call (match_operand:HI 0 "general_operand" "rR,Q")
b4324a14 1979 (match_operand:HI 1 "general_operand" "g,g"))]
2c9c2489
RK
1980 ;;- Don't use operand 1 for most machines.
1981 ""
aad2444d 1982 "jsr\tpc,%0"
0f237806 1983 [(set_attr "length" "2,4")])
2c9c2489
RK
1984
1985;;- jump to subroutine
1986(define_insn "call_value"
1987 [(set (match_operand 0 "" "")
e7f9979a 1988 (call (match_operand:HI 1 "general_operand" "rR,Q")
b4324a14 1989 (match_operand:HI 2 "general_operand" "g,g")))]
2c9c2489
RK
1990 ;;- Don't use operand 2 for most machines.
1991 ""
aad2444d 1992 "jsr\tpc,%1"
0f237806 1993 [(set_attr "length" "2,4")])
2c9c2489 1994
b4324a14
PK
1995(define_expand "untyped_call"
1996 [(parallel [(call (match_operand 0 "" "")
1997 (const_int 0))
1998 (match_operand 1 "" "")
1999 (match_operand 2 "" "")])]
2000 ""
2001{
2002 int i;
2003
2004 emit_call_insn (gen_call (operands[0], const0_rtx));
2005
2006 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2007 {
2008 rtx set = XVECEXP (operands[2], 0, i);
2009 emit_move_insn (SET_DEST (set), SET_SRC (set));
2010 }
2011
2012 /* The optimizer does not know that the call sets the function value
2013 registers we stored in the result block. We avoid problems by
2014 claiming that all hard registers are used and clobbered at this
2015 point. */
2016 emit_insn (gen_blockage ());
2017
2018 DONE;
2019})
2020
2c9c2489
RK
2021;;- nop instruction
2022(define_insn "nop"
2023 [(const_int 0)]
2024 ""
2025 "nop")
2026\f
2027
2028;;- multiply
2029
b4324a14 2030(define_insn_and_split "muldf3"
c67b2d4e
PK
2031 [(set (match_operand:DF 0 "register_operand" "=a,a")
2032 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
2033 (match_operand:DF 2 "float_operand" "fR,QF")))]
2c9c2489 2034 "TARGET_FPU"
b4324a14
PK
2035 "#"
2036 "&& reload_completed"
2037 [(parallel [(set (match_dup 0) (mult:DF (match_dup 1) (match_dup 2)))
2038 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
2039 ""
2040 [(set_attr "length" "2,4")])
b4324a14
PK
2041
2042(define_insn "muldf3<fcc_ccnz>"
2043 [(set (match_operand:DF 0 "register_operand" "=a,a")
2044 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
2045 (match_operand:DF 2 "float_operand" "fR,QF")))
2046 (clobber (reg:CC FCC_REGNUM))]
2047 "TARGET_FPU && reload_completed"
4aef57c9 2048 "{muld|mulf}\t%2,%0"
aad2444d
PK
2049 [(set_attr "length" "2,4")
2050 (set_attr "base_cost" "20")])
2c9c2489 2051
b4324a14 2052;; 16 bit result multiply. This uses odd numbered registers.
2c9c2489 2053
b4324a14 2054(define_insn_and_split "mulhi3"
2c9c2489
RK
2055 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
2056 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
b4324a14 2057 (match_operand:HI 2 "general_operand" "rR,Qi")))]
b56f8e7c 2058 "TARGET_40_PLUS"
b4324a14
PK
2059 "#"
2060 "&& reload_completed"
2061 [(parallel [(set (match_dup 0) (mult:HI (match_dup 1) (match_dup 2)))
2062 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
2063 ""
2064 [(set_attr "length" "2,4")])
b4324a14
PK
2065
2066(define_insn "mulhi3<cc_cc>"
2067 [(set (match_operand:HI 0 "register_operand" "=d,d")
2068 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
2069 (match_operand:HI 2 "general_operand" "rR,Qi")))
2070 (clobber (reg:CC CC_REGNUM))]
2071 "TARGET_40_PLUS && reload_completed"
4aef57c9 2072 "mul\t%2,%0"
aad2444d
PK
2073 [(set_attr "length" "2,4")
2074 (set_attr "base_cost" "20")])
2c9c2489 2075
b4324a14
PK
2076;; 32 bit result from 16 bit operands
2077(define_insn_and_split "mulhisi3"
2078 [(set (match_operand:SI 0 "register_operand" "=r,r")
2079 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
2080 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))]
b56f8e7c 2081 "TARGET_40_PLUS"
b4324a14
PK
2082 "#"
2083 "&& reload_completed"
2084 [(parallel [(set (match_dup 0)
2085 (mult:SI (sign_extend:SI (match_dup 1))
2086 (sign_extend:SI (match_dup 2))))
2087 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
2088 ""
2089 [(set_attr "length" "2,4")])
781e6f76 2090
b4324a14
PK
2091(define_insn "mulhisi3<cc_cc>"
2092 [(set (match_operand:SI 0 "register_operand" "=r,r")
2093 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,0"))
2094 (sign_extend:SI (match_operand:HI 2 "general_operand" "rR,Qi"))))
2095 (clobber (reg:CC CC_REGNUM))]
2096 "TARGET_40_PLUS && reload_completed"
4aef57c9 2097 "mul\t%2,%0"
aad2444d
PK
2098 [(set_attr "length" "2,4")
2099 (set_attr "base_cost" "20")])
2c9c2489
RK
2100
2101;;- divide
b4324a14 2102(define_insn_and_split "divdf3"
c67b2d4e
PK
2103 [(set (match_operand:DF 0 "register_operand" "=a,a")
2104 (div:DF (match_operand:DF 1 "register_operand" "0,0")
2105 (match_operand:DF 2 "general_operand" "fR,QF")))]
2c9c2489 2106 "TARGET_FPU"
b4324a14
PK
2107 "#"
2108 "&& reload_completed"
2109 [(parallel [(set (match_dup 0) (div:DF (match_dup 1) (match_dup 2)))
2110 (clobber (reg:CC FCC_REGNUM))])]
aad2444d
PK
2111 ""
2112 [(set_attr "length" "2,4")])
b4324a14
PK
2113
2114(define_insn "divdf3<fcc_ccnz>"
2115 [(set (match_operand:DF 0 "register_operand" "=a,a")
2116 (div:DF (match_operand:DF 1 "register_operand" "0,0")
2117 (match_operand:DF 2 "general_operand" "fR,QF")))
2118 (clobber (reg:CC FCC_REGNUM))]
2119 "TARGET_FPU && reload_completed"
4aef57c9 2120 "{divd|divf}\t%2,%0"
aad2444d
PK
2121 [(set_attr "length" "2,4")
2122 (set_attr "base_cost" "20")])
2c9c2489 2123
b4324a14
PK
2124(define_expand "divmodhi4"
2125 [(parallel
2126 [(set (subreg:HI (match_dup 1) 0)
8f808fc2 2127 (div:HI (match_operand:SI 1 "register_operand" "0")
0c253776 2128 (match_operand:HI 2 "general_operand" "g")))
b4324a14
PK
2129 (set (subreg:HI (match_dup 1) 2)
2130 (mod:HI (match_dup 1) (match_dup 2)))])
8f808fc2 2131 (set (match_operand:HI 0 "register_operand" "=r")
b4324a14
PK
2132 (subreg:HI (match_dup 1) 0))
2133 (set (match_operand:HI 3 "register_operand" "=r")
2134 (subreg:HI (match_dup 1) 2))]
b56f8e7c 2135 "TARGET_40_PLUS"
0c253776 2136 "")
2c9c2489 2137
b4324a14
PK
2138(define_insn_and_split "*divmodhi4"
2139 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
2140 (div:HI (match_operand:SI 1 "register_operand" "0,0")
2141 (match_operand:HI 2 "general_operand" "rR,Qi")))
2142 (set (subreg:HI (match_dup 1) 2)
2143 (mod:HI (match_dup 1) (match_dup 2)))]
b56f8e7c 2144 "TARGET_40_PLUS"
b4324a14
PK
2145 "#"
2146 "&& reload_completed"
2147 [(parallel [(set (subreg:HI (match_dup 0) 0)
2148 (div:HI (match_dup 1) (match_dup 2)))
2149 (set (subreg:HI (match_dup 1) 2)
2150 (mod:HI (match_dup 1) (match_dup 2)))
2151 (clobber (reg:CC CC_REGNUM))])]
aad2444d
PK
2152 ""
2153 [(set_attr "length" "2,4")])
2c9c2489 2154
b4324a14
PK
2155;; Note that there is no corresponding CC setter pattern.
2156;; The reason is that it won't be generated, because
e53b6e56 2157;; compare-elim.cc only does the transformation on input
b4324a14
PK
2158;; insns that have a two-element PARALLEL, as opposed to
2159;; the three-element one we have here.
2160(define_insn "divmodhi4_nocc"
2161 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r,r") 0)
2162 (div:HI (match_operand:SI 1 "register_operand" "0,0")
2163 (match_operand:HI 2 "general_operand" "rR,Qi")))
2164 (set (subreg:HI (match_dup 1) 2)
2165 (mod:HI (match_dup 1) (match_dup 2)))
2166 (clobber (reg:CC CC_REGNUM))]
b56f8e7c 2167 "TARGET_40_PLUS"
4aef57c9 2168 "div\t%2,%0"
aad2444d
PK
2169 [(set_attr "length" "2,4")
2170 (set_attr "base_cost" "40")])
2171
2172;; Byte swap
2173(define_insn_and_split "bswaphi2"
2174 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2175 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))]
2176 ""
2177 "#"
2178 "reload_completed"
2179 [(parallel [(set (match_dup 0) (bswap:HI (match_dup 1)))
2180 (clobber (reg:CC CC_REGNUM))])]
2181 ""
b4324a14 2182 [(set_attr "length" "2,4")])
aad2444d
PK
2183
2184(define_insn "bswaphi2<cc_ccnz>"
2185 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2186 (bswap:HI (match_operand:HI 1 "general_operand" "0,0")))
2187 (clobber (reg:CC CC_REGNUM))]
2188 ""
2189 "swab\t%0"
2190 [(set_attr "length" "2,4")])
2191
2192(define_insn_and_split "bswapsi2"
2193 [(set (match_operand:SI 0 "register_operand" "=&r")
2194 (bswap:SI (match_operand:SI 1 "general_operand" "g")))]
2195 ""
2196 "#"
2197 "reload_completed"
2198 [(parallel [(set (match_dup 0)
2199 (bswap:SI (match_dup 1)))
2200 (clobber (reg:CC CC_REGNUM))])]
2201 ""
2202 [(set_attr "length" "10")])
2203
2204(define_insn "bswapsi2_nocc"
2205 [(set (match_operand:SI 0 "register_operand" "=&r,&r,&r")
2206 (bswap:SI (match_operand:SI 1 "general_operand" "r,D,Q")))
2207 (clobber (reg:CC CC_REGNUM))]
2208 ""
2209 {
442fcea7 2210 rtx inops[2];
aad2444d
PK
2211 rtx exops[2][2];
2212 rtx t;
442fcea7
PK
2213
2214 inops[0] = operands[0];
2215 inops[1] = operands[1];
2216 pdp11_expand_operands (inops, exops, 2, 2, NULL, either);
aad2444d
PK
2217
2218 t = exops[0][0];
2219 exops[0][0] = exops[1][0];
2220 exops[1][0] = t;
2221
2222 output_asm_insn ("mov\t%0,%1", exops[0]);
2223 output_asm_insn ("mov\t%0,%1", exops[1]);
2224 output_asm_insn ("swab\t%0", exops[0]);
2225 output_asm_insn ("swab\t%0", exops[1]);
2226 return "";
2227 }
2228 [(set_attr "length" "8,10,12")])
2229
2230(define_expand "rotrhi3"
2231 [(match_operand:HI 0 "register_operand" "")
2232 (match_operand:HI 1 "register_operand" "")
2233 (match_operand:HI 2 "general_operand" "")]
2234 "TARGET_40_PLUS"
2235 "
2236{
2237 operands[2] = negate_rtx (HImode, operands[2]);
2238 emit_insn (gen_rotlhi3 (operands[0], operands[1], operands[2]));
2239 DONE;
2240}")
2241
2242(define_insn_and_split "rotlhi3"
2243 [(set (match_operand:HI 0 "register_operand" "=d,d")
2244 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2245 (match_operand:HI 2 "general_operand" "rR,Qi")))]
2246 "TARGET_40_PLUS"
2247 "#"
2248 "&& reload_completed"
2249 [(parallel [(set (match_dup 0)
2250 (rotate:HI (match_dup 1) (match_dup 2)))
2251 (clobber (reg:CC CC_REGNUM))])]
2252 ""
2253 [(set_attr "length" "2,4")
2254 (set_attr "base_cost" "8")])
2255
2256(define_insn "rotlhi3<cc_ccnz>"
2257 [(set (match_operand:HI 0 "register_operand" "=d,d")
2258 (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
2259 (match_operand:HI 2 "general_operand" "rR,Qi")))
2260 (clobber (reg:CC CC_REGNUM))]
2261 "TARGET_40_PLUS && reload_completed"
2262 "ashc\t%2,%0"
2263 [(set_attr "length" "2,4")
2264 (set_attr "base_cost" "8")])
2265
2266
2267
2268;; Some peephole optimizations
2269
2270;; Move then conditional branch on the result of the move is handled
2271;; by compare elimination, but an earlier pass sometimes changes the
2272;; compare operand to the move input, and then the compare is not
2273;; eliminated. Do so here.
2274(define_peephole2
2275 [(parallel [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
2276 (match_operand:PDPint 1 "general_operand" ""))
2277 (clobber (reg:CC CC_REGNUM))])
2278 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))]
2279 ""
2280 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
2281 (set (match_dup 0) (match_dup 1))])]
2282 "")