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