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