Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / usr.bin / gcc / cc1 / config / spur.md
CommitLineData
7409f4e5
C
1;;- Machine description for SPUR chip for GNU C compiler
2;; Copyright (C) 1988 Free Software Foundation, Inc.
3
4;; This file is part of GNU CC.
5
6;; GNU CC is free software; you can redistribute it and/or modify
7;; it under the terms of the GNU General Public License as published by
8;; the Free Software Foundation; either version 1, or (at your option)
9;; any later version.
10
11;; GNU CC is distributed in the hope that it will be useful,
12;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;; GNU General Public License for more details.
15
16;; You should have received a copy of the GNU General Public License
17;; along with GNU CC; see the file COPYING. If not, write to
18;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
20
21;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
22
23;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
24;;- updates for most instructions.
25
26;;- Operand classes for the register allocator:
27\f
28;; Compare instructions.
29;; This pattern is used for generating an "insn"
30;; which does just a compare and sets a (fictitious) condition code.
31
32;; The actual SPUR insns are compare-and-conditional-jump.
33;; The define_peephole's below recognize the combinations of
34;; compares and jumps, and output each pair as a single assembler insn.
35
36;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
37
38;; This controls RTL generation and register allocation.
39(define_insn "cmpsi"
40 [(set (cc0)
41 (compare (match_operand:SI 0 "nonmemory_operand" "rK")
42 (match_operand:SI 1 "nonmemory_operand" "rK")))]
43 ""
44 "*
45{
46 cc_status.value1 = operands[0], cc_status.value2 = operands[1];
47 return \"\";
48}")
49
50;; Put tstsi first among test insns so it matches a CONST_INT operand.
51
52;; We have to have this because cse can optimize the previous pattern
53;; into this one.
54
55(define_insn "tstsi"
56 [(set (cc0)
57 (match_operand:SI 0 "register_operand" "r"))]
58 ""
59 "*
60{
61 cc_status.value1 = operands[0], cc_status.value2 = const0_rtx;
62 return \"\";
63}")
64
65
66;; These control RTL generation for conditional jump insns
67;; and match them for register allocation.
68
69(define_insn "beq"
70 [(set (pc)
71 (if_then_else (eq (cc0)
72 (const_int 0))
73 (label_ref (match_operand 0 "" ""))
74 (pc)))]
75 ""
76 "* return output_compare (operands, \"eq\", \"eq\", \"ne\", \"ne\"); ")
77
78(define_insn "bne"
79 [(set (pc)
80 (if_then_else (ne (cc0)
81 (const_int 0))
82 (label_ref (match_operand 0 "" ""))
83 (pc)))]
84 ""
85 "* return output_compare (operands, \"ne\", \"ne\", \"eq\", \"eq\"); ")
86
87(define_insn "bgt"
88 [(set (pc)
89 (if_then_else (gt (cc0)
90 (const_int 0))
91 (label_ref (match_operand 0 "" ""))
92 (pc)))]
93 ""
94 "* return output_compare (operands, \"gt\", \"lt\", \"le\", \"ge\"); ")
95
96(define_insn "bgtu"
97 [(set (pc)
98 (if_then_else (gtu (cc0)
99 (const_int 0))
100 (label_ref (match_operand 0 "" ""))
101 (pc)))]
102 ""
103 "* return output_compare (operands, \"ugt\", \"ult\", \"ule\", \"uge\"); ")
104
105(define_insn "blt"
106 [(set (pc)
107 (if_then_else (lt (cc0)
108 (const_int 0))
109 (label_ref (match_operand 0 "" ""))
110 (pc)))]
111 ""
112 "* return output_compare (operands, \"lt\", \"gt\", \"ge\", \"le\"); ")
113
114(define_insn "bltu"
115 [(set (pc)
116 (if_then_else (ltu (cc0)
117 (const_int 0))
118 (label_ref (match_operand 0 "" ""))
119 (pc)))]
120 ""
121 "* return output_compare (operands, \"ult\", \"ugt\", \"uge\", \"ule\"); ")
122
123(define_insn "bge"
124 [(set (pc)
125 (if_then_else (ge (cc0)
126 (const_int 0))
127 (label_ref (match_operand 0 "" ""))
128 (pc)))]
129 ""
130 "* return output_compare (operands, \"ge\", \"le\", \"lt\", \"gt\"); ")
131
132(define_insn "bgeu"
133 [(set (pc)
134 (if_then_else (geu (cc0)
135 (const_int 0))
136 (label_ref (match_operand 0 "" ""))
137 (pc)))]
138 ""
139 "* return output_compare (operands, \"uge\", \"ule\", \"ult\", \"ugt\"); ")
140
141(define_insn "ble"
142 [(set (pc)
143 (if_then_else (le (cc0)
144 (const_int 0))
145 (label_ref (match_operand 0 "" ""))
146 (pc)))]
147 ""
148 "* return output_compare (operands, \"le\", \"ge\", \"gt\", \"lt\"); ")
149
150(define_insn "bleu"
151 [(set (pc)
152 (if_then_else (leu (cc0)
153 (const_int 0))
154 (label_ref (match_operand 0 "" ""))
155 (pc)))]
156 ""
157 "* return output_compare (operands, \"ule\", \"uge\", \"ugt\", \"ult\"); ")
158\f
159;; These match inverted jump insns for register allocation.
160
161(define_insn ""
162 [(set (pc)
163 (if_then_else (eq (cc0)
164 (const_int 0))
165 (pc)
166 (label_ref (match_operand 0 "" ""))))]
167 ""
168 "* return output_compare (operands, \"ne\", \"ne\", \"eq\", \"eq\"); ")
169
170(define_insn ""
171 [(set (pc)
172 (if_then_else (ne (cc0)
173 (const_int 0))
174 (pc)
175 (label_ref (match_operand 0 "" ""))))]
176 ""
177 "* return output_compare (operands, \"eq\", \"eq\", \"ne\", \"ne\"); ")
178
179(define_insn ""
180 [(set (pc)
181 (if_then_else (gt (cc0)
182 (const_int 0))
183 (pc)
184 (label_ref (match_operand 0 "" ""))))]
185 ""
186 "* return output_compare (operands, \"le\", \"ge\", \"gt\", \"lt\"); ")
187
188(define_insn ""
189 [(set (pc)
190 (if_then_else (gtu (cc0)
191 (const_int 0))
192 (pc)
193 (label_ref (match_operand 0 "" ""))))]
194 ""
195 "* return output_compare (operands, \"ule\", \"uge\", \"ugt\", \"ult\"); ")
196
197(define_insn ""
198 [(set (pc)
199 (if_then_else (lt (cc0)
200 (const_int 0))
201 (pc)
202 (label_ref (match_operand 0 "" ""))))]
203 ""
204 "* return output_compare (operands, \"ge\", \"le\", \"lt\", \"gt\"); ")
205
206(define_insn ""
207 [(set (pc)
208 (if_then_else (ltu (cc0)
209 (const_int 0))
210 (pc)
211 (label_ref (match_operand 0 "" ""))))]
212 ""
213 "* return output_compare (operands, \"uge\", \"ule\", \"ult\", \"ugt\"); ")
214
215(define_insn ""
216 [(set (pc)
217 (if_then_else (ge (cc0)
218 (const_int 0))
219 (pc)
220 (label_ref (match_operand 0 "" ""))))]
221 ""
222 "* return output_compare (operands, \"lt\", \"gt\", \"ge\", \"le\"); ")
223
224(define_insn ""
225 [(set (pc)
226 (if_then_else (geu (cc0)
227 (const_int 0))
228 (pc)
229 (label_ref (match_operand 0 "" ""))))]
230 ""
231 "* return output_compare (operands, \"ult\", \"ugt\", \"uge\", \"ule\"); ")
232
233(define_insn ""
234 [(set (pc)
235 (if_then_else (le (cc0)
236 (const_int 0))
237 (pc)
238 (label_ref (match_operand 0 "" ""))))]
239 ""
240 "* return output_compare (operands, \"gt\", \"lt\", \"le\", \"ge\"); ")
241
242(define_insn ""
243 [(set (pc)
244 (if_then_else (leu (cc0)
245 (const_int 0))
246 (pc)
247 (label_ref (match_operand 0 "" ""))))]
248 ""
249 "* return output_compare (operands, \"ugt\", \"ult\", \"ule\", \"uge\"); ")
250\f
251;; Move instructions
252
253(define_insn "movsi"
254 [(set (match_operand:SI 0 "general_operand" "=r,m")
255 (match_operand:SI 1 "general_operand" "rmi,rJ"))]
256 ""
257 "*
258{
259 if (GET_CODE (operands[0]) == MEM)
260 return \"st_32 %r1,%0\";
261 if (GET_CODE (operands[1]) == MEM)
262 return \"ld_32 %0,%1\;nop\";
263 if (GET_CODE (operands[1]) == REG)
264 return \"add_nt %0,%1,$0\";
265 if (GET_CODE (operands[1]) == SYMBOL_REF && operands[1]->unchanging)
266 return \"add_nt %0,r24,$(%1-0b)\";
267 return \"add_nt %0,r0,%1\";
268}")
269
270(define_insn ""
271 [(set (match_operand:SI 0 "register_operand" "=r")
272 (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
273 (match_operand:SI 2 "register_operand" "r"))))]
274 ""
275 "ld_32 %0,%1,%2\;nop")
276\f
277;; Generate insns for moving single bytes.
278
279(define_expand "movqi"
280 [(set (match_operand:QI 0 "general_operand" "")
281 (match_operand:QI 1 "general_operand" ""))]
282 ""
283 "
284{
285 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
286 operands[1] = copy_to_reg (operands[1]);
287
288 if (GET_CODE (operands[1]) == MEM)
289 {
290 rtx tem = gen_reg_rtx (SImode);
291 rtx addr = force_reg (SImode, XEXP (operands[1], 0));
292 rtx subreg;
293
294 emit_move_insn (tem, gen_rtx (MEM, SImode, addr));
295 if (GET_CODE (operands[0]) == SUBREG)
296 subreg = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[0]),
297 SUBREG_WORD (operands[0]));
298 else
299 subreg = gen_rtx (SUBREG, SImode, operands[0], 0);
300
301 emit_insn (gen_rtx (SET, VOIDmode, subreg,
302 gen_rtx (ZERO_EXTRACT, SImode, tem,
303 gen_rtx (CONST_INT, VOIDmode, 8),
304 addr)));
305 }
306 else if (GET_CODE (operands[0]) == MEM)
307 {
308 rtx tem = gen_reg_rtx (SImode);
309 rtx addr = force_reg (SImode, XEXP (operands[0], 0));
310 rtx subreg;
311
312 emit_move_insn (tem, gen_rtx (MEM, SImode, addr));
313 if (! CONSTANT_ADDRESS_P (operands[1]))
314 {
315 if (GET_CODE (operands[1]) == SUBREG)
316 subreg = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
317 SUBREG_WORD (operands[1]));
318 else
319 subreg = gen_rtx (SUBREG, SImode, operands[1], 0);
320 }
321
322 emit_insn (gen_rtx (SET, VOIDmode,
323 gen_rtx (ZERO_EXTRACT, SImode, tem,
324 gen_rtx (CONST_INT, VOIDmode, 8),
325 addr),
326 subreg));
327 emit_move_insn (gen_rtx (MEM, SImode, addr), tem);
328 }
329 else
330 {
331 emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
332 }
333 DONE;
334}")
335\f
336;; Recognize insns generated for moving single bytes.
337
338(define_insn ""
339 [(set (match_operand:QI 0 "general_operand" "=r,m")
340 (match_operand:QI 1 "general_operand" "rmi,r"))]
341 ""
342 "*
343{
344 if (GET_CODE (operands[0]) == MEM)
345 return \"st_32 %1,%0\";
346 if (GET_CODE (operands[1]) == MEM)
347 return \"ld_32 %0,%1\;nop\";
348 if (GET_CODE (operands[1]) == REG)
349 return \"add_nt %0,%1,$0\";
350 return \"add_nt %0,r0,%1\";
351}")
352
353(define_insn ""
354 [(set (match_operand:SI 0 "register_operand" "=r")
355 (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
356 (const_int 8)
357 (match_operand:SI 2 "nonmemory_operand" "rI")))]
358 ""
359 "extract %0,%1,%2")
360
361(define_insn ""
362 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
363 (const_int 8)
364 (match_operand:SI 1 "nonmemory_operand" "rI"))
365 (match_operand:SI 2 "nonmemory_operand" "ri"))]
366 ""
367 "wr_insert %1\;insert %0,%0,%2")
368
369;; Constant propagation can optimize the previous pattern into this pattern.
370;[Not any more. It could when the position-operand contains a MULT.]
371
372;(define_insn ""
373; [(set (zero_extract:QI (match_operand:SI 0 "register_operand" "+r")
374; (const_int 8)
375; (match_operand:SI 1 "immediate_operand" "I"))
376; (match_operand:QI 2 "register_operand" "r"))]
377; "GET_CODE (operands[1]) == CONST_INT
378; && INTVAL (operands[1]) % 8 == 0
379; && (unsigned) INTVAL (operands[1]) < 32"
380; "*
381;{
382; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8);
383; return \"wr_insert 0,0,%1\;insert %0,%0,%2\";
384;}")
385\f
386;; The three define_expand patterns on this page
387;; serve as subroutines of "movhi".
388
389;; Generate code to fetch an aligned halfword from memory.
390;; Operand 0 is the destination register (HImode).
391;; Operand 1 is the memory address (SImode).
392;; Operand 2 is a temporary (SImode).
393;; Operand 3 is a temporary (SImode).
394;; Operand 4 is a temporary (QImode).
395
396;; Operand 5 is an internal temporary (HImode).
397
398(define_expand "loadhi"
399 [(set (match_operand:SI 2 "register_operand" "")
400 (mem:SI (match_operand:SI 1 "register_operand" "")))
401 ;; Extract the low byte.
402 (set (subreg:SI (match_dup 5) 0)
403 (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 1)))
404 ;; Form address of high byte.
405 (set (match_operand:SI 3 "register_operand" "")
406 (plus:SI (match_dup 1) (const_int 1)))
407 ;; Extract the high byte.
408 (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0)
409 (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3)))
410 ;; Put the high byte in with the low one.
411 (set (zero_extract:SI (match_dup 5) (const_int 8) (const_int 1))
412 (subreg:SI (match_dup 4) 0))
413 (set (match_operand:HI 0 "register_operand" "") (match_dup 5))]
414 ""
415 "operands[5] = gen_reg_rtx (HImode);")
416
417;; Generate code to store an aligned halfword into memory.
418;; Operand 0 is the destination address (SImode).
419;; Operand 1 is the source register (HImode, not constant).
420;; Operand 2 is a temporary (SImode).
421;; Operand 3 is a temporary (SImode).
422;; Operand 4 is a temporary (QImode).
423
424;; Operand 5 is an internal variable made from operand 1.
425
426(define_expand "storehi"
427 [(set (match_operand:SI 2 "register_operand" "")
428 (mem:SI (match_operand:SI 0 "register_operand" "")))
429 ;; Insert the low byte.
430 (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0))
431 (match_dup 5))
432 ;; Form address of high byte.
433 (set (match_operand:SI 3 "register_operand" "")
434 (plus:SI (match_dup 0) (const_int 1)))
435 ;; Extract the high byte from the source.
436 (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0)
437 (zero_extract:SI (match_operand:HI 1 "register_operand" "")
438 (const_int 8) (const_int 1)))
439 ;; Store high byte into the memory word
440 (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))
441 (subreg:SI (match_dup 4) 0))
442 ;; Put memory word back into memory.
443 (set (mem:SI (match_dup 0))
444 (match_dup 2))]
445 ""
446 "
447{
448 if (GET_CODE (operands[1]) == SUBREG)
449 operands[5] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
450 SUBREG_WORD (operands[1]));
451 else
452 operands[5] = gen_rtx (SUBREG, SImode, operands[1], 0);
453}")
454
455;; Like storehi but operands[1] is a CONST_INT.
456
457(define_expand "storeinthi"
458 [(set (match_operand:SI 2 "register_operand" "")
459 (mem:SI (match_operand:SI 0 "register_operand" "")))
460 ;; Insert the low byte.
461 (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0))
462 (match_dup 5))
463 ;; Form address of high byte.
464 (set (match_operand:SI 3 "register_operand" "")
465 (plus:SI (match_dup 0) (const_int 1)))
466 ;; Store high byte into the memory word
467 (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))
468 (match_dup 6))
469 ;; Put memory word back into memory.
470 (set (mem:SI (match_dup 0))
471 (match_dup 2))]
472 ""
473 " operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 255);
474 operands[6] = gen_rtx (CONST_INT, VOIDmode,
475 (INTVAL (operands[1]) >> 8) & 255);
476")
477\f
478;; Main entry for generating insns to move halfwords.
479
480(define_expand "movhi"
481 [(set (match_operand:HI 0 "general_operand" "")
482 (match_operand:HI 1 "general_operand" ""))]
483 ""
484 "
485{
486 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
487 operands[1] = copy_to_reg (operands[1]);
488
489 if (GET_CODE (operands[1]) == MEM)
490 {
491 rtx insn =
492 emit_insn (gen_loadhi (operands[0],
493 force_reg (SImode, XEXP (operands[1], 0)),
494 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
495 gen_reg_rtx (QImode)));
496 /* Tell cse what value the loadhi produces, so it detect duplicates. */
497 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1],
498 REG_NOTES (insn));
499 }
500 else if (GET_CODE (operands[0]) == MEM)
501 {
502 if (GET_CODE (operands[1]) == CONST_INT)
503 emit_insn (gen_storeinthi (force_reg (SImode, XEXP (operands[0], 0)),
504 operands[1],
505 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
506 gen_reg_rtx (QImode)));
507 else
508 {
509 if (CONSTANT_P (operands[1]))
510 operands[1] = force_reg (HImode, operands[1]);
511 emit_insn (gen_storehi (force_reg (SImode, XEXP (operands[0], 0)),
512 operands[1],
513 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
514 gen_reg_rtx (QImode)));
515 }
516 }
517 else
518 emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
519 DONE;
520}")
521\f
522;; Recognize insns generated for moving halfwords.
523;; (Note that the extract and insert patterns for single-byte moves
524;; are also involved in recognizing some of the insns used for this purpose.)
525
526(define_insn ""
527 [(set (match_operand:HI 0 "general_operand" "=r,m")
528 (match_operand:HI 1 "general_operand" "rmi,r"))]
529 ""
530 "*
531{
532 if (GET_CODE (operands[0]) == MEM)
533 return \"st_32 %1,%0\";
534 if (GET_CODE (operands[1]) == MEM)
535 return \"ld_32 %0,%1\;nop\";
536 if (GET_CODE (operands[1]) == REG)
537 return \"add_nt %0,%1,$0\";
538 return \"add_nt %0,r0,%1\";
539}")
540
541(define_insn ""
542 [(set (match_operand:SI 0 "register_operand" "=r")
543 (zero_extract:SI (match_operand:HI 1 "register_operand" "r")
544 (const_int 8)
545 (match_operand:SI 2 "nonmemory_operand" "rI")))]
546 ""
547 "extract %0,%1,%2")
548
549(define_insn ""
550 [(set (zero_extract:SI (match_operand:HI 0 "register_operand" "+r")
551 (const_int 8)
552 (match_operand:SI 1 "nonmemory_operand" "rI"))
553 (match_operand:SI 2 "nonmemory_operand" "ri"))]
554 ""
555 "wr_insert %1\;insert %0,%0,%2")
556
557;; Constant propagation can optimize the previous pattern into this pattern.
558
559;(define_insn ""
560; [(set (zero_extract:QI (match_operand:HI 0 "register_operand" "+r")
561; (const_int 8)
562; (match_operand:SI 1 "immediate_operand" "I"))
563; (match_operand:QI 2 "register_operand" "r"))]
564; "GET_CODE (operands[1]) == CONST_INT
565; && INTVAL (operands[1]) % 8 == 0
566; && (unsigned) INTVAL (operands[1]) < 32"
567; "*
568;{
569; operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8);
570; return \"wr_insert 0,0,%1\;insert %0,%0,%2\";
571;}")
572\f
573;; This pattern forces (set (reg:DF ...) (const_double ...))
574;; to be reloaded by putting the constant into memory.
575;; It must come before the more general movdf pattern.
576(define_insn ""
577 [(set (match_operand:DF 0 "general_operand" "=&r,f,&o")
578 (match_operand:DF 1 "" "mG,m,G"))]
579 "GET_CODE (operands[1]) == CONST_DOUBLE"
580 "*
581{
582 if (FP_REG_P (operands[0]))
583 return output_fp_move_double (operands);
584 if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == REG)
585 {
586 operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
587 return \"add_nt %0,r0,$0\;add_nt %1,r0,$0\";
588 }
589 if (operands[1] == dconst0_rtx && GET_CODE (operands[0]) == MEM)
590 {
591 operands[1] = adj_offsettable_operand (operands[0], 4);
592 return \"st_32 r0,%0\;st_32 r0,%1\";
593 }
594 return output_move_double (operands);
595}
596")
597
598(define_insn "movdf"
599 [(set (match_operand:DF 0 "general_operand" "=r,&r,m,?f,?rm")
600 (match_operand:DF 1 "general_operand" "r,m,r,rfm,f"))]
601 ""
602 "*
603{
604 if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
605 return output_fp_move_double (operands);
606 return output_move_double (operands);
607}
608")
609
610(define_insn "movdi"
611 [(set (match_operand:DI 0 "general_operand" "=r,&r,m,?f,?rm")
612 (match_operand:DI 1 "general_operand" "r,m,r,rfm,f"))]
613 ""
614 "*
615{
616 if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
617 return output_fp_move_double (operands);
618 return output_move_double (operands);
619}
620")
621
622(define_insn "movsf"
623 [(set (match_operand:SF 0 "general_operand" "=rf,m")
624 (match_operand:SF 1 "general_operand" "rfm,rf"))]
625 ""
626 "*
627{
628 if (FP_REG_P (operands[0]))
629 {
630 if (FP_REG_P (operands[1]))
631 return \"fmov %0,%1\";
632 if (GET_CODE (operands[1]) == REG)
633 {
634 rtx xoperands[2];
635 int offset = - get_frame_size () - 8;
636 xoperands[1] = operands[1];
637 xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
638 output_asm_insn (\"st_32 %1,r25,%0\", xoperands);
639 xoperands[1] = operands[0];
640 output_asm_insn (\"ld_sgl %1,r25,%0\;nop\", xoperands);
641 return \"\";
642 }
643 return \"ld_sgl %0,%1\;nop\";
644 }
645 if (FP_REG_P (operands[1]))
646 {
647 if (GET_CODE (operands[0]) == REG)
648 {
649 rtx xoperands[2];
650 int offset = - get_frame_size () - 8;
651 xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
652 xoperands[1] = operands[1];
653 output_asm_insn (\"st_sgl %1,r25,%0\", xoperands);
654 xoperands[1] = operands[0];
655 output_asm_insn (\"ld_32 %1,r25,%0\;nop\", xoperands);
656 return \"\";
657 }
658 return \"st_sgl %1,%0\";
659 }
660 if (GET_CODE (operands[0]) == MEM)
661 return \"st_32 %r1,%0\";
662 if (GET_CODE (operands[1]) == MEM)
663 return \"ld_32 %0,%1\;nop\";
664 if (GET_CODE (operands[1]) == REG)
665 return \"add_nt %0,%1,$0\";
666 return \"add_nt %0,r0,%1\";
667}")
668\f
669;;- truncation instructions
670(define_insn "truncsiqi2"
671 [(set (match_operand:QI 0 "register_operand" "=r")
672 (truncate:QI
673 (match_operand:SI 1 "register_operand" "r")))]
674 ""
675 "add_nt %0,%1,$0")
676
677(define_insn "trunchiqi2"
678 [(set (match_operand:QI 0 "register_operand" "=r")
679 (truncate:QI
680 (match_operand:HI 1 "register_operand" "r")))]
681 ""
682 "add_nt %0,%1,$0")
683
684(define_insn "truncsihi2"
685 [(set (match_operand:HI 0 "register_operand" "=r")
686 (truncate:HI
687 (match_operand:SI 1 "register_operand" "r")))]
688 ""
689 "add_nt %0,%1,$0")
690\f
691;;- zero extension instructions
692
693;; Note that the one starting from HImode comes before those for QImode
694;; so that a constant operand will match HImode, not QImode.
695(define_expand "zero_extendhisi2"
696 [(set (match_operand:SI 0 "register_operand" "")
697 (and:SI (match_operand:HI 1 "register_operand" "") ;Changed to SI below
698 ;; This constant is invalid, but reloading will handle it.
699 ;; It's useless to generate here the insns to construct it
700 ;; because constant propagation would simplify them anyway.
701 (match_dup 2)))]
702 ""
703 "
704{
705 if (GET_CODE (operands[1]) == SUBREG)
706 operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
707 SUBREG_WORD (operands[1]));
708 else
709 operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
710
711 operands[2] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535));
712}")
713
714(define_insn "zero_extendqihi2"
715 [(set (match_operand:HI 0 "register_operand" "=r")
716 (zero_extend:HI
717 (match_operand:QI 1 "register_operand" "r")))]
718 ""
719 "extract %0,%1,$0")
720
721(define_insn "zero_extendqisi2"
722 [(set (match_operand:SI 0 "register_operand" "=r")
723 (zero_extend:SI
724 (match_operand:QI 1 "register_operand" "r")))]
725 ""
726 "extract %0,%1,$0")
727\f
728;;- sign extension instructions
729;; Note that the one starting from HImode comes before those for QImode
730;; so that a constant operand will match HImode, not QImode.
731
732(define_expand "extendhisi2"
733 [(set (match_dup 2)
734 (and:SI (match_operand:HI 1 "register_operand" "") ;Changed to SI below
735 (match_dup 4)))
736 (set (match_dup 3) (plus:SI (match_dup 2) (match_dup 5)))
737 (set (match_operand:SI 0 "register_operand" "")
738 (xor:SI (match_dup 3) (match_dup 5)))]
739 ""
740 "
741{
742 if (GET_CODE (operands[1]) == SUBREG)
743 operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
744 SUBREG_WORD (operands[1]));
745 else
746 operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
747
748 operands[2] = gen_reg_rtx (SImode);
749 operands[3] = gen_reg_rtx (SImode);
750 operands[4] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535));
751 operands[5] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, -32768));
752}")
753
754(define_expand "extendqihi2"
755 [(set (match_dup 2)
756 (and:HI (match_operand:QI 1 "register_operand" "") ;Changed to SI below
757 (const_int 255)))
758 (set (match_dup 3)
759 (plus:SI (match_dup 2) (const_int -128)))
760 (set (match_operand:HI 0 "register_operand" "")
761 (xor:SI (match_dup 3) (const_int -128)))]
762 ""
763 "
764{
765 if (GET_CODE (operands[1]) == SUBREG)
766 operands[1] = gen_rtx (SUBREG, HImode, SUBREG_REG (operands[1]),
767 SUBREG_WORD (operands[1]));
768 else
769 operands[1] = gen_rtx (SUBREG, HImode, operands[1], 0);
770
771 operands[2] = gen_reg_rtx (HImode);
772 operands[3] = gen_reg_rtx (HImode);
773}")
774
775(define_expand "extendqisi2"
776 [(set (match_dup 2)
777 (and:SI (match_operand:QI 1 "register_operand" "") ;Changed to SI below
778 (const_int 255)))
779 (set (match_dup 3) (plus:SI (match_dup 2) (const_int -128)))
780 (set (match_operand:SI 0 "register_operand" "")
781 (xor:SI (match_dup 3) (const_int -128)))]
782 ""
783 "
784{
785 if (GET_CODE (operands[1]) == SUBREG)
786 operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
787 SUBREG_WORD (operands[1]));
788 else
789 operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
790
791 operands[2] = gen_reg_rtx (SImode);
792 operands[3] = gen_reg_rtx (SImode);
793}")
794\f
795;;- arithmetic instructions
796
797(define_insn "addsi3"
798 [(set (match_operand:SI 0 "register_operand" "=r")
799 (plus:SI (match_operand:SI 1 "nonmemory_operand" "%r")
800 (match_operand:SI 2 "nonmemory_operand" "rI")))]
801 ""
802 "add %0,%1,%2")
803
804(define_insn ""
805 [(set (match_operand:SI 0 "register_operand" "=r")
806 (plus:SI (match_operand:SI 1 "nonmemory_operand" "%r")
807 (match_operand:SI 2 "big_immediate_operand" "g")))]
808 "GET_CODE (operands[2]) == CONST_INT
809 && (unsigned) (INTVAL (operands[2]) + 0x8000000) < 0x10000000"
810 "*
811{
812 return
813 output_add_large_offset (operands[0], operands[1], INTVAL (operands[2]));
814}")
815
816(define_insn "subsi3"
817 [(set (match_operand:SI 0 "register_operand" "=r")
818 (minus:SI (match_operand:SI 1 "register_operand" "r")
819 (match_operand:SI 2 "nonmemory_operand" "rI")))]
820 ""
821 "sub %0,%1,%2")
822
823(define_insn "andsi3"
824 [(set (match_operand:SI 0 "register_operand" "=r")
825 (and:SI (match_operand:SI 1 "nonmemory_operand" "%r")
826 (match_operand:SI 2 "nonmemory_operand" "rI")))]
827 ""
828 "and %0,%1,%2")
829
830(define_insn "iorsi3"
831 [(set (match_operand:SI 0 "register_operand" "=r")
832 (ior:SI (match_operand:SI 1 "nonmemory_operand" "%r")
833 (match_operand:SI 2 "nonmemory_operand" "rI")))]
834 ""
835 "or %0,%1,%2")
836
837(define_insn "xorsi3"
838 [(set (match_operand:SI 0 "register_operand" "=r")
839 (xor:SI (match_operand:SI 1 "nonmemory_operand" "%r")
840 (match_operand:SI 2 "nonmemory_operand" "rI")))]
841 ""
842 "xor %0,%1,%2")
843
844(define_insn "negsi2"
845 [(set (match_operand:SI 0 "register_operand" "=r")
846 (neg:SI (match_operand:SI 1 "nonmemory_operand" "rI")))]
847 ""
848 "sub %0,r0,%1")
849
850(define_insn "one_cmplsi2"
851 [(set (match_operand:SI 0 "register_operand" "=r")
852 (not:SI (match_operand:SI 1 "register_operand" "r")))]
853 ""
854 "xor %0,%1,$-1")
855\f
856;; Floating point arithmetic instructions.
857
858(define_insn "adddf3"
859 [(set (match_operand:DF 0 "register_operand" "=f")
860 (plus:DF (match_operand:DF 1 "register_operand" "f")
861 (match_operand:DF 2 "register_operand" "f")))]
862 "TARGET_FPU"
863 "fadd %0,%1,%2")
864
865(define_insn "addsf3"
866 [(set (match_operand:SF 0 "register_operand" "=f")
867 (plus:SF (match_operand:SF 1 "register_operand" "f")
868 (match_operand:SF 2 "register_operand" "f")))]
869 "TARGET_FPU"
870 "fadd %0,%1,%2")
871
872(define_insn "subdf3"
873 [(set (match_operand:DF 0 "register_operand" "=f")
874 (minus:DF (match_operand:DF 1 "register_operand" "f")
875 (match_operand:DF 2 "register_operand" "f")))]
876 "TARGET_FPU"
877 "fsub %0,%1,%2")
878
879(define_insn "subsf3"
880 [(set (match_operand:SF 0 "register_operand" "=f")
881 (minus:SF (match_operand:SF 1 "register_operand" "f")
882 (match_operand:SF 2 "register_operand" "f")))]
883 "TARGET_FPU"
884 "fsub %0,%1,%2")
885
886(define_insn "muldf3"
887 [(set (match_operand:DF 0 "register_operand" "=f")
888 (mult:DF (match_operand:DF 1 "register_operand" "f")
889 (match_operand:DF 2 "register_operand" "f")))]
890 "TARGET_FPU"
891 "fmul %0,%1,%2")
892
893(define_insn "mulsf3"
894 [(set (match_operand:SF 0 "register_operand" "=f")
895 (mult:SF (match_operand:SF 1 "register_operand" "f")
896 (match_operand:SF 2 "register_operand" "f")))]
897 "TARGET_FPU"
898 "fmul %0,%1,%2")
899
900(define_insn "divdf3"
901 [(set (match_operand:DF 0 "register_operand" "=f")
902 (div:DF (match_operand:DF 1 "register_operand" "f")
903 (match_operand:DF 2 "register_operand" "f")))]
904 "TARGET_FPU"
905 "fdiv %0,%1,%2")
906
907(define_insn "divsf3"
908 [(set (match_operand:SF 0 "register_operand" "=f")
909 (div:SF (match_operand:SF 1 "register_operand" "f")
910 (match_operand:SF 2 "register_operand" "f")))]
911 "TARGET_FPU"
912 "fdiv %0,%1,%2")
913
914(define_insn "negdf2"
915 [(set (match_operand:DF 0 "register_operand" "=f")
916 (neg:DF (match_operand:DF 1 "nonmemory_operand" "f")))]
917 "TARGET_FPU"
918 "fneg %0,%1")
919
920(define_insn "negsf2"
921 [(set (match_operand:SF 0 "register_operand" "=f")
922 (neg:SF (match_operand:SF 1 "nonmemory_operand" "f")))]
923 "TARGET_FPU"
924 "fneg %0,%1")
925
926(define_insn "absdf2"
927 [(set (match_operand:DF 0 "register_operand" "=f")
928 (abs:DF (match_operand:DF 1 "nonmemory_operand" "f")))]
929 "TARGET_FPU"
930 "fabs %0,%1")
931
932(define_insn "abssf2"
933 [(set (match_operand:SF 0 "register_operand" "=f")
934 (abs:SF (match_operand:SF 1 "nonmemory_operand" "f")))]
935 "TARGET_FPU"
936 "fabs %0,%1")
937\f
938;; Shift instructions
939
940(define_insn ""
941 [(set (match_operand:SI 0 "register_operand" "=r")
942 (ashift:SI (match_operand:SI 1 "register_operand" "r")
943 (match_operand:SI 2 "immediate_operand" "I")))]
944 "GET_CODE (operands[2]) == CONST_INT"
945 "*
946{
947 unsigned int amount = INTVAL (operands[2]);
948
949 switch (amount)
950 {
951 case 0:
952 return \"add_nt %0,%1,$0\";
953 case 1:
954 return \"sll %0,%1,$1\";
955 case 2:
956 return \"sll %0,%1,$2\";
957 default:
958 output_asm_insn (\"sll %0,%1,$3\", operands);
959
960 for (amount -= 3; amount >= 3; amount -= 3)
961 output_asm_insn (\"sll %0,%0,$3\", operands);
962
963 if (amount > 0)
964 output_asm_insn (amount == 1 ? \"sll %0,%0,$1\" : \"sll %0,%0,$2\",
965 operands);
966 return \"\";
967 }
968}")
969
970(define_insn ""
971 [(set (match_operand:SI 0 "register_operand" "=r")
972 (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
973 (match_operand:SI 2 "immediate_operand" "I")))]
974 "GET_CODE (operands[2]) == CONST_INT"
975 "*
976{
977 unsigned int amount = INTVAL (operands[2]);
978
979 if (amount == 0)
980 return \"add_nt %0,%1,$0\";
981 else
982 output_asm_insn (\"sra %0,%1,$1\", operands);
983
984 for (amount -= 1; amount > 0; amount -= 1)
985 output_asm_insn (\"sra %0,%0,$1\", operands);
986
987 return \"\";
988}")
989
990(define_insn ""
991 [(set (match_operand:SI 0 "register_operand" "=r")
992 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
993 (match_operand:SI 2 "immediate_operand" "I")))]
994 "GET_CODE (operands[2]) == CONST_INT"
995 "*
996{
997 unsigned int amount = INTVAL (operands[2]);
998
999 if (amount == 0)
1000 return \"add_nt %0,%1,$0\";
1001 else
1002 output_asm_insn (\"srl %0,%1,$1\", operands);
1003
1004 for (amount -= 1; amount > 0; amount -= 1)
1005 output_asm_insn (\"srl %0,%0,$1\", operands);
1006
1007 return \"\";
1008}")
1009
1010(define_expand "ashlsi3"
1011 [(set (match_operand:SI 0 "register_operand" "")
1012 (ashift:SI (match_operand:SI 1 "register_operand" "")
1013 (match_operand:SI 2 "nonmemory_operand" "")))]
1014 ""
1015 "
1016{
1017 if (GET_CODE (operands[2]) != CONST_INT
1018 || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 3))
1019 FAIL;
1020}")
1021
1022(define_expand "lshlsi3"
1023 [(set (match_operand:SI 0 "register_operand" "")
1024 (ashift:SI (match_operand:SI 1 "register_operand" "")
1025 (match_operand:SI 2 "nonmemory_operand" "")))]
1026 ""
1027 "
1028{
1029 if (GET_CODE (operands[2]) != CONST_INT
1030 || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 3))
1031 FAIL;
1032}")
1033
1034(define_expand "ashrsi3"
1035 [(set (match_operand:SI 0 "register_operand" "")
1036 (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
1037 (match_operand:SI 2 "nonmemory_operand" "")))]
1038 ""
1039 "
1040{
1041 if (GET_CODE (operands[2]) != CONST_INT
1042 || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 1))
1043 FAIL;
1044}")
1045
1046(define_expand "lshrsi3"
1047 [(set (match_operand:SI 0 "register_operand" "")
1048 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
1049 (match_operand:SI 2 "nonmemory_operand" "")))]
1050 ""
1051 "
1052{
1053 if (GET_CODE (operands[2]) != CONST_INT
1054 || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 1))
1055 FAIL;
1056}")
1057\f
1058;; Unconditional and other jump instructions
1059(define_insn "jump"
1060 [(set (pc)
1061 (label_ref (match_operand 0 "" "")))]
1062 ""
1063 "jump %l0\;nop")
1064
1065(define_insn "tablejump"
1066 [(set (pc) (match_operand:SI 0 "register_operand" "r"))
1067 (use (label_ref (match_operand 1 "" "")))]
1068 ""
1069 "jump_reg r0,%0\;nop")
1070
1071;;- jump to subroutine
1072(define_insn "call"
1073 [(call (match_operand:SI 0 "memory_operand" "m")
1074 (match_operand:SI 1 "general_operand" "g"))]
1075 ;;- Don't use operand 1 for most machines.
1076 ""
1077 "add_nt r2,%0\;call .+8\;jump_reg r0,r2\;nop")
1078
1079(define_insn "call_value"
1080 [(set (match_operand 0 "" "=g")
1081 (call (match_operand:SI 1 "memory_operand" "m")
1082 (match_operand:SI 2 "general_operand" "g")))]
1083 ;;- Don't use operand 1 for most machines.
1084 ""
1085 "add_nt r2,%1\;call .+8\;jump_reg r0,r2\;nop")
1086
1087;; A memory ref with constant address is not normally valid.
1088;; But it is valid in a call insns. This pattern allows the
1089;; loading of the address to combine with the call.
1090(define_insn ""
1091 [(call (mem:SI (match_operand:SI 0 "" "i"))
1092 (match_operand:SI 1 "general_operand" "g"))]
1093 ;;- Don't use operand 1 for most machines.
1094 "GET_CODE (operands[0]) == SYMBOL_REF"
1095 "call %0\;nop")
1096
1097(define_insn ""
1098 [(set (match_operand 0 "" "=g")
1099 (call (mem:SI (match_operand:SI 1 "" "i"))
1100 (match_operand:SI 2 "general_operand" "g")))]
1101 ;;- Don't use operand 1 for most machines.
1102 "GET_CODE (operands[1]) == SYMBOL_REF"
1103 "call %1\;nop")
1104
1105(define_insn "nop"
1106 [(const_int 0)]
1107 ""
1108 "nop")
1109\f
1110;;- Local variables:
1111;;- mode:emacs-lisp
1112;;- comment-start: ";;- "
1113;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
1114;;- eval: (modify-syntax-entry ?[ "(]")
1115;;- eval: (modify-syntax-entry ?] ")[")
1116;;- eval: (modify-syntax-entry ?{ "(}")
1117;;- eval: (modify-syntax-entry ?} "){")
1118;;- End:
1119