]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/pdp11/pdp11.md
explow.c (plus_constant_wide, case PLUS): Call find_constant_term and avoid checking...
[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 GNU CC.
7
8 ;; GNU CC 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 ;; GNU CC 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 GNU CC; 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")
625 (match_operand:DI 1 "general_operand" "g"))]
626 ""
627 "* return output_move_quad (operands);"
628 ;; what's the mose expensive code - say twice movsi = 16
629 [(set_attr "length" "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 "general_operand" "=rR,rR,Q,Q")
655 (match_operand:QI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
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,2,2,3")])
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" "=f,R,f,Q,f,m")
670 (match_operand:DF 1 "general_operand" "fR,f,Q,f,F,m"))]
671 ""
672 "* return output_move_quad (operands);"
673 ;; just a guess..
674 [(set_attr "length" "1,1,2,2,5,16")])
675
676 (define_insn "movsf"
677 [(set (match_operand:SF 0 "general_operand" "=g,r,g")
678 (match_operand:SF 1 "general_operand" "r,rmF,g"))]
679 "TARGET_FPU"
680 "* return output_move_double (operands);"
681 [(set_attr "length" "8,8,8")])
682
683 ;; maybe fiddle a bit with move_ratio, then
684 ;; let constraints only accept a register ...
685
686 (define_expand "movstrhi"
687 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
688 (match_operand:BLK 1 "general_operand" "g,g"))
689 (use (match_operand:HI 2 "arith_operand" "n,&mr"))
690 (use (match_operand:HI 3 "immediate_operand" "i,i"))
691 (clobber (match_scratch:HI 4 "=&r,X"))
692 (clobber (match_dup 5))
693 (clobber (match_dup 6))
694 (clobber (match_dup 2))])]
695 "(TARGET_BCOPY_BUILTIN)"
696 "
697 {
698 operands[0]
699 = change_address (operands[0], VOIDmode,
700 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
701 operands[1]
702 = change_address (operands[1], VOIDmode,
703 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
704
705 operands[5] = XEXP (operands[0], 0);
706 operands[6] = XEXP (operands[1], 0);
707 }")
708
709
710 (define_insn "" ; "movstrhi"
711 [(set (mem:BLK (match_operand:HI 0 "general_operand" "=r,r"))
712 (mem:BLK (match_operand:HI 1 "general_operand" "r,r")))
713 (use (match_operand:HI 2 "arith_operand" "n,&r"))
714 (use (match_operand:HI 3 "immediate_operand" "i,i"))
715 (clobber (match_scratch:HI 4 "=&r,X"))
716 (clobber (match_dup 0))
717 (clobber (match_dup 1))
718 (clobber (match_dup 2))]
719 "(TARGET_BCOPY_BUILTIN)"
720 "* return output_block_move (operands);"
721 ;;; just a guess
722 [(set_attr "length" "40")])
723
724
725 \f
726 ;;- truncation instructions
727
728 (define_insn "truncdfsf2"
729 [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
730 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
731 "TARGET_FPU"
732 "* if (which_alternative ==0)
733 {
734 output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
735 output_asm_insn(\"mov (sp)+, %0\", operands);
736 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
737 output_asm_insn(\"mov (sp)+, %0\", operands);
738 return \"\";
739 }
740 else if (which_alternative == 1)
741 return \"{stcdf|movfo} %1, %0\";
742 else
743 return \"{stcdf|movfo} %1, %0\";
744 "
745 [(set_attr "length" "3,1,2")])
746
747
748 (define_expand "truncsihi2"
749 [(set (match_operand:HI 0 "general_operand" "=g")
750 (subreg:HI
751 (match_operand:SI 1 "general_operand" "or")
752 0))]
753 ""
754 "")
755
756 \f
757 ;;- zero extension instructions
758
759 (define_insn "zero_extendqihi2"
760 [(set (match_operand:HI 0 "general_operand" "=r")
761 (zero_extend:HI (match_operand:QI 1 "general_operand" "0")))]
762 ""
763 "bic $(256*255), %0"
764 [(set_attr "length" "2")])
765
766 (define_expand "zero_extendhisi2"
767 [(set (subreg:HI
768 (match_dup 0)
769 2)
770 (match_operand:HI 1 "register_operand" "r"))
771 (set (subreg:HI
772 (match_operand:SI 0 "register_operand" "=r")
773 0)
774 (const_int 0))]
775 ""
776 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
777
778 \f
779 ;;- sign extension instructions
780
781 (define_insn "extendsfdf2"
782 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
783 (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
784 "TARGET_FPU"
785 "@
786 mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
787 {ldcfd|movof} %1, %0
788 {ldcfd|movof} %1, %0"
789 [(set_attr "length" "2,1,2")])
790
791 ;; does movb sign extend in register-to-register move?
792 (define_insn "extendqihi2"
793 [(set (match_operand:HI 0 "register_operand" "=r,r")
794 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
795 ""
796 "movb %1, %0"
797 [(set_attr "length" "1,2")])
798
799 (define_insn "extendqisi2"
800 [(set (match_operand:SI 0 "register_operand" "=r,r")
801 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
802 "TARGET_40_PLUS"
803 "*
804 {
805 rtx latehalf[2];
806
807 /* make register pair available */
808 latehalf[0] = operands[0];
809 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
810
811 output_asm_insn(\"movb %1, %0\", operands);
812 output_asm_insn(\"sxt %0\", latehalf);
813
814 return \"\";
815 }"
816 [(set_attr "length" "2,3")])
817
818 ;; maybe we have to use define_expand to say that we have the instruction,
819 ;; unconditionally, and then match dependent on CPU type:
820
821 (define_expand "extendhisi2"
822 [(set (match_operand:SI 0 "general_operand" "=g")
823 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
824 ""
825 "")
826
827 (define_insn "" ; "extendhisi2"
828 [(set (match_operand:SI 0 "general_operand" "=o,<,r")
829 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
830 "TARGET_40_PLUS"
831 "*
832 {
833 rtx latehalf[2];
834
835 /* we don't want to mess with auto increment */
836
837 switch (which_alternative)
838 {
839 case 0:
840
841 latehalf[0] = operands[0];
842 operands[0] = adjust_address(operands[0], HImode, 2);
843
844 output_asm_insn(\"mov %1, %0\", operands);
845 output_asm_insn(\"sxt %0\", latehalf);
846
847 return \"\";
848
849 case 1:
850
851 /* - auto-decrement - right direction ;-) */
852 output_asm_insn(\"mov %1, %0\", operands);
853 output_asm_insn(\"sxt %0\", operands);
854
855 return \"\";
856
857 case 2:
858
859 /* make register pair available */
860 latehalf[0] = operands[0];
861 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
862
863 output_asm_insn(\"mov %1, %0\", operands);
864 output_asm_insn(\"sxt %0\", latehalf);
865
866 return \"\";
867
868 default:
869
870 abort();
871 }
872 }"
873 [(set_attr "length" "5,3,3")])
874
875
876 (define_insn ""
877 [(set (match_operand:SI 0 "register_operand" "=r")
878 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
879 "(! TARGET_40_PLUS)"
880 "*
881 {
882 static int count = 0;
883 char buf[100];
884 rtx lateoperands[2];
885
886 lateoperands[0] = operands[0];
887 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
888
889 output_asm_insn(\"tst %0\", operands);
890 sprintf(buf, \"bge extendhisi%d\", count);
891 output_asm_insn(buf, NULL);
892 output_asm_insn(\"mov -1, %0\", lateoperands);
893 sprintf(buf, \"bne extendhisi%d\", count+1);
894 output_asm_insn(buf, NULL);
895 sprintf(buf, \"\\nextendhisi%d:\", count);
896 output_asm_insn(buf, NULL);
897 output_asm_insn(\"clr %0\", lateoperands);
898 sprintf(buf, \"\\nextendhisi%d:\", count+1);
899 output_asm_insn(buf, NULL);
900
901 count += 2;
902
903 return \"\";
904 }"
905 [(set_attr "length" "6")])
906
907 ;; make float to int and vice versa
908 ;; using the cc_status.flag field we could probably cut down
909 ;; on seti and setl
910 ;; assume that we are normally in double and integer mode -
911 ;; what do pdp library routines do to fpu mode ?
912
913 (define_insn "floatsidf2"
914 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
915 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
916 "TARGET_FPU"
917 "* if (which_alternative ==0)
918 {
919 rtx latehalf[2];
920
921 latehalf[0] = NULL;
922 latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
923 output_asm_insn(\"mov %1, -(sp)\", latehalf);
924 output_asm_insn(\"mov %1, -(sp)\", operands);
925
926 output_asm_insn(\"setl\", operands);
927 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
928 output_asm_insn(\"seti\", operands);
929 return \"\";
930 }
931 else if (which_alternative == 1)
932 return \"setl\;{ldcld|movif} %1, %0\;seti\";
933 else
934 return \"setl\;{ldcld|movif} %1, %0\;seti\";
935 "
936 [(set_attr "length" "5,3,4")])
937
938 (define_insn "floathidf2"
939 [(set (match_operand:DF 0 "register_operand" "=a,a")
940 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
941 "TARGET_FPU"
942 "{ldcid|movif} %1, %0"
943 [(set_attr "length" "1,2")])
944
945 ;; cut float to int
946 (define_insn "fix_truncdfsi2"
947 [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
948 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
949 "TARGET_FPU"
950 "* if (which_alternative ==0)
951 {
952 output_asm_insn(\"setl\", operands);
953 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
954 output_asm_insn(\"seti\", operands);
955 output_asm_insn(\"mov (sp)+, %0\", operands);
956 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
957 output_asm_insn(\"mov (sp)+, %0\", operands);
958 return \"\";
959 }
960 else if (which_alternative == 1)
961 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
962 else
963 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
964 "
965 [(set_attr "length" "5,3,4")])
966
967 (define_insn "fix_truncdfhi2"
968 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
969 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
970 "TARGET_FPU"
971 "{stcdi|movfi} %1, %0"
972 [(set_attr "length" "1,2")])
973
974 \f
975 ;;- arithmetic instructions
976 ;;- add instructions
977
978 (define_insn "adddf3"
979 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
980 (plus:DF (match_operand:DF 1 "register_operand" "%0,0,0")
981 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
982 "TARGET_FPU"
983 "{addd|addf} %2, %0"
984 [(set_attr "length" "1,2,5")])
985
986 (define_insn "addsi3"
987 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
988 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
989 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
990 ""
991 "*
992 { /* Here we trust that operands don't overlap
993
994 or is lateoperands the low word?? - looks like it! */
995
996 rtx lateoperands[3];
997
998 lateoperands[0] = operands[0];
999
1000 if (REG_P (operands[0]))
1001 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1002 else
1003 operands[0] = adjust_address (operands[0], HImode, 2);
1004
1005 if (! CONSTANT_P(operands[2]))
1006 {
1007 lateoperands[2] = operands[2];
1008
1009 if (REG_P (operands[2]))
1010 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1011 else
1012 operands[2] = adjust_address (operands[2], HImode, 2);
1013
1014 output_asm_insn (\"add %2, %0\", operands);
1015 output_asm_insn (\"adc %0\", lateoperands);
1016 output_asm_insn (\"add %2, %0\", lateoperands);
1017 return \"\";
1018 }
1019
1020 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1021 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1022
1023 if (INTVAL(operands[2]))
1024 {
1025 output_asm_insn (\"add %2, %0\", operands);
1026 output_asm_insn (\"adc %0\", lateoperands);
1027 }
1028
1029 if (INTVAL(lateoperands[2]))
1030 output_asm_insn (\"add %2, %0\", lateoperands);
1031
1032 return \"\";
1033 }"
1034 [(set_attr "length" "3,5,6,8,3,1,5,5,3,8")])
1035
1036 (define_insn "addhi3"
1037 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1038 (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1039 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1040 ""
1041 "*
1042 {
1043 if (GET_CODE (operands[2]) == CONST_INT)
1044 {
1045 if (INTVAL(operands[2]) == 1)
1046 return \"inc %0\";
1047 else if (INTVAL(operands[2]) == -1)
1048 return \"dec %0\";
1049 }
1050
1051 return \"add %2, %0\";
1052 }"
1053 [(set_attr "length" "1,2,2,3")])
1054
1055 (define_insn "addqi3"
1056 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1057 (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
1058 (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
1059 ""
1060 "*
1061 {
1062 if (GET_CODE (operands[2]) == CONST_INT)
1063 {
1064 if (INTVAL(operands[2]) == 1)
1065 return \"incb %0\";
1066 else if (INTVAL(operands[2]) == -1)
1067 return \"decb %0\";
1068 }
1069
1070 return \"addb %2, %0\";
1071 }"
1072 [(set_attr "length" "1,2,2,3")])
1073
1074 \f
1075 ;;- subtract instructions
1076 ;; we don't have to care for constant second
1077 ;; args, since they are canonical plus:xx now!
1078 ;; also for minus:DF ??
1079
1080 (define_insn "subdf3"
1081 [(set (match_operand:DF 0 "register_operand" "=a,a")
1082 (minus:DF (match_operand:DF 1 "register_operand" "0,0")
1083 (match_operand:DF 2 "general_operand" "fR,Q")))]
1084 "TARGET_FPU"
1085 "{subd|subf} %2, %0"
1086 [(set_attr "length" "1,2")])
1087
1088 (define_insn "subsi3"
1089 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
1090 (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
1091 (match_operand:SI 2 "general_operand" "r,o,r,o")))]
1092 ""
1093 "*
1094 { /* Here we trust that operands don't overlap
1095
1096 or is lateoperands the low word?? - looks like it! */
1097
1098 rtx lateoperands[3];
1099
1100 lateoperands[0] = operands[0];
1101
1102 if (REG_P (operands[0]))
1103 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1104 else
1105 operands[0] = adjust_address (operands[0], HImode, 2);
1106
1107 lateoperands[2] = operands[2];
1108
1109 if (REG_P (operands[2]))
1110 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1111 else
1112 operands[2] = adjust_address (operands[2], HImode, 2);
1113
1114 output_asm_insn (\"sub %2, %0\", operands);
1115 output_asm_insn (\"sbc %0\", lateoperands);
1116 output_asm_insn (\"sub %2, %0\", lateoperands);
1117 return \"\";
1118 }"
1119 ;; offsettable memory addresses always are expensive!!!
1120 [(set_attr "length" "3,5,6,8")])
1121
1122 (define_insn "subhi3"
1123 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1124 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1125 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
1126 ""
1127 "*
1128 {
1129 if (GET_CODE (operands[2]) == CONST_INT)
1130 abort();
1131
1132 return \"sub %2, %0\";
1133 }"
1134 [(set_attr "length" "1,2,2,3")])
1135
1136 (define_insn "subqi3"
1137 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1138 (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
1139 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
1140 ""
1141 "*
1142 {
1143 if (GET_CODE (operands[2]) == CONST_INT)
1144 abort();
1145
1146 return \"subb %2, %0\";
1147 }"
1148 [(set_attr "length" "1,2,2,3")])
1149
1150 ;;;;- and instructions
1151 ;; Bit-and on the pdp (like on the vax) is done with a clear-bits insn.
1152 (define_expand "andsi3"
1153 [(set (match_operand:SI 0 "general_operand" "=g")
1154 (and:SI (match_operand:SI 1 "general_operand" "0")
1155 (not:SI (match_operand:SI 2 "general_operand" "g"))))]
1156 ""
1157 "
1158 {
1159 extern rtx expand_unop ();
1160 if (GET_CODE (operands[2]) == CONST_INT)
1161 operands[2] = GEN_INT (~INTVAL (operands[2]));
1162 else
1163 operands[2] = expand_unop (SImode, one_cmpl_optab, operands[2], 0, 1);
1164 }")
1165
1166 (define_expand "andhi3"
1167 [(set (match_operand:HI 0 "general_operand" "=g")
1168 (and:HI (match_operand:HI 1 "general_operand" "0")
1169 (not:HI (match_operand:HI 2 "general_operand" "g"))))]
1170 ""
1171 "
1172 {
1173 extern rtx expand_unop ();
1174 if (GET_CODE (operands[2]) == CONST_INT)
1175 operands[2] = GEN_INT (~INTVAL (operands[2]));
1176 else
1177 operands[2] = expand_unop (HImode, one_cmpl_optab, operands[2], 0, 1);
1178 }")
1179
1180 (define_expand "andqi3"
1181 [(set (match_operand:QI 0 "general_operand" "=g")
1182 (and:QI (match_operand:QI 1 "general_operand" "0")
1183 (not:QI (match_operand:QI 2 "general_operand" "g"))))]
1184 ""
1185 "
1186 {
1187 extern rtx expand_unop ();
1188 rtx op = operands[2];
1189 if (GET_CODE (op) == CONST_INT)
1190 operands[2] = GEN_INT (((1 << 8) - 1) & ~INTVAL (op));
1191 else
1192 operands[2] = expand_unop (QImode, one_cmpl_optab, op, 0, 1);
1193 }")
1194
1195 (define_insn "andcbsi3"
1196 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
1197 (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
1198 (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
1199 ""
1200 "*
1201 { /* Here we trust that operands don't overlap
1202
1203 or is lateoperands the low word?? - looks like it! */
1204
1205 rtx lateoperands[3];
1206
1207 lateoperands[0] = operands[0];
1208
1209 if (REG_P (operands[0]))
1210 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1211 else
1212 operands[0] = adjust_address (operands[0], HImode, 2);
1213
1214 if (! CONSTANT_P(operands[2]))
1215 {
1216 lateoperands[2] = operands[2];
1217
1218 if (REG_P (operands[2]))
1219 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1220 else
1221 operands[2] = adjust_address (operands[2], HImode, 2);
1222
1223 output_asm_insn (\"bic %2, %0\", operands);
1224 output_asm_insn (\"bic %2, %0\", lateoperands);
1225 return \"\";
1226 }
1227
1228 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1229 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1230
1231 /* these have different lengths, so we should have
1232 different constraints! */
1233 if (INTVAL(operands[2]))
1234 output_asm_insn (\"bic %2, %0\", operands);
1235
1236 if (INTVAL(lateoperands[2]))
1237 output_asm_insn (\"bic %2, %0\", lateoperands);
1238
1239 return \"\";
1240 }"
1241 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
1242
1243 (define_insn "andcbhi3"
1244 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1245 (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1246 (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
1247 ""
1248 "bic %2, %0"
1249 [(set_attr "length" "1,2,2,3")])
1250
1251 (define_insn "andcbqi3"
1252 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1253 (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
1254 (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
1255 ""
1256 "bicb %2, %0"
1257 [(set_attr "length" "1,2,2,3")])
1258
1259 ;;- Bit set (inclusive or) instructions
1260 (define_insn "iorsi3"
1261 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
1262 (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
1263 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
1264 ""
1265 "*
1266 { /* Here we trust that operands don't overlap
1267
1268 or is lateoperands the low word?? - looks like it! */
1269
1270 rtx lateoperands[3];
1271
1272 lateoperands[0] = operands[0];
1273
1274 if (REG_P (operands[0]))
1275 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1276 else
1277 operands[0] = adjust_address (operands[0], HImode, 2);
1278
1279 if (! CONSTANT_P(operands[2]))
1280 {
1281 lateoperands[2] = operands[2];
1282
1283 if (REG_P (operands[2]))
1284 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1285 else
1286 operands[2] = adjust_address (operands[2], HImode, 2);
1287
1288 output_asm_insn (\"bis %2, %0\", operands);
1289 output_asm_insn (\"bis %2, %0\", lateoperands);
1290 return \"\";
1291 }
1292
1293 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1294 operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
1295
1296 /* these have different lengths, so we should have
1297 different constraints! */
1298 if (INTVAL(operands[2]))
1299 output_asm_insn (\"bis %2, %0\", operands);
1300
1301 if (INTVAL(lateoperands[2]))
1302 output_asm_insn (\"bis %2, %0\", lateoperands);
1303
1304 return \"\";
1305 }"
1306 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
1307
1308 (define_insn "iorhi3"
1309 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1310 (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1311 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
1312 ""
1313 "bis %2, %0"
1314 [(set_attr "length" "1,2,2,3")])
1315
1316 (define_insn "iorqi3"
1317 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1318 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
1319 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
1320 ""
1321 "bisb %2, %0")
1322
1323 ;;- xor instructions
1324 (define_insn "xorsi3"
1325 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1326 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
1327 (match_operand:SI 2 "arith_operand" "r,I,J,K")))]
1328 "TARGET_40_PLUS"
1329 "*
1330 { /* Here we trust that operands don't overlap */
1331
1332 rtx lateoperands[3];
1333
1334 lateoperands[0] = operands[0];
1335 operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
1336
1337 if (REG_P(operands[2]))
1338 {
1339 lateoperands[2] = operands[2];
1340 operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
1341
1342 output_asm_insn (\"xor %2, %0\", operands);
1343 output_asm_insn (\"xor %2, %0\", lateoperands);
1344
1345 return \"\";
1346 }
1347
1348 lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
1349 operands[2] = GEN_INT (INTVAL(operands[2]) & 0xffff);
1350
1351 if (INTVAL (operands[2]))
1352 output_asm_insn (\"xor %2, %0\", operands);
1353
1354 if (INTVAL (lateoperands[2]))
1355 output_asm_insn (\"xor %2, %0\", lateoperands);
1356
1357 return \"\";
1358 }"
1359 [(set_attr "length" "2,1,1,2")])
1360
1361 (define_insn "xorhi3"
1362 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1363 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1364 (match_operand:HI 2 "register_operand" "r,r")))]
1365 "TARGET_40_PLUS"
1366 "xor %2, %0"
1367 [(set_attr "length" "1,2")])
1368
1369 ;;- one complement instructions
1370
1371 (define_insn "one_cmplhi2"
1372 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1373 (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
1374 ""
1375 "com %0"
1376 [(set_attr "length" "1,2")])
1377
1378 (define_insn "one_cmplqi2"
1379 [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1380 (not:QI (match_operand:QI 1 "general_operand" "0,0")))]
1381 ""
1382 "comb %0"
1383 [(set_attr "length" "1,2")])
1384
1385 ;;- arithmetic shift instructions
1386 (define_insn "ashlsi3"
1387 [(set (match_operand:SI 0 "register_operand" "=r,r")
1388 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
1389 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1390 "TARGET_45"
1391 "ashc %2,%0"
1392 [(set_attr "length" "1,2")])
1393
1394 ;; Arithmetic right shift on the pdp works by negating the shift count.
1395 (define_expand "ashrsi3"
1396 [(set (match_operand:SI 0 "register_operand" "=r")
1397 (ashift:SI (match_operand:SI 1 "register_operand" "0")
1398 (match_operand:HI 2 "general_operand" "g")))]
1399 ""
1400 "
1401 {
1402 operands[2] = negate_rtx (HImode, operands[2]);
1403 }")
1404
1405 ;; define asl aslb asr asrb - ashc missing!
1406
1407 ;; asl
1408 (define_insn ""
1409 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1410 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1411 (const_int 1)))]
1412 ""
1413 "asl %0"
1414 [(set_attr "length" "1,2")])
1415
1416 ;; and another possibility for asr is << -1
1417 ;; might cause problems since -1 can also be encoded as 65535!
1418 ;; not in gcc2 ???
1419
1420 ;; asr
1421 (define_insn ""
1422 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1423 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1424 (const_int -1)))]
1425 ""
1426 "asr %0"
1427 [(set_attr "length" "1,2")])
1428
1429 ;; shift is by arbitrary count is expensive,
1430 ;; shift by one cheap - so let's do that, if
1431 ;; space doesn't matter
1432 (define_insn ""
1433 [(set (match_operand:HI 0 "general_operand" "=r")
1434 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1435 (match_operand:HI 2 "expand_shift_operand" "O")))]
1436 "! optimize_size"
1437 "*
1438 {
1439 register int i;
1440
1441 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1442 if (INTVAL(operands[2]) < 0)
1443 output_asm_insn(\"asr %0\", operands);
1444 else
1445 output_asm_insn(\"asl %0\", operands);
1446
1447 return \"\";
1448 }"
1449 ;; longest is 4
1450 [(set (attr "length") (const_int 4))])
1451
1452 ;; aslb
1453 (define_insn ""
1454 [(set (match_operand:QI 0 "general_operand" "=r,o")
1455 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1456 (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1457 ""
1458 "*
1459 { /* allowing predec or post_inc is possible, but hairy! */
1460 int i, cnt;
1461
1462 cnt = INTVAL(operands[2]) & 0x0007;
1463
1464 for (i=0 ; i < cnt ; i++)
1465 output_asm_insn(\"aslb %0\", operands);
1466
1467 return \"\";
1468 }"
1469 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1470 [(set_attr_alternative "length"
1471 [(const_int 7)
1472 (const_int 14)])])
1473
1474 ;;; asr
1475 ;(define_insn ""
1476 ; [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1477 ; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1478 ; (const_int 1)))]
1479 ; ""
1480 ; "asr %0"
1481 ; [(set_attr "length" "1,2")])
1482
1483 ;; asrb
1484 (define_insn ""
1485 [(set (match_operand:QI 0 "general_operand" "=r,o")
1486 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1487 (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1488 ""
1489 "*
1490 { /* allowing predec or post_inc is possible, but hairy! */
1491 int i, cnt;
1492
1493 cnt = INTVAL(operands[2]) & 0x0007;
1494
1495 for (i=0 ; i < cnt ; i++)
1496 output_asm_insn(\"asrb %0\", operands);
1497
1498 return \"\";
1499 }"
1500 [(set_attr_alternative "length"
1501 [(const_int 7)
1502 (const_int 14)])])
1503
1504 ;; the following is invalid - too complex!!! - just say 14 !!!
1505 ; [(set (attr "length") (plus (and (match_dup 2)
1506 ; (const_int 7))
1507 ; (and (match_dup 2)
1508 ; (const_int 7))))])
1509
1510
1511
1512 ;; can we get +-1 in the next pattern? should
1513 ;; have been caught by previous patterns!
1514
1515 (define_insn "ashlhi3"
1516 [(set (match_operand:HI 0 "register_operand" "=r,r")
1517 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1518 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1519 ""
1520 "*
1521 {
1522 if (GET_CODE(operands[2]) == CONST_INT)
1523 {
1524 if (INTVAL(operands[2]) == 1)
1525 return \"asl %0\";
1526 else if (INTVAL(operands[2]) == -1)
1527 return \"asr %0\";
1528 }
1529
1530 return \"ash %2,%0\";
1531 }"
1532 [(set_attr "length" "1,2")])
1533
1534 ;; Arithmetic right shift on the pdp works by negating the shift count.
1535 (define_expand "ashrhi3"
1536 [(set (match_operand:HI 0 "register_operand" "=r")
1537 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1538 (match_operand:HI 2 "general_operand" "g")))]
1539 ""
1540 "
1541 {
1542 operands[2] = negate_rtx (HImode, operands[2]);
1543 }")
1544
1545 ;;;;- logical shift instructions
1546 ;;(define_insn "lshrsi3"
1547 ;; [(set (match_operand:HI 0 "register_operand" "=r")
1548 ;; (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1549 ;; (match_operand:HI 2 "arith_operand" "rI")))]
1550 ;; ""
1551 ;; "srl %0,%2")
1552
1553 ;; absolute
1554
1555 (define_insn "absdf2"
1556 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1557 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1558 "TARGET_FPU"
1559 "{absd|absf} %0"
1560 [(set_attr "length" "1,2")])
1561
1562 (define_insn "abshi2"
1563 [(set (match_operand:HI 0 "general_operand" "=r,o")
1564 (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
1565 "TARGET_ABSHI_BUILTIN"
1566 "*
1567 {
1568 static int count = 0;
1569 char buf[200];
1570
1571 output_asm_insn(\"tst %0\", operands);
1572 sprintf(buf, \"bge abshi%d\", count);
1573 output_asm_insn(buf, NULL);
1574 output_asm_insn(\"neg %0\", operands);
1575 sprintf(buf, \"\\nabshi%d:\", count++);
1576 output_asm_insn(buf, NULL);
1577
1578 return \"\";
1579 }"
1580 [(set_attr "length" "3,5")])
1581
1582
1583 ;; define expand abshi - is much better !!! - but
1584 ;; will it be optimized into an abshi2 ?
1585 ;; it will leave better code, because the tsthi might be
1586 ;; optimized away!!
1587 ; -- just a thought - don't have time to check
1588 ;
1589 ;(define_expand "abshi2"
1590 ; [(match_operand:HI 0 "general_operand" "")
1591 ; (match_operand:HI 1 "general_operand" "")]
1592 ; ""
1593 ; "
1594 ;{
1595 ; rtx label = gen_label_rtx ();
1596 ;
1597 ; /* do I need this? */
1598 ; do_pending_stack_adjust ();
1599 ;
1600 ; emit_move_insn (operands[0], operands[1]);
1601 ;
1602 ; emit_insn (gen_tsthi (operands[0]));
1603 ; emit_insn (gen_bge (label1));
1604 ;
1605 ; emit_insn (gen_neghi(operands[0], operands[0])
1606 ;
1607 ; emit_barrier ();
1608 ;
1609 ; emit_label (label);
1610 ;
1611 ; /* allow REG_NOTES to be set on last insn (labels don't have enough
1612 ; fields, and can't be used for REG_NOTES anyway). */
1613 ; emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
1614 ; DONE;
1615 ;}")
1616
1617 ;; negate insns
1618
1619 (define_insn "negdf2"
1620 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1621 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1622 "TARGET_FPU"
1623 "{negd|negf} %0"
1624 [(set_attr "length" "1,2")])
1625
1626 (define_insn "neghi2"
1627 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1628 (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
1629 ""
1630 "neg %0"
1631 [(set_attr "length" "1,2")])
1632
1633 (define_insn "negqi2"
1634 [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1635 (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
1636 ""
1637 "negb %0"
1638 [(set_attr "length" "1,2")])
1639
1640
1641 ;; Unconditional and other jump instructions
1642 (define_insn "jump"
1643 [(set (pc)
1644 (label_ref (match_operand 0 "" "")))]
1645 ""
1646 "jmp %l0"
1647 [(set_attr "length" "2")])
1648
1649 (define_insn ""
1650 [(set (pc)
1651 (label_ref (match_operand 0 "" "")))
1652 (clobber (const_int 1))]
1653 ""
1654 "jmp %l0"
1655 [(set_attr "length" "2")])
1656
1657 (define_insn "tablejump"
1658 [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1659 (use (label_ref (match_operand 1 "" "")))]
1660 ""
1661 "jmp %0"
1662 [(set_attr "length" "1,2")])
1663
1664 ;; indirect jump - let's be conservative!
1665 ;; allow only register_operand, even though we could also
1666 ;; allow labels etc.
1667
1668 (define_insn "indirect_jump"
1669 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1670 ""
1671 "jmp (%0)")
1672
1673 ;;- jump to subroutine
1674
1675 (define_insn "call"
1676 [(call (match_operand:HI 0 "general_operand" "R,Q")
1677 (match_operand:HI 1 "general_operand" "g,g"))
1678 ;; (use (reg:HI 0)) what was that ???
1679 ]
1680 ;;- Don't use operand 1 for most machines.
1681 ""
1682 "jsr pc, %0"
1683 [(set_attr "length" "1,2")])
1684
1685 ;;- jump to subroutine
1686 (define_insn "call_value"
1687 [(set (match_operand 0 "" "")
1688 (call (match_operand:HI 1 "general_operand" "R,Q")
1689 (match_operand:HI 2 "general_operand" "g,g")))
1690 ;; (use (reg:HI 0)) - what was that ????
1691 ]
1692 ;;- Don't use operand 2 for most machines.
1693 ""
1694 "jsr pc, %1"
1695 [(set_attr "length" "1,2")])
1696
1697 ;;- nop instruction
1698 (define_insn "nop"
1699 [(const_int 0)]
1700 ""
1701 "nop")
1702 \f
1703
1704 ;;- multiply
1705
1706 (define_insn "muldf3"
1707 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1708 (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
1709 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1710 "TARGET_FPU"
1711 "{muld|mulf} %2, %0"
1712 [(set_attr "length" "1,2,5")])
1713
1714 ;; 16 bit result multiply:
1715 ;; currently we multiply only into odd registers, so we don't use two
1716 ;; registers - but this is a bit inefficient at times. If we define
1717 ;; a register class for each register, then we can specify properly
1718 ;; which register need which scratch register ....
1719
1720 (define_insn "mulhi3"
1721 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1722 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1723 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1724 "TARGET_45"
1725 "mul %2, %0"
1726 [(set_attr "length" "1,2")])
1727
1728 ;; 32 bit result
1729 (define_expand "mulhisi3"
1730 [(set (match_dup 3)
1731 (match_operand:HI 1 "general_operand" "g,g"))
1732 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1733 (mult:SI (truncate:HI
1734 (match_dup 0))
1735 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1736 "TARGET_45"
1737 "operands[3] = gen_lowpart(HImode, operands[1]);")
1738
1739 (define_insn ""
1740 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1741 (mult:SI (truncate:HI
1742 (match_operand:SI 1 "register_operand" "%0,0"))
1743 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1744 "TARGET_45"
1745 "mul %2, %0"
1746 [(set_attr "length" "1,2")])
1747
1748 ;(define_insn "mulhisi3"
1749 ; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1750 ; (mult:SI (truncate:HI
1751 ; (match_operand:SI 1 "register_operand" "%0,0"))
1752 ; (match_operand:HI 2 "general_operand" "rR,Qi")))]
1753 ; "TARGET_45"
1754 ; "mul %2, %0"
1755 ; [(set_attr "length" "1,2")])
1756
1757 ;;- divide
1758 (define_insn "divdf3"
1759 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1760 (div:DF (match_operand:DF 1 "register_operand" "0,0,0")
1761 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1762 "TARGET_FPU"
1763 "{divd|divf} %2, %0"
1764 [(set_attr "length" "1,2,5")])
1765
1766
1767 (define_expand "divhi3"
1768 [(set (subreg:HI (match_dup 1) 0)
1769 (div:HI (match_operand:SI 1 "general_operand" "0")
1770 (match_operand:HI 2 "general_operand" "g")))
1771 (set (match_operand:HI 0 "general_operand" "=r")
1772 (subreg:HI (match_dup 1) 0))]
1773 "TARGET_45"
1774 "")
1775
1776 (define_insn ""
1777 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1778 (div:HI (match_operand:SI 1 "general_operand" "0")
1779 (match_operand:HI 2 "general_operand" "g")))]
1780 "TARGET_45"
1781 "div %2,%0"
1782 [(set_attr "length" "2")])
1783
1784 (define_expand "modhi3"
1785 [(set (subreg:HI (match_dup 1) 2)
1786 (mod:HI (match_operand:SI 1 "general_operand" "0")
1787 (match_operand:HI 2 "general_operand" "g")))
1788 (set (match_operand:HI 0 "general_operand" "=r")
1789 (subreg:HI (match_dup 1) 2))]
1790 "TARGET_45"
1791 "")
1792
1793 (define_insn ""
1794 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 4)
1795 (mod:HI (match_operand:SI 1 "general_operand" "0")
1796 (match_operand:HI 2 "general_operand" "g")))]
1797 "TARGET_45"
1798 "div %2,%0"
1799 [(set_attr "length" "2")])
1800
1801 ;(define_expand "divmodhi4"
1802 ; [(parallel [(set (subreg:HI (match_dup 1) 0)
1803 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1804 ; (match_operand:HI 2 "general_operand" "g")))
1805 ; (set (subreg:HI (match_dup 1) 2)
1806 ; (mod:HI (match_dup 1)
1807 ; (match_dup 2)))])
1808 ; (set (match_operand:HI 3 "general_operand" "=r")
1809 ; (subreg:HI (match_dup 1) 2))
1810 ; (set (match_operand:HI 0 "general_operand" "=r")
1811 ; (subreg:HI (match_dup 1) 0))]
1812 ; "TARGET_45"
1813 ; "")
1814 ;
1815 ;(define_insn ""
1816 ; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1817 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1818 ; (match_operand:HI 2 "general_operand" "g")))
1819 ; (set (subreg:HI (match_dup 0) 2)
1820 ; (mod:HI (match_dup 1)
1821 ; (match_dup 2)))]
1822 ; "TARGET_45"
1823 ; "div %2, %0")
1824 ;
1825
1826 ;; is rotate doing the right thing to be included here ????