]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/pdp11/pdp11.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.md
CommitLineData
2c9c2489 1;;- Machine description for the pdp11 for GNU C compiler
818ab71a 2;; Copyright (C) 1994-2016 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
29 ])
30
7021d5df
PK
31(define_constants
32 [
33 ;; Register numbers
58dd8e86 34 (R0_REGNUM 0)
a01c666c 35 (RETVAL_REGNUM 0)
58dd8e86 36 (HARD_FRAME_POINTER_REGNUM 5)
7021d5df
PK
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)
58dd8e86
PK
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 (FIRST_PSEUDO_REGISTER 16)
7021d5df
PK
48 ;; Branch offset limits, as byte offsets from instruction address
49 (MIN_BRANCH -254)
50 (MAX_BRANCH 256)
51 (MIN_SOB -126)
52 (MAX_SOB 0)])
2c9c2489
RK
53
54;; HI is 16 bit
55;; QI is 8 bit
56
9546fe6a
PK
57;; Integer modes supported on the PDP11, with a mapping from machine mode
58;; to mnemonic suffix. SImode and DImode always are special cases.
59(define_mode_iterator PDPint [QI HI])
60(define_mode_attr isfx [(QI "b") (HI "")])
61
2c9c2489
RK
62;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
63
64;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
65;;- updates for most instructions.
66
67;;- Operand classes for the register allocator:
68\f
69;; Compare instructions.
70
71;; currently we only support df floats, which saves us quite some
72;; hassle switching the FP mode!
73;; we assume that CPU is always in long float mode, and
74;; 16 bit integer mode - currently, the prologue for main does this,
75;; but maybe we should just set up a NEW crt0 properly,
76;; -- and what about signal handling code?
77;; (we don't even let sf floats in the register file, so
78;; we only should have to worry about truncating and widening
79;; when going to memory)
80
81;; abort() call by g++ - must define libfunc for cmp_optab
82;; and ucmp_optab for mode SImode, because we don't have that!!!
83;; - yet since no libfunc is there, we abort ()
84
85;; The only thing that remains to be done then is output
86;; the floats in a way the assembler can handle it (and
87;; if you're really into it, use a PDP11 float emulation
3a598fbe 88;; library to do floating point constant folding - but
2c9c2489
RK
89;; I guess you'll get reasonable results even when not
90;; doing this)
91;; the last thing to do is fix the UPDATE_CC macro to check
92;; for floating point condition codes, and set cc_status
93;; properly, also setting the CC_IN_FCCR flag.
94
95;; define attributes
96;; currently type is only fpu or arith or unknown, maybe branch later ?
97;; default is arith
98(define_attr "type" "unknown,arith,fp" (const_string "arith"))
99
0f237806
PK
100;; length default is 2 bytes each
101(define_attr "length" "" (const_int 2))
2c9c2489 102
ddd5a7c1 103;; a user's asm statement
2c9c2489
RK
104(define_asm_attributes
105 [(set_attr "type" "unknown")
0f237806 106; length for asm is the max length per statement. That would be
c67b2d4e
PK
107; 3 words, for a two-operand instruction with extra word addressing
108; modes for both operands.
109 (set_attr "length" "6")])
2c9c2489
RK
110
111;; define function units
112
8662b2ba
RH
113;; Prologue and epilogue support.
114
115(define_expand "prologue"
116 [(const_int 0)]
117 ""
118{
119 pdp11_expand_prologue ();
120 DONE;
121})
122
123(define_expand "epilogue"
124 [(const_int 0)]
125 ""
126{
127 pdp11_expand_epilogue ();
128 DONE;
129})
130
131(define_expand "return"
132 [(return)]
133 "reload_completed && !frame_pointer_needed && pdp11_sp_frame_offset () == 0"
134 "")
135
136(define_insn "*rts"
137 [(return)]
138 ""
139 "rts pc")
140
141(define_insn "blockage"
142 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
143 ""
144 ""
145 [(set_attr "length" "0")])
146
147(define_insn "setd"
148 [(unspec_volatile [(const_int 0)] UNSPECV_SETD)]
149 ""
150 "setd")
151
152(define_insn "seti"
153 [(unspec_volatile [(const_int 0)] UNSPECV_SETI)]
154 ""
155 "seti")
156
2c9c2489
RK
157;; arithmetic - values here immediately when next insn issued
158;; or does it mean the number of cycles after this insn was issued?
159;; how do I say that fpu insns use cpu also? (pre-interaction phase)
160
161;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
162;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
163
164;; compare
f90b7a5a 165(define_insn "*cmpdf"
2c9c2489 166 [(set (cc0)
c67b2d4e
PK
167 (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,QF")
168 (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a")))]
2c9c2489
RK
169 "TARGET_FPU"
170 "*
171{
172 cc_status.flags = CC_IN_FPU;
f90b7a5a 173 if (which_alternative == 0 || which_alternative == 2)
825cb171 174 return \"{tstd|tstf} %0\;cfcc\";
f90b7a5a
PB
175 else
176 return \"{cmpd|cmpf} %0, %1\;cfcc\";
2c9c2489 177}"
c67b2d4e 178 [(set_attr "length" "4,4,6,6")])
2c9c2489 179
63caf8bb 180(define_insn "*cmp<mode>"
2c9c2489 181 [(set (cc0)
63caf8bb
PK
182 (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
183 (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
2c9c2489 184 ""
f90b7a5a 185 "@
63caf8bb
PK
186 tst<PDPint:isfx> %0
187 cmp<PDPint:isfx> %0,%1
188 cmp<PDPint:isfx> %0,%1
189 tst<PDPint:isfx> %0
190 cmp<PDPint:isfx> %0,%1
191 cmp<PDPint:isfx> %0,%1"
0f237806 192 [(set_attr "length" "2,2,4,4,4,6")])
f90b7a5a 193
2c9c2489
RK
194;; sob instruction - we need an assembler which can make this instruction
195;; valid under _all_ circumstances!
196
197(define_insn ""
198 [(set (pc)
199 (if_then_else
997718c7 200 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
2c9c2489
RK
201 (const_int -1))
202 (const_int 0))
203 (label_ref (match_operand 1 "" ""))
204 (pc)))
205 (set (match_dup 0)
206 (plus:HI (match_dup 0)
207 (const_int -1)))]
208 "TARGET_40_PLUS"
209 "*
210{
211 static int labelcount = 0;
212 static char buf[1000];
213
0f237806 214 if (get_attr_length (insn) == 2)
2c9c2489
RK
215 return \"sob %0, %l1\";
216
217 /* emulate sob */
218 output_asm_insn (\"dec %0\", operands);
219
220 sprintf (buf, \"bge LONG_SOB%d\", labelcount);
221 output_asm_insn (buf, NULL);
222
223 output_asm_insn (\"jmp %l1\", operands);
224
225 sprintf (buf, \"LONG_SOB%d:\", labelcount++);
226 output_asm_insn (buf, NULL);
227
228 return \"\";
229}"
7021d5df 230 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
2c9c2489 231 (pc))
7021d5df
PK
232 (const_int MIN_SOB))
233 (gt (minus (match_dup 0)
2c9c2489 234 (pc))
7021d5df 235 (const_int MAX_SOB)))
0f237806
PK
236 (const_int 8)
237 (const_int 2)))])
2c9c2489
RK
238
239;; These control RTL generation for conditional jump insns
240;; and match them for register allocation.
241
f90b7a5a
PB
242(define_expand "cbranchdf4"
243 [(set (cc0)
244 (compare (match_operand:DF 1 "general_operand")
a01c666c 245 (match_operand:DF 2 "register_or_const0_operand")))
f90b7a5a
PB
246 (set (pc)
247 (if_then_else (match_operator 0 "ordered_comparison_operator"
248 [(cc0) (const_int 0)])
249 (label_ref (match_operand 3 "" ""))
2c9c2489 250 (pc)))]
825cb171 251 "TARGET_FPU"
f90b7a5a 252 "")
2c9c2489 253
63caf8bb 254(define_expand "cbranch<mode>4"
f90b7a5a 255 [(set (cc0)
63caf8bb
PK
256 (compare (match_operand:PDPint 1 "general_operand")
257 (match_operand:PDPint 2 "general_operand")))
f90b7a5a
PB
258 (set (pc)
259 (if_then_else (match_operator 0 "ordered_comparison_operator"
260 [(cc0) (const_int 0)])
261 (label_ref (match_operand 3 "" ""))
2c9c2489
RK
262 (pc)))]
263 ""
f90b7a5a 264 "")
2c9c2489 265
f90b7a5a
PB
266;; problem with too short jump distance! we need an assembler which can
267;; make this valid for all jump distances!
268;; e.g. gas!
2c9c2489 269
f90b7a5a
PB
270;; these must be changed to check for CC_IN_FCCR if float is to be
271;; enabled
2c9c2489 272
f90b7a5a 273(define_insn "*branch"
2c9c2489 274 [(set (pc)
f90b7a5a
PB
275 (if_then_else (match_operator 0 "ordered_comparison_operator"
276 [(cc0) (const_int 0)])
277 (label_ref (match_operand 1 "" ""))
2c9c2489
RK
278 (pc)))]
279 ""
f90b7a5a 280 "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
7021d5df 281 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
2c9c2489 282 (pc))
7021d5df
PK
283 (const_int MIN_BRANCH))
284 (gt (minus (match_dup 1)
2c9c2489 285 (pc))
7021d5df 286 (const_int MAX_BRANCH)))
0f237806
PK
287 (const_int 6)
288 (const_int 2)))])
2c9c2489 289
2c9c2489 290
2c9c2489
RK
291;; These match inverted jump insns for register allocation.
292
f90b7a5a 293(define_insn "*branch_inverted"
2c9c2489 294 [(set (pc)
f90b7a5a
PB
295 (if_then_else (match_operator 0 "ordered_comparison_operator"
296 [(cc0) (const_int 0)])
2c9c2489 297 (pc)
f90b7a5a 298 (label_ref (match_operand 1 "" ""))))]
2c9c2489 299 ""
f90b7a5a 300 "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
7021d5df 301 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
2c9c2489 302 (pc))
7021d5df
PK
303 (const_int MIN_BRANCH))
304 (gt (minus (match_dup 1)
2c9c2489 305 (pc))
7021d5df 306 (const_int MAX_BRANCH)))
0f237806
PK
307 (const_int 6)
308 (const_int 2)))])
2c9c2489
RK
309\f
310;; Move instructions
311
312(define_insn "movdi"
30442c59
PK
313 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,g")
314 (match_operand:DI 1 "general_operand" "rN,g"))]
2c9c2489 315 ""
30442c59 316 "* return output_move_multiple (operands);"
2c9c2489 317;; what's the mose expensive code - say twice movsi = 16
30442c59 318 [(set_attr "length" "16,32")])
2c9c2489
RK
319
320(define_insn "movsi"
30442c59
PK
321 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,g,g")
322 (match_operand:SI 1 "general_operand" "rN,IJ,IJ,g"))]
2c9c2489 323 ""
30442c59 324 "* return output_move_multiple (operands);"
2c9c2489
RK
325;; what's the most expensive code ? - I think 8!
326;; we could split it up and make several sub-cases...
30442c59 327 [(set_attr "length" "4,6,8,16")])
2c9c2489 328
63caf8bb
PK
329(define_insn "mov<mode>"
330 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
331 (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
2c9c2489
RK
332 ""
333 "*
334{
335 if (operands[1] == const0_rtx)
63caf8bb 336 return \"clr<PDPint:isfx> %0\";
2c9c2489 337
63caf8bb 338 return \"mov<PDPint:isfx> %1, %0\";
2c9c2489 339}"
0f237806 340 [(set_attr "length" "2,4,4,6")])
2c9c2489 341
2c9c2489 342(define_insn "movdf"
166208c2 343 [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
c67b2d4e 344 (match_operand:DF 1 "float_operand" "fR,a,FQ,a,g"))]
825cb171
PK
345 "TARGET_FPU"
346 "* if (which_alternative ==0 || which_alternative == 2)
e7f9979a 347 return \"ldd %1, %0\";
825cb171 348 else if (which_alternative == 1 || which_alternative == 3)
e7f9979a
NS
349 return \"std %1, %0\";
350 else
30442c59 351 return output_move_multiple (operands); "
c67b2d4e
PK
352;; last one is worst-case
353 [(set_attr "length" "2,2,4,4,24")])
2c9c2489
RK
354
355(define_insn "movsf"
166208c2 356 [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
c67b2d4e 357 (match_operand:SF 1 "float_operand" "fR,a,FQ,a,g"))]
2c9c2489 358 "TARGET_FPU"
a01c666c
PK
359 "* if (which_alternative ==0 || which_alternative == 2)
360 return \"{ldcfd|movof} %1, %0\";
361 else if (which_alternative == 1 || which_alternative == 3)
362 return \"{stcdf|movfo} %1, %0\";
363 else
30442c59 364 return output_move_multiple (operands); "
c67b2d4e
PK
365;; last one is worst-case
366 [(set_attr "length" "2,2,4,4,12")])
2c9c2489
RK
367
368;; maybe fiddle a bit with move_ratio, then
ddd5a7c1 369;; let constraints only accept a register ...
2c9c2489 370
70128ad9 371(define_expand "movmemhi"
3a598fbe
JL
372 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
373 (match_operand:BLK 1 "general_operand" "g,g"))
dea44e56 374 (use (match_operand:HI 2 "general_operand" "n,mr"))
2c9c2489
RK
375 (use (match_operand:HI 3 "immediate_operand" "i,i"))
376 (clobber (match_scratch:HI 4 "=&r,X"))
3a598fbe
JL
377 (clobber (match_dup 5))
378 (clobber (match_dup 6))
2c9c2489
RK
379 (clobber (match_dup 2))])]
380 "(TARGET_BCOPY_BUILTIN)"
381 "
382{
3a598fbe 383 operands[0]
792760b9
RK
384 = replace_equiv_address (operands[0],
385 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
3a598fbe 386 operands[1]
792760b9
RK
387 = replace_equiv_address (operands[1],
388 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
3a598fbe
JL
389
390 operands[5] = XEXP (operands[0], 0);
391 operands[6] = XEXP (operands[1], 0);
2c9c2489
RK
392}")
393
394
dea44e56
PK
395(define_insn "movmemhi1"
396 [(set (mem:BLK (match_operand:HI 0 "register_operand" "r,r"))
397 (mem:BLK (match_operand:HI 1 "register_operand" "r,r")))
398 (use (match_operand:HI 2 "general_operand" "n,r"))
2c9c2489
RK
399 (use (match_operand:HI 3 "immediate_operand" "i,i"))
400 (clobber (match_scratch:HI 4 "=&r,X"))
401 (clobber (match_dup 0))
402 (clobber (match_dup 1))
403 (clobber (match_dup 2))]
404 "(TARGET_BCOPY_BUILTIN)"
405 "* return output_block_move (operands);"
406;;; just a guess
0f237806 407 [(set_attr "length" "80")])
2c9c2489
RK
408
409
410\f
411;;- truncation instructions
412
413(define_insn "truncdfsf2"
166208c2 414 [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
a01c666c 415 (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
2c9c2489 416 "TARGET_FPU"
e3be1b32
RK
417 "* if (which_alternative ==0)
418 {
e3be1b32
RK
419 return \"\";
420 }
421 else if (which_alternative == 1)
af36a4d2 422 return \"{stcdf|movfo} %1, %0\";
e3be1b32 423 else
af36a4d2 424 return \"{stcdf|movfo} %1, %0\";
e3be1b32 425 "
a01c666c 426 [(set_attr "length" "0,2,4")])
e3be1b32 427
2c9c2489
RK
428
429(define_expand "truncsihi2"
166208c2 430 [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
2c9c2489
RK
431 (subreg:HI
432 (match_operand:SI 1 "general_operand" "or")
433 0))]
434 ""
435 "")
436
437\f
438;;- zero extension instructions
439
440(define_insn "zero_extendqihi2"
166208c2 441 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
0f237806 442 (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
2c9c2489 443 ""
e7f9979a 444 "bic $0177400, %0"
0f237806 445 [(set_attr "length" "4,6")])
2c9c2489
RK
446
447(define_expand "zero_extendhisi2"
448 [(set (subreg:HI
449 (match_dup 0)
ddef6bc7 450 2)
2c9c2489
RK
451 (match_operand:HI 1 "register_operand" "r"))
452 (set (subreg:HI
453 (match_operand:SI 0 "register_operand" "=r")
454 0)
455 (const_int 0))]
456 ""
457 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
458
459\f
460;;- sign extension instructions
461
462(define_insn "extendsfdf2"
a01c666c 463 [(set (match_operand:DF 0 "register_operand" "=f,a,a")
166208c2 464 (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
2c9c2489 465 "TARGET_FPU"
e3be1b32 466 "@
a01c666c 467 /* nothing */
af36a4d2
JM
468 {ldcfd|movof} %1, %0
469 {ldcfd|movof} %1, %0"
a01c666c 470 [(set_attr "length" "0,2,4")])
2c9c2489
RK
471
472;; does movb sign extend in register-to-register move?
473(define_insn "extendqihi2"
474 [(set (match_operand:HI 0 "register_operand" "=r,r")
475 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
476 ""
477 "movb %1, %0"
0f237806 478 [(set_attr "length" "2,4")])
2c9c2489
RK
479
480(define_insn "extendqisi2"
481 [(set (match_operand:SI 0 "register_operand" "=r,r")
482 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
483 "TARGET_40_PLUS"
484 "*
485{
486 rtx latehalf[2];
487
488 /* make register pair available */
489 latehalf[0] = operands[0];
c5c76735
JL
490 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
491
2c9c2489
RK
492 output_asm_insn(\"movb %1, %0\", operands);
493 output_asm_insn(\"sxt %0\", latehalf);
494
495 return \"\";
496}"
0f237806 497 [(set_attr "length" "4,6")])
2c9c2489
RK
498
499;; maybe we have to use define_expand to say that we have the instruction,
500;; unconditionally, and then match dependent on CPU type:
501
502(define_expand "extendhisi2"
166208c2 503 [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
2c9c2489
RK
504 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
505 ""
506 "")
507
508(define_insn "" ; "extendhisi2"
166208c2 509 [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
2c9c2489
RK
510 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
511 "TARGET_40_PLUS"
512 "*
513{
514 rtx latehalf[2];
515
516 /* we don't want to mess with auto increment */
517
b72f00af 518 switch (which_alternative)
2c9c2489
RK
519 {
520 case 0:
521
522 latehalf[0] = operands[0];
b72f00af 523 operands[0] = adjust_address(operands[0], HImode, 2);
2c9c2489
RK
524
525 output_asm_insn(\"mov %1, %0\", operands);
526 output_asm_insn(\"sxt %0\", latehalf);
527
528 return \"\";
529
530 case 1:
531
532 /* - auto-decrement - right direction ;-) */
533 output_asm_insn(\"mov %1, %0\", operands);
534 output_asm_insn(\"sxt %0\", operands);
535
536 return \"\";
537
538 case 2:
539
540 /* make register pair available */
541 latehalf[0] = operands[0];
c5c76735 542 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
2c9c2489
RK
543
544 output_asm_insn(\"mov %1, %0\", operands);
545 output_asm_insn(\"sxt %0\", latehalf);
546
547 return \"\";
548
549 default:
550
d35d9223 551 gcc_unreachable ();
2c9c2489
RK
552 }
553}"
0f237806 554 [(set_attr "length" "10,6,6")])
2c9c2489
RK
555
556
557(define_insn ""
558 [(set (match_operand:SI 0 "register_operand" "=r")
559 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
560 "(! TARGET_40_PLUS)"
561 "*
562{
09b893bb 563 static int count = 0;
2c9c2489
RK
564 char buf[100];
565 rtx lateoperands[2];
566
567 lateoperands[0] = operands[0];
c5c76735 568 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
2c9c2489
RK
569
570 output_asm_insn(\"tst %0\", operands);
571 sprintf(buf, \"bge extendhisi%d\", count);
572 output_asm_insn(buf, NULL);
573 output_asm_insn(\"mov -1, %0\", lateoperands);
574 sprintf(buf, \"bne extendhisi%d\", count+1);
575 output_asm_insn(buf, NULL);
576 sprintf(buf, \"\\nextendhisi%d:\", count);
577 output_asm_insn(buf, NULL);
578 output_asm_insn(\"clr %0\", lateoperands);
579 sprintf(buf, \"\\nextendhisi%d:\", count+1);
580 output_asm_insn(buf, NULL);
581
582 count += 2;
583
584 return \"\";
585}"
0f237806 586 [(set_attr "length" "12")])
2c9c2489
RK
587
588;; make float to int and vice versa
ddd5a7c1 589;; using the cc_status.flag field we could probably cut down
2c9c2489
RK
590;; on seti and setl
591;; assume that we are normally in double and integer mode -
592;; what do pdp library routines do to fpu mode ?
593
594(define_insn "floatsidf2"
e3be1b32
RK
595 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
596 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
2c9c2489 597 "TARGET_FPU"
e3be1b32
RK
598 "* if (which_alternative ==0)
599 {
600 rtx latehalf[2];
601
602 latehalf[0] = NULL;
e7f9979a 603 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
e3be1b32
RK
604 output_asm_insn(\"mov %1, -(sp)\", latehalf);
605 output_asm_insn(\"mov %1, -(sp)\", operands);
606
607 output_asm_insn(\"setl\", operands);
af36a4d2 608 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
e3be1b32
RK
609 output_asm_insn(\"seti\", operands);
610 return \"\";
611 }
612 else if (which_alternative == 1)
af36a4d2 613 return \"setl\;{ldcld|movif} %1, %0\;seti\";
e3be1b32 614 else
af36a4d2 615 return \"setl\;{ldcld|movif} %1, %0\;seti\";
e3be1b32 616 "
0f237806 617 [(set_attr "length" "10,6,8")])
2c9c2489
RK
618
619(define_insn "floathidf2"
620 [(set (match_operand:DF 0 "register_operand" "=a,a")
621 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
622 "TARGET_FPU"
af36a4d2 623 "{ldcid|movif} %1, %0"
0f237806 624 [(set_attr "length" "2,4")])
2c9c2489
RK
625
626;; cut float to int
627(define_insn "fix_truncdfsi2"
166208c2 628 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
e3be1b32 629 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
2c9c2489 630 "TARGET_FPU"
e3be1b32
RK
631 "* if (which_alternative ==0)
632 {
633 output_asm_insn(\"setl\", operands);
af36a4d2 634 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
e3be1b32
RK
635 output_asm_insn(\"seti\", operands);
636 output_asm_insn(\"mov (sp)+, %0\", operands);
c5c76735 637 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
e3be1b32
RK
638 output_asm_insn(\"mov (sp)+, %0\", operands);
639 return \"\";
640 }
641 else if (which_alternative == 1)
af36a4d2 642 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
e3be1b32 643 else
af36a4d2 644 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
e3be1b32 645 "
0f237806 646 [(set_attr "length" "10,6,8")])
2c9c2489
RK
647
648(define_insn "fix_truncdfhi2"
166208c2 649 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2c9c2489
RK
650 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
651 "TARGET_FPU"
af36a4d2 652 "{stcdi|movfi} %1, %0"
0f237806 653 [(set_attr "length" "2,4")])
2c9c2489
RK
654
655\f
656;;- arithmetic instructions
657;;- add instructions
658
659(define_insn "adddf3"
c67b2d4e
PK
660 [(set (match_operand:DF 0 "register_operand" "=a,a")
661 (plus:DF (match_operand:DF 1 "register_operand" "%0,0")
662 (match_operand:DF 2 "general_operand" "fR,QF")))]
2c9c2489 663 "TARGET_FPU"
af36a4d2 664 "{addd|addf} %2, %0"
c67b2d4e 665 [(set_attr "length" "2,4")])
2c9c2489 666
30442c59
PK
667(define_insn "adddi3"
668 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
669 (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
670 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
2c9c2489
RK
671 ""
672 "*
30442c59
PK
673{
674 rtx inops[2];
675 rtx exops[4][2];
2c9c2489 676
30442c59
PK
677 inops[0] = operands[0];
678 inops[1] = operands[2];
679 pdp11_expand_operands (inops, exops, 2, NULL, either);
2c9c2489 680
30442c59
PK
681 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
682 output_asm_insn (\"add %1, %0\", exops[0]);
683 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
2c9c2489 684 {
30442c59
PK
685 output_asm_insn (\"add %1, %0\", exops[1]);
686 output_asm_insn (\"adc %0\", exops[0]);
687 }
688 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
689 {
690 output_asm_insn (\"add %1, %0\", exops[2]);
691 output_asm_insn (\"adc %0\", exops[1]);
692 output_asm_insn (\"adc %0\", exops[0]);
693 }
694 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
695 {
696 output_asm_insn (\"add %1, %0\", exops[3]);
697 output_asm_insn (\"adc %0\", exops[2]);
698 output_asm_insn (\"adc %0\", exops[1]);
699 output_asm_insn (\"adc %0\", exops[0]);
2c9c2489
RK
700 }
701
30442c59
PK
702 return \"\";
703}"
704 [(set_attr "length" "20,28,40,48")])
705
706;; Note that the register operand is not marked earlyclobber.
707;; The reason is that SI values go in register pairs, so they
708;; can't partially overlap. They can be either disjoint, or
709;; source and destination can be equal. The latter case is
710;; handled properly because of the ordering of the individual
711;; instructions used. Specifically, carry from the low to the
712;; high word is added at the end, so the adding of the high parts
713;; will always used the original high part and not a high part
714;; modified by carry (which would amount to double carry).
715(define_insn "addsi3"
716 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
717 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0")
718 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
719 ""
720 "*
721{
722 rtx inops[2];
723 rtx exops[2][2];
2c9c2489 724
30442c59
PK
725 inops[0] = operands[0];
726 inops[1] = operands[2];
727 pdp11_expand_operands (inops, exops, 2, NULL, either);
728
729 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
730 output_asm_insn (\"add %1, %0\", exops[0]);
731 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
732 {
733 output_asm_insn (\"add %1, %0\", exops[1]);
734 output_asm_insn (\"adc %0\", exops[0]);
2c9c2489
RK
735 }
736
2c9c2489
RK
737 return \"\";
738}"
30442c59 739 [(set_attr "length" "6,10,12,16")])
2c9c2489
RK
740
741(define_insn "addhi3"
166208c2 742 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
2c9c2489
RK
743 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
744 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
745 ""
746 "*
747{
748 if (GET_CODE (operands[2]) == CONST_INT)
09b893bb
JM
749 {
750 if (INTVAL(operands[2]) == 1)
751 return \"inc %0\";
752 else if (INTVAL(operands[2]) == -1)
753 return \"dec %0\";
754 }
2c9c2489
RK
755
756 return \"add %2, %0\";
757}"
0f237806 758 [(set_attr "length" "2,4,4,6")])
2c9c2489 759
2c9c2489
RK
760\f
761;;- subtract instructions
762;; we don't have to care for constant second
ddd5a7c1 763;; args, since they are canonical plus:xx now!
2c9c2489
RK
764;; also for minus:DF ??
765
766(define_insn "subdf3"
767 [(set (match_operand:DF 0 "register_operand" "=a,a")
768 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
769 (match_operand:DF 2 "general_operand" "fR,Q")))]
770 "TARGET_FPU"
af36a4d2 771 "{subd|subf} %2, %0"
0f237806 772 [(set_attr "length" "2,4")])
2c9c2489 773
30442c59
PK
774(define_insn "subdi3"
775 [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,o")
776 (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
777 (match_operand:DI 2 "general_operand" "r,on,r,on")))]
2c9c2489
RK
778 ""
779 "*
30442c59
PK
780{
781 rtx inops[2];
782 rtx exops[4][2];
783
784 inops[0] = operands[0];
785 inops[1] = operands[2];
786 pdp11_expand_operands (inops, exops, 2, NULL, either);
787
788 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
789 output_asm_insn (\"sub %1, %0\", exops[0]);
790 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
791 {
792 output_asm_insn (\"sub %1, %0\", exops[1]);
793 output_asm_insn (\"sbc %0\", exops[0]);
794 }
795 if (!CONSTANT_P (exops[2][1]) || INTVAL (exops[2][1]) != 0)
796 {
797 output_asm_insn (\"sub %1, %0\", exops[2]);
798 output_asm_insn (\"sbc %0\", exops[1]);
799 output_asm_insn (\"sbc %0\", exops[0]);
800 }
801 if (!CONSTANT_P (exops[3][1]) || INTVAL (exops[3][1]) != 0)
802 {
803 output_asm_insn (\"sub %1, %0\", exops[3]);
804 output_asm_insn (\"sbc %0\", exops[2]);
805 output_asm_insn (\"sbc %0\", exops[1]);
806 output_asm_insn (\"sbc %0\", exops[0]);
807 }
2c9c2489 808
30442c59
PK
809 return \"\";
810}"
811 [(set_attr "length" "20,28,40,48")])
2c9c2489 812
30442c59
PK
813(define_insn "subsi3"
814 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
815 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
816 (match_operand:SI 2 "general_operand" "r,on,r,on")))]
817 ""
818 "*
819{
820 rtx inops[2];
821 rtx exops[2][2];
2c9c2489 822
30442c59
PK
823 inops[0] = operands[0];
824 inops[1] = operands[2];
825 pdp11_expand_operands (inops, exops, 2, NULL, either);
2c9c2489 826
30442c59
PK
827 if (!CONSTANT_P (exops[0][1]) || INTVAL (exops[0][1]) != 0)
828 output_asm_insn (\"sub %1, %0\", exops[0]);
829 if (!CONSTANT_P (exops[1][1]) || INTVAL (exops[1][1]) != 0)
830 {
831 output_asm_insn (\"sub %1, %0\", exops[1]);
832 output_asm_insn (\"sbc %0\", exops[0]);
833 }
2c9c2489 834
2c9c2489
RK
835 return \"\";
836}"
0f237806 837 [(set_attr "length" "6,10,12,16")])
2c9c2489
RK
838
839(define_insn "subhi3"
166208c2 840 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
2c9c2489
RK
841 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
842 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
843 ""
844 "*
845{
d35d9223 846 gcc_assert (GET_CODE (operands[2]) != CONST_INT);
2c9c2489
RK
847
848 return \"sub %2, %0\";
849}"
0f237806 850 [(set_attr "length" "2,4,4,6")])
2c9c2489 851
2c9c2489 852;;;;- and instructions
8aeea6e6 853;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
2c9c2489 854
9546fe6a 855(define_expand "and<mode>3"
166208c2 856 [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
9546fe6a
PK
857 (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
858 (match_operand:PDPint 2 "general_operand" "")))]
2c9c2489 859 ""
9546fe6a
PK
860 "
861{
862 rtx op1 = operands[1];
2c9c2489 863
9546fe6a
PK
864 /* If there is a constant argument, complement that one.
865 Similarly, if one of the inputs is the same as the output,
866 complement the other input. */
867 if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
868 rtx_equal_p (operands[0], operands[1]))
869 {
870 operands[1] = operands[2];
871 operands[2] = op1;
872 op1 = operands[1];
873 }
2c9c2489 874
9546fe6a
PK
875 if (CONST_INT_P (op1))
876 operands[1] = GEN_INT (~INTVAL (op1));
2c9c2489 877 else
9546fe6a
PK
878 operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
879}")
2c9c2489 880
396acafd 881(define_insn "*bic<mode>"
166208c2 882 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
9546fe6a
PK
883 (and:PDPint
884 (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
885 (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
2c9c2489 886 ""
9546fe6a 887 "bic<PDPint:isfx> %1, %0"
0f237806 888 [(set_attr "length" "2,4,4,6")])
2c9c2489
RK
889
890;;- Bit set (inclusive or) instructions
63caf8bb
PK
891(define_insn "ior<mode>3"
892 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
893 (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
894 (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
2c9c2489 895 ""
63caf8bb 896 "bis<PDPint:isfx> %2, %0"
0f237806 897 [(set_attr "length" "2,4,4,6")])
2c9c2489 898
2c9c2489 899;;- xor instructions
2c9c2489 900(define_insn "xorhi3"
166208c2 901 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2c9c2489
RK
902 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
903 (match_operand:HI 2 "register_operand" "r,r")))]
904 "TARGET_40_PLUS"
905 "xor %2, %0"
0f237806 906 [(set_attr "length" "2,4")])
2c9c2489
RK
907
908;;- one complement instructions
909
63caf8bb
PK
910(define_insn "one_cmpl<mode>2"
911 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
912 (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
2c9c2489 913 ""
63caf8bb 914 "com<PDPint:isfx> %0"
0f237806 915 [(set_attr "length" "2,4")])
2c9c2489
RK
916
917;;- arithmetic shift instructions
918(define_insn "ashlsi3"
919 [(set (match_operand:SI 0 "register_operand" "=r,r")
920 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
921 (match_operand:HI 2 "general_operand" "rR,Qi")))]
b56f8e7c 922 "TARGET_40_PLUS"
2c9c2489 923 "ashc %2,%0"
0f237806 924 [(set_attr "length" "2,4")])
2c9c2489
RK
925
926;; Arithmetic right shift on the pdp works by negating the shift count.
927(define_expand "ashrsi3"
928 [(set (match_operand:SI 0 "register_operand" "=r")
929 (ashift:SI (match_operand:SI 1 "register_operand" "0")
930 (match_operand:HI 2 "general_operand" "g")))]
931 ""
932 "
933{
934 operands[2] = negate_rtx (HImode, operands[2]);
935}")
936
937;; define asl aslb asr asrb - ashc missing!
938
939;; asl
940(define_insn ""
166208c2 941 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2c9c2489
RK
942 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
943 (const_int 1)))]
944 ""
945 "asl %0"
0f237806 946 [(set_attr "length" "2,4")])
2c9c2489
RK
947
948;; and another possibility for asr is << -1
949;; might cause problems since -1 can also be encoded as 65535!
950;; not in gcc2 ???
951
952;; asr
953(define_insn ""
166208c2 954 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2c9c2489
RK
955 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
956 (const_int -1)))]
957 ""
958 "asr %0"
0f237806 959 [(set_attr "length" "2,4")])
2c9c2489 960
e7f9979a 961;; lsr
d5214afa 962(define_insn "lsrhi1"
166208c2 963 [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
e7f9979a
NS
964 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
965 (const_int 1)))]
966 ""
967 "clc\;ror %0"
0f237806 968 [(set_attr "length" "2,4")])
e7f9979a 969
d5214afa 970(define_insn "lsrsi1"
e7f9979a
NS
971 [(set (match_operand:SI 0 "register_operand" "=r")
972 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
973 (const_int 1)))]
974 ""
cf860dc2 975{
e7f9979a
NS
976
977 rtx lateoperands[2];
978
979 lateoperands[0] = operands[0];
980 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
981
982 lateoperands[1] = operands[1];
983 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
984
985 output_asm_insn (\"clc\", operands);
986 output_asm_insn (\"ror %0\", lateoperands);
987 output_asm_insn (\"ror %0\", operands);
988
989 return \"\";
990}
0f237806 991 [(set_attr "length" "10")])
e7f9979a 992
d5214afa
PK
993(define_expand "lshrsi3"
994 [(match_operand:SI 0 "register_operand" "")
995 (match_operand:SI 1 "register_operand" "0")
996 (match_operand:HI 2 "general_operand" "")]
997 ""
998 "
999{
1000 rtx r;
1001
1002 if (!TARGET_40_PLUS &&
1003 (GET_CODE (operands[2]) != CONST_INT ||
1004 (unsigned) INTVAL (operands[2]) > 3))
1005 FAIL;
1006 emit_insn (gen_lsrsi1 (operands[0], operands[1]));
1007 if (GET_CODE (operands[2]) != CONST_INT)
1008 {
1009 r = gen_reg_rtx (HImode);
b99fd9f4 1010 emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
d5214afa
PK
1011 emit_insn (gen_ashrsi3 (operands[0], operands[0], r));
1012 }
1013 else if ((unsigned) INTVAL (operands[2]) != 1)
1014 {
1015 emit_insn (gen_ashlsi3 (operands[0], operands[0],
1016 GEN_INT (1 - INTVAL (operands[2]))));
1017 }
1018 DONE;
1019}
1020"
1021)
1022
2c9c2489
RK
1023;; shift is by arbitrary count is expensive,
1024;; shift by one cheap - so let's do that, if
1025;; space doesn't matter
1026(define_insn ""
166208c2 1027 [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
2c9c2489
RK
1028 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1029 (match_operand:HI 2 "expand_shift_operand" "O")))]
f4190acc 1030 "! optimize_size"
2c9c2489
RK
1031 "*
1032{
1033 register int i;
1034
1035 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1036 if (INTVAL(operands[2]) < 0)
1037 output_asm_insn(\"asr %0\", operands);
1038 else
1039 output_asm_insn(\"asl %0\", operands);
1040
1041 return \"\";
1042}"
1043;; longest is 4
0f237806 1044 [(set (attr "length") (const_int 8))])
2c9c2489
RK
1045
1046;; aslb
1047(define_insn ""
166208c2 1048 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
2c9c2489 1049 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
19ce9cf1 1050 (match_operand:HI 2 "const_int_operand" "n,n")))]
2c9c2489
RK
1051 ""
1052 "*
1053{ /* allowing predec or post_inc is possible, but hairy! */
1054 int i, cnt;
1055
1056 cnt = INTVAL(operands[2]) & 0x0007;
1057
1058 for (i=0 ; i < cnt ; i++)
1059 output_asm_insn(\"aslb %0\", operands);
1060
1061 return \"\";
1062}"
1063;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1064 [(set_attr_alternative "length"
0f237806
PK
1065 [(const_int 14)
1066 (const_int 28)])])
2c9c2489
RK
1067
1068;;; asr
1069;(define_insn ""
166208c2 1070; [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
2c9c2489
RK
1071; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1072; (const_int 1)))]
1073; ""
1074; "asr %0"
0f237806 1075; [(set_attr "length" "2,4")])
2c9c2489
RK
1076
1077;; asrb
1078(define_insn ""
166208c2 1079 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
2c9c2489 1080 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
19ce9cf1 1081 (match_operand:HI 2 "const_int_operand" "n,n")))]
2c9c2489
RK
1082 ""
1083 "*
1084{ /* allowing predec or post_inc is possible, but hairy! */
1085 int i, cnt;
1086
1087 cnt = INTVAL(operands[2]) & 0x0007;
1088
1089 for (i=0 ; i < cnt ; i++)
1090 output_asm_insn(\"asrb %0\", operands);
1091
1092 return \"\";
1093}"
1094 [(set_attr_alternative "length"
0f237806
PK
1095 [(const_int 14)
1096 (const_int 28)])])
2c9c2489 1097
43b55a67 1098;; the following is invalid - too complex!!! - just say 14 !!!
2c9c2489 1099; [(set (attr "length") (plus (and (match_dup 2)
0f237806 1100; (const_int 14))
2c9c2489 1101; (and (match_dup 2)
0f237806 1102; (const_int 14))))])
2c9c2489
RK
1103
1104
1105
1106;; can we get +-1 in the next pattern? should
1107;; have been caught by previous patterns!
1108
1109(define_insn "ashlhi3"
1110 [(set (match_operand:HI 0 "register_operand" "=r,r")
1111 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1112 (match_operand:HI 2 "general_operand" "rR,Qi")))]
b56f8e7c 1113 "TARGET_40_PLUS"
2c9c2489
RK
1114 "*
1115{
1116 if (GET_CODE(operands[2]) == CONST_INT)
09b893bb
JM
1117 {
1118 if (INTVAL(operands[2]) == 1)
1119 return \"asl %0\";
1120 else if (INTVAL(operands[2]) == -1)
1121 return \"asr %0\";
1122 }
2c9c2489
RK
1123
1124 return \"ash %2,%0\";
1125}"
0f237806 1126 [(set_attr "length" "2,4")])
2c9c2489
RK
1127
1128;; Arithmetic right shift on the pdp works by negating the shift count.
1129(define_expand "ashrhi3"
1130 [(set (match_operand:HI 0 "register_operand" "=r")
1131 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1132 (match_operand:HI 2 "general_operand" "g")))]
1133 ""
1134 "
1135{
1136 operands[2] = negate_rtx (HImode, operands[2]);
1137}")
1138
d5214afa
PK
1139(define_expand "lshrhi3"
1140 [(match_operand:HI 0 "register_operand" "")
1141 (match_operand:HI 1 "register_operand" "")
1142 (match_operand:HI 2 "general_operand" "")]
1143 ""
1144 "
1145{
1146 rtx r;
1147
1148 if (!TARGET_40_PLUS &&
1149 (GET_CODE (operands[2]) != CONST_INT ||
1150 (unsigned) INTVAL (operands[2]) > 3))
1151 FAIL;
1152 emit_insn (gen_lsrhi1 (operands[0], operands[1]));
1153 if (GET_CODE (operands[2]) != CONST_INT)
1154 {
1155 r = gen_reg_rtx (HImode);
b99fd9f4 1156 emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
d5214afa
PK
1157 emit_insn (gen_ashrhi3 (operands[0], operands[0], r));
1158 }
1159 else if ((unsigned) INTVAL (operands[2]) != 1)
1160 {
1161 emit_insn (gen_ashlhi3 (operands[0], operands[0],
1162 GEN_INT (1 - INTVAL (operands[2]))));
1163 }
1164 DONE;
1165}
1166"
1167)
2c9c2489
RK
1168
1169;; absolute
1170
1171(define_insn "absdf2"
166208c2 1172 [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
2c9c2489
RK
1173 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1174 "TARGET_FPU"
af36a4d2 1175 "{absd|absf} %0"
0f237806 1176 [(set_attr "length" "2,4")])
2c9c2489 1177
2c9c2489
RK
1178
1179;; negate insns
1180
1181(define_insn "negdf2"
166208c2 1182 [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
2c9c2489
RK
1183 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1184 "TARGET_FPU"
af36a4d2 1185 "{negd|negf} %0"
0f237806 1186 [(set_attr "length" "2,4")])
2c9c2489 1187
30442c59
PK
1188(define_insn "negdi2"
1189 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
1190 (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
e7f9979a 1191 ""
cf860dc2 1192{
30442c59
PK
1193 rtx exops[4][2];
1194
1195 pdp11_expand_operands (operands, exops, 1, NULL, either);
e7f9979a 1196
30442c59
PK
1197 output_asm_insn (\"com %0\", exops[3]);
1198 output_asm_insn (\"com %0\", exops[2]);
1199 output_asm_insn (\"com %0\", exops[1]);
1200 output_asm_insn (\"com %0\", exops[0]);
1201 output_asm_insn (\"add $1, %0\", exops[3]);
1202 output_asm_insn (\"adc %0\", exops[2]);
1203 output_asm_insn (\"adc %0\", exops[1]);
1204 output_asm_insn (\"adc %0\", exops[0]);
e7f9979a 1205
30442c59
PK
1206 return \"\";
1207}
1208[(set_attr "length" "18,34")])
e7f9979a 1209
30442c59
PK
1210(define_insn "negsi2"
1211 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,o")
1212 (neg:SI (match_operand:SI 1 "general_operand" "0,0")))]
1213 ""
1214{
1215 rtx exops[2][2];
1216
1217 pdp11_expand_operands (operands, exops, 1, NULL, either);
e7f9979a 1218
30442c59
PK
1219 output_asm_insn (\"com %0\", exops[1]);
1220 output_asm_insn (\"com %0\", exops[0]);
1221 output_asm_insn (\"add $1, %0\", exops[1]);
1222 output_asm_insn (\"adc %0\", exops[0]);
e7f9979a
NS
1223
1224 return \"\";
1225}
30442c59 1226[(set_attr "length" "12,20")])
e7f9979a 1227
30442c59
PK
1228(define_insn "neg<mode>2"
1229 [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
1230 (neg:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
2c9c2489 1231 ""
30442c59 1232 "neg<isfx> %0"
0f237806 1233 [(set_attr "length" "2,4")])
2c9c2489
RK
1234
1235
1236;; Unconditional and other jump instructions
1237(define_insn "jump"
1238 [(set (pc)
1239 (label_ref (match_operand 0 "" "")))]
1240 ""
0f237806
PK
1241 "*
1242{
1243 if (get_attr_length (insn) == 2)
1244 return \"br %l0\";
1245 return \"jmp %l0\";
1246}"
7021d5df 1247 [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
0f237806 1248 (pc))
7021d5df
PK
1249 (const_int MIN_BRANCH))
1250 (gt (minus (match_dup 0)
0f237806 1251 (pc))
7021d5df 1252 (const_int MAX_BRANCH)))
0f237806
PK
1253 (const_int 4)
1254 (const_int 2)))])
2c9c2489
RK
1255
1256(define_insn ""
1257 [(set (pc)
1258 (label_ref (match_operand 0 "" "")))
1259 (clobber (const_int 1))]
1260 ""
1261 "jmp %l0"
0f237806 1262 [(set_attr "length" "4")])
2c9c2489
RK
1263
1264(define_insn "tablejump"
12eb6ed3 1265 [(set (pc) (match_operand:HI 0 "general_operand" "r,R,Q"))
2c9c2489
RK
1266 (use (label_ref (match_operand 1 "" "")))]
1267 ""
12eb6ed3
PK
1268 "@
1269 jmp (%0)
1270 jmp %@%0
1271 jmp %@%0"
1272 [(set_attr "length" "2,2,4")])
2c9c2489
RK
1273
1274;; indirect jump - let's be conservative!
1275;; allow only register_operand, even though we could also
1276;; allow labels etc.
1277
1278(define_insn "indirect_jump"
1279 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1280 ""
1281 "jmp (%0)")
1282
1283;;- jump to subroutine
1284
1285(define_insn "call"
e7f9979a 1286 [(call (match_operand:HI 0 "general_operand" "rR,Q")
2c9c2489
RK
1287 (match_operand:HI 1 "general_operand" "g,g"))
1288;; (use (reg:HI 0)) what was that ???
1289 ]
1290 ;;- Don't use operand 1 for most machines.
1291 ""
1292 "jsr pc, %0"
0f237806 1293 [(set_attr "length" "2,4")])
2c9c2489
RK
1294
1295;;- jump to subroutine
1296(define_insn "call_value"
1297 [(set (match_operand 0 "" "")
e7f9979a 1298 (call (match_operand:HI 1 "general_operand" "rR,Q")
2c9c2489
RK
1299 (match_operand:HI 2 "general_operand" "g,g")))
1300;; (use (reg:HI 0)) - what was that ????
1301 ]
1302 ;;- Don't use operand 2 for most machines.
1303 ""
1304 "jsr pc, %1"
0f237806 1305 [(set_attr "length" "2,4")])
2c9c2489
RK
1306
1307;;- nop instruction
1308(define_insn "nop"
1309 [(const_int 0)]
1310 ""
1311 "nop")
1312\f
1313
1314;;- multiply
1315
1316(define_insn "muldf3"
c67b2d4e
PK
1317 [(set (match_operand:DF 0 "register_operand" "=a,a")
1318 (mult:DF (match_operand:DF 1 "register_operand" "%0,0")
1319 (match_operand:DF 2 "float_operand" "fR,QF")))]
2c9c2489 1320 "TARGET_FPU"
af36a4d2 1321 "{muld|mulf} %2, %0"
c67b2d4e 1322 [(set_attr "length" "2,4")])
2c9c2489
RK
1323
1324;; 16 bit result multiply:
1325;; currently we multiply only into odd registers, so we don't use two
1326;; registers - but this is a bit inefficient at times. If we define
1327;; a register class for each register, then we can specify properly
1328;; which register need which scratch register ....
1329
1330(define_insn "mulhi3"
1331 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1332 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
166208c2 1333 (match_operand:HI 2 "float_operand" "rR,Qi")))]
b56f8e7c 1334 "TARGET_40_PLUS"
2c9c2489 1335 "mul %2, %0"
0f237806 1336 [(set_attr "length" "2,4")])
2c9c2489
RK
1337
1338;; 32 bit result
781e6f76
RK
1339(define_expand "mulhisi3"
1340 [(set (match_dup 3)
166208c2 1341 (match_operand:HI 1 "nonimmediate_operand" "g,g"))
781e6f76
RK
1342 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1343 (mult:SI (truncate:HI
1344 (match_dup 0))
1345 (match_operand:HI 2 "general_operand" "rR,Qi")))]
b56f8e7c 1346 "TARGET_40_PLUS"
781e6f76
RK
1347 "operands[3] = gen_lowpart(HImode, operands[1]);")
1348
1349(define_insn ""
2c9c2489 1350 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
781e6f76
RK
1351 (mult:SI (truncate:HI
1352 (match_operand:SI 1 "register_operand" "%0,0"))
2c9c2489 1353 (match_operand:HI 2 "general_operand" "rR,Qi")))]
b56f8e7c 1354 "TARGET_40_PLUS"
2c9c2489 1355 "mul %2, %0"
0f237806 1356 [(set_attr "length" "2,4")])
2c9c2489 1357
781e6f76
RK
1358;(define_insn "mulhisi3"
1359; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1360; (mult:SI (truncate:HI
1361; (match_operand:SI 1 "register_operand" "%0,0"))
1362; (match_operand:HI 2 "general_operand" "rR,Qi")))]
b56f8e7c 1363; "TARGET_40_PLUS"
781e6f76 1364; "mul %2, %0"
0f237806 1365; [(set_attr "length" "2,4")])
781e6f76 1366
2c9c2489 1367;;- divide
2c9c2489 1368(define_insn "divdf3"
c67b2d4e
PK
1369 [(set (match_operand:DF 0 "register_operand" "=a,a")
1370 (div:DF (match_operand:DF 1 "register_operand" "0,0")
1371 (match_operand:DF 2 "general_operand" "fR,QF")))]
2c9c2489 1372 "TARGET_FPU"
af36a4d2 1373 "{divd|divf} %2, %0"
c67b2d4e 1374 [(set_attr "length" "2,4")])
2c9c2489 1375
0c253776 1376
2c9c2489 1377(define_expand "divhi3"
0c253776 1378 [(set (subreg:HI (match_dup 1) 0)
8f808fc2 1379 (div:HI (match_operand:SI 1 "register_operand" "0")
0c253776 1380 (match_operand:HI 2 "general_operand" "g")))
8f808fc2 1381 (set (match_operand:HI 0 "register_operand" "=r")
0c253776 1382 (subreg:HI (match_dup 1) 0))]
b56f8e7c 1383 "TARGET_40_PLUS"
0c253776 1384 "")
2c9c2489 1385
2c9c2489 1386(define_insn ""
166208c2 1387 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
0c253776
RK
1388 (div:HI (match_operand:SI 1 "general_operand" "0")
1389 (match_operand:HI 2 "general_operand" "g")))]
b56f8e7c 1390 "TARGET_40_PLUS"
2c9c2489 1391 "div %2,%0"
0f237806 1392 [(set_attr "length" "4")])
2c9c2489
RK
1393
1394(define_expand "modhi3"
ddef6bc7 1395 [(set (subreg:HI (match_dup 1) 2)
8f808fc2 1396 (mod:HI (match_operand:SI 1 "register_operand" "0")
0c253776 1397 (match_operand:HI 2 "general_operand" "g")))
8f808fc2 1398 (set (match_operand:HI 0 "register_operand" "=r")
ddef6bc7 1399 (subreg:HI (match_dup 1) 2))]
b56f8e7c 1400 "TARGET_40_PLUS"
0c253776 1401 "")
2c9c2489 1402
2c9c2489 1403(define_insn ""
166208c2 1404 [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
0c253776
RK
1405 (mod:HI (match_operand:SI 1 "general_operand" "0")
1406 (match_operand:HI 2 "general_operand" "g")))]
b56f8e7c 1407 "TARGET_40_PLUS"
0c253776 1408 "div %2,%0"
0f237806 1409 [(set_attr "length" "4")])
2c9c2489 1410
0c253776
RK
1411;(define_expand "divmodhi4"
1412; [(parallel [(set (subreg:HI (match_dup 1) 0)
8f808fc2 1413; (div:HI (match_operand:SI 1 "register_operand" "0")
0c253776 1414; (match_operand:HI 2 "general_operand" "g")))
ddef6bc7 1415; (set (subreg:HI (match_dup 1) 2)
0c253776
RK
1416; (mod:HI (match_dup 1)
1417; (match_dup 2)))])
8f808fc2 1418; (set (match_operand:HI 3 "register_operand" "=r")
ddef6bc7 1419; (subreg:HI (match_dup 1) 2))
8f808fc2 1420; (set (match_operand:HI 0 "register_operand" "=r")
0c253776 1421; (subreg:HI (match_dup 1) 0))]
b56f8e7c 1422; "TARGET_40_PLUS"
0c253776
RK
1423; "")
1424;
1425;(define_insn ""
166208c2 1426; [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
0c253776
RK
1427; (div:HI (match_operand:SI 1 "general_operand" "0")
1428; (match_operand:HI 2 "general_operand" "g")))
ddef6bc7 1429; (set (subreg:HI (match_dup 0) 2)
0c253776
RK
1430; (mod:HI (match_dup 1)
1431; (match_dup 2)))]
b56f8e7c 1432; "TARGET_40_PLUS"
0c253776
RK
1433; "div %2, %0")
1434;
2c9c2489
RK
1435
1436;; is rotate doing the right thing to be included here ????