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