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