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