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