|
|
1.1 root 1: ;;- Machine description for ROMP chip for GNU C compiler
2: ;; Copyright (C) 1988, 1991, 1993 Free Software Foundation, Inc.
3: ;; Contributed by Richard Kenner ([email protected])
4:
5: ;; This file is part of GNU CC.
6:
7: ;; GNU CC is free software; you can redistribute it and/or modify
8: ;; it under the terms of the GNU General Public License as published by
9: ;; the Free Software Foundation; either version 2, or (at your option)
10: ;; any later version.
11:
12: ;; GNU CC is distributed in the hope that it will be useful,
13: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: ;; GNU General Public License for more details.
16:
17: ;; You should have received a copy of the GNU General Public License
18: ;; along with GNU CC; see the file COPYING. If not, write to
19: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20:
21:
22: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
23:
24: ;; Define the attributes for the ROMP.
25:
26: ;; Insn type. Used to default other attribute values.
27:
28: (define_attr "type"
29: "branch,ibranch,return,fp,load,loadz,store,call,address,arith,compare,multi,misc"
30: (const_string "arith"))
31:
32: ;; Length in bytes.
33:
34: (define_attr "length" ""
35: (cond [(eq_attr "type" "branch")
36: (if_then_else (and (ge (minus (pc) (match_dup 0))
37: (const_int -256))
38: (le (minus (pc) (match_dup 0))
39: (const_int 254)))
40: (const_int 2)
41: (const_int 4))
42: (eq_attr "type" "return,ibranch") (const_int 2)
43: (eq_attr "type" "fp") (const_int 10)
44: (eq_attr "type" "call") (const_int 4)
45: (eq_attr "type" "load")
46: (cond [(match_operand 1 "short_memory_operand" "") (const_int 2)
47: (match_operand 1 "symbolic_memory_operand" "") (const_int 8)]
48: (const_int 4))
49: (eq_attr "type" "loadz")
50: (cond [(match_operand 1 "zero_memory_operand" "") (const_int 2)
51: (match_operand 1 "symbolic_memory_operand" "") (const_int 8)]
52: (const_string "4"))
53: (eq_attr "type" "store")
54: (cond [(match_operand 0 "short_memory_operand" "") (const_int 2)
55: (match_operand 0 "symbolic_memory_operand" "") (const_int 8)]
56: (const_int 4))]
57: (const_int 4)))
58:
59: ;; Whether insn can be placed in a delay slot.
60:
61: (define_attr "in_delay_slot" "yes,no"
62: (cond [(eq_attr "length" "8,10,38") (const_string "no")
63: (eq_attr "type" "branch,ibranch,return,call,multi")
64: (const_string "no")]
65: (const_string "yes")))
66:
67: ;; Whether insn needs a delay slot. We have to say that two-byte
68: ;; branches do not need a delay slot. Otherwise, branch shortening will
69: ;; try to do something with delay slot insns (we want it to on the PA).
70: ;; This is a kludge, which should be cleaned up at some point.
71:
72: (define_attr "needs_delay_slot" "yes,no"
73: (if_then_else (ior (and (eq_attr "type" "branch")
74: (eq_attr "length" "4"))
75: (eq_attr "type" "ibranch,return,call"))
76: (const_string "yes") (const_string "no")))
77:
78: ;; What insn does to the condition code.
79:
80: (define_attr "cc"
81: "clobber,none,sets,change0,copy1to0,compare,tbit"
82: (cond [(eq_attr "type" "load,loadz") (const_string "change0")
83: (eq_attr "type" "store") (const_string "none")
84: (eq_attr "type" "fp,call") (const_string "clobber")
85: (eq_attr "type" "branch,ibranch,return") (const_string "none")
86: (eq_attr "type" "address") (const_string "change0")
87: (eq_attr "type" "compare") (const_string "compare")
88: (eq_attr "type" "arith") (const_string "sets")]
89: (const_string "clobber")))
90:
91: ;; Define attributes for `asm' insns.
92:
93: (define_asm_attributes [(set_attr "type" "misc")
94: (set_attr "length" "8")
95: (set_attr "in_delay_slot" "no")
96: (set_attr "cc" "clobber")])
97:
98: ;; Define the delay slot requirements for branches and calls. We don't have
99: ;; any annulled insns.
100: ;;
101: (define_delay (eq_attr "needs_delay_slot" "yes")
102: [(eq_attr "in_delay_slot" "yes") (nil) (nil)])
103:
104: ;; We cannot give a floating-point comparison a delay slot, even though it
105: ;; could make use of it. This is because it would confuse next_cc0_user
106: ;; to do so. Other fp insns can't get a delay slow because they set their
107: ;; result and use their input after the delay slot insn is executed. This
108: ;; isn't what reorg.c expects.
109:
110: ;; Define load & store delays. These were obtained by measurements done by
111: ;; [email protected].
112: ;;
113: ;; In general, the memory unit can support at most two simultaneous operations.
114: ;;
115: ;; Loads take 5 cycles to return the data and can be pipelined up to the
116: ;; limit of two simultaneous operations.
117: (define_function_unit "memory" 1 2 (eq_attr "type" "load,loadz") 5 0)
118:
119: ;; Stores do not return data, but tie up the memory unit for 2 cycles if the
120: ;; next insn is also a store.
121: (define_function_unit "memory" 1 2 (eq_attr "type" "store") 1 2
122: [(eq_attr "type" "store")])
123:
124: ;; Move word instructions.
125: ;;
126: ;; If destination is memory but source is not register, force source to
127: ;; register.
128: ;;
129: ;; If source is a constant that is too large to load in a single insn, build
130: ;; it in two pieces.
131: ;;
132: ;; If destination is memory and source is a register, a temporary register
133: ;; will be needed. In that case, make a PARALLEL of the SET and a
134: ;; CLOBBER of a SCRATCH to allocate the required temporary.
135: ;;
136: ;; This temporary is ACTUALLY only needed when the destination is a
137: ;; relocatable expression. For generating RTL, however, we always
138: ;; place the CLOBBER. In insns where it is not needed, the SCRATCH will
139: ;; not be allocated to a register.
140: ;;
141: ;; Also, avoid creating pseudo-registers or SCRATCH rtx's during reload as
142: ;; they will not be correctly handled. We never need pseudos for that
143: ;; case anyway.
144: ;;
145: ;; We do not use DEFINE_SPLIT for loading constants because the number
146: ;; of cases in the resulting unsplit insn would be too high to deal
147: ;; with practically.
148: (define_expand "movsi"
149: [(set (match_operand:SI 0 "general_operand" "")
150: (match_operand:SI 1 "general_operand" ""))]
151: ""
152: "
153: { rtx op0 = operands[0];
154: rtx op1 = operands[1];
155:
156: if (GET_CODE (op1) == REG && REGNO (op1) == 16)
157: DONE;
158:
159: if (GET_CODE (op0) == REG && REGNO (op0) == 16)
160: DONE;
161:
162: if (GET_CODE (op0) == MEM && ! reload_in_progress)
163: {
164: emit_insn (gen_storesi (operands[0], force_reg (SImode, operands[1])));
165: DONE;
166: }
167: else if (GET_CODE (op1) == CONST_INT)
168: {
169: int const_val = INTVAL (op1);
170:
171: /* Try a number of cases to see how to best load the constant. */
172: if ((const_val & 0xffff) == 0
173: || (const_val & 0xffff0000) == 0
174: || (unsigned) (const_val + 0x8000) < 0x10000)
175: /* Can do this in one insn, so generate it. */
176: ;
177: else if (((- const_val) & 0xffff) == 0
178: || ((- const_val) & 0xffff0000) == 0
179: || (unsigned) ((- const_val) + 0x8000) < 0x10000)
180: {
181: /* Can do this by loading the negative constant and then negating. */
182: emit_move_insn (operands[0],
183: gen_rtx (CONST_INT, VOIDmode, - const_val));
184: emit_insn (gen_negsi2 (operands[0], operands[0]));
185: DONE;
186: }
187: else
188: /* Do this the long way. */
189: {
190: unsigned int high_part = const_val & 0xffff0000;
191: unsigned int low_part = const_val & 0xffff;
192: int i;
193:
194: if (low_part >= 0x10 && exact_log2 (low_part) >= 0)
195: i = high_part, high_part = low_part, low_part = i;
196:
197: emit_move_insn (operands[0],
198: gen_rtx (CONST_INT, VOIDmode, low_part));
199: emit_insn (gen_iorsi3 (operands[0], operands[0],
200: gen_rtx (CONST_INT, VOIDmode, high_part)));
201: DONE;
202: }
203: }
204: }")
205:
206: ;; Move from a symbolic memory location to a register is special. In this
207: ;; case, we know in advance that the register cannot be r0, so we can improve
208: ;; register allocation by treating it separately.
209:
210: (define_insn ""
211: [(set (match_operand:SI 0 "register_operand" "=b")
212: (match_operand:SI 1 "symbolic_memory_operand" "m"))]
213: ""
214: "load %0,%1"
215: [(set_attr "type" "load")])
216:
217: ;; Generic single-word move insn. We avoid the case where the destination is
218: ;; a symbolic address, as that needs a temporary register.
219:
220: (define_insn ""
221: [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,r,r,r,b,Q")
222: (match_operand:SI 1 "romp_operand" "rR,I,K,L,M,S,s,Q,m,r"))]
223: "register_operand (operands[0], SImode)
224: || register_operand (operands[1], SImode)"
225: "@
226: cas %0,%1,r0
227: lis %0,%1
228: cal %0,%1(r0)
229: cal16 %0,%1(r0)
230: cau %0,%H1(r0)
231: ail %0,r14,%C1
232: get %0,$%1
233: l%M1 %0,%1
234: load %0,%1
235: st%M0 %1,%0"
236: [(set_attr "type" "address,address,address,address,address,arith,misc,load,load,store")
237: (set_attr "length" "2,2,4,4,4,4,8,*,*,*")])
238:
239: (define_insn "storesi"
240: [(set (match_operand:SI 0 "memory_operand" "=Q,m")
241: (match_operand:SI 1 "register_operand" "r,r"))
242: (clobber (match_scratch:SI 2 "=X,&b"))]
243: ""
244: "@
245: st%M0 %1,%0
246: store %1,%0,%2"
247: [(set_attr "type" "store")])
248:
249: ;; This pattern is used by reload when we store into a symbolic address. It
250: ;; provides the temporary register required. This pattern is only used
251: ;; when SECONDARY_OUTPUT_RELOAD_CLASS returns something other than
252: ;; NO_REGS, so we need not have any predicates here.
253:
254: (define_expand "reload_outsi"
255: [(parallel [(set (match_operand:SI 0 "symbolic_memory_operand" "=m")
256: (match_operand:SI 1 "" "r"))
257: (clobber (match_operand:SI 2 "" "=&b"))])]
258: ""
259: "")
260:
261: ;; Now do the same for the QI move instructions.
262: (define_expand "movqi"
263: [(set (match_operand:QI 0 "general_operand" "")
264: (match_operand:QI 1 "general_operand" ""))]
265: ""
266: "
267: { rtx op0 = operands[0];
268:
269: if (GET_CODE (op0) == MEM && ! reload_in_progress)
270: {
271: emit_insn (gen_storeqi (operands[0], force_reg (QImode, operands[1])));
272: DONE;
273: }
274: }")
275:
276: (define_insn ""
277: [(set (match_operand:QI 0 "register_operand" "=b")
278: (match_operand:QI 1 "symbolic_memory_operand" "m"))]
279: ""
280: "loadc %0,%1"
281: [(set_attr "type" "load")])
282:
283: (define_insn ""
284: [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q")
285: (match_operand:QI 1 "romp_operand" "r,I,n,s,Q,m,r"))]
286: "register_operand (operands[0], QImode)
287: || register_operand (operands[1], QImode)"
288: "@
289: cas %0,%1,r0
290: lis %0,%1
291: cal %0,%L1(r0)
292: get %0,$%1
293: lc%M1 %0,%1
294: loadc %0,%1
295: stc%M0 %1,%0"
296: [(set_attr "type" "address,address,address,misc,load,load,store")
297: (set_attr "length" "2,2,4,8,*,*,*")])
298:
299: (define_insn "storeqi"
300: [(set (match_operand:QI 0 "memory_operand" "=Q,m")
301: (match_operand:QI 1 "register_operand" "r,r"))
302: (clobber (match_scratch:SI 2 "=X,&b"))]
303: ""
304: "@
305: stc%M0 %1,%0
306: storec %1,%0,%2"
307: [(set_attr "type" "store")])
308:
309: (define_expand "reload_outqi"
310: [(parallel [(set (match_operand:QI 0 "symbolic_memory_operand" "=m")
311: (match_operand:QI 1 "" "r"))
312: (clobber (match_operand:SI 2 "" "=&b"))])]
313: ""
314: "")
315:
316: ;; Finally, the HI instructions.
317: (define_expand "movhi"
318: [(set (match_operand:HI 0 "general_operand" "")
319: (match_operand:HI 1 "general_operand" ""))]
320: ""
321: "
322: { rtx op0 = operands[0];
323:
324: if (GET_CODE (op0) == MEM && ! reload_in_progress)
325: {
326: emit_insn (gen_storehi (operands[0], force_reg (HImode, operands[1])));
327: DONE;
328: }
329: }")
330:
331: (define_insn ""
332: [(set (match_operand:HI 0 "register_operand" "=b")
333: (match_operand:HI 1 "symbolic_memory_operand" "m"))]
334: ""
335: "loadha %0,%1"
336: [(set_attr "type" "load")])
337:
338:
339: ;; use cal16 instead of cal for constant source because combine requires
340: ;; the high bits of the register to be 0 after a HImode load of a constant
341:
342: (define_insn ""
343: [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,b,Q")
344: (match_operand:HI 1 "romp_operand" "r,I,n,s,Q,m,r"))]
345: "register_operand (operands[0], HImode)
346: || register_operand (operands[1], HImode)"
347: "@
348: cas %0,%1,r0
349: lis %0,%1
350: cal16 %0,%L1(r0)
351: get %0,$%1
352: lh%N1 %0,%1
353: loadh %0,%1
354: sth%M0 %1,%0"
355: [(set_attr "type" "address,address,address,misc,loadz,loadz,store")
356: (set_attr "length" "2,2,4,8,*,*,*")])
357:
358: (define_insn "storehi"
359: [(set (match_operand:HI 0 "memory_operand" "=Q,m")
360: (match_operand:HI 1 "register_operand" "r,r"))
361: (clobber (match_scratch:SI 2 "=X,&b"))]
362: ""
363: "@
364: sth%M0 %1,%0
365: storeh %1,%0,%2"
366: [(set_attr "type" "store")])
367:
368: (define_expand "reload_outhi"
369: [(parallel [(set (match_operand:HI 0 "symbolic_memory_operand" "=m")
370: (match_operand:HI 1 "" "r"))
371: (clobber (match_operand:SI 2 "" "=&b"))])]
372: ""
373: "")
374:
375: ;; For DI move, if we have a constant, break the operation apart into
376: ;; two SImode moves because the optimizer may be able to do a better job
377: ;; with the resulting code.
378: ;;
379: ;; For memory stores, make the required pseudo for a temporary in case we
380: ;; are storing into an absolute address.
381: ;;
382: ;; We need to be careful about the cases where the output is a register that is
383: ;; the second register of the input.
384:
385: (define_expand "movdi"
386: [(set (match_operand:DI 0 "general_operand" "")
387: (match_operand:DI 1 "general_operand" ""))]
388: ""
389: "
390: { rtx op0 = operands[0];
391: rtx op1 = operands[1];
392:
393: if (CONSTANT_P (op1))
394: {
395: rtx insns;
396:
397: start_sequence ();
398: emit_move_insn (operand_subword (op0, 0, 1, DImode),
399: operand_subword (op1, 0, 1, DImode));
400: emit_move_insn (operand_subword (op0, 1, 1, DImode),
401: operand_subword (op1, 1, 1, DImode));
402: insns = get_insns ();
403: end_sequence ();
404:
405: emit_no_conflict_block (insns, op0, op1, 0, op1);
406: DONE;
407: }
408:
409: if (GET_CODE (op0) == MEM && ! reload_in_progress)
410: {
411: emit_insn (gen_storedi (operands[0], force_reg (DImode, operands[1])));
412: DONE;
413: }
414: }")
415:
416: (define_insn ""
417: [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q")
418: (match_operand:DI 1 "reg_or_mem_operand" "r,Q,m,r"))]
419: "register_operand (operands[0], DImode)
420: || register_operand (operands[1], DImode)"
421: "*
422: {
423: switch (which_alternative)
424: {
425: case 0:
426: if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
427: return \"cas %O0,%O1,r0\;cas %0,%1,r0\";
428: else
429: return \"cas %0,%1,r0\;cas %O0,%O1,r0\";
430: case 1:
431: /* Here we must see which word to load first. We default to the
432: low-order word unless it occurs in the address. */
433: if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
434: operands[1], 0))
435: return \"l%M1 %O0,%O1\;l%M1 %0,%1\";
436: else
437: return \"l%M1 %0,%1\;l%M1 %O0,%O1\";
438: case 2:
439: return \"get %O0,$%1\;ls %0,0(%O0)\;ls %O0,4(%O0)\";
440: case 3:
441: return \"st%M0 %1,%0\;st%M0 %O1,%O0\";
442: }
443: }"
444: [(set_attr "type" "multi")
445: (set_attr "cc" "change0,change0,change0,none")
446: (set_attr "length" "4,12,8,8")])
447:
448: (define_insn "storedi"
449: [(set (match_operand:DI 0 "memory_operand" "=Q,m")
450: (match_operand:DI 1 "register_operand" "r,r"))
451: (clobber (match_scratch:SI 2 "=X,&b"))]
452: ""
453: "@
454: st%M0 %1,%0\;st%M0 %O1,%O0
455: get %2,$%0\;sts %1,0(%2)\;sts %O1,4(%2)"
456: [(set_attr "type" "multi,multi")
457: (set_attr "cc" "none,none")
458: (set_attr "length" "8,12")])
459:
460: (define_expand "reload_outdi"
461: [(parallel [(set (match_operand:DI 0 "symbolic_memory_operand" "=m")
462: (match_operand:DI 1 "" "r"))
463: (clobber (match_operand:SI 2 "" "=&b"))])]
464: ""
465: "")
466:
467: ;; Split symbolic memory operands differently. We first load the address
468: ;; into a register and then do the two loads or stores. We can only do
469: ;; this if operand_subword won't produce a SUBREG, which is only when
470: ;; operands[0] is a hard register. Thus, these won't be used during the
471: ;; first insn scheduling pass.
472: (define_split
473: [(set (match_operand:DI 0 "register_operand" "")
474: (match_operand:DI 1 "symbolic_memory_operand" ""))]
475: "GET_CODE (operands[0]) == REG
476: && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER"
477: [(set (match_dup 2) (match_dup 3))
478: (set (match_dup 4) (match_dup 5))
479: (set (match_dup 6) (match_dup 7))]
480: "
481: { operands[2] = operand_subword (operands[0], 1, 0, DImode);
482: operands[3] = XEXP (operands[1], 0);
483: operands[4] = operand_subword (operands[0], 0, 0, DImode);
484: operands[5] = gen_rtx (MEM, SImode, operands[2]);
485: operands[6] = operands[2];
486: operands[7] = gen_rtx (MEM, SImode,
487: gen_rtx (PLUS, SImode, operands[2],
488: gen_rtx (CONST_INT, VOIDmode, 4)));
489:
490: if (operands[2] == 0 || operands[4] == 0)
491: FAIL;
492: }")
493:
494: (define_split
495: [(set (match_operand:DI 0 "symbolic_memory_operand" "")
496: (match_operand:DI 1 "register_operand" ""))
497: (clobber (match_operand:SI 2 "register_operand" ""))]
498: "GET_CODE (operands[0]) == REG
499: && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER"
500: [(set (match_dup 2) (match_dup 3))
501: (set (match_dup 4) (match_dup 5))
502: (set (match_dup 6) (match_dup 7))]
503: "
504: { operands[3] = XEXP (operands[0], 0);
505: operands[4] = gen_rtx (MEM, SImode, operands[2]);
506: operands[5] = operand_subword (operands[1], 0, 0, DImode);
507: operands[6] = gen_rtx (MEM, SImode,
508: gen_rtx (PLUS, SImode, operands[2],
509: gen_rtx (CONST_INT, VOIDmode, 4)));
510: operands[7] = operand_subword (operands[1], 1, 0, DImode);
511:
512: if (operands[5] == 0 || operands[7] == 0)
513: FAIL;
514: }")
515:
516: ;; If the output is a register and the input is memory, we have to be careful
517: ;; and see which word needs to be loaded first.
518: ;;
519: ;; Note that this case doesn't have a CLOBBER. Therefore, we must either
520: ;; be after reload or operand[0] must not be a MEM. So we don't need a
521: ;; CLOBBER on the new insns either.
522: ;;
523: ;; Due to a bug in sched.c, we do not want to split this insn if both
524: ;; operands are registers and they overlap unless reload has completed.
525: (define_split
526: [(set (match_operand:DI 0 "general_operand" "")
527: (match_operand:DI 1 "general_operand" ""))]
528: "! symbolic_memory_operand (operands[0], DImode)
529: && ! symbolic_memory_operand (operands[1], DImode)
530: && ! (GET_CODE (operands[0]) == REG
531: && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
532: && ! (GET_CODE (operands[1]) == REG
533: && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
534: && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
535: && ! reload_completed
536: && reg_overlap_mentioned_p (operands[0], operands[1]))"
537: [(set (match_dup 2) (match_dup 3))
538: (set (match_dup 4) (match_dup 5))]
539: "
540: { if (GET_CODE (operands[0]) != REG
541: || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
542: operands[1], 0))
543: {
544: operands[2] = operand_subword (operands[0], 0, 0, DImode);
545: operands[3] = operand_subword (operands[1], 0, 0, DImode);
546: operands[4] = operand_subword (operands[0], 1, 0, DImode);
547: operands[5] = operand_subword (operands[1], 1, 0, DImode);
548: }
549: else
550: {
551: operands[2] = operand_subword (operands[0], 1, 0, DImode);
552: operands[3] = operand_subword (operands[1], 1, 0, DImode);
553: operands[4] = operand_subword (operands[0], 0, 0, DImode);
554: operands[5] = operand_subword (operands[1], 0, 0, DImode);
555: }
556:
557: if (operands[2] == 0 || operands[3] == 0
558: || operands[4] == 0 || operands[5] == 0)
559: FAIL;
560: }")
561:
562: (define_split
563: [(set (match_operand:DI 0 "general_operand" "")
564: (match_operand:DI 1 "general_operand" ""))
565: (clobber (match_operand:SI 6 "register_operand" ""))]
566: "! symbolic_memory_operand (operands[0], DImode)
567: && ! symbolic_memory_operand (operands[1], DImode)
568: && ! (GET_CODE (operands[0]) == REG
569: && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
570: && ! (GET_CODE (operands[1]) == REG
571: && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
572: && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
573: && ! reload_completed
574: && reg_overlap_mentioned_p (operands[0], operands[1]))"
575: [(parallel [(set (match_dup 2) (match_dup 3))
576: (clobber (match_dup 7))])
577: (parallel [(set (match_dup 4) (match_dup 5))
578: (clobber (match_dup 8))])]
579: "
580: { if (GET_CODE (operands[0]) != REG
581: || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
582: operands[1], 0))
583: {
584: operands[2] = operand_subword (operands[0], 0, 0, DImode);
585: operands[3] = operand_subword (operands[1], 0, 0, DImode);
586: operands[4] = operand_subword (operands[0], 1, 0, DImode);
587: operands[5] = operand_subword (operands[1], 1, 0, DImode);
588: }
589: else
590: {
591: operands[2] = operand_subword (operands[0], 1, 0, DImode);
592: operands[3] = operand_subword (operands[1], 1, 0, DImode);
593: operands[4] = operand_subword (operands[0], 0, 0, DImode);
594: operands[5] = operand_subword (operands[1], 0, 0, DImode);
595: }
596:
597: if (operands[2] == 0 || operands[3] == 0
598: || operands[4] == 0 || operands[5] == 0)
599: FAIL;
600:
601: /* We must be sure to make two different SCRATCH operands, since they
602: are not allowed to be shared. After reload, however, we only have
603: a SCRATCH if we won't use the operand, so it is allowed to share it
604: then. */
605: if (reload_completed || GET_CODE (operands[6]) != SCRATCH)
606: operands[7] = operands[8] = operands[6];
607: else
608: {
609: operands[7] = gen_rtx (SCRATCH, SImode);
610: operands[8] = gen_rtx (SCRATCH, SImode);
611: }
612: }")
613:
614: ;; Define move insns for SF, and DF.
615: ;;
616: ;; For register-register copies or a copy of something to itself, emit a
617: ;; single SET insn since it will likely be optimized away.
618: ;;
619: ;; Otherwise, emit a floating-point move operation unless both input and
620: ;; output are either constant, memory, or a non-floating-point hard register.
621: (define_expand "movdf"
622: [(parallel [(set (match_operand:DF 0 "general_operand" "")
623: (match_operand:DF 1 "general_operand" ""))
624: (clobber (reg:SI 0))
625: (clobber (reg:SI 15))])]
626: ""
627: "
628: { rtx op0 = operands[0];
629: rtx op1 = operands[1];
630:
631: if (op0 == op1)
632: {
633: emit_insn (gen_rtx (SET, VOIDmode, op0, op1));
634: DONE;
635: }
636:
637: if ((GET_CODE (op0) == MEM
638: || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER
639: && ! FP_REGNO_P (REGNO (op0))))
640: && (GET_CODE (op1) == MEM
641: || GET_CODE (op1) == CONST_DOUBLE
642: || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER
643: && ! FP_REGNO_P (REGNO (op1)) && ! rtx_equal_p (op0, op1))))
644: {
645: rtx insns;
646:
647: if (GET_CODE (op1) == CONST_DOUBLE)
648: op1 = force_const_mem (DFmode, op1);
649:
650: start_sequence ();
651: if (GET_CODE (operands[0]) != REG
652: || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
653: operands[1]), 0)
654: {
655: emit_move_insn (operand_subword (op0, 0, 1, DFmode),
656: operand_subword_force (op1, 0, DFmode));
657: emit_move_insn (operand_subword (op0, 1, 1, DFmode),
658: operand_subword_force (op1, 1, DFmode));
659: }
660: else
661: {
662: emit_move_insn (operand_subword (op0, 1, 1, DFmode),
663: operand_subword_force (op1, 1, DFmode));
664: emit_move_insn (operand_subword (op0, 0, 1, DFmode),
665: operand_subword_force (op1, 0, DFmode));
666: }
667:
668: insns = get_insns ();
669: end_sequence ();
670:
671: emit_no_conflict_block (insns, op0, op1, 0, op1);
672: DONE;
673: }
674: }")
675:
676: (define_expand "movsf"
677: [(parallel [(set (match_operand:SF 0 "general_operand" "")
678: (match_operand:SF 1 "general_operand" ""))
679: (clobber (reg:SI 0))
680: (clobber (reg:SI 15))])]
681: ""
682: "
683: { rtx op0 = operands[0];
684: rtx op1 = operands[1];
685:
686: if (op0 == op1)
687: {
688: emit_insn (gen_rtx (SET, VOIDmode, op0, op1));
689: DONE;
690: }
691:
692: if ((GET_CODE (op0) == MEM
693: || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER
694: && ! FP_REGNO_P (REGNO (op0))))
695: && (GET_CODE (op1) == MEM
696: || GET_CODE (op1) == CONST_DOUBLE
697: || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER
698: && ! FP_REGNO_P (REGNO (op1)))))
699: {
700: rtx last;
701:
702: if (GET_CODE (op1) == CONST_DOUBLE)
703: op1 = force_const_mem (SFmode, op1);
704:
705: last = emit_move_insn (operand_subword (op0, 0, 1, SFmode),
706: operand_subword_force (op1, 0, SFmode));
707:
708: REG_NOTES (last) = gen_rtx (EXPR_LIST, REG_EQUAL, op1, REG_NOTES (last));
709: DONE;
710: }
711: }")
712:
713: ;; Define the move insns for SF and DF. Check for all general regs
714: ;; in the FP insns and make them non-FP if so. Do the same if the input and
715: ;; output are the same (the insn will be deleted in this case and we don't
716: ;; want to think there are FP insns when there might not be).
717: (define_insn ""
718: [(set (match_operand:SF 0 "general_operand" "=*frg")
719: (match_dup 0))]
720: ""
721: "nopr r0"
722: [(set_attr "type" "address")
723: (set_attr "length" "2")])
724:
725: (define_insn ""
726: [(set (match_operand:SF 0 "general_operand" "=r,*fr,r,r,Q,m,frg")
727: (match_operand:SF 1 "general_operand" "r,0,Q,m,r,r,frg"))
728: (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z"))
729: (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))]
730: ""
731: "*
732: { switch (which_alternative)
733: {
734: case 0:
735: return \"cas %0,%1,r0\";
736: case 1:
737: return \"nopr r0\";
738: case 2:
739: return \"l%M1 %0,%1\";
740: case 3:
741: return \"load %0,%1\";
742: case 4:
743: return \"st%M0 %1,%0\";
744: case 5:
745: return \"store %1,%0,%3\";
746: default:
747: return output_fpop (SET, operands[0], operands[1], 0, insn);
748: }
749: }"
750: [(set_attr "type" "address,address,load,load,store,store,fp")
751: (set_attr "length" "2,2,*,*,*,*,*")])
752:
753: (define_insn ""
754: [(set (match_operand:DF 0 "general_operand" "=*frg")
755: (match_dup 0))]
756: ""
757: "nopr r0"
758: [(set_attr "type" "address")
759: (set_attr "length" "2")])
760:
761: (define_insn ""
762: [(set (match_operand:DF 0 "general_operand" "=r,*fr,r,r,Q,m,frg")
763: (match_operand:DF 1 "general_operand" "r,0,Q,m,r,r,*frg"))
764: (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z"))
765: (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))]
766: ""
767: "*
768: { switch (which_alternative)
769: {
770: case 0:
771: if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
772: return \"cas %O0,%O1,r0\;cas %0,%1,r0\";
773: else
774: return \"cas %0,%1,r0\;cas %O0,%O1,r0\";
775: case 1:
776: return \"nopr r0\";
777: case 2:
778: /* Here we must see which word to load first. We default to the
779: low-order word unless it occurs in the address. */
780: if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
781: operands[1], 0))
782: return \"l%M1 %O0,%O1\;l%M1 %0,%1\";
783: else
784: return \"l%M1 %0,%1\;l%M1 %O0,%O1\";
785: case 3:
786: return \"get %3,$%1\;ls %0,0(%3)\;ls %O0,4(%3)\";
787: case 4:
788: return \"st%M0 %1,%0\;st%M0 %O1,%O0\";
789: case 5:
790: return \"get %3,$%0\;sts %1,0(%3)\;sts %O1,4(%3)\";
791: default:
792: return output_fpop (SET, operands[0], operands[1], 0, insn);
793: }
794: }"
795: [(set_attr "type" "address,multi,multi,multi,multi,multi,fp")
796: (set_attr "length" "2,4,*,*,*,*,*")])
797:
798: ;; Split all the above cases that involve multiple insns and no floating-point
799: ;; data block. If before reload, we can make a SCRATCH. Otherwise, use
800: ;; register 15.
801:
802: (define_split
803: [(set (match_operand:DF 0 "register_operand" "")
804: (match_operand:DF 1 "symbolic_memory_operand" ""))
805: (clobber (reg:SI 0))
806: (clobber (reg:SI 15))]
807: "GET_CODE (operands[0]) == REG && REGNO (operands[0]) < 16"
808: [(set (reg:SI 15) (match_dup 2))
809: (set (match_dup 3) (match_dup 4))
810: (set (match_dup 5) (match_dup 6))]
811: "
812: { operands[2] = XEXP (operands[1], 0);
813: operands[3] = operand_subword (operands[0], 0, 0, DFmode);
814: operands[4] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15));
815: operands[5] = operand_subword (operands[0], 1, 0, DFmode);
816: operands[6] = gen_rtx (MEM, SImode,
817: gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15),
818: gen_rtx (CONST_INT, VOIDmode, 4)));
819:
820: if (operands[3] == 0 || operands[5] == 0)
821: FAIL;
822: }")
823:
824: (define_split
825: [(set (match_operand:DF 0 "symbolic_memory_operand" "")
826: (match_operand:DF 1 "register_operand" ""))
827: (clobber (reg:SI 0))
828: (clobber (reg:SI 15))]
829: "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 16"
830: [(set (reg:SI 15) (match_dup 2))
831: (set (match_dup 3) (match_dup 4))
832: (set (match_dup 5) (match_dup 6))]
833: "
834: { operands[2] = XEXP (operands[0], 0);
835: operands[3] = gen_rtx (MEM, SImode, gen_rtx (REG, SImode, 15));
836: operands[4] = operand_subword (operands[1], 0, 0, DFmode);
837: operands[5] = gen_rtx (MEM, SImode,
838: gen_rtx (PLUS, SImode, gen_rtx (REG, SImode, 15),
839: gen_rtx (CONST_INT, VOIDmode, 4)));
840: operands[6] = operand_subword (operands[1], 1, 0, DFmode);
841:
842: if (operands[4] == 0 || operands[6] == 0)
843: FAIL;
844: }")
845:
846: ;; If the output is a register and the input is memory, we have to be careful
847: ;; and see which word needs to be loaded first. We also cannot to the
848: ;; split if the input is a constant because it would result in invalid
849: ;; insns. When the output is a MEM, we must put a CLOBBER on each of the
850: ;; resulting insn, when it is not a MEM, we must not.
851: (define_split
852: [(set (match_operand:DF 0 "memory_operand" "")
853: (match_operand:DF 1 "register_operand" ""))
854: (clobber (reg:SI 0))
855: (clobber (reg:SI 15))]
856: "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 15"
857: [(parallel [(set (match_dup 2) (match_dup 3))
858: (clobber (match_dup 6))])
859: (parallel [(set (match_dup 4) (match_dup 5))
860: (clobber (match_dup 7))])]
861: "
862: { operands[2] = operand_subword (operands[0], 0, 0, DFmode);
863: operands[3] = operand_subword (operands[1], 0, 0, DFmode);
864: operands[4] = operand_subword (operands[0], 1, 0, DFmode);
865: operands[5] = operand_subword (operands[1], 1, 0, DFmode);
866:
867: if (operands[2] == 0 || operands[3] == 0
868: || operands[4] == 0 || operands[5] == 0)
869: FAIL;
870:
871: if (reload_completed)
872: operands[6] = operands[7] = gen_rtx (REG, SImode, 15);
873: else
874: {
875: operands[6] = gen_rtx (SCRATCH, SImode);
876: operands[7] = gen_rtx (SCRATCH, SImode);
877: }
878: }")
879:
880: (define_split
881: [(set (match_operand:DF 0 "nonmemory_operand" "")
882: (match_operand:DF 1 "general_operand" ""))
883: (clobber (reg:SI 0))
884: (clobber (reg:SI 15))]
885: "! symbolic_memory_operand (operands[1], DFmode)
886: && GET_CODE (operands[1]) != CONST_DOUBLE
887: && (GET_CODE (operands[0]) != REG || REGNO (operands[0]) < 15)
888: && (GET_CODE (operands[1]) != REG || REGNO (operands[1]) < 15)
889: && (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)
890: && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
891: && ! reload_completed
892: && reg_overlap_mentioned_p (operands[0], operands[1]))"
893: [(set (match_dup 2) (match_dup 3))
894: (set (match_dup 4) (match_dup 5))]
895: "
896: { if (GET_CODE (operands[0]) != REG
897: || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
898: operands[1], 0))
899: {
900: operands[2] = operand_subword (operands[0], 0, 0, DFmode);
901: operands[3] = operand_subword (operands[1], 0, 0, DFmode);
902: operands[4] = operand_subword (operands[0], 1, 0, DFmode);
903: operands[5] = operand_subword (operands[1], 1, 0, DFmode);
904: }
905: else
906: {
907: operands[2] = operand_subword (operands[0], 1, 0, DFmode);
908: operands[3] = operand_subword (operands[1], 1, 0, DFmode);
909: operands[4] = operand_subword (operands[0], 0, 0, DFmode);
910: operands[5] = operand_subword (operands[1], 0, 0, DFmode);
911: }
912:
913: if (operands[2] == 0 || operands[3] == 0
914: || operands[4] == 0 || operands[5] == 0)
915: FAIL;
916: }")
917:
918: ;; Conversions from one integer mode to another.
919: ;; It is possible sometimes to sign- or zero-extend while fetching from memory.
920: ;;
921: ;; First, sign-extensions:
922: (define_expand "extendhisi2"
923: [(set (match_operand:SI 0 "register_operand" "")
924: (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
925: ""
926: "")
927:
928: (define_insn ""
929: [(set (match_operand:SI 0 "register_operand" "=b")
930: (sign_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))]
931: ""
932: "loadha %0,%1"
933: [(set_attr "type" "load")])
934:
935: (define_insn ""
936: [(set (match_operand:SI 0 "register_operand" "=r,r,b")
937: (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))]
938: ""
939: "@
940: exts %0,%1
941: lha%M1 %0,%1
942: loadha %0,%1"
943: [(set_attr "type" "arith,load,load")
944: (set_attr "length" "2,*,*")])
945:
946: (define_expand "extendqisi2"
947: [(set (match_dup 2)
948: (ashift:SI (match_operand:QI 1 "register_operand" "")
949: (const_int 24)))
950: (set (match_operand:SI 0 "register_operand" "")
951: (ashiftrt:SI (match_dup 2)
952: (const_int 24)))]
953: ""
954: "
955: { operands[1] = gen_lowpart (SImode, operands[1]);
956: operands[2] = gen_reg_rtx (SImode); }")
957:
958: (define_expand "extendqihi2"
959: [(set (match_dup 2)
960: (ashift:SI (match_operand:QI 1 "register_operand" "")
961: (const_int 24)))
962: (set (match_operand:HI 0 "register_operand" "")
963: (ashiftrt:SI (match_dup 2)
964: (const_int 24)))]
965: ""
966: "
967: { operands[0] = gen_lowpart (SImode, operands[0]);
968: operands[1] = gen_lowpart (SImode, operands[1]);
969: operands[2] = gen_reg_rtx (SImode); }")
970:
971: ;; Define peepholes to eliminate an instruction when we are doing a sign
972: ;; extension but cannot clobber the input.
973: ;;
974: ;; In this case we will shift left 24 bits, but need a copy first. The shift
975: ;; can be replaced by a "mc03" instruction, but this can only be done if
976: ;; followed by the right shift of 24 or more bits.
977: (define_peephole
978: [(set (match_operand:SI 0 "register_operand" "")
979: (subreg:SI (match_operand:QI 1 "register_operand" "") 0))
980: (set (match_dup 0)
981: (ashift:SI (match_dup 0)
982: (const_int 24)))
983: (set (match_dup 0)
984: (ashiftrt:SI (match_dup 0)
985: (match_operand:SI 2 "const_int_operand" "")))]
986: "INTVAL (operands[2]) >= 24"
987: "mc03 %0,%1\;sari16 %0,%S2"
988: [(set_attr "type" "multi")
989: (set_attr "length" "4")
990: (set_attr "cc" "sets")])
991:
992: ;; Now zero extensions:
993: (define_expand "zero_extendhisi2"
994: [(set (match_operand:SI 0 "register_operand" "")
995: (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
996: ""
997: "")
998:
999: (define_insn ""
1000: [(set (match_operand:SI 0 "register_operand" "=b")
1001: (zero_extend:SI (match_operand:HI 1 "symbolic_memory_operand" "m")))]
1002: ""
1003: "loadh %0,%1"
1004: [(set_attr "type" "load")])
1005:
1006: (define_insn ""
1007: [(set (match_operand:SI 0 "register_operand" "=r,r,b")
1008: (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Q,m")))]
1009: ""
1010: "@
1011: nilz %0,%1,65535
1012: lh%N1 %0,%1
1013: loadh %0,%1"
1014: [(set_attr "type" "arith,loadz,load")])
1015:
1016: (define_expand "zero_extendqisi2"
1017: [(set (match_operand:SI 0 "register_operand" "")
1018: (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
1019: ""
1020: "")
1021:
1022: (define_insn ""
1023: [(set (match_operand:SI 0 "register_operand" "=b")
1024: (zero_extend:SI (match_operand:QI 1 "symbolic_memory_operand" "m")))]
1025: ""
1026: "loadc %0,%1"
1027: [(set_attr "type" "load")])
1028:
1029: (define_insn ""
1030: [(set (match_operand:SI 0 "register_operand" "=r,r,b")
1031: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))]
1032: ""
1033: "@
1034: nilz %0,%1,255
1035: lc%M1 %0,%1
1036: loadc %0,%1"
1037: [(set_attr "type" "arith,load,load")])
1038:
1039: (define_expand "zero_extendqihi2"
1040: [(set (match_operand:HI 0 "register_operand" "")
1041: (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
1042: ""
1043: "")
1044:
1045: (define_insn ""
1046: [(set (match_operand:HI 0 "register_operand" "=b")
1047: (zero_extend:HI (match_operand:QI 1 "symbolic_memory_operand" "m")))]
1048: ""
1049: "loadc %0,%1"
1050: [(set_attr "type" "load")])
1051:
1052: (define_insn ""
1053: [(set (match_operand:HI 0 "register_operand" "=r,r,b")
1054: (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,Q,m")))]
1055: ""
1056: "@
1057: nilz %0,%1,255
1058: lc%M1 %0,%1
1059: loadc %0,%1"
1060: [(set_attr "type" "arith,load,load")])
1061:
1062: ;; Various extract and insertion operations.
1063: (define_expand "extzv"
1064: [(set (match_operand:SI 0 "register_operand" "")
1065: (zero_extract:SI (match_operand:SI 1 "register_operand" "")
1066: (match_operand:SI 2 "const_int_operand" "")
1067: (match_operand:SI 3 "const_int_operand" "")))]
1068: ""
1069: "
1070: {
1071: if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8)
1072: FAIL;
1073:
1074: if (GET_CODE (operands[3]) != CONST_INT)
1075: FAIL;
1076:
1077: if (INTVAL (operands[3]) != 0 && INTVAL (operands[3]) != 8
1078: && INTVAL (operands[3]) != 16 && INTVAL (operands[3]) != 24)
1079: FAIL;
1080: }")
1081:
1082: (define_insn ""
1083: [(set (match_operand:SI 0 "register_operand" "=&r")
1084: (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
1085: (const_int 8)
1086: (match_operand:SI 2 "const_int_operand" "n")))]
1087: "(INTVAL (operands[2]) & 7) == 0"
1088: "lis %0,0\;mc3%B2 %0,%1"
1089: [(set_attr "type" "multi")
1090: (set_attr "cc" "change0")])
1091:
1092: (define_split
1093: [(set (match_operand:SI 0 "register_operand" "=&r")
1094: (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
1095: (const_int 8)
1096: (match_operand:SI 2 "const_int_operand" "n")))]
1097: "(INTVAL (operands[2]) & 7) == 0"
1098: [(set (match_dup 0) (const_int 0))
1099: (set (zero_extract:SI (match_dup 0) (const_int 8) (const_int 24))
1100: (zero_extract:SI (match_dup 1) (const_int 8) (match_dup 2)))]
1101: "")
1102:
1103: (define_insn ""
1104: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
1105: (const_int 8)
1106: (const_int 24))
1107: (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
1108: (const_int 8)
1109: (match_operand:SI 2 "const_int_operand" "n")))]
1110: "(INTVAL (operands[2]) & 7) == 0"
1111: "mc3%B2 %0,%1"
1112: [(set_attr "type" "address")
1113: (set_attr "length" "2")])
1114:
1115: (define_expand "insv"
1116: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
1117: (match_operand:SI 1 "const_int_operand" "")
1118: (match_operand:SI 2 "const_int_operand" ""))
1119: (match_operand:SI 3 "register_operand" ""))]
1120: ""
1121: "
1122: {
1123: if (GET_CODE (operands[2]) != CONST_INT)
1124: FAIL;
1125:
1126: if (GET_CODE (operands[1]) != CONST_INT)
1127: FAIL;
1128:
1129: if (INTVAL (operands[1]) == 1)
1130: {
1131: emit_insn (gen_bit_insv (operands[0], operands[1], operands[2],
1132: operands[3]));
1133: DONE;
1134: }
1135: else if (INTVAL (operands[1]) == 8
1136: && (INTVAL (operands[2]) % 8 == 0))
1137: ; /* Accept aligned byte-wide field. */
1138: else
1139: FAIL;
1140: }")
1141:
1142: ;; For a single-bit insert, it is better to explicitly generate references
1143: ;; to the T bit. We will call the T bit "CC0" because it can be clobbered
1144: ;; by some CC0 sets (single-bit tests).
1145:
1146: (define_expand "bit_insv"
1147: [(set (cc0)
1148: (zero_extract:SI (match_operand:SI 3 "register_operand" "")
1149: (const_int 1)
1150: (const_int 31)))
1151: (parallel [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
1152: (match_operand:SI 1 "const_int_operand" "")
1153: (match_operand:SI 2 "const_int_operand" ""))
1154: (ne (cc0) (const_int 0)))
1155: (clobber (match_scratch:SI 4 ""))])]
1156: ""
1157: "")
1158:
1159: (define_insn ""
1160: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
1161: (const_int 8)
1162: (match_operand:SI 1 "const_int_operand" "n"))
1163: (match_operand:SI 2 "register_operand" "r"))]
1164: "(INTVAL (operands[1]) & 7) == 0"
1165: "mc%B1%.3 %0,%2"
1166: [(set_attr "type" "address")
1167: (set_attr "length" "2")])
1168:
1169: ;; This pattern cannot have any input reloads since if references CC0.
1170: ;; So we have to add code to support memory, which is the only other
1171: ;; thing that a "register_operand" can become. There is still a problem
1172: ;; if the address isn't valid and *it* needs a reload, but there is no
1173: ;; way to solve that problem, so let's hope it never happens.
1174:
1175: (define_insn ""
1176: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,m")
1177: (const_int 1)
1178: (match_operand:SI 1 "const_int_operand" "n,m"))
1179: (ne (cc0) (const_int 0)))
1180: (clobber (match_scratch:SI 2 "=X,b"))]
1181: ""
1182: "@
1183: mftbi%t1 %0,%S1
1184: l%M0 %2,%0\;mftb%t1 %2,%S1\;st%M0 %2,%0"
1185: [(set_attr "type" "*,multi")
1186: (set_attr "cc" "none,none")
1187: (set_attr "length" "2,10")])
1188:
1189: ;; Arithmetic instructions. First, add and subtract.
1190: ;;
1191: ;; It may be that the second input is either large or small enough that
1192: ;; the operation cannot be done in a single insn. In that case, emit two.
1193: (define_expand "addsi3"
1194: [(set (match_operand:SI 0 "register_operand" "")
1195: (plus:SI (match_operand:SI 1 "register_operand" "")
1196: (match_operand:SI 2 "nonmemory_operand" "")))]
1197: ""
1198: "
1199: {
1200: if (GET_CODE (operands[2]) == CONST_INT
1201: && (unsigned) (INTVAL (operands[2]) + 0x8000) >= 0x10000
1202: && (INTVAL (operands[2]) & 0xffff) != 0)
1203: {
1204: int low = INTVAL (operands[2]) & 0xffff;
1205: int high = (unsigned) INTVAL (operands[2]) >> 16;
1206:
1207: if (low & 0x8000)
1208: high++, low |= 0xffff0000;
1209:
1210: emit_insn (gen_addsi3 (operands[0], operands[1],
1211: gen_rtx (CONST_INT, VOIDmode, high << 16)));
1212: operands[1] = operands[0];
1213: operands[2] = gen_rtx (CONST_INT, VOIDmode, low);
1214: }
1215: }")
1216:
1217: ;; Put the insn to add a symbolic constant to a register separately to
1218: ;; improve register allocation since it has different register requirements.
1219: (define_insn ""
1220: [(set (match_operand:SI 0 "register_operand" "=b")
1221: (plus:SI (match_operand:SI 1 "register_operand" "%b")
1222: (match_operand:SI 2 "romp_symbolic_operand" "s")))]
1223: ""
1224: "get %0,$%2(%1)"
1225: [(set_attr "type" "address")
1226: (set_attr "length" "8")])
1227:
1228: (define_insn ""
1229: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,b")
1230: (plus:SI (match_operand:SI 1 "reg_or_add_operand" "%0,0,r,b,0,r,b")
1231: (match_operand:SI 2 "reg_or_add_operand" "I,J,K,M,r,b,s")))]
1232: "register_operand (operands[1], SImode)
1233: || register_operand (operands[2], SImode)"
1234: "@
1235: ais %0,%2
1236: sis %0,%n2
1237: ail %0,%1,%2
1238: cau %0,%H2(%1)
1239: a %0,%2
1240: cas %0,%1,%2
1241: get %0,$%2(%1)"
1242: [(set_attr "type" "arith,arith,arith,address,arith,address,misc")
1243: (set_attr "length" "2,2,4,4,2,2,8")])
1244:
1245: ;; Now subtract.
1246: ;;
1247: ;; 1. If third operand is constant integer, convert it to add of the negative
1248: ;; of that integer.
1249: ;; 2. If the second operand is not a valid constant integer, force it into a
1250: ;; register.
1251: (define_expand "subsi3"
1252: [(set (match_operand:SI 0 "register_operand" "")
1253: (minus:SI (match_operand:SI 1 "reg_or_any_cint_operand" "")
1254: (match_operand:SI 2 "reg_or_any_cint_operand" "")))]
1255: ""
1256: "
1257: {
1258: if (GET_CODE (operands [2]) == CONST_INT)
1259: {
1260: emit_insn (gen_addsi3 (operands[0], operands[1],
1261: gen_rtx (CONST_INT,
1262: VOIDmode, - INTVAL (operands[2]))));
1263: DONE;
1264: }
1265: else
1266: operands[2] = force_reg (SImode, operands[2]);
1267:
1268: if (GET_CODE (operands[1]) != CONST_INT
1269: || (unsigned) (INTVAL (operands[1]) + 0x8000) >= 0x10000)
1270: operands[1] = force_reg (SImode, operands[1]);
1271: }")
1272:
1273: (define_insn ""
1274: [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1275: (minus:SI (match_operand:SI 1 "reg_or_D_operand" "K,0,r")
1276: (match_operand:SI 2 "register_operand" "r,r,0")))]
1277: ""
1278: "@
1279: sfi %0,%2,%1
1280: s %0,%2
1281: sf %0,%1"
1282: [(set_attr "length" "4,2,2")])
1283:
1284: ;; Multiply either calls a special RT routine or is done in-line, depending
1285: ;; on the value of a -m flag.
1286: ;;
1287: ;; First define the way we call the subroutine.
1288: (define_expand "mulsi3_subr"
1289: [(set (reg:SI 2) (match_operand:SI 1 "register_operand" ""))
1290: (set (reg:SI 3) (match_operand:SI 2 "register_operand" ""))
1291: (parallel [(set (reg:SI 2) (mult:SI (reg:SI 2) (reg:SI 3)))
1292: (clobber (reg:SI 0))
1293: (clobber (reg:SI 15))])
1294: (set (match_operand:SI 0 "register_operand" "")
1295: (reg:SI 2))]
1296: ""
1297: "")
1298:
1299: (define_expand "mulsi3"
1300: [(set (match_operand:SI 0 "register_operand" "")
1301: (mult:SI (match_operand:SI 1 "register_operand" "")
1302: (match_operand:SI 2 "register_operand" "")))]
1303: ""
1304: "
1305: {
1306: if (! TARGET_IN_LINE_MUL)
1307: {
1308: emit_insn (gen_mulsi3_subr (operands[0], operands[1], operands[2]));
1309: DONE;
1310: }
1311: }")
1312:
1313: ;; Define the patterns to match.
1314: ;; We would like to provide a delay slot for the insns that call internal
1315: ;; routines, but doing so is risky since reorg will think that the use of
1316: ;; r2 and r3 is completed in the insn needing the delay slot. Also, it
1317: ;; won't know that the cc will be clobbered. So take the safe approach
1318: ;; and don't give them delay slots.
1319: (define_insn ""
1320: [(set (reg:SI 2)
1321: (mult:SI (reg:SI 2) (reg:SI 3)))
1322: (clobber (reg:SI 0))
1323: (clobber (reg:SI 15))]
1324: "! TARGET_IN_LINE_MUL"
1325: "bali%# r15,lmul$$"
1326: [(set_attr "type" "misc")
1327: (set_attr "in_delay_slot" "no")])
1328:
1329: (define_insn ""
1330: [(set (match_operand:SI 0 "register_operand" "=&r")
1331: (mult:SI (match_operand:SI 1 "register_operand" "%r")
1332: (match_operand:SI 2 "register_operand" "r")))]
1333: "TARGET_IN_LINE_MUL"
1334: "*
1335: { return output_in_line_mul (); }"
1336: [(set_attr "length" "38")
1337: (set_attr "type" "multi")])
1338:
1339: ;; Handle divide and modulus. The same function returns both values,
1340: ;; so use divmodsi4. This divides arg 1 by arg 2 with quotient to go
1341: ;; into arg 0 and remainder in arg 3.
1342: ;;
1343: ;; We want to put REG_EQUAL notes for the two outputs. So we need a
1344: ;; function to do everything else.
1345: (define_expand "divmodsi4_doit"
1346: [(set (reg:SI 2)
1347: (match_operand:SI 0 "register_operand" ""))
1348: (set (reg:SI 3)
1349: (match_operand:SI 1 "register_operand" ""))
1350: (parallel [(set (reg:SI 2) (div:SI (reg:SI 2) (reg:SI 3)))
1351: (set (reg:SI 3) (mod:SI (reg:SI 2) (reg:SI 3)))
1352: (clobber (reg:SI 0))
1353: (clobber (reg:SI 15))])]
1354: ""
1355: "")
1356:
1357: (define_expand "divmodsi4"
1358: [(parallel [(set (match_operand:SI 0 "register_operand" "")
1359: (div:SI (match_operand:SI 1 "register_operand" "")
1360: (match_operand:SI 2 "register_operand" "")))
1361: (set (match_operand:SI 3 "register_operand" "")
1362: (mod:SI (match_dup 1) (match_dup 2)))])]
1363: ""
1364: "
1365: {
1366: rtx insn;
1367:
1368: emit_insn (gen_divmodsi4_doit (operands[1], operands[2]));
1369: insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2));
1370: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
1371: gen_rtx (DIV, SImode, operands[1],
1372: operands[2]),
1373: REG_NOTES (insn));
1374: insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3));
1375: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
1376: gen_rtx (MOD, SImode, operands[1],
1377: operands[2]),
1378: REG_NOTES (insn));
1379: DONE;
1380: }")
1381:
1382: (define_insn ""
1383: [(set (reg:SI 2)
1384: (div:SI (reg:SI 2) (reg:SI 3)))
1385: (set (reg:SI 3)
1386: (mod:SI (reg:SI 2) (reg:SI 3)))
1387: (clobber (reg:SI 0))
1388: (clobber (reg:SI 15))]
1389: ""
1390: "bali%# r15,ldiv$$"
1391: [(set_attr "type" "misc")
1392: (set_attr "in_delay_slot" "no")])
1393:
1394: ;; Similarly for unsigned divide.
1395: (define_expand "udivmodsi4_doit"
1396: [(set (reg:SI 2)
1397: (match_operand:SI 0 "register_operand" ""))
1398: (set (reg:SI 3)
1399: (match_operand:SI 1 "register_operand" ""))
1400: (parallel [(set (reg:SI 2) (udiv:SI (reg:SI 2) (reg:SI 3)))
1401: (set (reg:SI 3) (umod:SI (reg:SI 2) (reg:SI 3)))
1402: (clobber (reg:SI 0))
1403: (clobber (reg:SI 15))])]
1404: ""
1405: "")
1406:
1407: (define_expand "udivmodsi4"
1408: [(parallel [(set (match_operand:SI 0 "register_operand" "")
1409: (udiv:SI (match_operand:SI 1 "register_operand" "")
1410: (match_operand:SI 2 "register_operand" "")))
1411: (set (match_operand:SI 3 "register_operand" "")
1412: (umod:SI (match_dup 1) (match_dup 2)))])]
1413: ""
1414: "
1415: {
1416: rtx insn;
1417:
1418: emit_insn (gen_udivmodsi4_doit (operands[1], operands[2]));
1419: insn = emit_move_insn (operands[0], gen_rtx (REG, SImode, 2));
1420: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
1421: gen_rtx (UDIV, SImode, operands[1],
1422: operands[2]),
1423: REG_NOTES (insn));
1424: insn = emit_move_insn (operands[3], gen_rtx (REG, SImode, 3));
1425: REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
1426: gen_rtx (UMOD, SImode, operands[1],
1427: operands[2]),
1428: REG_NOTES (insn));
1429: DONE;
1430: }")
1431:
1432: (define_insn ""
1433: [(set (reg:SI 2)
1434: (udiv:SI (reg:SI 2) (reg:SI 3)))
1435: (set (reg:SI 3)
1436: (umod:SI (reg:SI 2) (reg:SI 3)))
1437: (clobber (reg:SI 0))
1438: (clobber (reg:SI 15))]
1439: ""
1440: "bali%# r15,uldiv$$"
1441: [(set_attr "type" "misc")
1442: (set_attr "in_delay_slot" "no")])
1443:
1444: ;; Define DImode arithmetic operations.
1445: ;;
1446: ;; It is possible to do certain adds and subtracts with constants in a single
1447: ;; insn, but it doesn't seem worth the trouble.
1448: ;;
1449: ;; Don't use DEFINE_SPLIT on these because the dependency on CC can't be
1450: ;; easily tracked in that case!
1451: (define_insn "adddi3"
1452: [(set (match_operand:DI 0 "register_operand" "=r")
1453: (plus:DI (match_operand:DI 1 "register_operand" "%0")
1454: (match_operand:DI 2 "register_operand" "r")))]
1455: ""
1456: "a %O0,%O2\;ae %0,%2"
1457: [(set_attr "type" "multi")])
1458:
1459: (define_insn "subdi3"
1460: [(set (match_operand:DI 0 "register_operand" "=r")
1461: (minus:DI (match_operand:DI 1 "register_operand" "0")
1462: (match_operand:DI 2 "register_operand" "r")))]
1463: ""
1464: "s %O0,%O2\;se %0,%2"
1465: [(set_attr "type" "multi")])
1466:
1467: (define_insn "negdi2"
1468: [(set (match_operand:DI 0 "register_operand" "=r,&r")
1469: (neg:DI (match_operand:DI 1 "register_operand" "0,r")))]
1470: ""
1471: "twoc %O0,%O1\;onec %0,%1\;aei %0,%0,0"
1472: [(set_attr "type" "multi")
1473: (set_attr "length" "8")])
1474:
1475: ;; Unary arithmetic operations.
1476: (define_insn "abssi2"
1477: [(set (match_operand:SI 0 "register_operand" "=r")
1478: (abs:SI (match_operand:SI 1 "register_operand" "r")))]
1479: ""
1480: "abs %0,%1"
1481: [(set_attr "length" "2")])
1482:
1483: (define_insn "negsi2"
1484: [(set (match_operand:SI 0 "register_operand" "=r")
1485: (neg:SI (match_operand:SI 1 "register_operand" "r")))]
1486: ""
1487: "twoc %0,%1"
1488: [(set_attr "length" "2")])
1489:
1490: (define_insn "one_cmplsi2"
1491: [(set (match_operand:SI 0 "register_operand" "=r")
1492: (not:SI (match_operand:SI 1 "register_operand" "r")))]
1493: ""
1494: "onec %0,%1"
1495: [(set_attr "length" "2")])
1496:
1497:
1498: ;; Logical insns: AND, IOR, and XOR
1499: ;;
1500: ;; If the operation is being performed on a 32-bit constant such that
1501: ;; it cannot be done in one insn, do it in two. We may lose a bit on
1502: ;; CSE in pathological cases, but it seems better doing it this way.
1503: (define_expand "andsi3"
1504: [(set (match_operand:SI 0 "register_operand" "")
1505: (and:SI (match_operand:SI 1 "register_operand" "")
1506: (match_operand:SI 2 "reg_or_any_cint_operand" "")))]
1507: ""
1508: "
1509: {
1510: if (GET_CODE (operands[2]) == CONST_INT)
1511: {
1512: int top = (unsigned) INTVAL (operands[2]) >> 16;
1513: int bottom = INTVAL (operands[2]) & 0xffff;
1514:
1515: if (top != 0 && top != 0xffff && bottom != 0 && bottom != 0xffff)
1516: {
1517: emit_insn (gen_andsi3 (operands[0], operands[1],
1518: gen_rtx (CONST_INT, VOIDmode,
1519: (top << 16) | 0xffff)));
1520: operands[1] = operands[0];
1521: operands[2] = gen_rtx (CONST_INT, VOIDmode, 0xffff0000 | bottom);
1522: }
1523: }
1524: }");
1525:
1526: (define_insn ""
1527: [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1528: (and:SI (match_operand:SI 1 "reg_or_and_operand" "%0,r,0")
1529: (match_operand:SI 2 "reg_or_and_operand" "P,LMO,r")))]
1530: "register_operand (operands[1], SImode)
1531: || register_operand (operands[2], SImode)"
1532: "@
1533: clrb%k2 %0,%b2
1534: ni%z2 %0,%1,%Z2
1535: n %0,%2"
1536: [(set_attr "length" "2,4,2")])
1537:
1538: ;; logical OR (IOR)
1539: (define_expand "iorsi3"
1540: [(set (match_operand:SI 0 "register_operand" "")
1541: (ior:SI (match_operand:SI 1 "register_operand" "")
1542: (match_operand:SI 2 "reg_or_any_cint_operand" "")))]
1543: ""
1544: "
1545: {
1546: if (GET_CODE (operands[2]) == CONST_INT)
1547: {
1548: int top = (unsigned) INTVAL (operands[2]) >> 16;
1549: int bottom = INTVAL (operands[2]) & 0xffff;
1550:
1551: if (top != 0 && bottom != 0)
1552: {
1553: emit_insn (gen_iorsi3 (operands[0], operands[1],
1554: gen_rtx (CONST_INT, VOIDmode, (top << 16))));
1555: operands[1] = operands[0];
1556: operands[2] = gen_rtx (CONST_INT, VOIDmode, bottom);
1557: }
1558: }
1559: }");
1560:
1561: (define_insn ""
1562: [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1563: (ior:SI (match_operand:SI 1 "reg_or_cint_operand" "%0,r,0")
1564: (match_operand:SI 2 "reg_or_cint_operand" "N,LM,r")))]
1565: "register_operand (operands[1], SImode)
1566: || register_operand (operands[2], SImode)"
1567: "@
1568: setb%h2 %0,%b2
1569: oi%h2 %0,%1,%H2
1570: o %0,%2"
1571: [(set_attr "length" "2,4,2")])
1572:
1573: ;; exclusive-or (XOR)
1574: (define_expand "xorsi3"
1575: [(set (match_operand:SI 0 "register_operand" "")
1576: (xor:SI (match_operand:SI 1 "register_operand" "")
1577: (match_operand:SI 2 "reg_or_any_cint_operand" "")))]
1578: ""
1579: "
1580: {
1581: if (GET_CODE (operands[2]) == CONST_INT)
1582: {
1583: int top = (unsigned) INTVAL (operands[2]) >> 16;
1584: int bottom = INTVAL (operands[2]) & 0xffff;
1585:
1586: if (top == 0xffff && bottom == 0xffff)
1587: {
1588: emit_insn (gen_one_cmplsi2 (operands[0], operands[1]));
1589: DONE;
1590: }
1591: else if (top != 0 && bottom != 0)
1592: {
1593: emit_insn (gen_xorsi3 (operands[0], operands[1],
1594: gen_rtx (CONST_INT, VOIDmode, (top << 16))));
1595: operands[1] = operands[0];
1596: operands[2] = gen_rtx (CONST_INT, VOIDmode, bottom);
1597: }
1598: }
1599: }");
1600:
1601: (define_insn ""
1602: [(set (match_operand:SI 0 "register_operand" "=r,r")
1603: (xor:SI (match_operand:SI 1 "reg_or_cint_operand" "%r,0")
1604: (match_operand:SI 2 "reg_or_cint_operand" "LM,r")))]
1605: "register_operand (operands[1], SImode)
1606: || register_operand (operands[2], SImode)"
1607: "@
1608: xi%h2 %0,%1,%H2
1609: x %0,%2"
1610: [(set_attr "length" "4,2")])
1611:
1612: ;; Various shift insns
1613: (define_insn "ashrsi3"
1614: [(set (match_operand:SI 0 "register_operand" "=r,r")
1615: (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
1616: (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
1617: ""
1618: "@
1619: sar %0,%2
1620: sari%s2 %0,%S2"
1621: [(set_attr "length" "2")])
1622:
1623: (define_insn "lshrsi3"
1624: [(set (match_operand:SI 0 "register_operand" "=r,r")
1625: (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
1626: (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
1627: ""
1628: "@
1629: sr %0,%2
1630: sri%s2 %0,%S2"
1631: [(set_attr "length" "2")])
1632:
1633: (define_insn ""
1634: [(set (match_operand:SI 0 "register_operand" "=r")
1635: (ashift:SI (match_operand:SI 1 "register_operand" "b")
1636: (const_int 1)))]
1637: ""
1638: "cas %0,%1,%1"
1639: [(set_attr "length" "2")
1640: (set_attr "type" "address")])
1641:
1642: (define_insn "ashlsi3"
1643: [(set (match_operand:SI 0 "register_operand" "=r,r")
1644: (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
1645: (match_operand:SI 2 "reg_or_cint_operand" "r,n")))]
1646: ""
1647: "@
1648: sl %0,%2
1649: sli%s2 %0,%S2"
1650: [(set_attr "length" "2")])
1651:
1652: ;; Function call insns:
1653: ;;
1654: ;; On the ROMP, &fcn is actually a pointer to the data area, which is passed
1655: ;; to the function in r0. &.fcn is the actual starting address of the
1656: ;; function. Also, the word at &fcn contains &.fcn.
1657: ;;
1658: ;; For both functions that do and don't return values, there are two cases:
1659: ;; where the function's address is a constant, and where it isn't.
1660: ;;
1661: ;; Operand 1 (2 for `call_value') is the number of arguments and is not used.
1662: (define_expand "call"
1663: [(use (reg:SI 0))
1664: (parallel [(call (mem:SI (match_operand:SI 0 "address_operand" ""))
1665: (match_operand 1 "" ""))
1666: (clobber (reg:SI 15))])]
1667: ""
1668: "
1669: {
1670: if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
1671: abort();
1672:
1673: operands[0] = XEXP (operands[0], 0);
1674: if (GET_CODE (operands[0]) == SYMBOL_REF)
1675: {
1676: extern rtx get_symref ();
1677: char *real_fcnname =
1678: (char *) alloca (strlen (XSTR (operands[0], 0)) + 2);
1679:
1680: /* Copy the data area address to r0. */
1681: emit_move_insn (gen_rtx (REG, SImode, 0),
1682: force_reg (SImode, operands[0]));
1683: strcpy (real_fcnname, \".\");
1684: strcat (real_fcnname, XSTR (operands[0], 0));
1685: operands[0] = get_symref (real_fcnname);
1686: }
1687: else
1688: {
1689: rtx data_access;
1690:
1691: emit_move_insn (gen_rtx (REG, SImode, 0),
1692: force_reg (SImode, operands[0]));
1693: data_access = gen_rtx (MEM, SImode, operands[0]);
1694: RTX_UNCHANGING_P (data_access) = 1;
1695: operands[0] = copy_to_reg (data_access);
1696: }
1697: }")
1698:
1699: (define_insn ""
1700: [(call (mem:SI (match_operand:SI 0 "register_operand" "b"))
1701: (match_operand 1 "" "g"))
1702: (clobber (reg:SI 15))]
1703: ""
1704: "balr%# r15,%0"
1705: [(set_attr "type" "call")
1706: (set_attr "length" "2")])
1707:
1708: (define_insn ""
1709: [(call (mem:SI (match_operand:SI 0 "romp_symbolic_operand" "i"))
1710: (match_operand 1 "" "g"))
1711: (clobber (reg:SI 15))]
1712: "GET_CODE (operands[0]) == SYMBOL_REF"
1713: "bali%# r15,%0"
1714: [(set_attr "type" "call")])
1715:
1716: ;; Call a function and return a value.
1717: (define_expand "call_value"
1718: [(use (reg:SI 0))
1719: (parallel [(set (match_operand 0 "" "=fg")
1720: (call (mem:SI (match_operand:SI 1 "address_operand" ""))
1721: (match_operand 2 "" "")))
1722: (clobber (reg:SI 15))])]
1723: ""
1724: "
1725: {
1726: if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
1727: abort();
1728:
1729: operands[1] = XEXP (operands[1], 0);
1730: if (GET_CODE (operands[1]) == SYMBOL_REF)
1731: {
1732: extern rtx get_symref ();
1733: char *real_fcnname =
1734: (char *) alloca (strlen (XSTR (operands[1], 0)) + 2);
1735:
1736: /* Copy the data area address to r0. */
1737: emit_move_insn (gen_rtx (REG, SImode, 0),
1738: force_reg (SImode, operands[1]));
1739: strcpy (real_fcnname, \".\");
1740: strcat (real_fcnname, XSTR (operands[1], 0));
1741: operands[1] = get_symref (real_fcnname);
1742: }
1743: else
1744: {
1745: rtx data_access;
1746:
1747: emit_move_insn (gen_rtx (REG, SImode, 0),
1748: force_reg (SImode, operands[1]));
1749: data_access = gen_rtx (MEM, SImode, operands[1]);
1750: RTX_UNCHANGING_P (data_access) = 1;
1751: operands[1] = copy_to_reg (data_access);
1752: }
1753: }")
1754:
1755: (define_insn ""
1756: [(set (match_operand 0 "" "=fg")
1757: (call (mem:SI (match_operand:SI 1 "register_operand" "b"))
1758: (match_operand 2 "" "g")))
1759: (clobber (reg:SI 15))]
1760: ""
1761: "balr%# r15,%1"
1762: [(set_attr "length" "2")
1763: (set_attr "type" "call")])
1764:
1765: (define_insn ""
1766: [(set (match_operand 0 "" "=fg")
1767: (call (mem:SI (match_operand:SI 1 "romp_symbolic_operand" "i"))
1768: (match_operand 2 "" "g")))
1769: (clobber (reg:SI 15))]
1770: "GET_CODE (operands[1]) == SYMBOL_REF"
1771: "bali%# r15,%1"
1772: [(set_attr "type" "call")])
1773:
1774: ;; Call subroutine returning any type.
1775:
1776: (define_expand "untyped_call"
1777: [(parallel [(call (match_operand 0 "" "")
1778: (const_int 0))
1779: (match_operand 1 "" "")
1780: (match_operand 2 "" "")])]
1781: ""
1782: "
1783: {
1784: int i;
1785:
1786: emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
1787:
1788: for (i = 0; i < XVECLEN (operands[2], 0); i++)
1789: {
1790: rtx set = XVECEXP (operands[2], 0, i);
1791: emit_move_insn (SET_DEST (set), SET_SRC (set));
1792: }
1793:
1794: /* The optimizer does not know that the call sets the function value
1795: registers we stored in the result block. We avoid problems by
1796: claiming that all hard registers are used and clobbered at this
1797: point. */
1798: emit_insn (gen_blockage ());
1799:
1800: DONE;
1801: }")
1802:
1803: ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
1804: ;; all of memory. This blocks insns from being moved across this point.
1805:
1806: (define_insn "blockage"
1807: [(unspec_volatile [(const_int 0)] 0)]
1808: ""
1809: "")
1810:
1811: ;; No operation insn.
1812: (define_insn "nop"
1813: [(const_int 0)]
1814: ""
1815: "nopr r0"
1816: [(set_attr "type" "address")
1817: (set_attr "length" "2")
1818: (set_attr "cc" "none")])
1819:
1820: ;; Here are the floating-point operations.
1821: ;;
1822: ;; Start by providing DEFINE_EXPAND for each operation.
1823: ;; The insns will be handled with MATCH_OPERATOR; the methodology will be
1824: ;; discussed below.
1825:
1826: ;; First the conversion operations.
1827:
1828: (define_expand "truncdfsf2"
1829: [(parallel [(set (match_operand:SF 0 "general_operand" "")
1830: (float_truncate:SF (match_operand:DF 1 "general_operand" "")))
1831: (clobber (reg:SI 0))
1832: (clobber (reg:SI 15))])]
1833: ""
1834: "")
1835:
1836: (define_expand "extendsfdf2"
1837: [(parallel [(set (match_operand:DF 0 "general_operand" "")
1838: (float_extend:DF (match_operand:SF 1 "general_operand" "")))
1839: (clobber (reg:SI 0))
1840: (clobber (reg:SI 15))])]
1841: ""
1842: "")
1843:
1844: (define_expand "floatsisf2"
1845: [(parallel [(set (match_operand:SF 0 "general_operand" "")
1846: (float:SF (match_operand:SI 1 "general_operand" "")))
1847: (clobber (reg:SI 0))
1848: (clobber (reg:SI 15))])]
1849: ""
1850: "")
1851:
1852: (define_expand "floatsidf2"
1853: [(parallel [(set (match_operand:DF 0 "general_operand" "")
1854: (float:DF (match_operand:SI 1 "general_operand" "")))
1855: (clobber (reg:SI 0))
1856: (clobber (reg:SI 15))])]
1857: ""
1858: "")
1859:
1860: (define_expand "fix_truncsfsi2"
1861: [(parallel [(set (match_operand:SI 0 "general_operand" "")
1862: (fix:SI (match_operand:SF 1 "general_operand" "")))
1863: (clobber (reg:SI 0))
1864: (clobber (reg:SI 15))])]
1865: ""
1866: "")
1867:
1868: (define_expand "fix_truncdfsi2"
1869: [(parallel [(set (match_operand:SI 0 "general_operand" "")
1870: (fix:SI (match_operand:DF 1 "general_operand" "")))
1871: (clobber (reg:SI 0))
1872: (clobber (reg:SI 15))])]
1873: ""
1874: "")
1875:
1876: ;; Now the binary operations.
1877:
1878: (define_expand "addsf3"
1879: [(parallel [(set (match_operand:SF 0 "general_operand" "")
1880: (plus:SF (match_operand:SF 1 "general_operand" "")
1881: (match_operand:SF 2 "general_operand" "")))
1882: (clobber (reg:SI 0))
1883: (clobber (reg:SI 15))])]
1884: ""
1885: "")
1886:
1887: (define_expand "adddf3"
1888: [(parallel [(set (match_operand:DF 0 "general_operand" "")
1889: (plus:DF (match_operand:DF 1 "general_operand" "")
1890: (match_operand:DF 2 "general_operand" "")))
1891: (clobber (reg:SI 0))
1892: (clobber (reg:SI 15))])]
1893: ""
1894: "")
1895:
1896: (define_expand "subsf3"
1897: [(parallel [(set (match_operand:SF 0 "general_operand" "")
1898: (minus:SF (match_operand:SF 1 "general_operand" "")
1899: (match_operand:SF 2 "general_operand" "")))
1900: (clobber (reg:SI 0))
1901: (clobber (reg:SI 15))])]
1902: ""
1903: "")
1904:
1905: (define_expand "subdf3"
1906: [(parallel [(set (match_operand:DF 0 "general_operand" "")
1907: (minus:DF (match_operand:DF 1 "general_operand" "")
1908: (match_operand:DF 2 "general_operand" "")))
1909: (clobber (reg:SI 0))
1910: (clobber (reg:SI 15))])]
1911: ""
1912: "")
1913:
1914: (define_expand "mulsf3"
1915: [(parallel [(set (match_operand:SF 0 "general_operand" "")
1916: (mult:SF (match_operand:SF 1 "general_operand" "")
1917: (match_operand:SF 2 "general_operand" "")))
1918: (clobber (reg:SI 0))
1919: (clobber (reg:SI 15))])]
1920: ""
1921: "")
1922:
1923: (define_expand "muldf3"
1924: [(parallel [(set (match_operand:DF 0 "general_operand" "")
1925: (mult:DF (match_operand:DF 1 "general_operand" "")
1926: (match_operand:DF 2 "general_operand" "")))
1927: (clobber (reg:SI 0))
1928: (clobber (reg:SI 15))])]
1929: ""
1930: "")
1931:
1932: (define_expand "divsf3"
1933: [(parallel [(set (match_operand:SF 0 "general_operand" "")
1934: (div:SF (match_operand:SF 1 "general_operand" "")
1935: (match_operand:SF 2 "general_operand" "")))
1936: (clobber (reg:SI 0))
1937: (clobber (reg:SI 15))])]
1938: ""
1939: "")
1940:
1941: (define_expand "divdf3"
1942: [(parallel [(set (match_operand:DF 0 "general_operand" "")
1943: (div:DF (match_operand:DF 1 "general_operand" "")
1944: (match_operand:DF 2 "general_operand" "")))
1945: (clobber (reg:SI 0))
1946: (clobber (reg:SI 15))])]
1947: ""
1948: "")
1949:
1950: ;; Unary floating-point operations.
1951: ;;
1952: ;; Negations can be done without floating-point, since this is IEEE.
1953: ;; But we cannot do this if an operand is a hard FP register, since
1954: ;; the SUBREG we create would not be valid.
1955: (define_expand "negsf2"
1956: [(set (match_operand:SF 0 "register_operand" "")
1957: (neg:SF (match_operand:SF 1 "register_operand" "")))]
1958: ""
1959: "
1960: {
1961: if (! (GET_CODE (operands[0]) == REG
1962: && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
1963: && FP_REGNO_P (REGNO (operands[0])))
1964: && ! (GET_CODE (operands[1]) == REG
1965: && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
1966: && FP_REGNO_P (REGNO (operands[1]))))
1967: {
1968: rtx result;
1969: rtx target = operand_subword (operands[0], 0, 1, SFmode);
1970:
1971: result = expand_binop (SImode, xor_optab,
1972: operand_subword_force (operands[1], 0, SFmode),
1973: gen_rtx (CONST_INT, VOIDmode, 0x80000000),
1974: target, 0, OPTAB_WIDEN);
1975: if (result == 0)
1976: abort ();
1977:
1978: if (result != target)
1979: emit_move_insn (result, target);
1980:
1981: /* Make a place for REG_EQUAL. */
1982: emit_move_insn (operands[0], operands[0]);
1983: DONE;
1984: }
1985: }")
1986:
1987: (define_expand "negdf2"
1988: [(set (match_operand:DF 0 "register_operand" "")
1989: (neg:DF (match_operand:DF 1 "register_operand" "")))]
1990: ""
1991: "
1992: {
1993: if (! (GET_CODE (operands[0]) == REG
1994: && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER
1995: && FP_REGNO_P (REGNO (operands[0])))
1996: && ! (GET_CODE (operands[1]) == REG
1997: && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
1998: && FP_REGNO_P (REGNO (operands[1]))))
1999: {
2000: rtx result;
2001: rtx target = operand_subword (operands[0], 0, 1, DFmode);
2002: rtx insns;
2003:
2004: start_sequence ();
2005: result = expand_binop (SImode, xor_optab,
2006: operand_subword_force (operands[1], 0, DFmode),
2007: gen_rtx (CONST_INT, VOIDmode, 0x80000000),
2008: target, 0, OPTAB_WIDEN);
2009: if (result == 0)
2010: abort ();
2011:
2012: if (result != target)
2013: emit_move_insn (result, target);
2014:
2015: emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
2016: operand_subword_force (operands[1], 1, DFmode));
2017:
2018: insns = get_insns ();
2019: end_sequence ();
2020:
2021: emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
2022: DONE;
2023: }
2024: }")
2025:
2026: (define_expand "abssf2"
2027: [(parallel [(set (match_operand:SF 0 "general_operand" "")
2028: (abs:SF (match_operand:SF 1 "general_operand" "")))
2029: (clobber (reg:SI 0))
2030: (clobber (reg:SI 15))])]
2031: ""
2032: "")
2033:
2034: (define_expand "absdf2"
2035: [(parallel [(set (match_operand:DF 0 "general_operand" "")
2036: (abs:DF (match_operand:DF 1 "general_operand" "")))
2037: (clobber (reg:SI 0))
2038: (clobber (reg:SI 15))])]
2039: ""
2040: "")
2041:
2042: ;; Any floating-point operation can be either SFmode or DFmode, and each
2043: ;; operand (including the output) can be either a normal operand or a
2044: ;; conversion from a normal operand.
2045: ;;
2046: ;; We use MATCH_OPERATOR to match a floating-point binary or unary operator
2047: ;; and input and output conversions. So we need 2^N patterns for each type
2048: ;; of operation, where N is the number of operands, including the output.
2049: ;; There are thus a total of 14 patterns, 8 for binary operations, 4 for
2050: ;; unary operations and two for conversion/move operations (only one
2051: ;; operand can have a conversion for move operations). In addition, we have
2052: ;; to be careful that a floating-point reload register doesn't get allocated
2053: ;; for an integer. We take care of this for inputs with PREFERRED_RELOAD_CLASS
2054: ;; but need to have two different constraints for outputs. This means that
2055: ;; we have to duplicate each pattern where the output could be an integer.
2056: ;; This adds another 7 patterns, for a total of 21.
2057:
2058: ;; Start with conversion operations (moves are done above).
2059:
2060: (define_insn ""
2061: [(set (match_operand:SI 0 "general_operand" "=g")
2062: (match_operator 1 "float_conversion"
2063: [(match_operand 2 "general_operand" "frg")]))
2064: (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
2065: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
2066: ""
2067: "*
2068: { return output_fpop (SET, operands[0], operands[2], 0, insn);
2069: }"
2070: [(set_attr "type" "fp")])
2071:
2072: (define_insn ""
2073: [(set (match_operand 0 "general_operand" "=frg")
2074: (match_operator 1 "float_conversion"
2075: [(match_operand 2 "general_operand" "frg")]))
2076: (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
2077: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
2078: ""
2079: "*
2080: { return output_fpop (SET, operands[0], operands[2], 0, insn);
2081: }"
2082: [(set_attr "type" "fp")])
2083:
2084: ;; Next, binary floating-point operations.
2085:
2086: (define_insn ""
2087: [(set (match_operand 0 "general_operand" "=frg")
2088: (match_operator 1 "float_binary"
2089: [(match_operand 2 "general_operand" "frg")
2090: (match_operand 3 "general_operand" "frg")]))
2091: (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
2092: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
2093: "check_precision (GET_MODE (operands[1]), operands[2], operands[3])"
2094: "*
2095: { return output_fpop (GET_CODE (operands[1]), operands[0],
2096: operands[2], operands[3], insn);
2097: }"
2098: [(set_attr "type" "fp")])
2099:
2100: (define_insn ""
2101: [(set (match_operand 0 "general_operand" "=frg")
2102: (match_operator 1 "float_binary"
2103: [(match_operand 2 "general_operand" "frg")
2104: (match_operator 3 "float_conversion"
2105: [(match_operand 4 "general_operand" "frg")])]))
2106: (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
2107: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
2108: "check_precision (GET_MODE (operands[1]), operands[2], operands[4])"
2109: "*
2110: { return output_fpop (GET_CODE (operands[1]), operands[0],
2111: operands[2], operands[4], insn);
2112: }"
2113: [(set_attr "type" "fp")])
2114:
2115: (define_insn ""
2116: [(set (match_operand 0 "general_operand" "=frg")
2117: (match_operator 1 "float_binary"
2118: [(match_operator 2 "float_conversion"
2119: [(match_operand 3 "general_operand" "frg")])
2120: (match_operand 4 "general_operand" "frg")]))
2121: (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
2122: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
2123: "check_precision (GET_MODE (operands[1]), operands[3], operands[4])"
2124: "*
2125: { return output_fpop (GET_CODE (operands[1]), operands[0],
2126: operands[3], operands[4], insn);
2127: }"
2128: [(set_attr "type" "fp")])
2129:
2130: (define_insn ""
2131: [(set (match_operand 0 "general_operand" "=frg")
2132: (match_operator 1 "float_binary"
2133: [(match_operator 2 "float_conversion"
2134: [(match_operand 3 "general_operand" "frg")])
2135: (match_operator 4 "float_conversion"
2136: [(match_operand 5 "general_operand" "frg")])]))
2137: (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
2138: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
2139: "check_precision (GET_MODE (operands[1]), operands[3], operands[5])"
2140: "*
2141: { return output_fpop (GET_CODE (operands[1]), operands[0],
2142: operands[3], operands[5], insn);
2143: }"
2144: [(set_attr "type" "fp")])
2145:
2146: (define_insn ""
2147: [(set (match_operand:SI 0 "general_operand" "=g")
2148: (match_operator 1 "float_conversion"
2149: [(match_operator 2 "float_binary"
2150: [(match_operand 3 "general_operand" "frg")
2151: (match_operand 4 "general_operand" "frg")])]))
2152: (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
2153: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
2154: "check_precision (GET_MODE (operands[2]), operands[3], operands[4])"
2155: "*
2156: { return output_fpop (GET_CODE (operands[2]), operands[0],
2157: operands[3], operands[4], insn);
2158: }"
2159: [(set_attr "type" "fp")])
2160:
2161: (define_insn ""
2162: [(set (match_operand 0 "general_operand" "=frg")
2163: (match_operator 1 "float_conversion"
2164: [(match_operator 2 "float_binary"
2165: [(match_operand 3 "general_operand" "frg")
2166: (match_operand 4 "general_operand" "frg")])]))
2167: (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
2168: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
2169: "check_precision (GET_MODE (operands[2]), operands[3], operands[4])"
2170: "*
2171: { return output_fpop (GET_CODE (operands[2]), operands[0],
2172: operands[3], operands[4], insn);
2173: }"
2174: [(set_attr "type" "fp")])
2175:
2176: (define_insn ""
2177: [(set (match_operand:SI 0 "general_operand" "=g")
2178: (match_operator 1 "float_conversion"
2179: [(match_operator 2 "float_binary"
2180: [(match_operand 3 "general_operand" "frg")
2181: (match_operator 4 "float_conversion"
2182: [(match_operand 5 "general_operand" "frg")])])]))
2183: (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
2184: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
2185: "check_precision (GET_MODE (operands[2]), operands[3], operands[4])"
2186: "*
2187: { return output_fpop (GET_CODE (operands[2]), operands[0],
2188: operands[3], operands[5], insn);
2189: }"
2190: [(set_attr "type" "fp")])
2191:
2192: (define_insn ""
2193: [(set (match_operand 0 "general_operand" "=frg")
2194: (match_operator 1 "float_conversion"
2195: [(match_operator 2 "float_binary"
2196: [(match_operand 3 "general_operand" "frg")
2197: (match_operator 4 "float_conversion"
2198: [(match_operand 5 "general_operand" "frg")])])]))
2199: (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
2200: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
2201: "check_precision (GET_MODE (operands[2]), operands[3], operands[4])"
2202: "*
2203: { return output_fpop (GET_CODE (operands[2]), operands[0],
2204: operands[3], operands[5], insn);
2205: }"
2206: [(set_attr "type" "fp")])
2207:
2208: (define_insn ""
2209: [(set (match_operand:SI 0 "general_operand" "=g")
2210: (match_operator 1 "float_conversion"
2211: [(match_operator 2 "float_binary"
2212: [(match_operator 3 "float_conversion"
2213: [(match_operand 4 "general_operand" "frg")])
2214: (match_operand 5 "general_operand" "frg")])]))
2215: (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
2216: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
2217: "check_precision (GET_MODE (operands[2]), operands[4], operands[5])"
2218: "*
2219: { return output_fpop (GET_CODE (operands[2]), operands[0],
2220: operands[4], operands[5], insn);
2221: }"
2222: [(set_attr "type" "fp")])
2223:
2224: (define_insn ""
2225: [(set (match_operand 0 "general_operand" "=frg")
2226: (match_operator 1 "float_conversion"
2227: [(match_operator 2 "float_binary"
2228: [(match_operator 3 "float_conversion"
2229: [(match_operand 4 "general_operand" "frg")])
2230: (match_operand 5 "general_operand" "frg")])]))
2231: (clobber (match_operand:SI 6 "reg_0_operand" "=&z"))
2232: (clobber (match_operand:SI 7 "reg_15_operand" "=&t"))]
2233: "check_precision (GET_MODE (operands[2]), operands[4], operands[5])"
2234: "*
2235: { return output_fpop (GET_CODE (operands[2]), operands[0],
2236: operands[4], operands[5], insn);
2237: }"
2238: [(set_attr "type" "fp")])
2239:
2240: (define_insn ""
2241: [(set (match_operand:SI 0 "general_operand" "=g")
2242: (match_operator 1 "float_conversion"
2243: [(match_operator 2 "float_binary"
2244: [(match_operator 3 "float_conversion"
2245: [(match_operand 4 "general_operand" "frg")])
2246: (match_operator 5 "float_conversion"
2247: [(match_operand 6 "general_operand" "frg")])])]))
2248: (clobber (match_operand:SI 7 "reg_0_operand" "=&z"))
2249: (clobber (match_operand:SI 8 "reg_15_operand" "=&t"))]
2250: "check_precision (GET_MODE (operands[2]), operands[4], operands[6])"
2251: "*
2252: { return output_fpop (GET_CODE (operands[2]), operands[0],
2253: operands[4], operands[6], insn);
2254: }"
2255: [(set_attr "type" "fp")])
2256:
2257: (define_insn ""
2258: [(set (match_operand 0 "general_operand" "=frg")
2259: (match_operator 1 "float_conversion"
2260: [(match_operator 2 "float_binary"
2261: [(match_operator 3 "float_conversion"
2262: [(match_operand 4 "general_operand" "frg")])
2263: (match_operator 5 "float_conversion"
2264: [(match_operand 6 "general_operand" "frg")])])]))
2265: (clobber (match_operand:SI 7 "reg_0_operand" "=&z"))
2266: (clobber (match_operand:SI 8 "reg_15_operand" "=&t"))]
2267: "check_precision (GET_MODE (operands[2]), operands[4], operands[6])"
2268: "*
2269: { return output_fpop (GET_CODE (operands[2]), operands[0],
2270: operands[4], operands[6], insn);
2271: }"
2272: [(set_attr "type" "fp")])
2273:
2274: ;; Unary floating-point operations.
2275:
2276: (define_insn ""
2277: [(set (match_operand 0 "general_operand" "=frg")
2278: (match_operator 1 "float_unary"
2279: [(match_operand 2 "general_operand" "frg")]))
2280: (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
2281: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
2282: "check_precision (GET_MODE (operands[1]), operands[2], 0)"
2283: "*
2284: { return output_fpop (GET_CODE (operands[1]), operands[0], operands[2],
2285: 0, insn);
2286: }"
2287: [(set_attr "type" "fp")])
2288:
2289: (define_insn ""
2290: [(set (match_operand 0 "general_operand" "=frg")
2291: (match_operator 1 "float_unary"
2292: [(match_operator 2 "float_conversion"
2293: [(match_operand 3 "general_operand" "frg")])]))
2294: (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
2295: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
2296: "check_precision (GET_MODE (operands[1]), operands[3], 0)"
2297: "*
2298: { return output_fpop (GET_CODE (operands[1]), operands[0], operands[3],
2299: 0, insn);
2300: }"
2301: [(set_attr "type" "fp")])
2302:
2303: (define_insn ""
2304: [(set (match_operand:SI 0 "general_operand" "=g")
2305: (match_operator 1 "float_conversion"
2306: [(match_operator 2 "float_unary"
2307: [(match_operand 3 "general_operand" "frg")])]))
2308: (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
2309: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
2310: "check_precision (GET_MODE (operands[2]), operands[3], 0)"
2311: "*
2312: { return output_fpop (GET_CODE (operands[2]), operands[0], operands[3],
2313: 0, insn);
2314: }"
2315: [(set_attr "type" "fp")])
2316:
2317: (define_insn ""
2318: [(set (match_operand 0 "general_operand" "=frg")
2319: (match_operator 1 "float_conversion"
2320: [(match_operator 2 "float_unary"
2321: [(match_operand 3 "general_operand" "frg")])]))
2322: (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
2323: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
2324: "check_precision (GET_MODE (operands[2]), operands[3], 0)"
2325: "*
2326: { return output_fpop (GET_CODE (operands[2]), operands[0], operands[3],
2327: 0, insn);
2328: }"
2329: [(set_attr "type" "fp")])
2330:
2331: (define_insn ""
2332: [(set (match_operand:SI 0 "general_operand" "=g")
2333: (match_operator 1 "float_conversion"
2334: [(match_operator 2 "float_unary"
2335: [(match_operator 3 "float_conversion"
2336: [(match_operand 4 "general_operand" "frg")])])]))
2337: (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
2338: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
2339: "check_precision (GET_MODE (operands[2]), operands[4], 0)"
2340: "*
2341: { return output_fpop (GET_CODE (operands[2]), operands[0], operands[4],
2342: 0, insn);
2343: }"
2344: [(set_attr "type" "fp")])
2345:
2346: (define_insn ""
2347: [(set (match_operand 0 "general_operand" "=frg")
2348: (match_operator 1 "float_conversion"
2349: [(match_operator 2 "float_unary"
2350: [(match_operator 3 "float_conversion"
2351: [(match_operand 4 "general_operand" "frg")])])]))
2352: (clobber (match_operand:SI 5 "reg_0_operand" "=&z"))
2353: (clobber (match_operand:SI 6 "reg_15_operand" "=&t"))]
2354: "check_precision (GET_MODE (operands[2]), operands[4], 0)"
2355: "*
2356: { return output_fpop (GET_CODE (operands[2]), operands[0], operands[4],
2357: 0, insn);
2358: }"
2359: [(set_attr "type" "fp")])
2360:
2361: ;; Compare insns are next. Note that the ROMP has two types of compares,
2362: ;; signed & unsigned, and one type of branch. Use the routine
2363: ;; `next_insn_tests_no_unsigned' to see which type to use.
2364: (define_expand "tstsi"
2365: [(set (cc0)
2366: (match_operand:SI 0 "register_operand" "r"))]
2367: ""
2368: "")
2369:
2370: (define_expand "cmpsi"
2371: [(set (cc0)
2372: (compare (match_operand:SI 0 "register_operand" "")
2373: (match_operand:SI 1 "reg_or_cint_operand" "")))]
2374: ""
2375: "")
2376:
2377: ;; Signed compare, `test' first.
2378:
2379: (define_insn ""
2380: [(set (cc0)
2381: (match_operand:SI 0 "register_operand" "r"))]
2382: "next_insn_tests_no_unsigned (insn)"
2383: "cis %0,0"
2384: [(set_attr "length" "2")
2385: (set_attr "type" "compare")])
2386:
2387: (define_insn ""
2388: [(set (cc0) (match_operand:SI 0 "register_operand" "r,r,r"))
2389: (set (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "=0,r,Q")
2390: (match_dup 0))]
2391: "next_insn_tests_no_unsigned (insn)"
2392: "@
2393: cis %1,0
2394: nilo %1,%0,65535
2395: st%M1 %0,%1\;cis %0,0"
2396: [(set_attr "type" "compare,compare,store")
2397: (set_attr "length" "2,4,6")
2398: (set_attr "cc" "compare")])
2399:
2400: (define_insn ""
2401: [(set (cc0)
2402: (compare (match_operand:SI 0 "register_operand" "r,r,r")
2403: (match_operand:SI 1 "reg_or_cint_operand" "I,K,r")))]
2404: "next_insn_tests_no_unsigned (insn)"
2405: "@
2406: cis %0,%1
2407: cil %0,%1
2408: c %0,%1"
2409: [(set_attr "length" "2,4,2")
2410: (set_attr "type" "compare")])
2411:
2412: ;; Unsigned comparisons, `test' first, again.
2413: (define_insn ""
2414: [(set (cc0)
2415: (match_operand:SI 0 "register_operand" "r"))]
2416: "! next_insn_tests_no_unsigned (insn)"
2417: "clil %0,0"
2418: [(set_attr "type" "compare")])
2419:
2420: (define_insn ""
2421: [(set (cc0)
2422: (compare (match_operand:SI 0 "register_operand" "r,r")
2423: (match_operand:SI 1 "reg_or_cint_operand" "K,r")))]
2424: "! next_insn_tests_no_unsigned (insn)"
2425: "@
2426: clil %0,%1
2427: cl %0,%1"
2428: [(set_attr "length" "4,2")
2429: (set_attr "type" "compare")])
2430:
2431: ;; Bit test insn. Many cases are converted into this by combine. This
2432: ;; uses the ROMP test bit.
2433:
2434: (define_insn ""
2435: [(set (cc0)
2436: (zero_extract (match_operand:SI 0 "register_operand" "r,r")
2437: (const_int 1)
2438: (match_operand:SI 1 "reg_or_any_cint_operand" "r,n")))]
2439: "next_insn_tests_no_inequality (insn)"
2440: "@
2441: mttb %0,%1
2442: mttbi%t1 %0,%S1"
2443: [(set_attr "length" "2")
2444: (set_attr "type" "compare")
2445: (set_attr "cc" "tbit")])
2446:
2447: ;; Floating-point comparisons. There are two, equality and order.
2448: ;; The difference will be that a trap for NaN will be given on the orderr
2449: ;; comparisons only.
2450:
2451: (define_expand "cmpsf"
2452: [(parallel [(set (cc0) (compare (match_operand:SF 0 "general_operand" "")
2453: (match_operand:SF 1 "general_operand" "")))
2454: (clobber (reg:SI 0))
2455: (clobber (reg:SI 15))])]
2456: ""
2457: "")
2458:
2459: (define_expand "cmpdf"
2460: [(parallel [(set (cc0) (compare (match_operand:DF 0 "general_operand" "")
2461: (match_operand:DF 1 "general_operand" "")))
2462: (clobber (reg:SI 0))
2463: (clobber (reg:SI 15))])]
2464: ""
2465: "")
2466:
2467: (define_expand "tstsf"
2468: [(parallel [(set (cc0) (match_operand:SF 0 "general_operand" ""))
2469: (clobber (reg:SI 0))
2470: (clobber (reg:SI 15))])]
2471: ""
2472: "")
2473:
2474: (define_expand "tstdf"
2475: [(parallel [(set (cc0) (match_operand:DF 0 "general_operand" ""))
2476: (clobber (reg:SI 0))
2477: (clobber (reg:SI 15))])]
2478: ""
2479: "")
2480:
2481: ;; There are four cases for compare and two for test. These correspond
2482: ;; to each input having a floating-point conversion or not.
2483:
2484: (define_insn ""
2485: [(set (cc0) (compare (match_operand 0 "general_operand" "frg")
2486: (match_operand 1 "general_operand" "frg")))
2487: (clobber (match_operand:SI 2 "reg_0_operand" "=&z"))
2488: (clobber (match_operand:SI 3 "reg_15_operand" "=&t"))]
2489: "GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode"
2490: "*
2491: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
2492: operands[0], operands[1], 0, insn);
2493: }"
2494: [(set_attr "type" "fp")
2495: (set_attr "cc" "compare")])
2496:
2497: (define_insn ""
2498: [(set (cc0) (compare (match_operand 0 "general_operand" "frg")
2499: (match_operator 1 "float_conversion"
2500: [(match_operand 2 "general_operand" "frg")])))
2501: (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
2502: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
2503: ""
2504: "*
2505: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
2506: operands[0], operands[2], 0, insn);
2507: }"
2508: [(set_attr "type" "fp")
2509: (set_attr "cc" "compare")])
2510:
2511: (define_insn ""
2512: [(set (cc0) (compare (match_operator 0 "float_conversion"
2513: [(match_operand 1 "general_operand" "frg")])
2514: (match_operand 2 "general_operand" "frg")))
2515: (clobber (match_operand:SI 3 "reg_0_operand" "=&z"))
2516: (clobber (match_operand:SI 4 "reg_15_operand" "=&t"))]
2517: ""
2518: "*
2519: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
2520: operands[1], operands[2], 0, insn);
2521: }"
2522: [(set_attr "type" "fp")
2523: (set_attr "cc" "compare")])
2524:
2525: (define_insn ""
2526: [(set (cc0) (compare (match_operator 0 "float_conversion"
2527: [(match_operand 1 "general_operand" "frg")])
2528: (match_operator 2 "float_conversion"
2529: [(match_operand 3 "general_operand" "frg")])))
2530: (clobber (match_operand:SI 4 "reg_0_operand" "=&z"))
2531: (clobber (match_operand:SI 5 "reg_15_operand" "=&t"))]
2532: ""
2533: "*
2534: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
2535: operands[1], operands[3], 0, insn);
2536: }"
2537: [(set_attr "type" "fp")
2538: (set_attr "cc" "compare")])
2539:
2540: (define_insn ""
2541: [(set (cc0) (match_operand 0 "general_operand" "frg"))
2542: (clobber (match_operand:SI 1 "reg_0_operand" "=&z"))
2543: (clobber (match_operand:SI 2 "reg_15_operand" "=&t"))]
2544: "GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode"
2545: "*
2546: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
2547: operands[0], immed_real_const_1 (0, 0,
2548: GET_MODE (operands[0])),
2549: 0, insn);
2550: }"
2551: [(set_attr "type" "fp")
2552: (set_attr "cc" "compare")])
2553:
2554: (define_insn ""
2555: [(set (cc0) (match_operator 0 "float_conversion"
2556: [(match_operand 1 "general_operand" "frg")]))
2557: (clobber (match_operand:SI 2 "reg_0_operand" "=&z"))
2558: (clobber (match_operand:SI 3 "reg_15_operand" "=&t"))]
2559: ""
2560: "*
2561: { return output_fpop (next_insn_tests_no_inequality (insn) ? EQ : GE,
2562: operands[1], immed_real_const_1 (0, 0,
2563: GET_MODE (operands[1])),
2564: 0, insn);
2565: }"
2566: [(set_attr "type" "fp")
2567: (set_attr "cc" "compare")])
2568:
2569: ;; Branch insns. Unsigned vs. signed have already
2570: ;; been taken care of. The only insns that need to be concerned about the
2571: ;; test bit are beq and bne because the rest are either always true,
2572: ;; always false, or converted to EQ or NE.
2573:
2574: ;; For conditional branches, we use `define_expand' and just have two patterns
2575: ;; that match them. Operand printing does most of the work.
2576:
2577: (define_expand "beq"
2578: [(set (pc)
2579: (if_then_else (eq (cc0)
2580: (const_int 0))
2581: (label_ref (match_operand 0 "" ""))
2582: (pc)))]
2583: ""
2584: "")
2585:
2586: (define_expand "bne"
2587: [(set (pc)
2588: (if_then_else (ne (cc0)
2589: (const_int 0))
2590: (label_ref (match_operand 0 "" ""))
2591: (pc)))]
2592: ""
2593: "")
2594:
2595: (define_expand "bgt"
2596: [(set (pc)
2597: (if_then_else (gt (cc0)
2598: (const_int 0))
2599: (label_ref (match_operand 0 "" ""))
2600: (pc)))]
2601: ""
2602: "")
2603:
2604: (define_expand "bgtu"
2605: [(set (pc)
2606: (if_then_else (gtu (cc0)
2607: (const_int 0))
2608: (label_ref (match_operand 0 "" ""))
2609: (pc)))]
2610: ""
2611: "")
2612:
2613: (define_expand "blt"
2614: [(set (pc)
2615: (if_then_else (lt (cc0)
2616: (const_int 0))
2617: (label_ref (match_operand 0 "" ""))
2618: (pc)))]
2619: ""
2620: "")
2621:
2622: (define_expand "bltu"
2623: [(set (pc)
2624: (if_then_else (ltu (cc0)
2625: (const_int 0))
2626: (label_ref (match_operand 0 "" ""))
2627: (pc)))]
2628: ""
2629: "")
2630:
2631: (define_expand "bge"
2632: [(set (pc)
2633: (if_then_else (ge (cc0)
2634: (const_int 0))
2635: (label_ref (match_operand 0 "" ""))
2636: (pc)))]
2637: ""
2638: "")
2639:
2640: (define_expand "bgeu"
2641: [(set (pc)
2642: (if_then_else (geu (cc0)
2643: (const_int 0))
2644: (label_ref (match_operand 0 "" ""))
2645: (pc)))]
2646: ""
2647: "")
2648:
2649: (define_expand "ble"
2650: [(set (pc)
2651: (if_then_else (le (cc0)
2652: (const_int 0))
2653: (label_ref (match_operand 0 "" ""))
2654: (pc)))]
2655: ""
2656: "")
2657:
2658: (define_expand "bleu"
2659: [(set (pc)
2660: (if_then_else (leu (cc0)
2661: (const_int 0))
2662: (label_ref (match_operand 0 "" ""))
2663: (pc)))]
2664: ""
2665: "")
2666:
2667: ;; Define both directions of branch and return.
2668:
2669: (define_insn ""
2670: [(set (pc)
2671: (if_then_else (match_operator 1 "comparison_operator"
2672: [(cc0) (const_int 0)])
2673: (label_ref (match_operand 0 "" ""))
2674: (pc)))]
2675: ""
2676: "*
2677: {
2678: if (restore_compare_p (operands[1]))
2679: return 0;
2680: else if (get_attr_length (insn) == 2)
2681: return \"j%j1 %l0\";
2682: else
2683: return \"b%j1%# %l0\";
2684: }"
2685: [(set_attr "type" "branch")])
2686:
2687: (define_insn ""
2688: [(set (pc)
2689: (if_then_else (match_operator 0 "comparison_operator"
2690: [(cc0) (const_int 0)])
2691: (return)
2692: (pc)))]
2693: "null_epilogue ()"
2694: "*
2695: {
2696: if (restore_compare_p (operands[0]))
2697: return 0;
2698: else
2699: return \"b%j0r%# r15\";
2700: }"
2701: [(set_attr "type" "return")])
2702:
2703: (define_insn ""
2704: [(set (pc)
2705: (if_then_else (match_operator 1 "comparison_operator"
2706: [(cc0) (const_int 0)])
2707: (pc)
2708: (label_ref (match_operand 0 "" ""))))]
2709: ""
2710: "*
2711: {
2712: if (restore_compare_p (operands[1]))
2713: return 0;
2714: else if (get_attr_length (insn) == 2)
2715: return \"j%J1 %l0\";
2716: else
2717: return \"b%J1%# %l0\";
2718: }"
2719: [(set_attr "type" "branch")])
2720:
2721: (define_insn ""
2722: [(set (pc)
2723: (if_then_else (match_operator 0 "comparison_operator"
2724: [(cc0) (const_int 0)])
2725: (pc)
2726: (return)))]
2727: "null_epilogue ()"
2728: "*
2729: {
2730: if (restore_compare_p (operands[0]))
2731: return 0;
2732: else
2733: return \"b%J0r%# r15\";
2734: }"
2735: [(set_attr "type" "return")])
2736:
2737: ;; Unconditional branch and return.
2738:
2739: (define_insn "jump"
2740: [(set (pc)
2741: (label_ref (match_operand 0 "" "")))]
2742: ""
2743: "*
2744: {
2745: if (get_attr_length (insn) == 2)
2746: return \"j %l0\";
2747: else
2748: return \"b%# %l0\";
2749: }"
2750: [(set_attr "type" "branch")])
2751:
2752: (define_insn "return"
2753: [(return)]
2754: "null_epilogue ()"
2755: "br%# r15"
2756: [(set_attr "type" "return")])
2757:
2758: (define_insn "indirect_jump"
2759: [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
2760: ""
2761: "br%# %0"
2762: [(set_attr "type" "ibranch")])
2763:
2764: ;; Table jump for switch statements:
2765: (define_insn "tablejump"
2766: [(set (pc)
2767: (match_operand:SI 0 "register_operand" "r"))
2768: (use (label_ref (match_operand 1 "" "")))]
2769: ""
2770: "br%# %0"
2771: [(set_attr "type" "ibranch")])
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.