|
|
1.1 root 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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.