]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/pdp11/pdp11.md
Joseph S.
[thirdparty/gcc.git] / gcc / config / pdp11 / pdp11.md
1 ;;- Machine description for the pdp11 for GNU C compiler
2 ;; Copyright (C) 1994, 1995, 1997, 1999 Free Software Foundation, Inc.
3 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
4
5 ;; This file is part of GNU CC.
6
7 ;; GNU CC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 1, or (at your option)
10 ;; any later version.
11
12 ;; GNU CC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU CC; see the file COPYING. If not, write to
19 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
21
22
23 ;; HI is 16 bit
24 ;; QI is 8 bit
25
26 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27
28 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
29 ;;- updates for most instructions.
30
31 ;;- Operand classes for the register allocator:
32 \f
33 ;; Compare instructions.
34
35 ;; currently we only support df floats, which saves us quite some
36 ;; hassle switching the FP mode!
37 ;; we assume that CPU is always in long float mode, and
38 ;; 16 bit integer mode - currently, the prologue for main does this,
39 ;; but maybe we should just set up a NEW crt0 properly,
40 ;; -- and what about signal handling code?
41 ;; (we don't even let sf floats in the register file, so
42 ;; we only should have to worry about truncating and widening
43 ;; when going to memory)
44
45 ;; abort() call by g++ - must define libfunc for cmp_optab
46 ;; and ucmp_optab for mode SImode, because we don't have that!!!
47 ;; - yet since no libfunc is there, we abort ()
48
49 ;; The only thing that remains to be done then is output
50 ;; the floats in a way the assembler can handle it (and
51 ;; if you're really into it, use a PDP11 float emulation
52 ;; library to do floating point constant folding - but
53 ;; I guess you'll get reasonable results even when not
54 ;; doing this)
55 ;; the last thing to do is fix the UPDATE_CC macro to check
56 ;; for floating point condition codes, and set cc_status
57 ;; properly, also setting the CC_IN_FCCR flag.
58
59 ;; define attributes
60 ;; currently type is only fpu or arith or unknown, maybe branch later ?
61 ;; default is arith
62 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
63
64 ;; length default is 1 word each
65 (define_attr "length" "" (const_int 1))
66
67 ;; a user's asm statement
68 (define_asm_attributes
69 [(set_attr "type" "unknown")
70 ; all bets are off how long it is - make it 256, forces long jumps
71 ; whenever jumping around it !!!
72 (set_attr "length" "256")])
73
74 ;; define function units
75
76 ;; arithmetic - values here immediately when next insn issued
77 ;; or does it mean the number of cycles after this insn was issued?
78 ;; how do I say that fpu insns use cpu also? (pre-interaction phase)
79
80 ;(define_function_unit "cpu" 1 1 (eq_attr "type" "arith") 0 0)
81 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
82
83 ;; compare
84 (define_insn "cmpdf"
85 [(set (cc0)
86 (compare (match_operand:DF 0 "general_operand" "fR,Q,F")
87 (match_operand:DF 1 "register_operand" "a,a,a")))]
88 "TARGET_FPU"
89 "*
90 {
91 cc_status.flags = CC_IN_FPU;
92 return \"{cmpd|cmpf} %0, %1\;cfcc\";
93 }"
94 [(set_attr "length" "2,3,6")])
95
96 ;; a bit of brain damage, maybe inline later -
97 ;; problem is - gcc seems to NEED SImode because
98 ;; of the cmp weirdness - maybe change gcc to handle this?
99
100 (define_expand "cmpsi"
101 [(set (reg:SI 0)
102 (match_operand:SI 0 "general_operand" "g"))
103 (set (reg:SI 2)
104 (match_operand:SI 1 "general_operand" "g"))
105 (parallel [(set (cc0)
106 (compare (reg:SI 0)
107 (reg:SI 2)))
108 (clobber (reg:SI 0))])]
109 "0" ;; disable for test
110 "")
111
112 ;; check for next insn for branch code - does this still
113 ;; work in gcc 2.* ?
114
115 (define_insn ""
116 [(set (cc0)
117 (compare (reg:SI 0)
118 (reg:SI 2)))
119 (clobber (reg:SI 0))]
120 ""
121 "*
122 {
123 rtx br_insn = NEXT_INSN (insn);
124 RTX_CODE br_code;
125
126 if (GET_CODE (br_insn) != JUMP_INSN)
127 abort();
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 abort();
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")
624 (match_operand:DI 1 "general_operand" "g"))]
625 ""
626 "* return output_move_quad (operands);"
627 ;; what's the mose expensive code - say twice movsi = 16
628 [(set_attr "length" "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 "general_operand" "=rR,rR,Q,Q")
654 (match_operand:QI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
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,2,2,3")])
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" "=f,R,f,Q,f,m")
669 (match_operand:DF 1 "general_operand" "fR,f,Q,f,F,m"))]
670 ""
671 "* return output_move_quad (operands);"
672 ;; just a guess..
673 [(set_attr "length" "1,1,2,2,5,16")])
674
675 (define_insn "movsf"
676 [(set (match_operand:SF 0 "general_operand" "=g,r,g")
677 (match_operand:SF 1 "general_operand" "r,rmF,g"))]
678 "TARGET_FPU"
679 "* return output_move_double (operands);"
680 [(set_attr "length" "8,8,8")])
681
682 ;; maybe fiddle a bit with move_ratio, then
683 ;; let constraints only accept a register ...
684
685 (define_expand "movstrhi"
686 [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
687 (match_operand:BLK 1 "general_operand" "g,g"))
688 (use (match_operand:HI 2 "arith_operand" "n,&mr"))
689 (use (match_operand:HI 3 "immediate_operand" "i,i"))
690 (clobber (match_scratch:HI 4 "=&r,X"))
691 (clobber (match_dup 5))
692 (clobber (match_dup 6))
693 (clobber (match_dup 2))])]
694 "(TARGET_BCOPY_BUILTIN)"
695 "
696 {
697 operands[0]
698 = change_address (operands[0], VOIDmode,
699 copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
700 operands[1]
701 = change_address (operands[1], VOIDmode,
702 copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
703
704 operands[5] = XEXP (operands[0], 0);
705 operands[6] = XEXP (operands[1], 0);
706 }")
707
708
709 (define_insn "" ; "movstrhi"
710 [(set (mem:BLK (match_operand:HI 0 "general_operand" "=r,r"))
711 (mem:BLK (match_operand:HI 1 "general_operand" "r,r")))
712 (use (match_operand:HI 2 "arith_operand" "n,&r"))
713 (use (match_operand:HI 3 "immediate_operand" "i,i"))
714 (clobber (match_scratch:HI 4 "=&r,X"))
715 (clobber (match_dup 0))
716 (clobber (match_dup 1))
717 (clobber (match_dup 2))]
718 "(TARGET_BCOPY_BUILTIN)"
719 "* return output_block_move (operands);"
720 ;;; just a guess
721 [(set_attr "length" "40")])
722
723
724 \f
725 ;;- truncation instructions
726
727 (define_insn "truncdfsf2"
728 [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
729 (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
730 "TARGET_FPU"
731 "* if (which_alternative ==0)
732 {
733 output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
734 output_asm_insn(\"mov (sp)+, %0\", operands);
735 operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
736 output_asm_insn(\"mov (sp)+, %0\", operands);
737 return \"\";
738 }
739 else if (which_alternative == 1)
740 return \"{stcdf|movfo} %1, %0\";
741 else
742 return \"{stcdf|movfo} %1, %0\";
743 "
744 [(set_attr "length" "3,1,2")])
745
746
747 (define_expand "truncsihi2"
748 [(set (match_operand:HI 0 "general_operand" "=g")
749 (subreg:HI
750 (match_operand:SI 1 "general_operand" "or")
751 0))]
752 ""
753 "")
754
755 \f
756 ;;- zero extension instructions
757
758 (define_insn "zero_extendqihi2"
759 [(set (match_operand:HI 0 "general_operand" "=r")
760 (zero_extend:HI (match_operand:QI 1 "general_operand" "0")))]
761 ""
762 "bic $(256*255), %0"
763 [(set_attr "length" "2")])
764
765 (define_expand "zero_extendhisi2"
766 [(set (subreg:HI
767 (match_dup 0)
768 1)
769 (match_operand:HI 1 "register_operand" "r"))
770 (set (subreg:HI
771 (match_operand:SI 0 "register_operand" "=r")
772 0)
773 (const_int 0))]
774 ""
775 "/* operands[1] = make_safe_from (operands[1], operands[0]); */")
776
777 \f
778 ;;- sign extension instructions
779
780 (define_insn "extendsfdf2"
781 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
782 (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
783 "TARGET_FPU"
784 "@
785 mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
786 {ldcfd|movof} %1, %0
787 {ldcfd|movof} %1, %0"
788 [(set_attr "length" "2,1,2")])
789
790 ;; does movb sign extend in register-to-register move?
791 (define_insn "extendqihi2"
792 [(set (match_operand:HI 0 "register_operand" "=r,r")
793 (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
794 ""
795 "movb %1, %0"
796 [(set_attr "length" "1,2")])
797
798 (define_insn "extendqisi2"
799 [(set (match_operand:SI 0 "register_operand" "=r,r")
800 (sign_extend:SI (match_operand:QI 1 "general_operand" "rR,Q")))]
801 "TARGET_40_PLUS"
802 "*
803 {
804 rtx latehalf[2];
805
806 /* make register pair available */
807 latehalf[0] = operands[0];
808 operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
809
810 output_asm_insn(\"movb %1, %0\", operands);
811 output_asm_insn(\"sxt %0\", latehalf);
812
813 return \"\";
814 }"
815 [(set_attr "length" "2,3")])
816
817 ;; maybe we have to use define_expand to say that we have the instruction,
818 ;; unconditionally, and then match dependent on CPU type:
819
820 (define_expand "extendhisi2"
821 [(set (match_operand:SI 0 "general_operand" "=g")
822 (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
823 ""
824 "")
825
826 (define_insn "" ; "extendhisi2"
827 [(set (match_operand:SI 0 "general_operand" "=o,<,r")
828 (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
829 "TARGET_40_PLUS"
830 "*
831 {
832 rtx latehalf[2];
833
834 /* we don't want to mess with auto increment */
835
836 switch(which_alternative)
837 {
838 case 0:
839
840 latehalf[0] = operands[0];
841 operands[0] = adj_offsettable_operand(operands[0], 2);
842
843 output_asm_insn(\"mov %1, %0\", operands);
844 output_asm_insn(\"sxt %0\", latehalf);
845
846 return \"\";
847
848 case 1:
849
850 /* - auto-decrement - right direction ;-) */
851 output_asm_insn(\"mov %1, %0\", operands);
852 output_asm_insn(\"sxt %0\", operands);
853
854 return \"\";
855
856 case 2:
857
858 /* make register pair available */
859 latehalf[0] = operands[0];
860 operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
861
862 output_asm_insn(\"mov %1, %0\", operands);
863 output_asm_insn(\"sxt %0\", latehalf);
864
865 return \"\";
866
867 default:
868
869 abort();
870 }
871 }"
872 [(set_attr "length" "5,3,3")])
873
874
875 (define_insn ""
876 [(set (match_operand:SI 0 "register_operand" "=r")
877 (sign_extend:SI (match_operand:HI 1 "general_operand" "0")))]
878 "(! TARGET_40_PLUS)"
879 "*
880 {
881 static int count = 0;
882 char buf[100];
883 rtx lateoperands[2];
884
885 lateoperands[0] = operands[0];
886 operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
887
888 output_asm_insn(\"tst %0\", operands);
889 sprintf(buf, \"bge extendhisi%d\", count);
890 output_asm_insn(buf, NULL);
891 output_asm_insn(\"mov -1, %0\", lateoperands);
892 sprintf(buf, \"bne extendhisi%d\", count+1);
893 output_asm_insn(buf, NULL);
894 sprintf(buf, \"\\nextendhisi%d:\", count);
895 output_asm_insn(buf, NULL);
896 output_asm_insn(\"clr %0\", lateoperands);
897 sprintf(buf, \"\\nextendhisi%d:\", count+1);
898 output_asm_insn(buf, NULL);
899
900 count += 2;
901
902 return \"\";
903 }"
904 [(set_attr "length" "6")])
905
906 ;; make float to int and vice versa
907 ;; using the cc_status.flag field we could probably cut down
908 ;; on seti and setl
909 ;; assume that we are normally in double and integer mode -
910 ;; what do pdp library routines do to fpu mode ?
911
912 (define_insn "floatsidf2"
913 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
914 (float:DF (match_operand:SI 1 "general_operand" "r,R,Q")))]
915 "TARGET_FPU"
916 "* if (which_alternative ==0)
917 {
918 rtx latehalf[2];
919
920 latehalf[0] = NULL;
921 latehalf[1] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
922 output_asm_insn(\"mov %1, -(sp)\", latehalf);
923 output_asm_insn(\"mov %1, -(sp)\", operands);
924
925 output_asm_insn(\"setl\", operands);
926 output_asm_insn(\"{ldcld|movif} (sp)+, %0\", operands);
927 output_asm_insn(\"seti\", operands);
928 return \"\";
929 }
930 else if (which_alternative == 1)
931 return \"setl\;{ldcld|movif} %1, %0\;seti\";
932 else
933 return \"setl\;{ldcld|movif} %1, %0\;seti\";
934 "
935 [(set_attr "length" "5,3,4")])
936
937 (define_insn "floathidf2"
938 [(set (match_operand:DF 0 "register_operand" "=a,a")
939 (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
940 "TARGET_FPU"
941 "{ldcid|movif} %1, %0"
942 [(set_attr "length" "1,2")])
943
944 ;; cut float to int
945 (define_insn "fix_truncdfsi2"
946 [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
947 (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
948 "TARGET_FPU"
949 "* if (which_alternative ==0)
950 {
951 output_asm_insn(\"setl\", operands);
952 output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
953 output_asm_insn(\"seti\", operands);
954 output_asm_insn(\"mov (sp)+, %0\", operands);
955 operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
956 output_asm_insn(\"mov (sp)+, %0\", operands);
957 return \"\";
958 }
959 else if (which_alternative == 1)
960 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
961 else
962 return \"setl\;{stcdl|movfi} %1, %0\;seti\";
963 "
964 [(set_attr "length" "5,3,4")])
965
966 (define_insn "fix_truncdfhi2"
967 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
968 (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
969 "TARGET_FPU"
970 "{stcdi|movfi} %1, %0"
971 [(set_attr "length" "1,2")])
972
973 \f
974 ;;- arithmetic instructions
975 ;;- add instructions
976
977 (define_insn "adddf3"
978 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
979 (plus:DF (match_operand:DF 1 "register_operand" "%0,0,0")
980 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
981 "TARGET_FPU"
982 "{addd|addf} %2, %0"
983 [(set_attr "length" "1,2,5")])
984
985 (define_insn "addsi3"
986 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
987 (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
988 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
989 ""
990 "*
991 { /* Here we trust that operands don't overlap
992
993 or is lateoperands the low word?? - looks like it! */
994
995 unsigned int i;
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] = adj_offsettable_operand (operands[0], 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] = adj_offsettable_operand(operands[2], 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 unsigned int i;
1099 rtx lateoperands[3];
1100
1101 lateoperands[0] = operands[0];
1102
1103 if (REG_P (operands[0]))
1104 operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
1105 else
1106 operands[0] = adj_offsettable_operand (operands[0], 2);
1107
1108 lateoperands[2] = operands[2];
1109
1110 if (REG_P (operands[2]))
1111 operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
1112 else
1113 operands[2] = adj_offsettable_operand(operands[2], 2);
1114
1115 output_asm_insn (\"sub %2, %0\", operands);
1116 output_asm_insn (\"sbc %0\", lateoperands);
1117 output_asm_insn (\"sub %2, %0\", lateoperands);
1118 return \"\";
1119 }"
1120 ;; offsettable memory addresses always are expensive!!!
1121 [(set_attr "length" "3,5,6,8")])
1122
1123 (define_insn "subhi3"
1124 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1125 (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1126 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
1127 ""
1128 "*
1129 {
1130 if (GET_CODE (operands[2]) == CONST_INT)
1131 abort();
1132
1133 return \"sub %2, %0\";
1134 }"
1135 [(set_attr "length" "1,2,2,3")])
1136
1137 (define_insn "subqi3"
1138 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1139 (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
1140 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
1141 ""
1142 "*
1143 {
1144 if (GET_CODE (operands[2]) == CONST_INT)
1145 abort();
1146
1147 return \"subb %2, %0\";
1148 }"
1149 [(set_attr "length" "1,2,2,3")])
1150
1151 ;;;;- and instructions
1152 ;; Bit-and on the pdp (like on the vax) is done with a clear-bits insn.
1153 (define_expand "andsi3"
1154 [(set (match_operand:SI 0 "general_operand" "=g")
1155 (and:SI (match_operand:SI 1 "general_operand" "0")
1156 (not:SI (match_operand:SI 2 "general_operand" "g"))))]
1157 ""
1158 "
1159 {
1160 extern rtx expand_unop ();
1161 if (GET_CODE (operands[2]) == CONST_INT)
1162 operands[2] = GEN_INT (~INTVAL (operands[2]));
1163 else
1164 operands[2] = expand_unop (SImode, one_cmpl_optab, operands[2], 0, 1);
1165 }")
1166
1167 (define_expand "andhi3"
1168 [(set (match_operand:HI 0 "general_operand" "=g")
1169 (and:HI (match_operand:HI 1 "general_operand" "0")
1170 (not:HI (match_operand:HI 2 "general_operand" "g"))))]
1171 ""
1172 "
1173 {
1174 extern rtx expand_unop ();
1175 if (GET_CODE (operands[2]) == CONST_INT)
1176 operands[2] = GEN_INT (~INTVAL (operands[2]));
1177 else
1178 operands[2] = expand_unop (HImode, one_cmpl_optab, operands[2], 0, 1);
1179 }")
1180
1181 (define_expand "andqi3"
1182 [(set (match_operand:QI 0 "general_operand" "=g")
1183 (and:QI (match_operand:QI 1 "general_operand" "0")
1184 (not:QI (match_operand:QI 2 "general_operand" "g"))))]
1185 ""
1186 "
1187 {
1188 extern rtx expand_unop ();
1189 rtx op = operands[2];
1190 if (GET_CODE (op) == CONST_INT)
1191 operands[2] = GEN_INT (((1 << 8) - 1) & ~INTVAL (op));
1192 else
1193 operands[2] = expand_unop (QImode, one_cmpl_optab, op, 0, 1);
1194 }")
1195
1196 (define_insn "andcbsi3"
1197 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
1198 (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
1199 (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
1200 ""
1201 "*
1202 { /* Here we trust that operands don't overlap
1203
1204 or is lateoperands the low word?? - looks like it! */
1205
1206 unsigned int i;
1207 rtx lateoperands[3];
1208
1209 lateoperands[0] = operands[0];
1210
1211 if (REG_P (operands[0]))
1212 operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
1213 else
1214 operands[0] = adj_offsettable_operand (operands[0], 2);
1215
1216 if (! CONSTANT_P(operands[2]))
1217 {
1218 lateoperands[2] = operands[2];
1219
1220 if (REG_P (operands[2]))
1221 operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
1222 else
1223 operands[2] = adj_offsettable_operand(operands[2], 2);
1224
1225 output_asm_insn (\"bic %2, %0\", operands);
1226 output_asm_insn (\"bic %2, %0\", lateoperands);
1227 return \"\";
1228 }
1229
1230 lateoperands[2] = GEN_INT ((INTVAL(operands[2]) >> 16) & 0xffff);
1231 operands[2] = GEN_INT (INTVAL(operands[2]) & 0xffff);
1232
1233 /* these have different lengths, so we should have
1234 different constraints! */
1235 if (INTVAL(operands[2]))
1236 output_asm_insn (\"bic %2, %0\", operands);
1237
1238 if (INTVAL(lateoperands[2]))
1239 output_asm_insn (\"bic %2, %0\", lateoperands);
1240
1241 return \"\";
1242 }"
1243 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
1244
1245 (define_insn "andcbhi3"
1246 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1247 (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
1248 (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
1249 ""
1250 "bic %2, %0"
1251 [(set_attr "length" "1,2,2,3")])
1252
1253 (define_insn "andcbqi3"
1254 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1255 (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
1256 (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
1257 ""
1258 "bicb %2, %0"
1259 [(set_attr "length" "1,2,2,3")])
1260
1261 ;;- Bit set (inclusive or) instructions
1262 (define_insn "iorsi3"
1263 [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
1264 (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
1265 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
1266 ""
1267 "*
1268 { /* Here we trust that operands don't overlap
1269
1270 or is lateoperands the low word?? - looks like it! */
1271
1272 unsigned int i;
1273 rtx lateoperands[3];
1274
1275 lateoperands[0] = operands[0];
1276
1277 if (REG_P (operands[0]))
1278 operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
1279 else
1280 operands[0] = adj_offsettable_operand (operands[0], 2);
1281
1282 if (! CONSTANT_P(operands[2]))
1283 {
1284 lateoperands[2] = operands[2];
1285
1286 if (REG_P (operands[2]))
1287 operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
1288 else
1289 operands[2] = adj_offsettable_operand(operands[2], 2);
1290
1291 output_asm_insn (\"bis %2, %0\", operands);
1292 output_asm_insn (\"bis %2, %0\", lateoperands);
1293 return \"\";
1294 }
1295
1296 lateoperands[2] = GEN_INT ((INTVAL(operands[2]) >> 16) & 0xffff);
1297 operands[2] = GEN_INT (INTVAL(operands[2]) & 0xffff);
1298
1299 /* these have different lengths, so we should have
1300 different constraints! */
1301 if (INTVAL(operands[2]))
1302 output_asm_insn (\"bis %2, %0\", operands);
1303
1304 if (INTVAL(lateoperands[2]))
1305 output_asm_insn (\"bis %2, %0\", lateoperands);
1306
1307 return \"\";
1308 }"
1309 [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
1310
1311 (define_insn "iorhi3"
1312 [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
1313 (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
1314 (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
1315 ""
1316 "bis %2, %0"
1317 [(set_attr "length" "1,2,2,3")])
1318
1319 (define_insn "iorqi3"
1320 [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
1321 (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
1322 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
1323 ""
1324 "bisb %2, %0")
1325
1326 ;;- xor instructions
1327 (define_insn "xorsi3"
1328 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1329 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
1330 (match_operand:SI 2 "arith_operand" "r,I,J,K")))]
1331 "TARGET_40_PLUS"
1332 "*
1333 { /* Here we trust that operands don't overlap */
1334
1335 unsigned int i;
1336 rtx lateoperands[3];
1337
1338 lateoperands[0] = operands[0];
1339 operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
1340
1341 if (REG_P(operands[2]))
1342 {
1343 lateoperands[2] = operands[2];
1344 operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
1345
1346 output_asm_insn (\"xor %2, %0\", operands);
1347 output_asm_insn (\"xor %2, %0\", lateoperands);
1348
1349 return \"\";
1350 }
1351
1352 lateoperands[2] = GEN_INT ((INTVAL(operands[2]) >> 16) & 0xffff);
1353 operands[2] = GEN_INT (INTVAL(operands[2]) & 0xffff);
1354
1355 if (INTVAL(operands[2]))
1356 output_asm_insn (\"xor %2, %0\", operands);
1357
1358 if (INTVAL(lateoperands[2]))
1359 output_asm_insn (\"xor %2, %0\", lateoperands);
1360
1361 return \"\";
1362 }"
1363 [(set_attr "length" "2,1,1,2")])
1364
1365 (define_insn "xorhi3"
1366 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1367 (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
1368 (match_operand:HI 2 "register_operand" "r,r")))]
1369 "TARGET_40_PLUS"
1370 "xor %2, %0"
1371 [(set_attr "length" "1,2")])
1372
1373 ;;- one complement instructions
1374
1375 (define_insn "one_cmplhi2"
1376 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1377 (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
1378 ""
1379 "com %0"
1380 [(set_attr "length" "1,2")])
1381
1382 (define_insn "one_cmplqi2"
1383 [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1384 (not:QI (match_operand:QI 1 "general_operand" "0,0")))]
1385 ""
1386 "comb %0"
1387 [(set_attr "length" "1,2")])
1388
1389 ;;- arithmetic shift instructions
1390 (define_insn "ashlsi3"
1391 [(set (match_operand:SI 0 "register_operand" "=r,r")
1392 (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
1393 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1394 "TARGET_45"
1395 "ashc %2,%0"
1396 [(set_attr "length" "1,2")])
1397
1398 ;; Arithmetic right shift on the pdp works by negating the shift count.
1399 (define_expand "ashrsi3"
1400 [(set (match_operand:SI 0 "register_operand" "=r")
1401 (ashift:SI (match_operand:SI 1 "register_operand" "0")
1402 (match_operand:HI 2 "general_operand" "g")))]
1403 ""
1404 "
1405 {
1406 operands[2] = negate_rtx (HImode, operands[2]);
1407 }")
1408
1409 ;; define asl aslb asr asrb - ashc missing!
1410
1411 ;; asl
1412 (define_insn ""
1413 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1414 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1415 (const_int 1)))]
1416 ""
1417 "asl %0"
1418 [(set_attr "length" "1,2")])
1419
1420 ;; and another possibility for asr is << -1
1421 ;; might cause problems since -1 can also be encoded as 65535!
1422 ;; not in gcc2 ???
1423
1424 ;; asr
1425 (define_insn ""
1426 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1427 (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
1428 (const_int -1)))]
1429 ""
1430 "asr %0"
1431 [(set_attr "length" "1,2")])
1432
1433 ;; shift is by arbitrary count is expensive,
1434 ;; shift by one cheap - so let's do that, if
1435 ;; space doesn't matter
1436 (define_insn ""
1437 [(set (match_operand:HI 0 "general_operand" "=r")
1438 (ashift:HI (match_operand:HI 1 "general_operand" "0")
1439 (match_operand:HI 2 "expand_shift_operand" "O")))]
1440 "! optimize_size"
1441 "*
1442 {
1443 register int i;
1444
1445 for (i = 1; i <= abs(INTVAL(operands[2])); i++)
1446 if (INTVAL(operands[2]) < 0)
1447 output_asm_insn(\"asr %0\", operands);
1448 else
1449 output_asm_insn(\"asl %0\", operands);
1450
1451 return \"\";
1452 }"
1453 ;; longest is 4
1454 [(set (attr "length") (const_int 4))])
1455
1456 ;; aslb
1457 (define_insn ""
1458 [(set (match_operand:QI 0 "general_operand" "=r,o")
1459 (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
1460 (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1461 ""
1462 "*
1463 { /* allowing predec or post_inc is possible, but hairy! */
1464 int i, cnt;
1465
1466 cnt = INTVAL(operands[2]) & 0x0007;
1467
1468 for (i=0 ; i < cnt ; i++)
1469 output_asm_insn(\"aslb %0\", operands);
1470
1471 return \"\";
1472 }"
1473 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
1474 [(set_attr_alternative "length"
1475 [(const_int 7)
1476 (const_int 14)])])
1477
1478 ;;; asr
1479 ;(define_insn ""
1480 ; [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1481 ; (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
1482 ; (const_int 1)))]
1483 ; ""
1484 ; "asr %0"
1485 ; [(set_attr "length" "1,2")])
1486
1487 ;; asrb
1488 (define_insn ""
1489 [(set (match_operand:QI 0 "general_operand" "=r,o")
1490 (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
1491 (match_operand:HI 2 "const_immediate_operand" "n,n")))]
1492 ""
1493 "*
1494 { /* allowing predec or post_inc is possible, but hairy! */
1495 int i, cnt;
1496
1497 cnt = INTVAL(operands[2]) & 0x0007;
1498
1499 for (i=0 ; i < cnt ; i++)
1500 output_asm_insn(\"asrb %0\", operands);
1501
1502 return \"\";
1503 }"
1504 [(set_attr_alternative "length"
1505 [(const_int 7)
1506 (const_int 14)])])
1507
1508 ;; the following is invalid - too complex!!! - just say 14 !!!
1509 ; [(set (attr "length") (plus (and (match_dup 2)
1510 ; (const_int 7))
1511 ; (and (match_dup 2)
1512 ; (const_int 7))))])
1513
1514
1515
1516 ;; can we get +-1 in the next pattern? should
1517 ;; have been caught by previous patterns!
1518
1519 (define_insn "ashlhi3"
1520 [(set (match_operand:HI 0 "register_operand" "=r,r")
1521 (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
1522 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1523 ""
1524 "*
1525 {
1526 if (GET_CODE(operands[2]) == CONST_INT)
1527 {
1528 if (INTVAL(operands[2]) == 1)
1529 return \"asl %0\";
1530 else if (INTVAL(operands[2]) == -1)
1531 return \"asr %0\";
1532 }
1533
1534 return \"ash %2,%0\";
1535 }"
1536 [(set_attr "length" "1,2")])
1537
1538 ;; Arithmetic right shift on the pdp works by negating the shift count.
1539 (define_expand "ashrhi3"
1540 [(set (match_operand:HI 0 "register_operand" "=r")
1541 (ashift:HI (match_operand:HI 1 "register_operand" "0")
1542 (match_operand:HI 2 "general_operand" "g")))]
1543 ""
1544 "
1545 {
1546 operands[2] = negate_rtx (HImode, operands[2]);
1547 }")
1548
1549 ;;;;- logical shift instructions
1550 ;;(define_insn "lshrsi3"
1551 ;; [(set (match_operand:HI 0 "register_operand" "=r")
1552 ;; (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
1553 ;; (match_operand:HI 2 "arith_operand" "rI")))]
1554 ;; ""
1555 ;; "srl %0,%2")
1556
1557 ;; absolute
1558
1559 (define_insn "absdf2"
1560 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1561 (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
1562 "TARGET_FPU"
1563 "{absd|absf} %0"
1564 [(set_attr "length" "1,2")])
1565
1566 (define_insn "abshi2"
1567 [(set (match_operand:HI 0 "general_operand" "=r,o")
1568 (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
1569 "TARGET_ABSHI_BUILTIN"
1570 "*
1571 {
1572 static int count = 0;
1573 char buf[200];
1574
1575 output_asm_insn(\"tst %0\", operands);
1576 sprintf(buf, \"bge abshi%d\", count);
1577 output_asm_insn(buf, NULL);
1578 output_asm_insn(\"neg %0\", operands);
1579 sprintf(buf, \"\\nabshi%d:\", count++);
1580 output_asm_insn(buf, NULL);
1581
1582 return \"\";
1583 }"
1584 [(set_attr "length" "3,5")])
1585
1586
1587 ;; define expand abshi - is much better !!! - but
1588 ;; will it be optimized into an abshi2 ?
1589 ;; it will leave better code, because the tsthi might be
1590 ;; optimized away!!
1591 ; -- just a thought - don't have time to check
1592 ;
1593 ;(define_expand "abshi2"
1594 ; [(match_operand:HI 0 "general_operand" "")
1595 ; (match_operand:HI 1 "general_operand" "")]
1596 ; ""
1597 ; "
1598 ;{
1599 ; rtx label = gen_label_rtx ();
1600 ;
1601 ; /* do I need this? */
1602 ; do_pending_stack_adjust ();
1603 ;
1604 ; emit_move_insn (operands[0], operands[1]);
1605 ;
1606 ; emit_insn (gen_tsthi (operands[0]));
1607 ; emit_insn (gen_bge (label1));
1608 ;
1609 ; emit_insn (gen_neghi(operands[0], operands[0])
1610 ;
1611 ; emit_barrier ();
1612 ;
1613 ; emit_label (label);
1614 ;
1615 ; /* allow REG_NOTES to be set on last insn (labels don't have enough
1616 ; fields, and can't be used for REG_NOTES anyway). */
1617 ; emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
1618 ; DONE;
1619 ;}")
1620
1621 ;; negate insns
1622
1623 (define_insn "negdf2"
1624 [(set (match_operand:DF 0 "general_operand" "=fR,Q")
1625 (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
1626 "TARGET_FPU"
1627 "{negd|negf} %0"
1628 [(set_attr "length" "1,2")])
1629
1630 (define_insn "neghi2"
1631 [(set (match_operand:HI 0 "general_operand" "=rR,Q")
1632 (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
1633 ""
1634 "neg %0"
1635 [(set_attr "length" "1,2")])
1636
1637 (define_insn "negqi2"
1638 [(set (match_operand:QI 0 "general_operand" "=rR,Q")
1639 (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
1640 ""
1641 "negb %0"
1642 [(set_attr "length" "1,2")])
1643
1644
1645 ;; Unconditional and other jump instructions
1646 (define_insn "jump"
1647 [(set (pc)
1648 (label_ref (match_operand 0 "" "")))]
1649 ""
1650 "jmp %l0"
1651 [(set_attr "length" "2")])
1652
1653 (define_insn ""
1654 [(set (pc)
1655 (label_ref (match_operand 0 "" "")))
1656 (clobber (const_int 1))]
1657 ""
1658 "jmp %l0"
1659 [(set_attr "length" "2")])
1660
1661 (define_insn "tablejump"
1662 [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
1663 (use (label_ref (match_operand 1 "" "")))]
1664 ""
1665 "jmp %0"
1666 [(set_attr "length" "1,2")])
1667
1668 ;; indirect jump - let's be conservative!
1669 ;; allow only register_operand, even though we could also
1670 ;; allow labels etc.
1671
1672 (define_insn "indirect_jump"
1673 [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
1674 ""
1675 "jmp (%0)")
1676
1677 ;;- jump to subroutine
1678
1679 (define_insn "call"
1680 [(call (match_operand:HI 0 "general_operand" "R,Q")
1681 (match_operand:HI 1 "general_operand" "g,g"))
1682 ;; (use (reg:HI 0)) what was that ???
1683 ]
1684 ;;- Don't use operand 1 for most machines.
1685 ""
1686 "jsr pc, %0"
1687 [(set_attr "length" "1,2")])
1688
1689 ;;- jump to subroutine
1690 (define_insn "call_value"
1691 [(set (match_operand 0 "" "")
1692 (call (match_operand:HI 1 "general_operand" "R,Q")
1693 (match_operand:HI 2 "general_operand" "g,g")))
1694 ;; (use (reg:HI 0)) - what was that ????
1695 ]
1696 ;;- Don't use operand 2 for most machines.
1697 ""
1698 "jsr pc, %1"
1699 [(set_attr "length" "1,2")])
1700
1701 ;;- nop instruction
1702 (define_insn "nop"
1703 [(const_int 0)]
1704 ""
1705 "nop")
1706 \f
1707
1708 ;;- multiply
1709
1710 (define_insn "muldf3"
1711 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1712 (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
1713 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1714 "TARGET_FPU"
1715 "{muld|mulf} %2, %0"
1716 [(set_attr "length" "1,2,5")])
1717
1718 ;; 16 bit result multiply:
1719 ;; currently we multiply only into odd registers, so we don't use two
1720 ;; registers - but this is a bit inefficient at times. If we define
1721 ;; a register class for each register, then we can specify properly
1722 ;; which register need which scratch register ....
1723
1724 (define_insn "mulhi3"
1725 [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
1726 (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
1727 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1728 "TARGET_45"
1729 "mul %2, %0"
1730 [(set_attr "length" "1,2")])
1731
1732 ;; 32 bit result
1733 (define_expand "mulhisi3"
1734 [(set (match_dup 3)
1735 (match_operand:HI 1 "general_operand" "g,g"))
1736 (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1737 (mult:SI (truncate:HI
1738 (match_dup 0))
1739 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1740 "TARGET_45"
1741 "operands[3] = gen_lowpart(HImode, operands[1]);")
1742
1743 (define_insn ""
1744 [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1745 (mult:SI (truncate:HI
1746 (match_operand:SI 1 "register_operand" "%0,0"))
1747 (match_operand:HI 2 "general_operand" "rR,Qi")))]
1748 "TARGET_45"
1749 "mul %2, %0"
1750 [(set_attr "length" "1,2")])
1751
1752 ;(define_insn "mulhisi3"
1753 ; [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
1754 ; (mult:SI (truncate:HI
1755 ; (match_operand:SI 1 "register_operand" "%0,0"))
1756 ; (match_operand:HI 2 "general_operand" "rR,Qi")))]
1757 ; "TARGET_45"
1758 ; "mul %2, %0"
1759 ; [(set_attr "length" "1,2")])
1760
1761 ;;- divide
1762 (define_insn "divdf3"
1763 [(set (match_operand:DF 0 "register_operand" "=a,a,a")
1764 (div:DF (match_operand:DF 1 "register_operand" "0,0,0")
1765 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
1766 "TARGET_FPU"
1767 "{divd|divf} %2, %0"
1768 [(set_attr "length" "1,2,5")])
1769
1770
1771 (define_expand "divhi3"
1772 [(set (subreg:HI (match_dup 1) 0)
1773 (div:HI (match_operand:SI 1 "general_operand" "0")
1774 (match_operand:HI 2 "general_operand" "g")))
1775 (set (match_operand:HI 0 "general_operand" "=r")
1776 (subreg:HI (match_dup 1) 0))]
1777 "TARGET_45"
1778 "")
1779
1780 (define_insn ""
1781 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1782 (div:HI (match_operand:SI 1 "general_operand" "0")
1783 (match_operand:HI 2 "general_operand" "g")))]
1784 "TARGET_45"
1785 "div %2,%0"
1786 [(set_attr "length" "2")])
1787
1788 (define_expand "modhi3"
1789 [(set (subreg:HI (match_dup 1) 1)
1790 (mod:HI (match_operand:SI 1 "general_operand" "0")
1791 (match_operand:HI 2 "general_operand" "g")))
1792 (set (match_operand:HI 0 "general_operand" "=r")
1793 (subreg:HI (match_dup 1) 1))]
1794 "TARGET_45"
1795 "")
1796
1797 (define_insn ""
1798 [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 1)
1799 (mod:HI (match_operand:SI 1 "general_operand" "0")
1800 (match_operand:HI 2 "general_operand" "g")))]
1801 "TARGET_45"
1802 "div %2,%0"
1803 [(set_attr "length" "2")])
1804
1805 ;(define_expand "divmodhi4"
1806 ; [(parallel [(set (subreg:HI (match_dup 1) 0)
1807 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1808 ; (match_operand:HI 2 "general_operand" "g")))
1809 ; (set (subreg:HI (match_dup 1) 1)
1810 ; (mod:HI (match_dup 1)
1811 ; (match_dup 2)))])
1812 ; (set (match_operand:HI 3 "general_operand" "=r")
1813 ; (subreg:HI (match_dup 1) 1))
1814 ; (set (match_operand:HI 0 "general_operand" "=r")
1815 ; (subreg:HI (match_dup 1) 0))]
1816 ; "TARGET_45"
1817 ; "")
1818 ;
1819 ;(define_insn ""
1820 ; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
1821 ; (div:HI (match_operand:SI 1 "general_operand" "0")
1822 ; (match_operand:HI 2 "general_operand" "g")))
1823 ; (set (subreg:HI (match_dup 0) 1)
1824 ; (mod:HI (match_dup 1)
1825 ; (match_dup 2)))]
1826 ; "TARGET_45"
1827 ; "div %2, %0")
1828 ;
1829
1830 ;; is rotate doing the right thing to be included here ????