]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/pdp11/pdp11.md
builtins.c: Rename movstr*, except for movstrict*, to movmem* and clrstr* to clrmem*.
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.md
1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
5
6 ;; This file is part of GCC.
7
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
11 ;; any later version.
12
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING. If not, write to
20 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
21 ;; Boston, MA 02111-1307, USA.
22
23
24 ;; HI is 16 bit
25 ;; QI is 8 bit
26
27 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28
29 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
30 ;;- updates for most instructions.
31
32 ;;- Operand classes for the register allocator:
33 \f
34 ;; Compare instructions.
35
36 ;; currently we only support df floats, which saves us quite some
37 ;; hassle switching the FP mode!
38 ;; we assume that CPU is always in long float mode, and
39 ;; 16 bit integer mode - currently, the prologue for main does this,
40 ;; but maybe we should just set up a NEW crt0 properly,
41 ;; -- and what about signal handling code?
42 ;; (we don't even let sf floats in the register file, so
43 ;; we only should have to worry about truncating and widening
44 ;; when going to memory)
45
46 ;; abort() call by g++ - must define libfunc for cmp_optab
47 ;; and ucmp_optab for mode SImode, because we don't have that!!!
48 ;; - yet since no libfunc is there, we abort ()
49
50 ;; The only thing that remains to be done then is output
51 ;; the floats in a way the assembler can handle it (and
52 ;; if you're really into it, use a PDP11 float emulation
53 ;; library to do floating point constant folding - but
54 ;; I guess you'll get reasonable results even when not
55 ;; doing this)
56 ;; the last thing to do is fix the UPDATE_CC macro to check
57 ;; for floating point condition codes, and set cc_status
58 ;; properly, also setting the CC_IN_FCCR flag.
59
60 ;; define attributes
61 ;; currently type is only fpu or arith or unknown, maybe branch later ?
62 ;; default is arith
63 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
64
65 ;; length default is 1 word each
66 (define_attr "length" "" (const_int 1))
67
68 ;; a user's asm statement
69 (define_asm_attributes
70 [(set_attr "type" "unknown")
71 ; all bets are off how long it is - make it 256, forces long jumps
72 ; whenever jumping around it !!!
73 (set_attr "length" "256")])
74
75 ;; define function units
76
77 ;; arithmetic - values here immediately when next insn issued
78 ;; or does it mean the number of cycles after this insn was issued?
79 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
80
81 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
82 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
83
84 ;; compare
85 (define_insn "cmpdf"
86 [(set (cc0)
87 (compare (match_operand:DF 0 "general_operand" "fR,Q,F")
88 (match_operand:DF 1 "register_operand" "a,a,a")))]
89 "TARGET_FPU"
90 "*
91 {
92 cc_status.flags = CC_IN_FPU;
93 return \"{cmpd|cmpf} %0, %1\;cfcc\";
94 }"
95 [(set_attr "length" "2,3,6")])
96
97 ;; a bit of brain damage, maybe inline later -
98 ;; problem is - gcc seems to NEED SImode because
99 ;; of the cmp weirdness - maybe change gcc to handle this?
100
101 (define_expand "cmpsi"
102 [(set (reg:SI 0)
103 (match_operand:SI 0 "general_operand" "g"))
104 (set (reg:SI 2)
105 (match_operand:SI 1 "general_operand" "g"))
106 (parallel [(set (cc0)
107 (compare (reg:SI 0)
108 (reg:SI 2)))
109 (clobber (reg:SI 0))])]
110 "0" ;; disable for test
111 "")
112
113 ;; check for next insn for branch code - does this still
114 ;; work in gcc 2.* ?
115
116 (define_insn ""
117 [(set (cc0)
118 (compare (reg:SI 0)
119 (reg:SI 2)))
120 (clobber (reg:SI 0))]
121 ""
122 "*
123 {
124 rtx br_insn = NEXT_INSN (insn);
125 RTX_CODE br_code;
126
127 if (GET_CODE (br_insn) != JUMP_INSN)
128 abort();
129 br_code = GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
130
131 switch(br_code)
132 {
133 case GEU:
134 case LTU:
135 case GTU:
136 case LEU:
137
138 return \"jsr pc, ___ucmpsi\;cmp $1,r0\";
139
140 case GE:
141 case LT:
142 case GT:
143 case LE:
144 case EQ:
145 case NE:
146
147 return \"jsr pc, ___cmpsi\;tst r0\";
148
149 default:
150
151 abort();
152 }
153 }"
154 [(set_attr "length" "4")])
155
156
157 (define_insn "cmphi"
158 [(set (cc0)
159 (compare (match_operand:HI 0 "general_operand" "rR,rR,Qi,Qi")
160 (match_operand:HI 1 "general_operand" "rR,Qi,rR,Qi")))]
161 ""
162 "cmp %0,%1"
163 [(set_attr "length" "1,2,2,3")])
164
165 (define_insn "cmpqi"
166 [(set (cc0)
167 (compare (match_operand:QI 0 "general_operand" "rR,rR,Qi,Qi")
168 (match_operand:QI 1 "general_operand" "rR,Qi,rR,Qi")))]
169 ""
170 "cmpb %0,%1"
171 [(set_attr "length" "1,2,2,3")])
172
173
174 ;; We have to have this because cse can optimize the previous pattern
175 ;; into this one.
176
177 (define_insn "tstdf"
178 [(set (cc0)
179 (match_operand:DF 0 "general_operand" "fR,Q"))]
180 "TARGET_FPU"
181 "*
182 {
183 cc_status.flags = CC_IN_FPU;
184 return \"{tstd|tstf} %0\;cfcc\";
185 }"
186 [(set_attr "length" "2,3")])
187
188
189 (define_expand "tstsi"
190 [(set (reg:SI 0)
191 (match_operand:SI 0 "general_operand" "g"))
192 (parallel [(set (cc0)
193 (reg:SI 0))
194 (clobber (reg:SI 0))])]
195 "0" ;; disable for test
196 "")
197
198 (define_insn ""
199 [(set (cc0)
200 (reg:SI 0))
201 (clobber (reg:SI 0))]
202 ""
203 "jsr pc, ___tstsi\;tst r0"
204 [(set_attr "length" "3")])
205
206
207 (define_insn "tsthi"
208 [(set (cc0)
209 (match_operand:HI 0 "general_operand" "rR,Q"))]
210 ""
211 "tst %0"
212 [(set_attr "length" "1,2")])
213
214 (define_insn "tstqi"
215 [(set (cc0)
216 (match_operand:QI 0 "general_operand" "rR,Q"))]
217 ""
218 "tstb %0"
219 [(set_attr "length" "1,2")])
220
221 ;; sob instruction - we need an assembler which can make this instruction
222 ;; valid under _all_ circumstances!
223
224 (define_insn ""
225 [(set (pc)
226 (if_then_else
227 (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
228 (const_int -1))
229 (const_int 0))
230 (label_ref (match_operand 1 "" ""))
231 (pc)))
232 (set (match_dup 0)
233 (plus:HI (match_dup 0)
234 (const_int -1)))]
235 "TARGET_40_PLUS"
236 "*
237 {
238 static int labelcount = 0;
239 static char buf[1000];
240
241 if (get_attr_length (insn) == 1)
242 return \"sob %0, %l1\";
243
244 /* emulate sob */
245 output_asm_insn (\"dec %0\", operands);
246
247 sprintf (buf, \"bge LONG_SOB%d\", labelcount);
248 output_asm_insn (buf, NULL);
249
250 output_asm_insn (\"jmp %l1\", operands);
251
252 sprintf (buf, \"LONG_SOB%d:\", labelcount++);
253 output_asm_insn (buf, NULL);
254
255 return \"\";
256 }"
257 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
258 (pc))
259 (const_int -256))
260 (ge (minus (match_dup 0)
261 (pc))
262 (const_int 0)))
263 (const_int 4)
264 (const_int 1)))])
265
266 ;; These control RTL generation for conditional jump insns
267 ;; and match them for register allocation.
268
269 ;; problem with too short jump distance! we need an assembler which can
270 ;; make this valid for all jump distances!
271 ;; e.g. gas!
272
273 ;; these must be changed to check for CC_IN_FCCR if float is to be
274 ;; enabled
275
276 (define_insn "beq"
277 [(set (pc)
278 (if_then_else (eq (cc0)
279 (const_int 0))
280 (label_ref (match_operand 0 "" ""))
281 (pc)))]
282 ""
283 "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
284 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
285 (pc))
286 (const_int -128))
287 (ge (minus (match_dup 0)
288 (pc))
289 (const_int 128)))
290 (const_int 3)
291 (const_int 1)))])
292
293
294 (define_insn "bne"
295 [(set (pc)
296 (if_then_else (ne (cc0)
297 (const_int 0))
298 (label_ref (match_operand 0 "" ""))
299 (pc)))]
300 ""
301 "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
302 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
303 (pc))
304 (const_int -128))
305 (ge (minus (match_dup 0)
306 (pc))
307 (const_int 128)))
308 (const_int 3)
309 (const_int 1)))])
310
311 (define_insn "bgt"
312 [(set (pc)
313 (if_then_else (gt (cc0)
314 (const_int 0))
315 (label_ref (match_operand 0 "" ""))
316 (pc)))]
317 ""
318 "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
319 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
320 (pc))
321 (const_int -128))
322 (ge (minus (match_dup 0)
323 (pc))
324 (const_int 128)))
325 (const_int 3)
326 (const_int 1)))])
327
328 (define_insn "bgtu"
329 [(set (pc)
330 (if_then_else (gtu (cc0)
331 (const_int 0))
332 (label_ref (match_operand 0 "" ""))
333 (pc)))]
334 ""
335 "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
336 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
337 (pc))
338 (const_int -128))
339 (ge (minus (match_dup 0)
340 (pc))
341 (const_int 128)))
342 (const_int 3)
343 (const_int 1)))])
344
345 (define_insn "blt"
346 [(set (pc)
347 (if_then_else (lt (cc0)
348 (const_int 0))
349 (label_ref (match_operand 0 "" ""))
350 (pc)))]
351 ""
352 "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
353 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
354 (pc))
355 (const_int -128))
356 (ge (minus (match_dup 0)
357 (pc))
358 (const_int 128)))
359 (const_int 3)
360 (const_int 1)))])
361
362
363 (define_insn "bltu"
364 [(set (pc)
365 (if_then_else (ltu (cc0)
366 (const_int 0))
367 (label_ref (match_operand 0 "" ""))
368 (pc)))]
369 ""
370 "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
371 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
372 (pc))
373 (const_int -128))
374 (ge (minus (match_dup 0)
375 (pc))
376 (const_int 128)))
377 (const_int 3)
378 (const_int 1)))])
379
380 (define_insn "bge"
381 [(set (pc)
382 (if_then_else (ge (cc0)
383 (const_int 0))
384 (label_ref (match_operand 0 "" ""))
385 (pc)))]
386 ""
387 "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
388 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
389 (pc))
390 (const_int -128))
391 (ge (minus (match_dup 0)
392 (pc))
393 (const_int 128)))
394 (const_int 3)
395 (const_int 1)))])
396
397 (define_insn "bgeu"
398 [(set (pc)
399 (if_then_else (geu (cc0)
400 (const_int 0))
401 (label_ref (match_operand 0 "" ""))
402 (pc)))]
403 ""
404 "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
405 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
406 (pc))
407 (const_int -128))
408 (ge (minus (match_dup 0)
409 (pc))
410 (const_int 128)))
411 (const_int 3)
412 (const_int 1)))])
413
414 (define_insn "ble"
415 [(set (pc)
416 (if_then_else (le (cc0)
417 (const_int 0))
418 (label_ref (match_operand 0 "" ""))
419 (pc)))]
420 ""
421 "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
422 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
423 (pc))
424 (const_int -128))
425 (ge (minus (match_dup 0)
426 (pc))
427 (const_int 128)))
428 (const_int 3)
429 (const_int 1)))])
430
431 (define_insn "bleu"
432 [(set (pc)
433 (if_then_else (leu (cc0)
434 (const_int 0))
435 (label_ref (match_operand 0 "" ""))
436 (pc)))]
437 ""
438 "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
439 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
440 (pc))
441 (const_int -128))
442 (ge (minus (match_dup 0)
443 (pc))
444 (const_int 128)))
445 (const_int 3)
446 (const_int 1)))])
447
448 \f
449 ;; These match inverted jump insns for register allocation.
450
451 (define_insn ""
452 [(set (pc)
453 (if_then_else (eq (cc0)
454 (const_int 0))
455 (pc)
456 (label_ref (match_operand 0 "" ""))))]
457 ""
458 "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
459 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
460 (pc))
461 (const_int -128))
462 (ge (minus (match_dup 0)
463 (pc))
464 (const_int 128)))
465 (const_int 3)
466 (const_int 1)))])
467
468 (define_insn ""
469 [(set (pc)
470 (if_then_else (ne (cc0)
471 (const_int 0))
472 (pc)
473 (label_ref (match_operand 0 "" ""))))]
474 ""
475 "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
476 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
477 (pc))
478 (const_int -128))
479 (ge (minus (match_dup 0)
480 (pc))
481 (const_int 128)))
482 (const_int 3)
483 (const_int 1)))])
484
485 (define_insn ""
486 [(set (pc)
487 (if_then_else (gt (cc0)
488 (const_int 0))
489 (pc)
490 (label_ref (match_operand 0 "" ""))))]
491 ""
492 "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
493 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
494 (pc))
495 (const_int -128))
496 (ge (minus (match_dup 0)
497 (pc))
498 (const_int 128)))
499 (const_int 3)
500 (const_int 1)))])
501
502 (define_insn ""
503 [(set (pc)
504 (if_then_else (gtu (cc0)
505 (const_int 0))
506 (pc)
507 (label_ref (match_operand 0 "" ""))))]
508 ""
509 "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
510 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
511 (pc))
512 (const_int -128))
513 (ge (minus (match_dup 0)
514 (pc))
515 (const_int 128)))
516 (const_int 3)
517 (const_int 1)))])
518
519 (define_insn ""
520 [(set (pc)
521 (if_then_else (lt (cc0)
522 (const_int 0))
523 (pc)
524 (label_ref (match_operand 0 "" ""))))]
525 ""
526 "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
527 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
528 (pc))
529 (const_int -128))
530 (ge (minus (match_dup 0)
531 (pc))
532 (const_int 128)))
533 (const_int 3)
534 (const_int 1)))])
535
536 (define_insn ""
537 [(set (pc)
538 (if_then_else (ltu (cc0)
539 (const_int 0))
540 (pc)
541 (label_ref (match_operand 0 "" ""))))]
542 ""
543 "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
544 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
545 (pc))
546 (const_int -128))
547 (ge (minus (match_dup 0)
548 (pc))
549 (const_int 128)))
550 (const_int 3)
551 (const_int 1)))])
552
553 (define_insn ""
554 [(set (pc)
555 (if_then_else (ge (cc0)
556 (const_int 0))
557 (pc)
558 (label_ref (match_operand 0 "" ""))))]
559 ""
560 "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
561 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
562 (pc))
563 (const_int -128))
564 (ge (minus (match_dup 0)
565 (pc))
566 (const_int 128)))
567 (const_int 3)
568 (const_int 1)))])
569
570 (define_insn ""
571 [(set (pc)
572 (if_then_else (geu (cc0)
573 (const_int 0))
574 (pc)
575 (label_ref (match_operand 0 "" ""))))]
576 ""
577 "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
578 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
579 (pc))
580 (const_int -128))
581 (ge (minus (match_dup 0)
582 (pc))
583 (const_int 128)))
584 (const_int 3)
585 (const_int 1)))])
586
587 (define_insn ""
588 [(set (pc)
589 (if_then_else (le (cc0)
590 (const_int 0))
591 (pc)
592 (label_ref (match_operand 0 "" ""))))]
593 ""
594 "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
595 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
596 (pc))
597 (const_int -128))
598 (ge (minus (match_dup 0)
599 (pc))
600 (const_int 128)))
601 (const_int 3)
602 (const_int 1)))])
603
604 (define_insn ""
605 [(set (pc)
606 (if_then_else (leu (cc0)
607 (const_int 0))
608 (pc)
609 (label_ref (match_operand 0 "" ""))))]
610 ""
611 "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
612 [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
613 (pc))
614 (const_int -128))
615 (ge (minus (match_dup 0)
616 (pc))
617 (const_int 128)))
618 (const_int 3)
619 (const_int 1)))])
620 \f
621 ;; Move instructions
622
623 (define_insn "movdi"
624 [(set (match_operand:DI 0 "general_operand" "=g,rm,o")
625 (match_operand:DI 1 "general_operand" "m,r,a"))]
626 ""
627 "* return output_move_quad (operands);"
628 ;; what's the mose expensive code - say twice movsi = 16
629 [(set_attr "length" "16,16,16")])
630
631 (define_insn "movsi"
632 [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
633 (match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
634 ""
635 "* return output_move_double (operands);"
636 ;; what's the most expensive code ? - I think 8!
637 ;; we could split it up and make several sub-cases...
638 [(set_attr "length" "2,3,4,8,8")])
639
640 (define_insn "movhi"
641 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
642 (match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
643 ""
644 "*
645 {
646 if (operands[1] == const0_rtx)
647 return \"clr %0\";
648
649 return \"mov %1, %0\";
650 }"
651 [(set_attr "length" "1,2,2,3")])
652
653 (define_insn "movqi"
654 [(set (match_operand:QI 0 "nonimmediate_operand" "=g")
655 (match_operand:QI 1 "general_operand" "g"))]
656 ""
657 "*
658 {
659 if (operands[1] == const0_rtx)
660 return \"clrb %0\";
661
662 return \"movb %1, %0\";
663 }"
664 [(set_attr "length" "1")])
665
666 ;; do we have to supply all these moves? e.g. to
667 ;; NO_LOAD_FPU_REGs ?
668 (define_insn "movdf"
669 [(set (match_operand:DF 0 "general_operand" "=a,fR,a,Q,m")
670 (match_operand:DF 1 "general_operand" "fFR,a,Q,a,m"))]
671 ""
672 "* if (which_alternative ==0)
673 return \"ldd %1, %0\";
674 else if (which_alternative == 1)
675 return \"std %1, %0\";
676 else
677 return output_move_quad (operands); "
678 ;; just a guess..
679 [(set_attr "length" "1,1,5,5,16")])
680
681 (define_insn "movsf"
682 [(set (match_operand:SF 0 "general_operand" "=g,r,g")
683 (match_operand:SF 1 "general_operand" "r,rmF,g"))]
684 "TARGET_FPU"
685 "* return output_move_double (operands);"
686 [(set_attr "length" "8,8,8")])
687
688 ;; maybe fiddle a bit with move_ratio, then
689 ;; let constraints only accept a register ...
690
691 (define_expand "movmemhi"
692 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
693 (match_operand:BLK 1 "general_operand" "g,g"))
694 (use (match_operand:HI 2 "arith_operand" "n,&mr"))
695 (use (match_operand:HI 3 "immediate_operand" "i,i"))
696 (clobber (match_scratch:HI 4 "=&r,X"))
697 (clobber (match_dup 5))
698 (clobber (match_dup 6))
699 (clobber (match_dup 2))])]
700 "(TARGET_BCOPY_BUILTIN)"
701 "
702 {
703 operands[0]
704 = replace_equiv_address (operands[0],
705 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
706 operands[1]
707 = replace_equiv_address (operands[1],
708 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
709
710 operands[5] = XEXP (operands[0], 0);
711 operands[6] = XEXP (operands[1], 0);
712 }")
713
714
715 (define_insn "" ; "movmemhi"
716 [(set (mem:BLK (match_operand:HI 0 "general_operand" "=r,r"))
717 (mem:BLK (match_operand:HI 1 "general_operand" "r,r")))
718 (use (match_operand:HI 2 "arith_operand" "n,&r"))
719 (use (match_operand:HI 3 "immediate_operand" "i,i"))
720 (clobber (match_scratch:HI 4 "=&r,X"))
721 (clobber (match_dup 0))
722 (clobber (match_dup 1))
723 (clobber (match_dup 2))]
724 "(TARGET_BCOPY_BUILTIN)"
725 "* return output_block_move (operands);"
726 ;;; just a guess
727 [(set_attr "length" "40")])
728
729
730 \f
731 ;;- truncation instructions
732
733 (define_insn "truncdfsf2"
734 [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
735 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
736 "TARGET_FPU"
737 "* if (which_alternative ==0)
738 {
739 output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
740 output_asm_insn(\"mov (sp)+, %0\", operands);
741 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
742 output_asm_insn(\"mov (sp)+, %0\", operands);
743 return \"\";
744 }
745 else if (which_alternative == 1)
746 return \"{stcdf|movfo} %1, %0\";
747 else
748 return \"{stcdf|movfo} %1, %0\";
749 "
750 [(set_attr "length" "3,1,2")])
751
752
753 (define_expand "truncsihi2"
754 [(set (match_operand:HI 0 "general_operand" "=g")
755 (subreg:HI
756 (match_operand:SI 1 "general_operand" "or")
757 0))]
758 ""
759 "")
760
761 \f
762 ;;- zero extension instructions
763
764 (define_insn "zero_extendqihi2"
765 [(set (match_operand:HI 0 "general_operand" "=r")
766 (zero_extend:HI (match_operand:QI 1 "general_operand" "0")))]
767 ""
768 "bic $0177400, %0"
769 [(set_attr "length" "2")])
770
771 (define_expand "zero_extendhisi2"
772 [(set (subreg:HI
773 (match_dup 0)
774 2)
775 (match_operand:HI 1 "register_operand" "r"))
776 (set (subreg:HI
777 (match_operand:SI 0 "register_operand" "=r")
778 0)
779 (const_int 0))]
780 ""
781 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
782
783 \f
784 ;;- sign extension instructions
785
786 (define_insn "extendsfdf2"
787 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
788 (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
789 "TARGET_FPU"
790 "@
791 mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
792 {ldcfd|movof} %1, %0
793 {ldcfd|movof} %1, %0"
794 [(set_attr "length" "2,1,2")])
795
796 ;; does movb sign extend in register-to-register move?
797 (define_insn "extendqihi2"
798 [(set (match_operand:HI 0 "register_operand" "=r,r")
799 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
800 ""
801 "movb %1, %0"
802 [(set_attr "length" "1,2")])
803
804 (define_insn "extendqisi2"
805 [(set (match_operand:SI 0 "register_operand" "=r,r")
806 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
807 "TARGET_40_PLUS"
808 "*
809 {
810 rtx latehalf[2];
811
812 /* make register pair available */
813 latehalf[0] = operands[0];
814 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
815
816 output_asm_insn(\"movb %1, %0\", operands);
817 output_asm_insn(\"sxt %0\", latehalf);
818
819 return \"\";
820 }"
821 [(set_attr "length" "2,3")])
822
823 ;; maybe we have to use define_expand to say that we have the instruction,
824 ;; unconditionally, and then match dependent on CPU type:
825
826 (define_expand "extendhisi2"
827 [(set (match_operand:SI 0 "general_operand" "=g")
828 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
829 ""
830 "")
831
832 (define_insn "" ; "extendhisi2"
833 [(set (match_operand:SI 0 "general_operand" "=o,<,r")
834 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
835 "TARGET_40_PLUS"
836 "*
837 {
838 rtx latehalf[2];
839
840 /* we don't want to mess with auto increment */
841
842 switch (which_alternative)
843 {
844 case 0:
845
846 latehalf[0] = operands[0];
847 operands[0] = adjust_address(operands[0], HImode, 2);
848
849 output_asm_insn(\"mov %1, %0\", operands);
850 output_asm_insn(\"sxt %0\", latehalf);
851
852 return \"\";
853
854 case 1:
855
856 /* - auto-decrement - right direction ;-) */
857 output_asm_insn(\"mov %1, %0\", operands);
858 output_asm_insn(\"sxt %0\", operands);
859
860 return \"\";
861
862 case 2:
863
864 /* make register pair available */
865 latehalf[0] = operands[0];
866 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
867
868 output_asm_insn(\"mov %1, %0\", operands);
869 output_asm_insn(\"sxt %0\", latehalf);
870
871 return \"\";
872
873 default:
874
875 abort();
876 }
877 }"
878 [(set_attr "length" "5,3,3")])
879
880
881 (define_insn ""
882 [(set (match_operand:SI 0 "register_operand" "=r")
883 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
884 "(! TARGET_40_PLUS)"
885 "*
886 {
887 static int count = 0;
888 char buf[100];
889 rtx lateoperands[2];
890
891 lateoperands[0] = operands[0];
892 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
893
894 output_asm_insn(\"tst %0\", operands);
895 sprintf(buf, \"bge extendhisi%d\", count);
896 output_asm_insn(buf, NULL);
897 output_asm_insn(\"mov -1, %0\", lateoperands);
898 sprintf(buf, \"bne extendhisi%d\", count+1);
899 output_asm_insn(buf, NULL);
900 sprintf(buf, \"\\nextendhisi%d:\", count);
901 output_asm_insn(buf, NULL);
902 output_asm_insn(\"clr %0\", lateoperands);
903 sprintf(buf, \"\\nextendhisi%d:\", count+1);
904 output_asm_insn(buf, NULL);
905
906 count += 2;
907
908 return \"\";
909 }"
910 [(set_attr "length" "6")])
911
912 ;; make float to int and vice versa
913 ;; using the cc_status.flag field we could probably cut down
914 ;; on seti and setl
915 ;; assume that we are normally in double and integer mode -
916 ;; what do pdp library routines do to fpu mode ?
917
918 (define_insn "floatsidf2"
919 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
920 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
921 "TARGET_FPU"
922 "* if (which_alternative ==0)
923 {
924 rtx latehalf[2];
925
926 latehalf[0] = NULL;
927 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
928 output_asm_insn(\"mov %1, -(sp)\", latehalf);
929 output_asm_insn(\"mov %1, -(sp)\", operands);
930
931 output_asm_insn(\"setl\", operands);
932 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
933 output_asm_insn(\"seti\", operands);
934 return \"\";
935 }
936 else if (which_alternative == 1)
937 return \"setl\;{ldcld|movif} %1, %0\;seti\";
938 else
939 return \"setl\;{ldcld|movif} %1, %0\;seti\";
940 "
941 [(set_attr "length" "5,3,4")])
942
943 (define_insn "floathidf2"
944 [(set (match_operand:DF 0 "register_operand" "=a,a")
945 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
946 "TARGET_FPU"
947 "{ldcid|movif} %1, %0"
948 [(set_attr "length" "1,2")])
949
950 ;; cut float to int
951 (define_insn "fix_truncdfsi2"
952 [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
953 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
954 "TARGET_FPU"
955 "* if (which_alternative ==0)
956 {
957 output_asm_insn(\"setl\", operands);
958 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
959 output_asm_insn(\"seti\", operands);
960 output_asm_insn(\"mov (sp)+, %0\", operands);
961 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
962 output_asm_insn(\"mov (sp)+, %0\", operands);
963 return \"\";
964 }
965 else if (which_alternative == 1)
966 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
967 else
968 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
969 "
970 [(set_attr "length" "5,3,4")])
971
972 (define_insn "fix_truncdfhi2"
973 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
974 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
975 "TARGET_FPU"
976 "{stcdi|movfi} %1, %0"
977 [(set_attr "length" "1,2")])
978
979 \f
980 ;;- arithmetic instructions
981 ;;- add instructions
982
983 (define_insn "adddf3"
984 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
985 (plus:DF (match_operand:DF 1 "register_operand" "%0,0,0")
986 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
987 "TARGET_FPU"
988 "{addd|addf} %2, %0"
989 [(set_attr "length" "1,2,5")])
990
991 (define_insn "addsi3"
992 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
993 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
994 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
995 ""
996 "*
997 { /* Here we trust that operands don't overlap
998
999 or is lateoperands the low word?? - looks like it! */
1000
1001 rtx lateoperands[3];
1002
1003 lateoperands[0] = operands[0];
1004
1005 if (REG_P (operands[0]))
1006 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1007 else
1008 operands[0] = adjust_address (operands[0], HImode, 2);
1009
1010 if (! CONSTANT_P(operands[2]))
1011 {
1012 lateoperands[2] = operands[2];
1013
1014 if (REG_P (operands[2]))
1015 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1016 else
1017 operands[2] = adjust_address (operands[2], HImode, 2);
1018
1019 output_asm_insn (\"add %2, %0\", operands);
1020 output_asm_insn (\"adc %0\", lateoperands);
1021 output_asm_insn (\"add %2, %0\", lateoperands);
1022 return \"\";
1023 }
1024
1025 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1026 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1027
1028 if (INTVAL(operands[2]))
1029 {
1030 output_asm_insn (\"add %2, %0\", operands);
1031 output_asm_insn (\"adc %0\", lateoperands);
1032 }
1033
1034 if (INTVAL(lateoperands[2]))
1035 output_asm_insn (\"add %2, %0\", lateoperands);
1036
1037 return \"\";
1038 }"
1039 [(set_attr "length" "3,5,6,8,3,1,5,5,3,8")])
1040
1041 (define_insn "addhi3"
1042 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1043 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1044 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1045 ""
1046 "*
1047 {
1048 if (GET_CODE (operands[2]) == CONST_INT)
1049 {
1050 if (INTVAL(operands[2]) == 1)
1051 return \"inc %0\";
1052 else if (INTVAL(operands[2]) == -1)
1053 return \"dec %0\";
1054 }
1055
1056 return \"add %2, %0\";
1057 }"
1058 [(set_attr "length" "1,2,2,3")])
1059
1060 (define_insn "addqi3"
1061 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1062 (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
1063 (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1064 ""
1065 "*
1066 {
1067 if (GET_CODE (operands[2]) == CONST_INT)
1068 {
1069 if (INTVAL(operands[2]) == 1)
1070 return \"incb %0\";
1071 else if (INTVAL(operands[2]) == -1)
1072 return \"decb %0\";
1073 }
1074
1075 return \"add %2, %0\";
1076 }"
1077 [(set_attr "length" "1,2,2,3")])
1078
1079 \f
1080 ;;- subtract instructions
1081 ;; we don't have to care for constant second
1082 ;; args, since they are canonical plus:xx now!
1083 ;; also for minus:DF ??
1084
1085 (define_insn "subdf3"
1086 [(set (match_operand:DF 0 "register_operand" "=a,a")
1087 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1088 (match_operand:DF 2 "general_operand" "fR,Q")))]
1089 "TARGET_FPU"
1090 "{subd|subf} %2, %0"
1091 [(set_attr "length" "1,2")])
1092
1093 (define_insn "subsi3"
1094 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
1095 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1096 (match_operand:SI 2 "general_operand" "r,o,r,o")))]
1097 ""
1098 "*
1099 { /* Here we trust that operands don't overlap
1100
1101 or is lateoperands the low word?? - looks like it! */
1102
1103 rtx lateoperands[3];
1104
1105 lateoperands[0] = operands[0];
1106
1107 if (REG_P (operands[0]))
1108 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1109 else
1110 operands[0] = adjust_address (operands[0], HImode, 2);
1111
1112 lateoperands[2] = operands[2];
1113
1114 if (REG_P (operands[2]))
1115 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1116 else
1117 operands[2] = adjust_address (operands[2], HImode, 2);
1118
1119 output_asm_insn (\"sub %2, %0\", operands);
1120 output_asm_insn (\"sbc %0\", lateoperands);
1121 output_asm_insn (\"sub %2, %0\", lateoperands);
1122 return \"\";
1123 }"
1124 ;; offsettable memory addresses always are expensive!!!
1125 [(set_attr "length" "3,5,6,8")])
1126
1127 (define_insn "subhi3"
1128 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1129 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1130 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
1131 ""
1132 "*
1133 {
1134 if (GET_CODE (operands[2]) == CONST_INT)
1135 abort();
1136
1137 return \"sub %2, %0\";
1138 }"
1139 [(set_attr "length" "1,2,2,3")])
1140
1141 (define_insn "subqi3"
1142 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1143 (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
1144 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
1145 ""
1146 "*
1147 {
1148 if (GET_CODE (operands[2]) == CONST_INT)
1149 abort();
1150
1151 return \"sub %2, %0\";
1152 }"
1153 [(set_attr "length" "1,2,2,3")])
1154
1155 ;;;;- and instructions
1156 ;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
1157
1158 (define_insn "andsi3"
1159 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
1160 (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
1161 (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
1162 ""
1163 "*
1164 { /* Here we trust that operands don't overlap
1165
1166 or is lateoperands the low word?? - looks like it! */
1167
1168 rtx lateoperands[3];
1169
1170 lateoperands[0] = operands[0];
1171
1172 if (REG_P (operands[0]))
1173 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1174 else
1175 operands[0] = adjust_address (operands[0], HImode, 2);
1176
1177 if (! CONSTANT_P(operands[2]))
1178 {
1179 lateoperands[2] = operands[2];
1180
1181 if (REG_P (operands[2]))
1182 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1183 else
1184 operands[2] = adjust_address (operands[2], HImode, 2);
1185
1186 output_asm_insn (\"bic %2, %0\", operands);
1187 output_asm_insn (\"bic %2, %0\", lateoperands);
1188 return \"\";
1189 }
1190
1191 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1192 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1193
1194 /* these have different lengths, so we should have
1195 different constraints! */
1196 if (INTVAL(operands[2]))
1197 output_asm_insn (\"bic %2, %0\", operands);
1198
1199 if (INTVAL(lateoperands[2]))
1200 output_asm_insn (\"bic %2, %0\", lateoperands);
1201
1202 return \"\";
1203 }"
1204 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
1205
1206 (define_insn "andhi3"
1207 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1208 (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1209 (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
1210 ""
1211 "bic %2, %0"
1212 [(set_attr "length" "1,2,2,3")])
1213
1214 (define_insn "andqi3"
1215 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1216 (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
1217 (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
1218 ""
1219 "bicb %2, %0"
1220 [(set_attr "length" "1,2,2,3")])
1221
1222 ;;- Bit set (inclusive or) instructions
1223 (define_insn "iorsi3"
1224 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
1225 (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
1226 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
1227 ""
1228 "*
1229 { /* Here we trust that operands don't overlap
1230
1231 or is lateoperands the low word?? - looks like it! */
1232
1233 rtx lateoperands[3];
1234
1235 lateoperands[0] = operands[0];
1236
1237 if (REG_P (operands[0]))
1238 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1239 else
1240 operands[0] = adjust_address (operands[0], HImode, 2);
1241
1242 if (! CONSTANT_P(operands[2]))
1243 {
1244 lateoperands[2] = operands[2];
1245
1246 if (REG_P (operands[2]))
1247 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1248 else
1249 operands[2] = adjust_address (operands[2], HImode, 2);
1250
1251 output_asm_insn (\"bis %2, %0\", operands);
1252 output_asm_insn (\"bis %2, %0\", lateoperands);
1253 return \"\";
1254 }
1255
1256 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1257 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1258
1259 /* these have different lengths, so we should have
1260 different constraints! */
1261 if (INTVAL(operands[2]))
1262 output_asm_insn (\"bis %2, %0\", operands);
1263
1264 if (INTVAL(lateoperands[2]))
1265 output_asm_insn (\"bis %2, %0\", lateoperands);
1266
1267 return \"\";
1268 }"
1269 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
1270
1271 (define_insn "iorhi3"
1272 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1273 (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1274 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
1275 ""
1276 "bis %2, %0"
1277 [(set_attr "length" "1,2,2,3")])
1278
1279 (define_insn "iorqi3"
1280 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1281 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
1282 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
1283 ""
1284 "bisb %2, %0")
1285
1286 ;;- xor instructions
1287 (define_insn "xorsi3"
1288 [(set (match_operand:SI 0 "register_operand" "=r")
1289 (xor:SI (match_operand:SI 1 "register_operand" "%0")
1290 (match_operand:SI 2 "arith_operand" "r")))]
1291 "TARGET_40_PLUS"
1292 "*
1293 { /* Here we trust that operands don't overlap */
1294
1295 rtx lateoperands[3];
1296
1297 lateoperands[0] = operands[0];
1298 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1299
1300 if (REG_P(operands[2]))
1301 {
1302 lateoperands[2] = operands[2];
1303 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1304
1305 output_asm_insn (\"xor %2, %0\", operands);
1306 output_asm_insn (\"xor %2, %0\", lateoperands);
1307
1308 return \"\";
1309 }
1310
1311 }"
1312 [(set_attr "length" "2")])
1313
1314 (define_insn "xorhi3"
1315 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1316 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1317 (match_operand:HI 2 "register_operand" "r,r")))]
1318 "TARGET_40_PLUS"
1319 "xor %2, %0"
1320 [(set_attr "length" "1,2")])
1321
1322 ;;- one complement instructions
1323
1324 (define_insn "one_cmplhi2"
1325 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1326 (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
1327 ""
1328 "com %0"
1329 [(set_attr "length" "1,2")])
1330
1331 (define_insn "one_cmplqi2"
1332 [(set (match_operand:QI 0 "general_operand" "=rR,rR")
1333 (not:QI (match_operand:QI 1 "general_operand" "0,g")))]
1334 ""
1335 "@
1336 comb %0
1337 movb %1, %0\; comb %0"
1338 [(set_attr "length" "1,2")])
1339
1340 ;;- arithmetic shift instructions
1341 (define_insn "ashlsi3"
1342 [(set (match_operand:SI 0 "register_operand" "=r,r")
1343 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
1344 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1345 "TARGET_45"
1346 "ashc %2,%0"
1347 [(set_attr "length" "1,2")])
1348
1349 ;; Arithmetic right shift on the pdp works by negating the shift count.
1350 (define_expand "ashrsi3"
1351 [(set (match_operand:SI 0 "register_operand" "=r")
1352 (ashift:SI (match_operand:SI 1 "register_operand" "0")
1353 (match_operand:HI 2 "general_operand" "g")))]
1354 ""
1355 "
1356 {
1357 operands[2] = negate_rtx (HImode, operands[2]);
1358 }")
1359
1360 ;; define asl aslb asr asrb - ashc missing!
1361
1362 ;; asl
1363 (define_insn ""
1364 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1365 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1366 (const_int 1)))]
1367 ""
1368 "asl %0"
1369 [(set_attr "length" "1,2")])
1370
1371 ;; and another possibility for asr is << -1
1372 ;; might cause problems since -1 can also be encoded as 65535!
1373 ;; not in gcc2 ???
1374
1375 ;; asr
1376 (define_insn ""
1377 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1378 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1379 (const_int -1)))]
1380 ""
1381 "asr %0"
1382 [(set_attr "length" "1,2")])
1383
1384 ;; lsr
1385 (define_insn ""
1386 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1387 (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1388 (const_int 1)))]
1389 ""
1390 "clc\;ror %0"
1391 [(set_attr "length" "1,2")])
1392
1393 (define_insn "lshrsi3"
1394 [(set (match_operand:SI 0 "register_operand" "=r")
1395 (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
1396 (const_int 1)))]
1397 ""
1398 {
1399
1400 rtx lateoperands[2];
1401
1402 lateoperands[0] = operands[0];
1403 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1404
1405 lateoperands[1] = operands[1];
1406 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1407
1408 output_asm_insn (\"clc\", operands);
1409 output_asm_insn (\"ror %0\", lateoperands);
1410 output_asm_insn (\"ror %0\", operands);
1411
1412 return \"\";
1413 }
1414 [(set_attr "length" "5")])
1415
1416 ;; shift is by arbitrary count is expensive,
1417 ;; shift by one cheap - so let's do that, if
1418 ;; space doesn't matter
1419 (define_insn ""
1420 [(set (match_operand:HI 0 "general_operand" "=r")
1421 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1422 (match_operand:HI 2 "expand_shift_operand" "O")))]
1423 "! optimize_size"
1424 "*
1425 {
1426 register int i;
1427
1428 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1429 if (INTVAL(operands[2]) < 0)
1430 output_asm_insn(\"asr %0\", operands);
1431 else
1432 output_asm_insn(\"asl %0\", operands);
1433
1434 return \"\";
1435 }"
1436 ;; longest is 4
1437 [(set (attr "length") (const_int 4))])
1438
1439 ;; aslb
1440 (define_insn ""
1441 [(set (match_operand:QI 0 "general_operand" "=r,o")
1442 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1443 (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1444 ""
1445 "*
1446 { /* allowing predec or post_inc is possible, but hairy! */
1447 int i, cnt;
1448
1449 cnt = INTVAL(operands[2]) & 0x0007;
1450
1451 for (i=0 ; i < cnt ; i++)
1452 output_asm_insn(\"aslb %0\", operands);
1453
1454 return \"\";
1455 }"
1456 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1457 [(set_attr_alternative "length"
1458 [(const_int 7)
1459 (const_int 14)])])
1460
1461 ;;; asr
1462 ;(define_insn ""
1463 ; [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1464 ; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1465 ; (const_int 1)))]
1466 ; ""
1467 ; "asr %0"
1468 ; [(set_attr "length" "1,2")])
1469
1470 ;; asrb
1471 (define_insn ""
1472 [(set (match_operand:QI 0 "general_operand" "=r,o")
1473 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1474 (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1475 ""
1476 "*
1477 { /* allowing predec or post_inc is possible, but hairy! */
1478 int i, cnt;
1479
1480 cnt = INTVAL(operands[2]) & 0x0007;
1481
1482 for (i=0 ; i < cnt ; i++)
1483 output_asm_insn(\"asrb %0\", operands);
1484
1485 return \"\";
1486 }"
1487 [(set_attr_alternative "length"
1488 [(const_int 7)
1489 (const_int 14)])])
1490
1491 ;; the following is invalid - too complex!!! - just say 14 !!!
1492 ; [(set (attr "length") (plus (and (match_dup 2)
1493 ; (const_int 7))
1494 ; (and (match_dup 2)
1495 ; (const_int 7))))])
1496
1497
1498
1499 ;; can we get +-1 in the next pattern? should
1500 ;; have been caught by previous patterns!
1501
1502 (define_insn "ashlhi3"
1503 [(set (match_operand:HI 0 "register_operand" "=r,r")
1504 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1505 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1506 ""
1507 "*
1508 {
1509 if (GET_CODE(operands[2]) == CONST_INT)
1510 {
1511 if (INTVAL(operands[2]) == 1)
1512 return \"asl %0\";
1513 else if (INTVAL(operands[2]) == -1)
1514 return \"asr %0\";
1515 }
1516
1517 return \"ash %2,%0\";
1518 }"
1519 [(set_attr "length" "1,2")])
1520
1521 ;; Arithmetic right shift on the pdp works by negating the shift count.
1522 (define_expand "ashrhi3"
1523 [(set (match_operand:HI 0 "register_operand" "=r")
1524 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1525 (match_operand:HI 2 "general_operand" "g")))]
1526 ""
1527 "
1528 {
1529 operands[2] = negate_rtx (HImode, operands[2]);
1530 }")
1531
1532 ;;;;- logical shift instructions
1533 ;;(define_insn "lshrsi3"
1534 ;; [(set (match_operand:HI 0 "register_operand" "=r")
1535 ;; (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1536 ;; (match_operand:HI 2 "arith_operand" "rI")))]
1537 ;; ""
1538 ;; "srl %0,%2")
1539
1540 ;; absolute
1541
1542 (define_insn "absdf2"
1543 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1544 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1545 "TARGET_FPU"
1546 "{absd|absf} %0"
1547 [(set_attr "length" "1,2")])
1548
1549 (define_insn "abshi2"
1550 [(set (match_operand:HI 0 "general_operand" "=r,o")
1551 (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
1552 "TARGET_ABSHI_BUILTIN"
1553 "*
1554 {
1555 static int count = 0;
1556 char buf[200];
1557
1558 output_asm_insn(\"tst %0\", operands);
1559 sprintf(buf, \"bge abshi%d\", count);
1560 output_asm_insn(buf, NULL);
1561 output_asm_insn(\"neg %0\", operands);
1562 sprintf(buf, \"\\nabshi%d:\", count++);
1563 output_asm_insn(buf, NULL);
1564
1565 return \"\";
1566 }"
1567 [(set_attr "length" "3,5")])
1568
1569
1570 ;; define expand abshi - is much better !!! - but
1571 ;; will it be optimized into an abshi2 ?
1572 ;; it will leave better code, because the tsthi might be
1573 ;; optimized away!!
1574 ; -- just a thought - don't have time to check
1575 ;
1576 ;(define_expand "abshi2"
1577 ; [(match_operand:HI 0 "general_operand" "")
1578 ; (match_operand:HI 1 "general_operand" "")]
1579 ; ""
1580 ; "
1581 ;{
1582 ; rtx label = gen_label_rtx ();
1583 ;
1584 ; /* do I need this? */
1585 ; do_pending_stack_adjust ();
1586 ;
1587 ; emit_move_insn (operands[0], operands[1]);
1588 ;
1589 ; emit_insn (gen_tsthi (operands[0]));
1590 ; emit_insn (gen_bge (label1));
1591 ;
1592 ; emit_insn (gen_neghi(operands[0], operands[0])
1593 ;
1594 ; emit_barrier ();
1595 ;
1596 ; emit_label (label);
1597 ;
1598 ; /* allow REG_NOTES to be set on last insn (labels don't have enough
1599 ; fields, and can't be used for REG_NOTES anyway). */
1600 ; emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
1601 ; DONE;
1602 ;}")
1603
1604 ;; negate insns
1605
1606 (define_insn "negdf2"
1607 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1608 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1609 "TARGET_FPU"
1610 "{negd|negf} %0"
1611 [(set_attr "length" "1,2")])
1612
1613 (define_insn "negsi2"
1614 [(set (match_operand:SI 0 "register_operand" "=r")
1615 (neg:SI (match_operand:SI 1 "general_operand" "0")))]
1616 ""
1617 {
1618
1619 rtx lateoperands[2];
1620
1621 lateoperands[0] = operands[0];
1622 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1623
1624 lateoperands[1] = operands[1];
1625 operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
1626
1627 output_asm_insn (\"com %0\", operands);
1628 output_asm_insn (\"com %0\", lateoperands);
1629 output_asm_insn (\"inc %0\", operands);
1630 output_asm_insn (\"adc %0\", lateoperands);
1631
1632 return \"\";
1633 }
1634 [(set_attr "length" "5")])
1635
1636 (define_insn "neghi2"
1637 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1638 (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
1639 ""
1640 "neg %0"
1641 [(set_attr "length" "1,2")])
1642
1643 (define_insn "negqi2"
1644 [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1645 (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
1646 ""
1647 "negb %0"
1648 [(set_attr "length" "1,2")])
1649
1650
1651 ;; Unconditional and other jump instructions
1652 (define_insn "jump"
1653 [(set (pc)
1654 (label_ref (match_operand 0 "" "")))]
1655 ""
1656 "jmp %l0"
1657 [(set_attr "length" "2")])
1658
1659 (define_insn ""
1660 [(set (pc)
1661 (label_ref (match_operand 0 "" "")))
1662 (clobber (const_int 1))]
1663 ""
1664 "jmp %l0"
1665 [(set_attr "length" "2")])
1666
1667 (define_insn "tablejump"
1668 [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1669 (use (label_ref (match_operand 1 "" "")))]
1670 ""
1671 "jmp %0"
1672 [(set_attr "length" "1,2")])
1673
1674 ;; indirect jump - let's be conservative!
1675 ;; allow only register_operand, even though we could also
1676 ;; allow labels etc.
1677
1678 (define_insn "indirect_jump"
1679 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1680 ""
1681 "jmp (%0)")
1682
1683 ;;- jump to subroutine
1684
1685 (define_insn "call"
1686 [(call (match_operand:HI 0 "general_operand" "rR,Q")
1687 (match_operand:HI 1 "general_operand" "g,g"))
1688 ;; (use (reg:HI 0)) what was that ???
1689 ]
1690 ;;- Don't use operand 1 for most machines.
1691 ""
1692 "jsr pc, %0"
1693 [(set_attr "length" "1,2")])
1694
1695 ;;- jump to subroutine
1696 (define_insn "call_value"
1697 [(set (match_operand 0 "" "")
1698 (call (match_operand:HI 1 "general_operand" "rR,Q")
1699 (match_operand:HI 2 "general_operand" "g,g")))
1700 ;; (use (reg:HI 0)) - what was that ????
1701 ]
1702 ;;- Don't use operand 2 for most machines.
1703 ""
1704 "jsr pc, %1"
1705 [(set_attr "length" "1,2")])
1706
1707 ;;- nop instruction
1708 (define_insn "nop"
1709 [(const_int 0)]
1710 ""
1711 "nop")
1712 \f
1713
1714 ;;- multiply
1715
1716 (define_insn "muldf3"
1717 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1718 (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
1719 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1720 "TARGET_FPU"
1721 "{muld|mulf} %2, %0"
1722 [(set_attr "length" "1,2,5")])
1723
1724 ;; 16 bit result multiply:
1725 ;; currently we multiply only into odd registers, so we don't use two
1726 ;; registers - but this is a bit inefficient at times. If we define
1727 ;; a register class for each register, then we can specify properly
1728 ;; which register need which scratch register ....
1729
1730 (define_insn "mulhi3"
1731 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1732 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1733 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1734 "TARGET_45"
1735 "mul %2, %0"
1736 [(set_attr "length" "1,2")])
1737
1738 ;; 32 bit result
1739 (define_expand "mulhisi3"
1740 [(set (match_dup 3)
1741 (match_operand:HI 1 "general_operand" "g,g"))
1742 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1743 (mult:SI (truncate:HI
1744 (match_dup 0))
1745 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1746 "TARGET_45"
1747 "operands[3] = gen_lowpart(HImode, operands[1]);")
1748
1749 (define_insn ""
1750 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1751 (mult:SI (truncate:HI
1752 (match_operand:SI 1 "register_operand" "%0,0"))
1753 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1754 "TARGET_45"
1755 "mul %2, %0"
1756 [(set_attr "length" "1,2")])
1757
1758 ;(define_insn "mulhisi3"
1759 ; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1760 ; (mult:SI (truncate:HI
1761 ; (match_operand:SI 1 "register_operand" "%0,0"))
1762 ; (match_operand:HI 2 "general_operand" "rR,Qi")))]
1763 ; "TARGET_45"
1764 ; "mul %2, %0"
1765 ; [(set_attr "length" "1,2")])
1766
1767 ;;- divide
1768 (define_insn "divdf3"
1769 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1770 (div:DF (match_operand:DF 1 "register_operand" "0,0,0")
1771 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1772 "TARGET_FPU"
1773 "{divd|divf} %2, %0"
1774 [(set_attr "length" "1,2,5")])
1775
1776
1777 (define_expand "divhi3"
1778 [(set (subreg:HI (match_dup 1) 0)
1779 (div:HI (match_operand:SI 1 "general_operand" "0")
1780 (match_operand:HI 2 "general_operand" "g")))
1781 (set (match_operand:HI 0 "general_operand" "=r")
1782 (subreg:HI (match_dup 1) 0))]
1783 "TARGET_45"
1784 "")
1785
1786 (define_insn ""
1787 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1788 (div:HI (match_operand:SI 1 "general_operand" "0")
1789 (match_operand:HI 2 "general_operand" "g")))]
1790 "TARGET_45"
1791 "div %2,%0"
1792 [(set_attr "length" "2")])
1793
1794 (define_expand "modhi3"
1795 [(set (subreg:HI (match_dup 1) 2)
1796 (mod:HI (match_operand:SI 1 "general_operand" "0")
1797 (match_operand:HI 2 "general_operand" "g")))
1798 (set (match_operand:HI 0 "general_operand" "=r")
1799 (subreg:HI (match_dup 1) 2))]
1800 "TARGET_45"
1801 "")
1802
1803 (define_insn ""
1804 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 2)
1805 (mod:HI (match_operand:SI 1 "general_operand" "0")
1806 (match_operand:HI 2 "general_operand" "g")))]
1807 "TARGET_45"
1808 "div %2,%0"
1809 [(set_attr "length" "2")])
1810
1811 ;(define_expand "divmodhi4"
1812 ; [(parallel [(set (subreg:HI (match_dup 1) 0)
1813 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1814 ; (match_operand:HI 2 "general_operand" "g")))
1815 ; (set (subreg:HI (match_dup 1) 2)
1816 ; (mod:HI (match_dup 1)
1817 ; (match_dup 2)))])
1818 ; (set (match_operand:HI 3 "general_operand" "=r")
1819 ; (subreg:HI (match_dup 1) 2))
1820 ; (set (match_operand:HI 0 "general_operand" "=r")
1821 ; (subreg:HI (match_dup 1) 0))]
1822 ; "TARGET_45"
1823 ; "")
1824 ;
1825 ;(define_insn ""
1826 ; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1827 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1828 ; (match_operand:HI 2 "general_operand" "g")))
1829 ; (set (subreg:HI (match_dup 0) 2)
1830 ; (mod:HI (match_dup 1)
1831 ; (match_dup 2)))]
1832 ; "TARGET_45"
1833 ; "div %2, %0")
1834 ;
1835
1836 ;; is rotate doing the right thing to be included here ????