|
|
1.1 root 1: ;;- Machine description for the Motorola 88000 for GNU C compiler
2: ;; Copyright (C) 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
3: ;; Contributed by Michael Tiemann ([email protected])
4: ;; Additional changes by Michael Meissner ([email protected])
5: ;; Currently supported by Tom Wood ([email protected])
6:
7: ;; This file is part of GNU CC.
8:
9: ;; GNU CC is free software; you can redistribute it and/or modify
10: ;; it under the terms of the GNU General Public License as published by
11: ;; the Free Software Foundation; either version 2, or (at your option)
12: ;; any later version.
13:
14: ;; GNU CC is distributed in the hope that it will be useful,
15: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: ;; GNU General Public License for more details.
18:
19: ;; You should have received a copy of the GNU General Public License
20: ;; along with GNU CC; see the file COPYING. If not, write to
21: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22:
23:
24: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25:
26: ;; SCCS rev field. This is a NOP, just to get the SCCS id into the
27: ;; program image.
28: (define_expand "m88k_sccs_id"
29: [(match_operand:SI 0 "" "")]
30: ""
1.1.1.2 ! root 31: "{ static char sccs_id[] = \"@(#)m88k.md 2.0.3.4 20 Mar 1992 15:09:03\";
1.1 root 32: FAIL; }")
33:
34: ;; Attribute specifications
35:
1.1.1.2 ! root 36: ; Target CPU.
! 37: (define_attr "cpu" "m88000,m88100,m88110"
! 38: (const (symbol_ref "m88k_cpu")))
! 39:
1.1 root 40: ; Type of each instruction. Default is arithmetic.
41: ; I'd like to write the list as this, but genattrtab won't accept it.
42: ;
43: ; "branch,jump,call, ; flow-control instructions
44: ; load,store,loada, ; data unit instructions
45: ; spadd,dpadd,spdiv,dpdiv,idiv, ; FPU add instructions
46: ; spmul,dpmul,imul, ; FPU multiply instructions
47: ; arith, ; integer unit instructions
48: ; marith,mstore,mfp,weird" ; multi-word instructions
49:
50: ; Classification of each insn. Some insns of TYPE_BRANCH are multi-word.
51: (define_attr "type"
52: "branch,jump,call,load,store,loada,spadd,dpadd,spdiv,dpdiv,idiv,spmul,dpmul,imul,arith,marith,mstore,mfp,weird"
53: (const_string "arith"))
54:
55: ; Convenience attributes.
56: (define_attr "fpu" "yes,no"
57: (if_then_else
58: (eq_attr "type" "spmul,dpmul,imul,spadd,dpadd,spdiv,dpdiv,idiv,mfp")
59: (const_string "yes") (const_string "no")))
60:
61: ; Length in # of instructions of each insn. The values are not exact, but
62: ; are safe.
63: (define_attr "length" ""
64: (cond [(eq_attr "type" "marith,mstore,mfp")
65: (const_int 2)]
66: (const_int 1)))
67:
68: ; Describe a user's asm statement.
69: (define_asm_attributes
70: [(set_attr "type" "weird")])
71:
72: ; Define the delay slot requirements for branches and calls.
73: ; The m88100 annuls instructions if a conditional branch is taken.
74: ; For insns of TYPE_BRANCH that are multi-word instructions, the
75: ; delay slot applies to the first instruction.
76:
77: ; @@ For the moment, reorg.c requires that the delay slot of a branch not
78: ; be a call or branch.
79:
80: (define_delay (eq_attr "type" "branch,jump")
81: [(and
82: (and
83: (eq_attr "type" "!branch,jump,call,marith,mstore,mfp,weird") ; required.
84: (eq_attr "type" "!load")) ; issue as-soon-as-possible.
85: (eq_attr "fpu" "no")) ; issue as-soon-as-possible.
86: (eq_attr "type" "!call,branch,jump") (nil)]) ; @@ was (const_int 1)
87:
88: ; output_call supports an unconditional branch in the delay slot of
89: ; a call. (@@ Support for this case is expected in reorg.c soon.)
90:
91: (define_delay (eq_attr "type" "call")
92: [(eq_attr "type" "!branch,call,marith,mstore,mfp,weird") ; required.
93: (nil) (nil)])
94:
95: ; An abstract block diagram of the function units for the m88100.
96: ;
97: ; *
98: ; |
99: ; +---v----+
100: ; | decode |
101: ; +-vv-v-v-+ fpu
102: ; ,----------'| | `----------------------.
103: ; | | | | ,-----.
104: ; load | store | | arith | | |
105: ; | | | +-v-v-+ | dp source
106: ; | | | | fp1 |---'
107: ; store | | | div +-v-v-+
108: ; ,------. | | | ,-----. ,-----------' `-----------.
109: ; | | | | | | | | |
110: ; | +--v---v--+ ,---' | | +-v-v---+ +---v---+
111: ; | | stage 2 | | | `---| add 2 | | mul 2 |
112: ; | +---------+ | +--v--+ +-------+ imul +-------+
113: ; | | stage 1 | | | alu | | add 3 | ,--------| mul 3 |
114: ; | +---------+ | +--v--+ +-------+ | +-------+
115: ; | | stage 0 | | | | add 4 | | | mul 4 |
116: ; | +--v---v--+ | | +---v---+ | +-------+
117: ; | | | | | | | | mul 5 |
118: ; | * | | | | | +---v---+
119: ; | | | | | +----v----+ |
120: ; | load | | | fp add `------>| fp last |<------' fp mul
121: ; | | | | +---v-v--^+
122: ; | | | | | | |
123: ; | | | | | `--' dp dest
124: ; | | +--v-----v--+ |
125: ; | `--->| writeback |<--------------------'
126: ; | +--v-----v--+
127: ; | | |
128: ; `------------------' *
129: ;
130: ; The decode unit need not be specified.
131: ; Consideration of writeback contention is critical to superb scheduling.
132: ;
133: ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
134: ; TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST])
135:
136: ;(define_function_unit "decode" 1 1 (const_int 1) 0 1)
137:
138: ; Describing the alu is currently not useful.
139: ;(define_function_unit "alu" 1 0 (eq_attr "type"
140: ; "!store,mstore,marith,mfp,weird") 1 0)
141: ;(define_function_unit "alu" 1 0 (eq_attr "type" "marith,weird") 2 0)
142:
143: (define_function_unit "memory" 1 3 (eq_attr "type" "load") 3 2)
144:
145: ; The fp1 and fplast descriptions currently have no effect.
146: ;(define_function_unit "fp1" 1 1 (eq_attr "fpu" "yes") 1 2)
147:
148: ; The times are adjusted to include fp1 and fplast, but then are further
149: ; adjusted based on the actual generated code. The notation to the right
150: ; is the total latency. A range denotes a group of instructions and/or
151: ; conditions (the extra clock of fplast time with some sequences).
152: (define_function_unit "fpmul" 1 4 (eq_attr "type" "spmul") 4 2) ; 6-8
153: (define_function_unit "fpmul" 1 4 (eq_attr "type" "dpmul,mfp") 7 2) ; 9-10
154: (define_function_unit "fpmul" 1 4 (eq_attr "type" "imul") 3 2) ; 4
155:
156: (define_function_unit "fpadd" 1 3 (eq_attr "type" "spadd") 3 2) ; 5-6
157: (define_function_unit "fpadd" 1 3 (eq_attr "type" "dpadd") 4 2) ; 6-7
158: (define_function_unit "fpadd" 1 3 (eq_attr "type" "spdiv") 30 2) ; 30-31
159: (define_function_unit "fpadd" 1 3 (eq_attr "type" "dpdiv") 60 2) ; 60-61
160: (define_function_unit "fpadd" 1 3 (eq_attr "type" "idiv") 38 2) ; 38
161:
162: ;(define_function_unit "fplast" 1 1 (eq_attr "fpu" "yes") 1 2)
163:
164: ; Describing writeback contention is currently not useful.
165: ;(define_function_unit "writeback" 1 1
166: ; (eq_attr "type" "!store,mstore,branch,jump,call") 0 1)
167:
168: ; Describing stores is currently not useful. The suggestion here is that the
169: ; function unit ordering has already been established (writeback is last) and
1.1.1.2 ! root 170: ; that store insns use the units in an unusual order.
1.1 root 171: ;(define_function_unit "writeback" 1 1 (eq_attr "type" "store,mstore") 0 1)
172: ;(define_function_unit "memory" 1 3 (eq_attr "type" "store,mstore") 1 2)
173:
174: ;; This rich set of complex patterns are mostly due to Torbjorn Granlund
175: ;; ([email protected]). They've changed since then, so don't complain to him
176: ;; if they don't work right.
177:
178: ;; Regarding shifts, gen_lshlsi3 generates ASHIFT. LSHIFT opcodes are
179: ;; not produced and should not normally occur. Also, the gen functions
180: ;; produce the necessary insns to support TARGET_*_LARGE_SHIFT, so nothing
181: ;; special needs to be done here.
182:
183: ;; (a << int1) >> int2 optimizations into a single extract.
184: ;; These patterns need to occur before the normal shift patterns
185:
186: (define_insn ""
187: [(set (match_operand:SI 0 "register_operand" "=r")
188: (ashiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
189: (match_operand:SI 2 "int5_operand" ""))
190: (match_operand:SI 3 "int5_operand" "")))]
191: "INTVAL (operands [2]) <= INTVAL (operands [3])"
1.1.1.2 ! root 192: "*
! 193: {
! 194: operands[4] = gen_rtx (CONST_INT, SImode,
! 195: INTVAL (operands[3]) - INTVAL (operands[2]));
! 196: return \"ext %0,%1,%w3<%4>\"; /* <(%3-%2)> */
! 197: }")
1.1 root 198:
199: (define_insn ""
200: [(set (match_operand:SI 0 "register_operand" "=r")
201: (lshiftrt:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
202: (match_operand:SI 2 "int5_operand" ""))
203: (match_operand:SI 3 "int5_operand" "")))]
204: "INTVAL (operands [2]) <= INTVAL (operands [3])"
1.1.1.2 ! root 205: "*
! 206: {
! 207: operands[4] = gen_rtx (CONST_INT, SImode,
! 208: INTVAL (operands[3]) - INTVAL (operands[2]));
! 209: return \"extu %0,%1,%w3<%4>\"; /* <(%3-%2)> */
! 210: }")
1.1 root 211:
212: ;; Optimize possible cases of the set instruction.
213:
214: (define_insn ""
215: [(set (match_operand:SI 0 "register_operand" "=r")
216: (ashift:SI (const_int -1)
217: (match_operand:SI 1 "register_operand" "r")))]
218: ""
219: "set %0,%#r0,%1")
220:
221: (define_insn ""
222: [(set (match_operand:SI 0 "register_operand" "=r")
223: (ior:SI (ashift:SI (const_int -1)
224: (match_operand:SI 1 "register_operand" "r"))
225: (match_operand:SI 2 "register_operand" "r")))]
226: ""
227: "set %0,%2,%1")
228:
229: (define_insn ""
230: [(set (match_operand:SI 0 "register_operand" "=r")
231: (ior:SI (match_operand:SI 1 "register_operand" "r")
232: (ashift:SI (const_int -1)
233: (match_operand:SI 2 "register_operand" "r"))))]
234: ""
235: "set %0,%1,%2")
236:
237: ;; Optimize possible cases of the mak instruction.
238:
239: (define_insn ""
240: [(set (match_operand:SI 0 "register_operand" "=r")
241: (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
242: (match_operand:SI 2 "int5_operand" ""))
243: (match_operand:SI 3 "immediate_operand" "n")))]
244: "mak_mask_p (INTVAL (operands[3]) >> INTVAL (operands[2]))"
245: "*
246: {
247: operands[4] = gen_rtx (CONST_INT, SImode,
248: exact_log2 (1 + (INTVAL (operands[3])
249: >> INTVAL(operands[2]))));
250: return \"mak %0,%1,%4<%2>\";
251: }")
252:
253: ;; Optimize possible cases of output_and.
254:
255: (define_insn ""
256: [(set (match_operand:SI 0 "register_operand" "=r")
257: (ashift:SI (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
258: (match_operand:SI 2 "int5_operand" "")
259: (match_operand:SI 3 "int5_operand" ""))
260: (match_operand:SI 4 "int5_operand" "")))]
261: "INTVAL (operands[2]) + INTVAL (operands[3]) + INTVAL (operands[4]) == 32"
262: "*
263: {
264: operands[2]
265: = gen_rtx (CONST_INT, SImode,
266: ((1 << INTVAL (operands[2])) - 1) << INTVAL (operands[4]));
267: return output_and (operands);
268: }"
269: [(set_attr "type" "marith")]) ; length is 1 or 2.
270:
271: ;; Recognize bcnd instructions for integer values. This is distinguished
272: ;; from a conditional branch instruction (below) with SImode instead of
273: ;; CCmode.
274:
275: (define_insn ""
276: [(set (pc)
277: (if_then_else
278: (match_operator 0 "relop_no_unsigned"
279: [(match_operand:SI 1 "register_operand" "r")
280: (const_int 0)])
281: (match_operand 2 "pc_or_label_ref" "")
282: (match_operand 3 "pc_or_label_ref" "")))]
283: ""
284: "bcnd%. %R3%B0,%1,%P2%P3"
285: [(set_attr "type" "branch")])
286:
287: ;; Recognize tests for sign and zero.
288:
289: (define_insn ""
290: [(set (pc)
291: (if_then_else
292: (match_operator 0 "equality_op"
293: [(match_operand:SI 1 "register_operand" "r")
294: (const_int -2147483648)])
295: (match_operand 2 "pc_or_label_ref" "")
296: (match_operand 3 "pc_or_label_ref" "")))]
297: ""
298: "bcnd%. %R3%E0,%1,%P2%P3"
299: [(set_attr "type" "branch")])
300:
301: (define_insn ""
302: [(set (pc)
303: (if_then_else
304: (match_operator 0 "equality_op"
305: [(zero_extract:SI
306: (match_operand:SI 1 "register_operand" "r")
307: (const_int 31)
308: (const_int 1))
309: (const_int 0)])
310: (match_operand 2 "pc_or_label_ref" "")
311: (match_operand 3 "pc_or_label_ref" "")))]
312: ""
313: "bcnd%. %R3%D0,%1,%P2%P3"
314: [(set_attr "type" "branch")])
315:
316: ;; Recognize bcnd instructions for double integer values
317:
318: (define_insn ""
319: [(set (pc)
320: (if_then_else
321: (match_operator 0 "relop_no_unsigned"
322: [(sign_extend:DI
323: (match_operand:SI 1 "register_operand" "r"))
324: (const_int 0)])
325: (match_operand 2 "pc_or_label_ref" "")
326: (match_operand 3 "pc_or_label_ref" "")))]
327: ""
328: "bcnd%. %R3%B0,%1,%P2%P3"
329: [(set_attr "type" "branch")])
330:
331: (define_insn ""
332: [(set (pc)
333: (if_then_else
334: (match_operator 0 "equality_op"
335: [(zero_extend:DI
336: (match_operand:SI 1 "register_operand" "r"))
337: (const_int 0)])
338: (match_operand 2 "pc_or_label_ref" "")
339: (match_operand 3 "pc_or_label_ref" "")))]
340: ""
341: "bcnd%. %R3%B0,%1,%P2%P3"
342: [(set_attr "type" "branch")])
343:
344: ; @@ I doubt this is interesting until cmpdi is provided. Anyway, it needs
345: ; to be reworked.
346: ;
347: ;(define_insn ""
348: ; [(set (pc)
349: ; (if_then_else
350: ; (match_operator 0 "relop_no_unsigned"
351: ; [(match_operand:DI 1 "register_operand" "r")
352: ; (const_int 0)])
353: ; (match_operand 2 "pc_or_label_ref" "")
354: ; (match_operand 3 "pc_or_label_ref" "")))]
355: ; ""
356: ; "*
357: ;{
358: ; switch (GET_CODE (operands[0]))
359: ; {
360: ; case EQ:
361: ; case NE:
362: ; /* I'm not sure if it's safe to use .n here. */
363: ; return \"or %!,%1,%d1\;bcnd %R3%B0,%!,%P2%P3\";
364: ; case GE:
365: ; case LT:
366: ; return \"bcnd%. %R3%B0,%1,%P2%P3\";
367: ; case GT:
368: ; {
369: ; rtx op2 = operands[2];
370: ; operands[2] = operands[3];
371: ; operands[3] = op2;
372: ; }
373: ; case LE:
374: ; if (GET_CODE (operands[3]) == LABEL_REF)
375: ; {
376: ; int label_num;
377: ; operands[2] = gen_label_rtx ();
378: ; label_num = XINT (operands[2], 3);
379: ; output_asm_insn
380: ; (\"bcnd%. %#lt0,%1,%2\;or %!,%1,%d1\;bcnd %#ne0,%!,%3\", operands);
381: ; output_label (label_num);
382: ; return \"\";
383: ; }
384: ; else
385: ; return \"bcnd%. %#lt0,%1,%2\;or %!,%1,%d1\;bcnd %#eq0,%!,%2\";
386: ; }
387: ;}")
388:
389: ;; Recognize bcnd instructions for single precision float values
390: ;; Exclude relational operations as they must signal NaNs.
391:
392: ;; @@ These bcnd insns for float and double values don't seem to be recognized.
393:
394: (define_insn ""
395: [(set (pc)
396: (if_then_else
397: (match_operator 0 "equality_op"
398: [(float_extend:DF
399: (match_operand:SF 1 "register_operand" "r"))
400: (const_int 0)])
401: (match_operand 2 "pc_or_label_ref" "")
402: (match_operand 3 "pc_or_label_ref" "")))]
403: ""
404: "bcnd%. %R3%D0,%1,%P2%P3"
405: [(set_attr "type" "branch")])
406:
407: (define_insn ""
408: [(set (pc)
409: (if_then_else
410: (match_operator 0 "equality_op"
411: [(match_operand:SF 1 "register_operand" "r")
412: (const_int 0)])
413: (match_operand 2 "pc_or_label_ref" "")
414: (match_operand 3 "pc_or_label_ref" "")))]
415: ""
416: "bcnd%. %R3%D0,%1,%P2%P3"
417: [(set_attr "type" "branch")])
418:
419: ;; Recognize bcnd instructions for double precision float values
420: ;; Exclude relational operations as they must signal NaNs.
421:
422: (define_insn ""
423: [(set (pc)
424: (if_then_else
425: (match_operator 0 "equality_op"
426: [(match_operand:DF 1 "register_operand" "r")
427: (const_int 0)])
428: (match_operand 2 "pc_or_label_ref" "")
429: (match_operand 3 "pc_or_label_ref" "")))]
430: ""
431: "*
432: {
433: int label_num;
434:
435: if (GET_CODE (operands[0]) == NE)
436: {
437: rtx op2 = operands[2];
438: operands[2] = operands[3];
439: operands[3] = op2;
440: }
441: if (GET_CODE (operands[3]) == LABEL_REF)
442: return \"bcnd%. 0x5,%1,%3\;bcnd %#ne0,%d1,%3\";
443:
444: operands[3] = gen_label_rtx ();
445: label_num = XINT (operands[3], 3);
446: output_asm_insn (\"bcnd%. 0x5,%1,%3\;bcnd %#eq0,%d1,%2\", operands);
447: output_label (label_num);
448: return \"\";
449: }"
450: [(set_attr "type" "branch")])
451:
452: ;; Recognize bb0 and bb1 instructions. These use two unusual template
453: ;; patterns, %Lx and %Px. %Lx outputs a 1 if operand `x' is a LABEL_REF
454: ;; otherwise it outputs a 0. It then may print ".n" if the delay slot
455: ;; is used. %Px does noting if `x' is PC and outputs the operand if `x'
456: ;; is a LABEL_REF.
457:
458: (define_insn ""
459: [(set (pc)
460: (if_then_else
461: (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "r")
462: (const_int 1)
463: (match_operand:SI 1 "int5_operand" ""))
464: (const_int 0))
465: (match_operand 2 "pc_or_label_ref" "")
466: (match_operand 3 "pc_or_label_ref" "")))]
467: ""
468: "bb%L2 (31-%1),%0,%P2%P3"
469: [(set_attr "type" "branch")])
470:
471: (define_insn ""
472: [(set (pc)
473: (if_then_else
474: (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "r")
475: (const_int 1)
476: (match_operand:SI 1 "int5_operand" ""))
477: (const_int 0))
478: (match_operand 2 "pc_or_label_ref" "")
479: (match_operand 3 "pc_or_label_ref" "")))]
480: ""
481: "bb%L3 (31-%1),%0,%P2%P3"
482: [(set_attr "type" "branch")])
483:
484: (define_insn ""
485: [(set (pc)
486: (if_then_else
487: (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
488: (const_int 1)
489: (match_operand:SI 1 "int5_operand" ""))
490: (const_int 0))
491: (match_operand 2 "pc_or_label_ref" "")
492: (match_operand 3 "pc_or_label_ref" "")))]
493: ""
494: "bb%L2 (31-%1),%0,%P2%P3"
495: [(set_attr "type" "branch")])
496:
497: (define_insn ""
498: [(set (pc)
499: (if_then_else
500: (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
501: (const_int 1)
502: (match_operand:SI 1 "int5_operand" ""))
503: (const_int 0))
504: (match_operand 2 "pc_or_label_ref" "")
505: (match_operand 3 "pc_or_label_ref" "")))]
506: ""
507: "bb%L3 (31-%1),%0,%P2%P3"
508: [(set_attr "type" "branch")])
509:
510: (define_insn ""
511: [(set (pc)
512: (if_then_else
513: (eq (and:SI (match_operand:SI 0 "reg_or_bbx_mask_operand" "%r")
514: (match_operand:SI 1 "reg_or_bbx_mask_operand" "n"))
515: (const_int 0))
516: (match_operand 2 "pc_or_label_ref" "")
517: (match_operand 3 "pc_or_label_ref" "")))]
518: "(GET_CODE (operands[0]) == CONST_INT)
519: != (GET_CODE (operands[1]) == CONST_INT)"
520: "bb%L3 %p1,%0,%P2%P3"
521: [(set_attr "type" "branch")])
522:
523: (define_insn ""
524: [(set (pc)
525: (if_then_else
526: (ne (and:SI (match_operand:SI 0 "reg_or_bbx_mask_operand" "%r")
527: (match_operand:SI 1 "reg_or_bbx_mask_operand" "n"))
528: (const_int 0))
529: (match_operand 2 "pc_or_label_ref" "")
530: (match_operand 3 "pc_or_label_ref" "")))]
531: "(GET_CODE (operands[0]) == CONST_INT)
532: != (GET_CODE (operands[1]) == CONST_INT)"
533: "bb%L2 %p1,%0,%P2%P3"
534: [(set_attr "type" "branch")])
535:
536: ;; The comparison operations store the comparison into a register and
537: ;; record that register. The following Bxx or Sxx insn uses that
538: ;; register as an input. To facilitate use of bcnd instead of cmp/bb1,
539: ;; cmpsi records it's operands and produces no code when any operand
540: ;; is constant. In this case, the Bxx insns use gen_bcnd and the
541: ;; Sxx insns use gen_test to ensure a cmp has been emitted.
542: ;;
543: ;; This could also be done for SFmode and DFmode having only beq and bne
544: ;; use gen_bcnd. The others must signal NaNs. It seems though that zero
545: ;; has already been copied into a register.
546: ;;
547: ;; cmpsi/beq and cmpsi/bne can always be done with bcnd if any operand
548: ;; is a constant. (This idea is due to Torbjorn Granlund.) Others can
549: ;; use bcnd only if an operand is zero.
550: ;;
551: ;; It is necessary to distinguish a register holding condition codes.
552: ;; This is done by context.
553:
554: (define_expand "test"
555: [(set (match_dup 2)
556: (compare:CC (match_operand 0 "" "")
557: (match_operand 1 "" "")))]
558: ""
559: "
560: {
561: if (m88k_compare_reg)
562: abort ();
563:
564: if (GET_CODE (operands[0]) == CONST_INT
565: && ! SMALL_INT (operands[0]))
566: operands[0] = force_reg (SImode, operands[0]);
567:
568: if (GET_CODE (operands[1]) == CONST_INT
569: && ! SMALL_INT (operands[1]))
570: operands[1] = force_reg (SImode, operands[1]);
571:
572: operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);
573: }")
574:
575: ; @@ The docs say don't do this. It's probably a nop since the insn looks
576: ; identical to cmpsi against zero. Is there an advantage to providing
577: ; this, perhaps with a different form?
578:
579: ;(define_expand "tstsi"
580: ; [(set (match_dup 1)
581: ; (compare:CC (match_operand:SI 0 "register_operand" "")
582: ; (const_int 0)))]
583: ; ""
584: ; "
585: ;{
586: ; m88k_compare_reg = 0;
587: ; m88k_compare_op0 = operands[0];
588: ; m88k_compare_op1 = const0_rtx;
589: ; DONE;
590: ;}")
591:
592: (define_expand "cmpsi"
593: [(set (match_dup 2)
594: (compare:CC (match_operand:SI 0 "register_operand" "")
595: (match_operand:SI 1 "arith32_operand" "")))]
596: ""
597: "
598: {
599: if (GET_CODE (operands[0]) == CONST_INT
600: || GET_CODE (operands[1]) == CONST_INT)
601: {
602: m88k_compare_reg = 0;
603: m88k_compare_op0 = operands[0];
604: m88k_compare_op1 = operands[1];
605: DONE;
606: }
607: operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);
608: }")
609:
610: (define_expand "cmpsf"
611: [(set (match_dup 2)
612: (compare:CC (match_operand:SF 0 "register_operand" "")
613: (match_operand:SF 1 "register_operand" "")))]
614: ""
615: "operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);")
616:
617: (define_expand "cmpdf"
618: [(set (match_dup 2)
619: (compare:CC (match_operand:DF 0 "general_operand" "")
620: (match_operand:DF 1 "general_operand" "")))]
621: ""
622: "
623: {
624: operands[0] = legitimize_operand (operands[0], DFmode);
625: operands[1] = legitimize_operand (operands[1], DFmode);
626: operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);
627: }")
628:
629: ; @@ Get back to this later on.
630: ;
631: ;(define_insn "cmpdi"
632: ; [(set (cc0)
633: ; (compare:CC (match_operand:DI 0 "register_operand" "r")
634: ; (match_operand:DI 1 "register_operand" "r")))]
635: ; ""
636: ; "*
637: ;{
638: ; if ((cc_status.mdep & MDEP_LS_CHANGE) != 0)
639: ; abort (); /* output_move_double MDEP_LS_CHANGE bits were set. */
640: ;
641: ; cc_status.mdep &= ~ MDEP_LS_MASK;
642: ;
643: ; operands[2] = gen_label_rtx ();
644: ; /* Remember, %! is the condition code register and %@ is the
645: ; literal synthesis register. */
646: ;
647: ; output_asm_insn (\"cmp %!,%0,%1\;bb0 %#eq,%!,%l2\;cmp %!,%d0,%d1\",
648: ; operands);
649: ;
650: ; output_asm_insn (\"extu %@,%!,4<8>\;clr %!,%!,4<4>\", operands);
651: ; output_asm_insn (\"mak %@,%@,4<4>\;or %!,%!,%@\", operands);
652: ; output_label (XINT (operands[2], 3));
653: ; return \"\";
654: ;}"
655:
656: ;; The actual compare instructions.
657:
658: (define_insn ""
1.1.1.2 ! root 659: [(set (match_operand:CC 0 "register_operand" "=r")
! 660: (compare:CC (match_operand:SI 1 "register_operand" "rO")
! 661: (match_operand:SI 2 "arith_operand" "rI")))]
1.1 root 662: ""
1.1.1.2 ! root 663: "cmp %0,%r1,%2")
1.1 root 664:
665: (define_insn ""
666: [(set (match_operand:CC 0 "register_operand" "=r,r")
667: (compare:CC (match_operand:SF 1 "register_operand" "r,r")
668: (match_operand:SF 2 "real_or_0_operand" "r,G")))]
669: ""
670: "@
671: fcmp.sss %0,%1,%2
672: fcmp.sss %0,%1,%#r0"
673: [(set_attr "type" "spadd")])
674:
675: (define_insn ""
676: [(set (match_operand:CC 0 "register_operand" "=r")
677: (compare:CC (match_operand:DF 1 "register_operand" "r")
678: (float_extend:DF
679: (match_operand:SF 2 "register_operand" "r"))))]
680: ""
681: "fcmp.sds %0,%1,%2"
682: [(set_attr "type" "dpadd")])
683:
684: (define_insn ""
685: [(set (match_operand:CC 0 "register_operand" "=r")
686: (compare:CC (float_extend:DF
687: (match_operand:SF 1 "register_operand" "r"))
688: (match_operand:DF 2 "register_operand" "r")))]
689: ""
690: "fcmp.ssd %0,%1,%2"
691: [(set_attr "type" "dpadd")])
692:
693: (define_insn ""
694: [(set (match_operand:CC 0 "register_operand" "=r,r")
695: (compare:CC (match_operand:DF 1 "register_operand" "r,r")
696: (match_operand:DF 2 "real_or_0_operand" "r,G")))]
697: ""
698: "@
699: fcmp.sdd %0,%1,%2
700: fcmp.sds %0,%1,%#r0"
701: [(set_attr "type" "dpadd")])
702:
703: ;; Store condition code insns. The compare insns set a register
704: ;; rather than cc0 and record that register for use here. See above
705: ;; for the special treatment of cmpsi with a constant operand.
706:
707: (define_expand "seq"
708: [(set (match_operand:SI 0 "register_operand" "")
709: (match_dup 1))]
710: ""
711: "operands[1] = emit_test (EQ, SImode);")
712:
713: (define_expand "sne"
714: [(set (match_operand:SI 0 "register_operand" "")
715: (match_dup 1))]
716: ""
717: "operands[1] = emit_test (NE, SImode);")
718:
719: (define_expand "sgt"
720: [(set (match_operand:SI 0 "register_operand" "")
721: (match_dup 1))]
722: ""
723: "operands[1] = emit_test (GT, SImode);")
724:
725: (define_expand "sgtu"
726: [(set (match_operand:SI 0 "register_operand" "")
727: (match_dup 1))]
728: ""
729: "operands[1] = emit_test (GTU, SImode);")
730:
731: (define_expand "slt"
732: [(set (match_operand:SI 0 "register_operand" "")
733: (match_dup 1))]
734: ""
735: "operands[1] = emit_test (LT, SImode);")
736:
737: (define_expand "sltu"
738: [(set (match_operand:SI 0 "register_operand" "")
739: (match_dup 1))]
740: ""
741: "operands[1] = emit_test (LTU, SImode);")
742:
743: (define_expand "sge"
744: [(set (match_operand:SI 0 "register_operand" "")
745: (match_dup 1))]
746: ""
747: "operands[1] = emit_test (GE, SImode);")
748:
749: (define_expand "sgeu"
750: [(set (match_operand:SI 0 "register_operand" "")
751: (match_dup 1))]
752: ""
753: "operands[1] = emit_test (GEU, SImode);")
754:
755: (define_expand "sle"
756: [(set (match_operand:SI 0 "register_operand" "")
757: (match_dup 1))]
758: ""
759: "operands[1] = emit_test (LE, SImode);")
760:
761: (define_expand "sleu"
762: [(set (match_operand:SI 0 "register_operand" "")
763: (match_dup 1))]
764: ""
765: "operands[1] = emit_test (LEU, SImode);")
766:
767: ;; The actual set condition code instruction.
768:
769: (define_insn ""
770: [(set (match_operand:SI 0 "register_operand" "=r")
771: (match_operator:SI 1 "relop"
772: [(match_operand:CC 2 "register_operand" "r")
773: (const_int 0)]))]
774: ""
775: "ext %0,%2,1<%C1>")
776:
777: (define_insn ""
778: [(set (match_operand:SI 0 "register_operand" "=r")
779: (neg:SI
780: (match_operator:SI 1 "relop"
781: [(match_operand:CC 2 "register_operand" "r")
782: (const_int 0)])))]
783: ""
784: "extu %0,%2,1<%C1>")
785:
786: ;; Conditional branch insns. The compare insns set a register
787: ;; rather than cc0 and record that register for use here. See above
788: ;; for the special case of cmpsi with a constant operand.
789:
790: (define_expand "bcnd"
791: [(set (pc)
792: (if_then_else (match_operand 0 "" "")
793: (label_ref (match_operand 1 "" ""))
794: (pc)))]
795: ""
796: "if (m88k_compare_reg) abort ();")
797:
798: (define_expand "bxx"
799: [(set (pc)
800: (if_then_else (match_operand 0 "" "")
801: (label_ref (match_operand 1 "" ""))
802: (pc)))]
803: ""
804: "if (m88k_compare_reg == 0) abort ();")
805:
806: (define_expand "beq"
807: [(set (pc)
808: (if_then_else (eq (match_dup 1) (const_int 0))
809: (label_ref (match_operand 0 "" ""))
810: (pc)))]
811: ""
812: "if (m88k_compare_reg == 0)
813: {
814: emit_bcnd (EQ, operands[0]);
815: DONE;
816: }
817: operands[1] = m88k_compare_reg;")
818:
819: (define_expand "bne"
820: [(set (pc)
821: (if_then_else (ne (match_dup 1) (const_int 0))
822: (label_ref (match_operand 0 "" ""))
823: (pc)))]
824: ""
825: "if (m88k_compare_reg == 0)
826: {
827: emit_bcnd (NE, operands[0]);
828: DONE;
829: }
830: operands[1] = m88k_compare_reg;")
831:
832: (define_expand "bgt"
833: [(set (pc)
834: (if_then_else (gt (match_dup 1) (const_int 0))
835: (label_ref (match_operand 0 "" ""))
836: (pc)))]
837: ""
838: "if (m88k_compare_reg == 0)
839: {
840: emit_bcnd (GT, operands[0]);
841: DONE;
842: }
843: operands[1] = m88k_compare_reg;")
844:
845: (define_expand "bgtu"
846: [(set (pc)
847: (if_then_else (gtu (match_dup 1) (const_int 0))
848: (label_ref (match_operand 0 "" ""))
849: (pc)))]
850: ""
851: "if (m88k_compare_reg == 0)
852: {
853: emit_jump_insn (gen_bxx (emit_test (GTU, VOIDmode), operands[0]));
854: DONE;
855: }
856: operands[1] = m88k_compare_reg;")
857:
858: (define_expand "blt"
859: [(set (pc)
860: (if_then_else (lt (match_dup 1) (const_int 0))
861: (label_ref (match_operand 0 "" ""))
862: (pc)))]
863: ""
864: "if (m88k_compare_reg == 0)
865: {
866: emit_bcnd (LT, operands[0]);
867: DONE;
868: }
869: operands[1] = m88k_compare_reg;")
870:
871: (define_expand "bltu"
872: [(set (pc)
873: (if_then_else (ltu (match_dup 1) (const_int 0))
874: (label_ref (match_operand 0 "" ""))
875: (pc)))]
876: ""
877: "if (m88k_compare_reg == 0)
878: {
879: emit_jump_insn (gen_bxx (emit_test (LTU, VOIDmode), operands[0]));
880: DONE;
881: }
882: operands[1] = m88k_compare_reg;")
883:
884: (define_expand "bge"
885: [(set (pc)
886: (if_then_else (ge (match_dup 1) (const_int 0))
887: (label_ref (match_operand 0 "" ""))
888: (pc)))]
889: ""
890: "if (m88k_compare_reg == 0)
891: {
892: emit_bcnd (GE, operands[0]);
893: DONE;
894: }
895: operands[1] = m88k_compare_reg;")
896:
897: (define_expand "bgeu"
898: [(set (pc)
899: (if_then_else (geu (match_dup 1) (const_int 0))
900: (label_ref (match_operand 0 "" ""))
901: (pc)))]
902: ""
903: "if (m88k_compare_reg == 0)
904: {
905: emit_jump_insn (gen_bxx (emit_test (GEU, VOIDmode), operands[0]));
906: DONE;
907: }
908: operands[1] = m88k_compare_reg;")
909:
910: (define_expand "ble"
911: [(set (pc)
912: (if_then_else (le (match_dup 1) (const_int 0))
913: (label_ref (match_operand 0 "" ""))
914: (pc)))]
915: ""
916: "if (m88k_compare_reg == 0)
917: {
918: emit_bcnd (LE, operands[0]);
919: DONE;
920: }
921: operands[1] = m88k_compare_reg;")
922:
923: (define_expand "bleu"
924: [(set (pc)
925: (if_then_else (leu (match_dup 1) (const_int 0))
926: (label_ref (match_operand 0 "" ""))
927: (pc)))]
928: ""
929: "if (m88k_compare_reg == 0)
930: {
931: emit_jump_insn (gen_bxx (emit_test (LEU, VOIDmode), operands[0]));
932: DONE;
933: }
934: operands[1] = m88k_compare_reg;")
935:
936: ;; The actual conditional branch instruction (both directions). This
937: ;; uses two unusual template patterns, %Rx and %Px. %Rx is a prefix code
938: ;; for the immediately following condition and reverses the condition iff
939: ;; operand `x' is a LABEL_REF. %Px does nothing if `x' is PC and outputs
940: ;; the operand if `x' is a LABEL_REF.
941:
942: (define_insn ""
943: [(set (pc) (if_then_else
944: (match_operator 0 "relop"
945: [(match_operand:CC 1 "register_operand" "r")
946: (const_int 0)])
947: (match_operand 2 "pc_or_label_ref" "")
948: (match_operand 3 "pc_or_label_ref" "")))]
949: ""
950: "bb1%. %R3%C0,%1,%P2%P3"
951: [(set_attr "type" "branch")])
952:
953: ;; SImode move instructions
954:
955: (define_expand "movsi"
956: [(set (match_operand:SI 0 "general_operand" "")
957: (match_operand:SI 1 "general_operand" ""))]
958: ""
959: "
960: {
961: if (emit_move_sequence (operands, SImode))
962: DONE;
963: }")
964:
965: (define_insn ""
966: [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r")
967: (match_operand:SI 1 "move_operand" "rI,m,rO,J,M"))]
968: "(register_operand (operands[0], SImode)
969: || register_operand (operands[1], SImode)
970: || operands[1] == const0_rtx)"
971: "@
972: or %0,%#r0,%1
973: ld %0,%1
974: st %r1,%0
975: subu %0,%#r0,%n1
976: set %0,%#r0,%s1"
977: [(set_attr "type" "arith,load,store,arith,arith")])
978:
979: (define_insn ""
980: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
981: (match_operand:SI 1 "arith32_operand" "rI,J,L,M,n"))]
982: ""
983: "@
984: or %0,%#r0,%1
985: subu %0,%#r0,%n1
986: or.u %0,%#r0,%X1
987: set %0,%#r0,%s1
988: or.u %0,%#r0,%X1\;or %0,%0,%x1"
989: [(set_attr "type" "arith,arith,arith,arith,marith")])
990:
991: ;; @@ Why the constraint "in"? Doesn't `i' include `n'?
992: (define_insn ""
993: [(set (match_operand:SI 0 "register_operand" "=r")
994: (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
995: (match_operand:SI 2 "immediate_operand" "in")))]
996: ""
997: "or %0,%1,%#lo16(%g2)")
998:
999: (define_insn ""
1000: [(set (match_operand:SI 0 "register_operand" "=r")
1001: (high:SI (match_operand 1 "" "")))]
1002: ""
1003: "or.u %0,%#r0,%#hi16(%g1)")
1004:
1005: ;; HImode move instructions
1006:
1007: (define_expand "movhi"
1008: [(set (match_operand:HI 0 "general_operand" "")
1009: (match_operand:HI 1 "general_operand" ""))]
1010: ""
1011: "
1012: {
1013: if (emit_move_sequence (operands, HImode))
1014: DONE;
1015: }")
1016:
1017: (define_insn ""
1018: [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
1019: (match_operand:HI 1 "move_operand" "rP,m,rO,N"))]
1020: "(register_operand (operands[0], HImode)
1021: || register_operand (operands[1], HImode)
1022: || operands[1] == const0_rtx)"
1023: "@
1024: or %0,%#r0,%h1
1025: ld.hu %0,%1
1026: st.h %r1,%0
1027: subu %0,%#r0,%H1"
1028: [(set_attr "type" "arith,load,store,arith")])
1029:
1030: (define_insn ""
1031: [(set (match_operand:HI 0 "register_operand" "=r")
1032: (subreg:HI (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1033: (match_operand:SI 2 "immediate_operand" "in")) 0))]
1034: "!flag_pic"
1035: "or %0,%1,%#lo16(%2)")
1036:
1037: ;; QImode move instructions
1038:
1039: (define_expand "movqi"
1040: [(set (match_operand:QI 0 "general_operand" "")
1041: (match_operand:QI 1 "general_operand" ""))]
1042: ""
1043: "
1044: {
1045: if (emit_move_sequence (operands, QImode))
1046: DONE;
1047: }")
1048:
1049: (define_insn ""
1050: [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r")
1051: (match_operand:QI 1 "move_operand" "rP,m,rO,N"))]
1052: "(register_operand (operands[0], QImode)
1053: || register_operand (operands[1], QImode)
1054: || operands[1] == const0_rtx)"
1055: "@
1056: or %0,%#r0,%q1
1057: ld.bu %0,%1
1058: st.b %r1,%0
1059: subu %r0,%#r0,%Q1"
1060: [(set_attr "type" "arith,load,store,arith")])
1061:
1062: (define_insn ""
1063: [(set (match_operand:QI 0 "register_operand" "=r")
1064: (subreg:QI (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1065: (match_operand:SI 2 "immediate_operand" "in")) 0))]
1066: "!flag_pic"
1067: "or %0,%1,%#lo16(%2)")
1068:
1069: ;; DImode move instructions
1070:
1071: (define_expand "movdi"
1072: [(set (match_operand:DI 0 "general_operand" "")
1073: (match_operand:DI 1 "general_operand" ""))]
1074: ""
1075: "
1076: {
1077: if (emit_move_sequence (operands, DImode))
1078: DONE;
1079: }")
1080:
1081: (define_insn ""
1082: [(set (match_operand:DI 0 "register_operand" "=r")
1083: (const_int 0))]
1084: ""
1085: "or %0,%#r0,0\;or %d0,%#r0,0"
1086: [(set_attr "type" "marith")])
1087:
1088: (define_insn ""
1089: [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
1090: (match_operand:DI 1 "nonimmediate_operand" "r,m,r"))]
1091: ""
1092: "@
1093: or %0,%#r0,%1\;or %d0,%#r0,%d1
1094: ld.d %0,%1
1095: st.d %1,%0"
1096: [(set_attr "type" "marith,load,store")])
1097:
1098: (define_insn ""
1099: [(set (match_operand:DI 0 "register_operand" "=r")
1100: (subreg:DI (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1101: (match_operand:SI 2 "immediate_operand" "in")) 0))]
1102: "!flag_pic"
1103: "or %0,%1,%#lo16(%2)")
1104:
1105: (define_insn ""
1106: [(set (match_operand:DI 0 "register_operand" "=r")
1107: (match_operand:DI 1 "immediate_operand" "n"))]
1108: ""
1109: "* return output_load_const_dimode (operands);"
1110: [(set_attr "type" "marith")
1111: (set_attr "length" "4")]) ; length is 2, 3 or 4.
1112:
1113: ;; DFmode move instructions
1114:
1115: (define_expand "movdf"
1116: [(set (match_operand:DF 0 "general_operand" "")
1117: (match_operand:DF 1 "general_operand" ""))]
1118: ""
1119: "
1120: {
1121: if (emit_move_sequence (operands, DFmode))
1122: DONE;
1123: }")
1124:
1125: ;; @@ This pattern is incomplete and doesn't appear necessary.
1126: ;;
1127: ;; This pattern forces (set (reg:DF ...) (const_double ...))
1128: ;; to be reloaded by putting the constant into memory.
1129: ;; It must come before the more general movdf pattern.
1130:
1131: ;(define_insn ""
1132: ; [(set (match_operand:DF 0 "general_operand" "=r,o")
1133: ; (match_operand:DF 1 "" "G,G"))]
1134: ; "GET_CODE (operands[1]) == CONST_DOUBLE"
1135: ; "*
1136: ;{
1137: ; switch (which_alternative)
1138: ; {
1139: ; case 0:
1140: ; return \"or %0,%#r0,0\;or %d0,%#r0,0\";
1141: ; case 1:
1142: ; operands[1] = adj_offsettable_operand (operands[0], 4);
1143: ; return \"st %#r0,%0\;st %#r0,%1\";
1144: ; }
1145: ;}")
1146:
1147: (define_insn ""
1148: [(set (match_operand:DF 0 "register_operand" "=r")
1149: (const_int 0))]
1150: ""
1151: "or %0,%#r0,0\;or %d0,%#r0,0"
1152: [(set_attr "type" "marith")])
1153:
1154: (define_insn ""
1155: [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
1156: (match_operand:DF 1 "nonimmediate_operand" "r,m,r"))]
1157: ""
1158: "@
1159: or %0,%#r0,%1\;or %d0,%#r0,%d1
1160: ld.d %0,%1
1161: st.d %1,%0"
1162: [(set_attr "type" "marith,load,store")])
1163:
1164: (define_insn ""
1165: [(set (match_operand:DF 0 "register_operand" "=r")
1166: (subreg:DF (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1167: (match_operand:SI 2 "immediate_operand" "in")) 0))]
1168: "!flag_pic"
1169: "or %0,%1,%#lo16(%2)")
1170:
1171: (define_insn ""
1172: [(set (match_operand:DF 0 "register_operand" "=r")
1173: (match_operand:DF 1 "immediate_operand" "F"))]
1174: ""
1175: "* return output_load_const_double (operands);"
1176: [(set_attr "type" "marith")
1177: (set_attr "length" "4")]) ; length is 2, 3, or 4.
1178:
1179: ;; SFmode move instructions
1180:
1181: (define_expand "movsf"
1182: [(set (match_operand:SF 0 "general_operand" "")
1183: (match_operand:SF 1 "general_operand" ""))]
1184: ""
1185: "
1186: {
1187: if (emit_move_sequence (operands, SFmode))
1188: DONE;
1189: }")
1190:
1191: ;; @@ What happens to fconst0_rtx?
1192: (define_insn ""
1193: [(set (match_operand:SF 0 "register_operand" "=r")
1194: (const_int 0))]
1195: ""
1196: "or %0,%#r0,0")
1197:
1198: (define_insn ""
1199: [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
1200: (match_operand:SF 1 "nonimmediate_operand" "r,m,r"))]
1201: ""
1202: "@
1203: or %0,%#r0,%1
1204: ld %0,%1
1205: st %r1,%0"
1206: [(set_attr "type" "arith,load,store")])
1207:
1208: (define_insn ""
1209: [(set (match_operand:SF 0 "register_operand" "=r")
1210: (subreg:SF (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
1211: (match_operand:SI 2 "immediate_operand" "in")) 0))]
1212: "!flag_pic"
1213: "or %0,%1,%#lo16(%2)")
1214:
1215: (define_insn ""
1216: [(set (match_operand:SF 0 "register_operand" "=r")
1217: (match_operand:SF 1 "immediate_operand" "F"))]
1218: "operands[1] != const0_rtx"
1219: "* return output_load_const_float (operands);"
1220: [(set_attr "type" "marith")]) ; length is 1 or 2.
1221:
1222: ;; String/block move insn. See m88k.c for details.
1223:
1224: (define_expand "movstrsi"
1225: [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
1226: (mem:BLK (match_operand:BLK 1 "general_operand" "")))
1227: (use (match_operand:SI 2 "arith32_operand" ""))
1228: (use (match_operand:SI 3 "immediate_operand" ""))])]
1229: ""
1230: "
1231: {
1232: rtx dest_mem = operands[0];
1233: rtx src_mem = operands[1];
1234: operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
1235: operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
1236: expand_block_move (dest_mem, src_mem, operands);
1237: DONE;
1238: }")
1239:
1240: ;; Call a non-looping block move library function (e.g. __movstrSI96x64).
1241: ;; operand 0 is the function name
1242: ;; operand 1 is the destination pointer
1243: ;; operand 2 is the source pointer
1244: ;; operand 3 is the offset for the source and destination pointers
1245: ;; operand 4 is the first value to be loaded
1246: ;; operand 5 is the register to hold the value (r4 or r5)
1247: ;; Upon completion, r2 and r3 are unchanged
1248:
1249: (define_expand "call_block_move"
1250: [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r")
1251: (match_operand:SI 3 "immediate_operand" "i")))
1252: (set (match_operand 5 "register_operand" "r")
1253: (match_operand 4 "memory_operand" "m"))
1254: (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r")
1255: (match_dup 3)))
1256: (use (reg:SI 2))
1257: (use (reg:SI 3))
1258: (use (reg:SI 4))
1259: (use (reg:SI 5))
1260: (parallel [(call (mem:SI (match_operand 0 "" ""))
1261: (const_int 0))
1262: (use (reg:SI 1))])
1263: (clobber (reg:SI 4))
1264: (clobber (reg:SI 5))]
1265: ""
1266: "")
1267:
1268: ;; Call a looping block move library function (e.g. __movstrSI64n68).
1269: ;; operands 0-5 as in the non-looping interface
1270: ;; operand 6 is the loop count
1271:
1272: (define_expand "call_block_move_loop"
1273: [(set (reg:SI 3) (minus:SI (match_operand:SI 2 "register_operand" "r")
1274: (match_operand:SI 3 "immediate_operand" "i")))
1275: (set (match_operand:SI 5 "register_operand" "r")
1276: (match_operand:SI 4 "memory_operand" "m"))
1277: (set (reg:SI 2) (minus:SI (match_operand:SI 1 "register_operand" "r")
1278: (match_dup 3)))
1279: (set (reg:SI 6) (match_operand:SI 6 "immediate_operand" "i"))
1280: (use (reg:SI 2))
1281: (use (reg:SI 3))
1282: (use (reg:SI 4))
1283: (use (reg:SI 5))
1284: (use (reg:SI 6))
1285: (parallel [(call (mem:SI (match_operand 0 "" ""))
1286: (const_int 0))
1287: (use (reg:SI 1))])
1288: (clobber (reg:SI 4))
1289: (clobber (reg:SI 5))
1290: (clobber (reg:SI 6))]
1291: ""
1292: "")
1293:
1294: ;;- zero extension instructions
1295:
1296: (define_expand "zero_extendhisi2"
1297: [(set (match_operand:SI 0 "register_operand" "")
1298: (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
1299: ""
1300: "
1301: {
1302: if (GET_CODE (operands[1]) == MEM
1303: && symbolic_address_p (XEXP (operands[1], 0)))
1304: operands[1]
1305: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
1306: }")
1307:
1308: (define_insn ""
1309: [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1310: (zero_extend:SI (match_operand:HI 1 "move_operand" "!r,n,m")))]
1311: "GET_CODE (operands[1]) != CONST_INT"
1312: "@
1313: mask %0,%1,0xffff
1314: or %0,%#r0,%h1
1315: ld.hu %0,%1"
1316: [(set_attr "type" "arith,arith,load")])
1317:
1318: (define_expand "zero_extendqihi2"
1319: [(set (match_operand:HI 0 "register_operand" "")
1320: (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
1321: ""
1322: "
1323: {
1324: if (GET_CODE (operands[1]) == MEM
1325: && symbolic_address_p (XEXP (operands[1], 0)))
1326: operands[1]
1327: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
1328: }")
1329:
1330: (define_insn ""
1331: [(set (match_operand:HI 0 "register_operand" "=r,r,r")
1332: (zero_extend:HI (match_operand:QI 1 "move_operand" "r,n,m")))]
1333: "GET_CODE (operands[1]) != CONST_INT"
1334: "@
1335: mask %0,%1,0xff
1336: or %0,%#r0,%q1
1337: ld.bu %0,%1"
1338: [(set_attr "type" "arith,arith,load")])
1339:
1340: (define_expand "zero_extendqisi2"
1341: [(set (match_operand:SI 0 "register_operand" "")
1342: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1343: ""
1344: "
1345: {
1346: if (GET_CODE (operands[1]) == MEM
1347: && symbolic_address_p (XEXP (operands[1], 0)))
1348: {
1349: operands[1]
1350: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
1351: emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1352: gen_rtx (ZERO_EXTEND, SImode, operands[1])));
1353: DONE;
1354: }
1355: }")
1356:
1357: (define_insn ""
1358: [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1359: (zero_extend:SI (match_operand:QI 1 "move_operand" "r,n,m")))]
1360: "GET_CODE (operands[1]) != CONST_INT"
1361: "@
1362: mask %0,%1,0xff
1363: or %0,%#r0,%q1
1364: ld.bu %0,%1"
1365: [(set_attr "type" "arith,arith,load")])
1366:
1367: ;;- sign extension instructions
1368:
1369: (define_expand "extendsidi2"
1370: [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 1)
1371: (match_operand:SI 1 "general_operand" "g"))
1372: (set (subreg:SI (match_dup 0) 0)
1373: (ashiftrt:SI (subreg:SI (match_dup 0) 1)
1374: (const_int 31)))]
1375: ""
1376: "")
1377:
1378: (define_expand "extendhisi2"
1379: [(set (match_operand:SI 0 "register_operand" "")
1380: (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
1381: ""
1382: "
1383: {
1384: if (GET_CODE (operands[1]) == MEM
1385: && symbolic_address_p (XEXP (operands[1], 0)))
1386: operands[1]
1387: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
1388: }")
1389:
1390: (define_insn ""
1391: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1392: (sign_extend:SI (match_operand:HI 1 "move_operand" "!r,P,N,m")))]
1393: "GET_CODE (operands[1]) != CONST_INT"
1394: "@
1395: ext %0,%1,16<0>
1396: or %0,%#r0,%h1
1397: subu %0,%#r0,%H1
1398: ld.h %0,%1"
1399: [(set_attr "type" "arith,arith,arith,load")])
1400:
1401: (define_expand "extendqihi2"
1402: [(set (match_operand:HI 0 "register_operand" "")
1403: (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
1404: ""
1405: "
1406: {
1407: if (GET_CODE (operands[1]) == MEM
1408: && symbolic_address_p (XEXP (operands[1], 0)))
1409: operands[1]
1410: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
1411: }")
1412:
1413: (define_insn ""
1414: [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
1415: (sign_extend:HI (match_operand:QI 1 "move_operand" "!r,P,N,m")))]
1416: "GET_CODE (operands[1]) != CONST_INT"
1417: "@
1418: ext %0,%1,8<0>
1419: or %0,%#r0,%q1
1420: subu %0,%#r0,%Q1
1421: ld.b %0,%1"
1422: [(set_attr "type" "arith,arith,arith,load")])
1423:
1424: (define_expand "extendqisi2"
1425: [(set (match_operand:SI 0 "register_operand" "")
1426: (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
1427: ""
1428: "
1429: {
1430: if (GET_CODE (operands[1]) == MEM
1431: && symbolic_address_p (XEXP (operands[1], 0)))
1432: operands[1]
1433: = legitimize_address (flag_pic, operands[1], gen_reg_rtx (Pmode));
1434: }")
1435:
1436: (define_insn ""
1437: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1438: (sign_extend:SI (match_operand:QI 1 "move_operand" "!r,P,N,m")))]
1439: "GET_CODE (operands[1]) != CONST_INT"
1440: "@
1441: ext %0,%1,8<0>
1442: or %0,%#r0,%q1
1443: subu %0,%#r0,%Q1
1444: ld.b %0,%1"
1445: [(set_attr "type" "arith,arith,arith,load")])
1446:
1447: ;; Conversions between float and double.
1448:
1449: ;; The fadd instruction does not conform to IEEE 754 when used to
1450: ;; convert between float and double. In particular, the sign of -0 is
1451: ;; not preserved. Interestingly, fsub does conform.
1452:
1453: (define_insn "extendsfdf2"
1454: [(set (match_operand:DF 0 "register_operand" "=r")
1455: (float_extend:DF (match_operand:SF 1 "register_operand" "r")))]
1456: ""
1457: "fsub.dss %0,%1,%#r0"
1458: [(set_attr "type" "spadd")])
1459:
1460: (define_insn "truncdfsf2"
1461: [(set (match_operand:SF 0 "register_operand" "=r")
1462: (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
1463: ""
1464: "fsub.sds %0,%1,%#r0"
1465: [(set_attr "type" "dpadd")])
1466:
1467: ;; Conversions between floating point and integer
1468:
1469: (define_insn "floatsidf2"
1470: [(set (match_operand:DF 0 "register_operand" "=r")
1471: (float:DF (match_operand:SI 1 "register_operand" "r")))]
1472: ""
1473: "flt.ds %0,%1"
1474: [(set_attr "type" "spadd")])
1475:
1476: (define_insn "floatsisf2"
1477: [(set (match_operand:SF 0 "register_operand" "=r")
1478: (float:SF (match_operand:SI 1 "register_operand" "r")))]
1479: ""
1480: "flt.ss %0,%1"
1481: [(set_attr "type" "spadd")])
1482:
1483: (define_insn "fix_truncdfsi2"
1484: [(set (match_operand:SI 0 "register_operand" "=r")
1485: (fix:SI (match_operand:DF 1 "register_operand" "r")))]
1486: ""
1487: "trnc.sd %0,%1"
1488: [(set_attr "type" "dpadd")])
1489:
1490: (define_insn "fix_truncsfsi2"
1491: [(set (match_operand:SI 0 "register_operand" "=r")
1492: (fix:SI (match_operand:SF 1 "register_operand" "r")))]
1493: ""
1494: "trnc.ss %0,%1"
1495: [(set_attr "type" "spadd")])
1496:
1497:
1498: ;;- arithmetic instructions
1499: ;;- add instructions
1500:
1501: (define_insn "addsi3"
1502: [(set (match_operand:SI 0 "register_operand" "=r,r")
1503: (plus:SI (match_operand:SI 1 "add_operand" "%r,r")
1504: (match_operand:SI 2 "add_operand" "rI,J")))]
1505: ""
1506: "@
1507: addu %0,%1,%2
1508: subu %0,%1,%n2")
1509:
1510: ;; In unusual contexts, an add of a large value is generated (case statements
1511: ;; for example). In these contexts, it is sufficient to accept only those
1512: ;; cases where the two registers are different.
1513:
1514: (define_insn ""
1515: [(set (match_operand:SI 0 "register_operand" "=r,&r")
1516: (plus:SI (match_operand:SI 1 "arith32_operand" "%r,r")
1517: (match_operand:SI 2 "arith32_operand" "r,!n")))]
1518: ""
1519: "*
1520: {
1521: rtx xoperands[10];
1522:
1523: if (which_alternative == 0)
1524: return \"addu %0,%1,%2\";
1525:
1526: xoperands[0] = operands[0];
1527: xoperands[1] = operands[2];
1528: output_asm_insn (output_load_const_int (SImode, xoperands),
1529: xoperands);
1530:
1531: return \"addu %0,%1,%0\";
1532: }"
1533: [(set_attr "type" "arith,marith")
1534: (set_attr "length" "1,3")]) ; may be 2 or 3.
1535:
1536: ;; patterns for mixed mode floating point.
1537: ;; Do not define patterns that utilize mixed mode arithmetic that result
1538: ;; in narrowing the precision, because it loses accuracy, since the standard
1539: ;; requires double rounding, whereas the 88000 instruction only rounds once.
1540:
1541: (define_expand "adddf3"
1542: [(set (match_operand:DF 0 "register_operand" "=r")
1543: (plus:DF (match_operand:DF 1 "general_operand" "%r")
1544: (match_operand:DF 2 "general_operand" "r")))]
1545: ""
1546: "
1547: {
1548: operands[1] = legitimize_operand (operands[1], DFmode);
1549: operands[2] = legitimize_operand (operands[2], DFmode);
1550: }")
1551:
1552: (define_insn ""
1553: [(set (match_operand:DF 0 "register_operand" "=r")
1554: (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
1555: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
1556: ""
1557: "fadd.dss %0,%1,%2"
1558: [(set_attr "type" "spadd")])
1559:
1560: (define_insn ""
1561: [(set (match_operand:DF 0 "register_operand" "=r")
1562: (plus:DF (match_operand:DF 1 "register_operand" "r")
1563: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
1564: ""
1565: "fadd.dds %0,%1,%2"
1566: [(set_attr "type" "dpadd")])
1567:
1568: (define_insn ""
1569: [(set (match_operand:DF 0 "register_operand" "=r")
1570: (plus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
1571: (match_operand:DF 2 "register_operand" "r")))]
1572: ""
1573: "fadd.dsd %0,%1,%2"
1574: [(set_attr "type" "dpadd")])
1575:
1576: (define_insn ""
1577: [(set (match_operand:DF 0 "register_operand" "=r")
1578: (plus:DF (match_operand:DF 1 "register_operand" "%r")
1579: (match_operand:DF 2 "register_operand" "r")))]
1580: ""
1581: "fadd.ddd %0,%1,%2"
1582: [(set_attr "type" "dpadd")])
1583:
1584: (define_insn "addsf3"
1585: [(set (match_operand:SF 0 "register_operand" "=r")
1586: (plus:SF (match_operand:SF 1 "register_operand" "%r")
1587: (match_operand:SF 2 "register_operand" "r")))]
1588: ""
1589: "fadd.sss %0,%1,%2"
1590: [(set_attr "type" "spadd")])
1591:
1592: (define_insn ""
1593: [(set (match_operand:DI 0 "register_operand" "=r")
1594: (plus:DI (match_operand:DI 1 "register_operand" "r")
1595: (zero_extend:DI
1596: (match_operand:SI 2 "register_operand" "r"))))]
1597: ""
1598: "addu.co %d0,%d1,%2\;addu.ci %0,%1,%#r0"
1599: [(set_attr "type" "marith")])
1600:
1601: (define_insn ""
1602: [(set (match_operand:DI 0 "register_operand" "=r")
1603: (plus:DI (zero_extend:DI
1604: (match_operand:SI 1 "register_operand" "r"))
1605: (match_operand:DI 2 "register_operand" "r")))]
1606: ""
1607: "addu.co %d0,%1,%d2\;addu.ci %0,%#r0,%2"
1608: [(set_attr "type" "marith")])
1609:
1610: (define_insn "adddi3"
1611: [(set (match_operand:DI 0 "register_operand" "=r")
1612: (plus:DI (match_operand:DI 1 "register_operand" "%r")
1613: (match_operand:DI 2 "register_operand" "r")))]
1614: ""
1615: "addu.co %d0,%d1,%d2\;addu.ci %0,%1,%2"
1616: [(set_attr "type" "marith")])
1617:
1618: ;;- subtract instructions
1619:
1620: (define_insn "subsi3"
1621: [(set (match_operand:SI 0 "register_operand" "=r")
1622: (minus:SI (match_operand:SI 1 "register_operand" "r")
1623: (match_operand:SI 2 "arith32_operand" "rI")))]
1624: ""
1625: "subu %0,%1,%2")
1626:
1627: ;; patterns for mixed mode floating point
1628: ;; Do not define patterns that utilize mixed mode arithmetic that result
1629: ;; in narrowing the precision, because it loses accuracy, since the standard
1630: ;; requires double rounding, whereas the 88000 instruction only rounds once.
1631:
1632: (define_expand "subdf3"
1633: [(set (match_operand:DF 0 "register_operand" "=r")
1634: (minus:DF (match_operand:DF 1 "general_operand" "r")
1635: (match_operand:DF 2 "general_operand" "r")))]
1636: ""
1637: "
1638: {
1639: operands[1] = legitimize_operand (operands[1], DFmode);
1640: operands[2] = legitimize_operand (operands[2], DFmode);
1641: }")
1642:
1643: (define_insn ""
1644: [(set (match_operand:DF 0 "register_operand" "=r")
1645: (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
1646: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
1647: ""
1648: "fsub.dss %0,%1,%2"
1649: [(set_attr "type" "spadd")])
1650:
1651: (define_insn ""
1652: [(set (match_operand:DF 0 "register_operand" "=r")
1653: (minus:DF (match_operand:DF 1 "register_operand" "r")
1654: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
1655: ""
1656: "fsub.dds %0,%1,%2"
1657: [(set_attr "type" "dpadd")])
1658:
1659: (define_insn ""
1660: [(set (match_operand:DF 0 "register_operand" "=r")
1661: (minus:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
1662: (match_operand:DF 2 "register_operand" "r")))]
1663: ""
1664: "fsub.dsd %0,%1,%2"
1665: [(set_attr "type" "dpadd")])
1666:
1667: (define_insn ""
1668: [(set (match_operand:DF 0 "register_operand" "=r")
1669: (minus:DF (match_operand:DF 1 "register_operand" "r")
1670: (match_operand:DF 2 "register_operand" "r")))]
1671: ""
1672: "fsub.ddd %0,%1,%2"
1673: [(set_attr "type" "dpadd")])
1674:
1675: (define_insn "subsf3"
1676: [(set (match_operand:SF 0 "register_operand" "=r")
1677: (minus:SF (match_operand:SF 1 "register_operand" "r")
1678: (match_operand:SF 2 "register_operand" "r")))]
1679: ""
1680: "fsub.sss %0,%1,%2"
1681: [(set_attr "type" "spadd")])
1682:
1683: (define_insn ""
1684: [(set (match_operand:DI 0 "register_operand" "=r")
1685: (minus:DI (match_operand:DI 1 "register_operand" "r")
1686: (zero_extend:DI
1687: (match_operand:SI 2 "register_operand" "r"))))]
1688: ""
1689: "subu.co %d0,%d1,%2\;subu.ci %0,%1,%#r0"
1690: [(set_attr "type" "marith")])
1691:
1692: (define_insn ""
1693: [(set (match_operand:DI 0 "register_operand" "=r")
1694: (minus:DI (zero_extend:DI
1695: (match_operand:SI 1 "register_operand" "r"))
1696: (match_operand:DI 2 "register_operand" "r")))]
1697: ""
1698: "subu.co %d0,%1,%d2\;subu.ci %0,%#r0,%2"
1699: [(set_attr "type" "marith")])
1700:
1701: (define_insn "subdi3"
1702: [(set (match_operand:DI 0 "register_operand" "=r")
1703: (minus:DI (match_operand:DI 1 "register_operand" "r")
1704: (match_operand:DI 2 "register_operand" "r")))]
1705: ""
1706: "subu.co %d0,%d1,%d2\;subu.ci %0,%1,%2"
1707: [(set_attr "type" "marith")])
1708:
1709: ;;- multiply instructions
1710: ;;
1711: ;; There is an unfounded silicon eratta for E.1 requiring that an
1712: ;; immediate constant value in div/divu/mul instructions be less than
1713: ;; 0x800. This is no longer provided for.
1714:
1715: (define_insn "mulsi3"
1716: [(set (match_operand:SI 0 "register_operand" "=r")
1717: (mult:SI (match_operand:SI 1 "arith32_operand" "%r")
1718: (match_operand:SI 2 "arith32_operand" "rI")))]
1719: ""
1720: "mul %0,%1,%2"
1721: [(set_attr "type" "imul")])
1722:
1723: ;; patterns for mixed mode floating point
1724: ;; Do not define patterns that utilize mixed mode arithmetic that result
1725: ;; in narrowing the precision, because it loses accuracy, since the standard
1726: ;; requires double rounding, whereas the 88000 instruction only rounds once.
1727:
1728: (define_expand "muldf3"
1729: [(set (match_operand:DF 0 "register_operand" "=r")
1730: (mult:DF (match_operand:DF 1 "general_operand" "%r")
1731: (match_operand:DF 2 "general_operand" "r")))]
1732: ""
1733: "
1734: {
1735: operands[1] = legitimize_operand (operands[1], DFmode);
1736: operands[2] = legitimize_operand (operands[2], DFmode);
1737: }")
1738:
1739: (define_insn ""
1740: [(set (match_operand:DF 0 "register_operand" "=r")
1741: (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
1742: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
1743: ""
1744: "fmul.dss %0,%1,%2"
1745: [(set_attr "type" "spmul")])
1746:
1747: (define_insn ""
1748: [(set (match_operand:DF 0 "register_operand" "=r")
1749: (mult:DF (match_operand:DF 1 "register_operand" "r")
1750: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
1751: ""
1752: "fmul.dds %0,%1,%2"
1753: [(set_attr "type" "spmul")])
1754:
1755: (define_insn ""
1756: [(set (match_operand:DF 0 "register_operand" "=r")
1757: (mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
1758: (match_operand:DF 2 "register_operand" "r")))]
1759: ""
1760: "fmul.dsd %0,%1,%2"
1761: [(set_attr "type" "spmul")])
1762:
1763: (define_insn ""
1764: [(set (match_operand:DF 0 "register_operand" "=r")
1765: (mult:DF (match_operand:DF 1 "register_operand" "%r")
1766: (match_operand:DF 2 "register_operand" "r")))]
1767: ""
1768: "fmul.ddd %0,%1,%2"
1769: [(set_attr "type" "dpmul")])
1770:
1771: (define_insn "mulsf3"
1772: [(set (match_operand:SF 0 "register_operand" "=r")
1773: (mult:SF (match_operand:SF 1 "register_operand" "%r")
1774: (match_operand:SF 2 "register_operand" "r")))]
1775: ""
1776: "fmul.sss %0,%1,%2"
1777: [(set_attr "type" "spmul")])
1778:
1779: ;;- divide instructions
1780: ;;
1781: ;; The 88k div and divu instructions don't reliably trap on
1782: ;; divide-by-zero. A trap to vector 503 asserts divide-by-zero. The
1783: ;; general scheme for doing divide is to do a 4-way split based on the
1784: ;; sign of the two operand and do the appropriate negates.
1785: ;;
1786: ;; The conditional trap instruction is not used as this serializes the
1787: ;; processor. Instead a conditional branch and an unconditional trap
1788: ;; are used, but after the divu. Since the divu takes up to 38 cycles,
1789: ;; the conditional branch is essentially free.
1790: ;;
1791: ;; Two target options control how divide is done. One options selects
1792: ;; whether to do the branch and negate scheme instead of using the div
1793: ;; instruction; the other option selects whether to explicitly check
1794: ;; for divide-by-zero or take your chances. If the div instruction is
1795: ;; used, the O/S must complete the operation if the operands are
1796: ;; negative. The O/S will signal an overflow condition if the most
1797: ;; negative number (-214783648) is divided by negative 1.
1798: ;;
1799: ;; There is an unfounded silicon eratta for E.1 requiring that an
1800: ;; immediate constant value in div/divu/mul instructions be less than
1801: ;; 0x800. This is no longer provided for.
1802:
1803: ;; Division by 0 trap
1804: (define_insn "trap_divide_by_zero"
1805: [(trap_if (const_int 1) 503)]
1806: ""
1807: "tb0 0,%#r0,503"
1808: [(set_attr "type" "weird")])
1809:
1810: ;; Conditional division by 0 trap.
1811: (define_expand "tcnd_divide_by_zero"
1812: [(set (pc)
1813: (if_then_else (eq (match_operand:SI 0 "register_operand" "")
1814: (const_int 0))
1815: (pc)
1816: (match_operand 1 "" "")))
1817: (trap_if (const_int 1) 503)]
1818: ""
1819: "
1820: {
1821: emit_insn (gen_cmpsi (operands[0], const0_rtx));
1822: emit_jump_insn (gen_bne (operands[1]));
1823: emit_insn (gen_trap_divide_by_zero ());
1824: emit_barrier ();
1825: DONE;
1826: }")
1827:
1828: (define_expand "divsi3"
1829: [(set (match_operand:SI 0 "register_operand" "")
1830: (div:SI (match_operand:SI 1 "arith32_operand" "")
1831: (match_operand:SI 2 "arith32_operand" "")))]
1832: ""
1833: "
1834: {
1835: rtx op0 = operands[0];
1836: rtx op1 = operands[1];
1837: rtx op2 = operands[2];
1838: rtx join_label;
1839:
1840: /* @@ This needs to be reworked. Torbjorn Granlund has suggested making
1841: it a runtime (perhaps quite special). */
1842:
1843: if (GET_CODE (op1) == CONST_INT)
1844: op1 = force_reg (SImode, op1);
1845:
1846: else if (GET_CODE (op2) == CONST_INT
1847: && ! SMALL_INT (operands[2]))
1848: op2 = force_reg (SImode, op2);
1849:
1850: if (op2 == const0_rtx)
1851: {
1852: emit_insn (gen_trap_divide_by_zero ());
1853: emit_barrier ();
1854: emit_insn (gen_dummy (op0));
1855: DONE;
1856: }
1857:
1858: if (TARGET_USE_DIV)
1859: {
1860: emit_move_insn (op0, gen_rtx (DIV, SImode, op1, op2));
1861: if (TARGET_CHECK_ZERO_DIV && GET_CODE (op2) != CONST_INT)
1862: {
1863: rtx label = gen_label_rtx ();
1864: emit_insn (gen_tcnd_divide_by_zero (op2, label));
1865: emit_label (label);
1866: emit_insn (gen_dummy (op0));
1867: }
1868: DONE;
1869: }
1870:
1871: join_label = gen_label_rtx ();
1872: if (GET_CODE (op1) == CONST_INT)
1873: {
1874: int neg = FALSE;
1875: rtx neg_op2 = gen_reg_rtx (SImode);
1876: rtx label1 = gen_label_rtx ();
1877:
1878: if (INTVAL (op1) < 0)
1879: {
1880: neg = TRUE;
1881: op1 = gen_rtx (CONST_INT, VOIDmode, -INTVAL (op1));
1882: }
1883: op1 = force_reg (SImode, op1);
1884:
1885: emit_insn (gen_negsi2 (neg_op2, op2));
1886: emit_insn (gen_cmpsi (op2, const0_rtx));
1887: emit_jump_insn (gen_bgt (label1));
1888: /* constant / 0-or-negative */
1889: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, neg_op2));
1890: if (!neg)
1891: emit_insn (gen_negsi2 (op0, op0));
1892:
1893: if (TARGET_CHECK_ZERO_DIV)
1894: emit_insn (gen_tcnd_divide_by_zero (op2, join_label));
1895: else
1896: {
1897: emit_jump_insn (gen_jump (join_label));
1898: emit_barrier ();
1899: }
1900:
1901: emit_label (label1); /* constant / positive */
1902: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2));
1903: if (neg)
1904: emit_insn (gen_negsi2 (op0, op0));
1905: }
1906:
1907: else if (GET_CODE (op2) == CONST_INT)
1908: {
1909: int neg = FALSE;
1910: rtx neg_op1 = gen_reg_rtx (SImode);
1911: rtx label1 = gen_label_rtx ();
1912:
1913: if (INTVAL (op2) < 0)
1914: {
1915: neg = TRUE;
1916: op2 = gen_rtx (CONST_INT, VOIDmode, -INTVAL (op2));
1917: }
1918: else if (! SMALL_INT (operands[2]))
1919: op2 = force_reg (SImode, op2);
1920:
1921: emit_insn (gen_negsi2 (neg_op1, op1));
1922: emit_insn (gen_cmpsi (op1, const0_rtx));
1923: emit_jump_insn (gen_bge (label1));
1924: /* 0-or-negative / constant */
1925: emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, op2));
1926: if (!neg)
1927: emit_insn (gen_negsi2 (op0, op0));
1928:
1929: emit_jump_insn (gen_jump (join_label));
1930: emit_barrier ();
1931:
1932: emit_label (label1); /* positive / constant */
1933: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2));
1934: if (neg)
1935: emit_insn (gen_negsi2 (op0, op0));
1936: }
1937:
1938: else
1939: {
1940: rtx neg_op1 = gen_reg_rtx (SImode);
1941: rtx neg_op2 = gen_reg_rtx (SImode);
1942: rtx label1 = gen_label_rtx ();
1943: rtx label2 = gen_label_rtx ();
1944: rtx label3 = gen_label_rtx ();
1945: rtx label4;
1946:
1947: emit_insn (gen_negsi2 (neg_op2, op2));
1948: emit_insn (gen_cmpsi (op2, const0_rtx));
1949: emit_jump_insn (gen_bgt (label1));
1950:
1951: emit_insn (gen_negsi2 (neg_op1, op1));
1952: emit_insn (gen_cmpsi (op1, const0_rtx));
1953: emit_jump_insn (gen_bge (label2));
1954: /* negative / negative-or-0 */
1955: emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, neg_op2));
1956:
1957: if (TARGET_CHECK_ZERO_DIV)
1958: {
1959: label4 = gen_label_rtx ();
1960: emit_insn (gen_cmpsi (op2, const0_rtx));
1961: emit_jump_insn (gen_bne (join_label));
1962: emit_label (label4);
1963: emit_insn (gen_trap_divide_by_zero ());
1964: emit_barrier ();
1965: }
1966: else
1967: {
1968: emit_jump_insn (gen_jump (join_label));
1969: emit_barrier ();
1970: }
1971:
1972: emit_label (label2); /* pos.-or-0 / neg.-or-0 */
1973: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, neg_op2));
1974:
1975: if (TARGET_CHECK_ZERO_DIV)
1976: {
1977: emit_insn (gen_cmpsi (op2, const0_rtx));
1978: emit_jump_insn (gen_beq (label4));
1979: }
1980:
1981: emit_insn (gen_negsi2 (op0, op0));
1982: emit_jump_insn (gen_jump (join_label));
1983: emit_barrier ();
1984:
1985: emit_label (label1);
1986: emit_insn (gen_negsi2 (neg_op1, op1));
1987: emit_insn (gen_cmpsi (op1, const0_rtx));
1988: emit_jump_insn (gen_bge (label3));
1989: /* negative / positive */
1990: emit_move_insn (op0, gen_rtx (UDIV, SImode, neg_op1, op2));
1991: emit_insn (gen_negsi2 (op0, op0));
1992: emit_jump_insn (gen_jump (join_label));
1993: emit_barrier ();
1994:
1995: emit_label (label3); /* positive-or-0 / positive */
1996: emit_move_insn (op0, gen_rtx (UDIV, SImode, op1, op2));
1997: }
1998:
1999: emit_label (join_label);
2000:
2001: emit_insn (gen_dummy (op0));
2002: DONE;
2003: }")
2004:
2005: (define_insn ""
2006: [(set (match_operand:SI 0 "register_operand" "=r")
2007: (div:SI (match_operand:SI 1 "register_operand" "r")
2008: (match_operand:SI 2 "arith_operand" "rI")))]
2009: ""
2010: "div %0,%1,%2"
2011: [(set_attr "type" "idiv")])
2012:
2013: (define_expand "udivsi3"
2014: [(set (match_operand:SI 0 "register_operand" "")
2015: (udiv:SI (match_operand:SI 1 "register_operand" "")
2016: (match_operand:SI 2 "arith32_operand" "")))]
2017: ""
2018: "
2019: {
2020: rtx op2 = operands[2];
2021:
2022: if (op2 == const0_rtx)
2023: {
2024: emit_insn (gen_trap_divide_by_zero ());
2025: emit_barrier ();
2026: emit_insn (gen_dummy (operands[0]));
2027: DONE;
2028: }
2029: else if (GET_CODE (op2) != CONST_INT && TARGET_CHECK_ZERO_DIV)
2030: {
2031: rtx label = gen_label_rtx ();
2032: emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2033: gen_rtx (UDIV, SImode, operands[1], op2)));
2034: emit_insn (gen_tcnd_divide_by_zero (op2, label));
2035: emit_label (label);
2036: emit_insn (gen_dummy (operands[0]));
2037: DONE;
2038: }
2039: }")
2040:
2041: (define_insn ""
2042: [(set (match_operand:SI 0 "register_operand" "=r")
2043: (udiv:SI (match_operand:SI 1 "register_operand" "r")
2044: (match_operand:SI 2 "arith32_operand" "rI")))]
2045: "operands[2] != const0_rtx"
2046: "divu %0,%1,%2"
2047: [(set_attr "type" "idiv")])
2048:
2049: (define_insn ""
2050: [(set (match_operand:SI 0 "register_operand" "=r")
2051: (udiv:SI (match_operand:SI 1 "register_operand" "r")
2052: (const_int 0)))]
2053: ""
2054: "tb0 0,%#r0,503"
2055: [(set_attr "type" "weird")])
2056:
2057: ;; patterns for mixed mode floating point.
2058: ;; Do not define patterns that utilize mixed mode arithmetic that result
2059: ;; in narrowing the precision, because it loses accuracy, since the standard
2060: ;; requires double rounding, whereas the 88000 instruction only rounds once.
2061:
2062: (define_expand "divdf3"
2063: [(set (match_operand:DF 0 "register_operand" "=r")
2064: (div:DF (match_operand:DF 1 "general_operand" "r")
2065: (match_operand:DF 2 "general_operand" "r")))]
2066: ""
2067: "
2068: {
2069: operands[1] = legitimize_operand (operands[1], DFmode);
2070: if (real_power_of_2_operand (operands[2]))
2071: {
2072: union real_extract u;
2073: bcopy (&CONST_DOUBLE_LOW (operands[2]), &u, sizeof u);
2074: emit_insn (gen_muldf3 (operands[0], operands[1],
2075: CONST_DOUBLE_FROM_REAL_VALUE (1.0/u.d, DFmode)));
2076: DONE;
2077: }
2078: else if (! register_operand (operands[2], DFmode))
2079: operands[2] = force_reg (DFmode, operands[2]);
2080: }")
2081:
2082: (define_insn ""
2083: [(set (match_operand:DF 0 "register_operand" "=r")
2084: (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
2085: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
2086: ""
2087: "fdiv.dss %0,%1,%2"
2088: [(set_attr "type" "dpdiv")])
2089:
2090: (define_insn ""
2091: [(set (match_operand:DF 0 "register_operand" "=r")
2092: (div:DF (match_operand:DF 1 "register_operand" "r")
2093: (float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
2094: ""
2095: "fdiv.dds %0,%1,%2"
2096: [(set_attr "type" "dpdiv")])
2097:
2098: (define_insn ""
2099: [(set (match_operand:DF 0 "register_operand" "=r")
2100: (div:DF (float_extend:DF (match_operand:SF 1 "register_operand" "r"))
2101: (match_operand:DF 2 "register_operand" "r")))]
2102: ""
2103: "fdiv.dsd %0,%1,%2"
2104: [(set_attr "type" "dpdiv")])
2105:
2106: (define_insn "divsf3"
2107: [(set (match_operand:SF 0 "register_operand" "=r")
2108: (div:SF (match_operand:SF 1 "register_operand" "r")
2109: (match_operand:SF 2 "register_operand" "r")))]
2110: ""
2111: "fdiv.sss %0,%1,%2"
2112: [(set_attr "type" "spdiv")])
2113:
2114: (define_insn ""
2115: [(set (match_operand:DF 0 "register_operand" "=r")
2116: (div:DF (match_operand:DF 1 "register_operand" "r")
2117: (match_operand:DF 2 "register_operand" "r")))]
2118: ""
2119: "fdiv.ddd %0,%1,%2"
2120: [(set_attr "type" "dpdiv")])
2121:
2122: ;; - remainder instructions, don't define, since the hardware doesn't have any
2123: ;; direct support, and GNU can synthesis them out of div/mul just fine.
2124:
2125: ;;- load effective address, must come after add, so that we favor using
2126: ;; addu reg,reg,reg instead of: lda reg,reg,reg (addu doesn't require
2127: ;; the data unit), and also future 88k chips might not support unscaled
2128: ;; lda instructions.
2129:
2130: (define_insn ""
2131: [(set (match_operand:SI 0 "register_operand" "=r")
2132: (match_operand:SI 1 "address_operand" "p"))]
2133: "m88k_gp_threshold > 0 && symbolic_address_p (operands[1])"
2134: "addu %0,%a1")
2135:
2136: (define_insn ""
2137: [(set (match_operand:SI 0 "register_operand" "=r")
2138: (match_operand:HI 1 "address_operand" "p"))]
2139: ""
2140: "lda.h %0,%a1"
2141: [(set_attr "type" "loada")])
2142:
2143: (define_insn ""
2144: [(set (match_operand:SI 0 "register_operand" "=r")
2145: (match_operand:SI 1 "address_operand" "p"))]
2146: ""
2147: "lda %0,%a1"
2148: [(set_attr "type" "loada")])
2149:
2150: (define_insn ""
2151: [(set (match_operand:SI 0 "register_operand" "=r")
2152: (match_operand:DI 1 "address_operand" "p"))]
2153: ""
2154: "lda.d %0,%a1"
2155: [(set_attr "type" "loada")])
2156:
2157: (define_insn ""
2158: [(set (match_operand:SI 0 "register_operand" "=r")
2159: (match_operand:SF 1 "address_operand" "p"))]
2160: ""
2161: "lda %0,%a1"
2162: [(set_attr "type" "loada")])
2163:
2164: (define_insn ""
2165: [(set (match_operand:SI 0 "register_operand" "=r")
2166: (match_operand:DF 1 "address_operand" "p"))]
2167: ""
2168: "lda.d %0,%a1"
2169: [(set_attr "type" "loada")])
2170:
2171: ;;- and instructions (with complement also)
2172: (define_insn ""
2173: [(set (match_operand:SI 0 "register_operand" "=r")
2174: (and:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
2175: (match_operand:SI 2 "register_operand" "r")))]
2176: ""
2177: "and.c %0,%2,%1")
2178:
2179: ;; If the operation is being performed on a 32-bit constant such that
2180: ;; it cannot be done in one insn, do it in two. We may lose a bit on
2181: ;; CSE in pathological cases, but it seems better doing it this way.
2182:
2183: (define_expand "andsi3"
2184: [(set (match_operand:SI 0 "register_operand" "")
2185: (and:SI (match_operand:SI 1 "arith32_operand" "")
2186: (match_operand:SI 2 "arith32_operand" "")))]
2187: ""
2188: "
2189: {
2190: if (GET_CODE (operands[2]) == CONST_INT)
2191: {
2192: int value = INTVAL (operands[2]);
2193:
2194: if (! (SMALL_INTVAL (value)
2195: || (value & 0xffff0000) == 0xffff0000
2196: || (value & 0xffff) == 0xffff
2197: || (value & 0xffff) == 0
2198: || integer_ok_for_set (~value)))
2199: {
2200: emit_insn (gen_andsi3 (operands[0], operands[1],
2201: gen_rtx (CONST_INT, VOIDmode,
2202: value | 0xffff)));
2203: operands[1] = operands[0];
2204: operands[2] = gen_rtx (CONST_INT, VOIDmode, value | 0xffff0000);
2205: }
2206: }
2207: }")
2208:
2209: (define_insn ""
2210: [(set (match_operand:SI 0 "register_operand" "=r,r")
2211: (and:SI (match_operand:SI 1 "arith32_operand" "%r,r")
2212: (match_operand:SI 2 "arith32_operand" "rIJL,rn")))]
2213: ""
2214: "* return output_and (operands);"
2215: [(set_attr "type" "arith,marith")])
2216:
2217: (define_insn ""
2218: [(set (match_operand:DI 0 "register_operand" "=r")
2219: (and:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
2220: (match_operand:DI 2 "register_operand" "r")))]
2221: ""
2222: "and.c %d0,%d2,%d1\;and.c %0,%2,%1"
2223: [(set_attr "type" "marith")])
2224:
2225: (define_insn "anddi3"
2226: [(set (match_operand:DI 0 "register_operand" "=r")
2227: (and:DI (match_operand:DI 1 "arith64_operand" "%r")
2228: (match_operand:DI 2 "arith64_operand" "rn")))]
2229: ""
2230: "*
2231: {
2232: rtx xoperands[10];
2233:
2234: xoperands[0] = operand_subword (operands[0], 1, 0, DImode);
2235: xoperands[1] = operand_subword (operands[1], 1, 0, DImode);
2236: xoperands[2] = operand_subword (operands[2], 1, 0, DImode);
2237:
2238: output_asm_insn (output_and (xoperands), xoperands);
2239:
2240: operands[0] = operand_subword (operands[0], 0, 0, DImode);
2241: operands[1] = operand_subword (operands[1], 0, 0, DImode);
2242: operands[2] = operand_subword (operands[2], 0, 0, DImode);
2243:
2244: return output_and (operands);
2245: }"
2246: [(set_attr "type" "marith")
2247: (set_attr "length" "4")]) ; length is 2, 3, or 4.
2248:
2249: ;;- Bit set (inclusive or) instructions (with complement also)
2250: (define_insn ""
2251: [(set (match_operand:SI 0 "register_operand" "=r")
2252: (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
2253: (match_operand:SI 2 "register_operand" "r")))]
2254: ""
2255: "or.c %0,%2,%1")
2256:
2257: (define_expand "iorsi3"
2258: [(set (match_operand:SI 0 "register_operand" "")
2259: (ior:SI (match_operand:SI 1 "arith32_operand" "")
2260: (match_operand:SI 2 "arith32_operand" "")))]
2261: ""
2262: "
2263: {
2264: if (GET_CODE (operands[2]) == CONST_INT)
2265: {
2266: int value = INTVAL (operands[2]);
2267:
2268: if (! (SMALL_INTVAL (value)
2269: || (value & 0xffff) == 0
2270: || integer_ok_for_set (value)))
2271: {
2272: emit_insn (gen_iorsi3 (operands[0], operands[1],
2273: gen_rtx (CONST_INT, VOIDmode,
2274: value & 0xffff0000)));
2275: operands[1] = operands[0];
2276: operands[2] = gen_rtx (CONST_INT, VOIDmode, value & 0xffff);
2277: }
2278: }
2279: }")
2280:
2281: (define_insn ""
2282: [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
2283: (ior:SI (match_operand:SI 1 "arith32_operand" "%r,r,r,r")
2284: (match_operand:SI 2 "arith32_operand" "rI,L,M,n")))]
2285: ""
2286: "@
2287: or %0,%1,%2
2288: or.u %0,%1,%X2
2289: set %0,%1,%s2
2290: or.u %0,%1,%X2\;or %0,%0,%x2"
2291: [(set_attr "type" "arith,arith,arith,marith")])
2292:
2293: (define_insn ""
2294: [(set (match_operand:DI 0 "register_operand" "=r")
2295: (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
2296: (match_operand:DI 2 "register_operand" "r")))]
2297: ""
2298: "or.c %d0,%d2,%d1\;or.c %0,%2,%1"
2299: [(set_attr "type" "marith")])
2300:
2301: (define_insn "iordi3"
2302: [(set (match_operand:DI 0 "register_operand" "=r")
2303: (ior:DI (match_operand:DI 1 "arith64_operand" "%r")
2304: (match_operand:DI 2 "arith64_operand" "rn")))]
2305: ""
2306: "*
2307: {
2308: rtx xoperands[10];
2309:
2310: xoperands[0] = operand_subword (operands[0], 1, 0, DImode);
2311: xoperands[1] = operand_subword (operands[1], 1, 0, DImode);
2312: xoperands[2] = operand_subword (operands[2], 1, 0, DImode);
2313:
2314: output_asm_insn (output_ior (xoperands), xoperands);
2315:
2316: operands[0] = operand_subword (operands[0], 0, 0, DImode);
2317: operands[1] = operand_subword (operands[1], 0, 0, DImode);
2318: operands[2] = operand_subword (operands[2], 0, 0, DImode);
2319:
2320: return output_ior (operands);
2321: }"
2322: [(set_attr "type" "marith")
2323: (set_attr "length" "4")]) ; length is 2, 3, or 4.
2324:
2325: ;;- xor instructions (with complement also)
2326: (define_insn ""
2327: [(set (match_operand:SI 0 "register_operand" "=r")
2328: (not:SI (xor:SI (match_operand:SI 1 "register_operand" "%r")
2329: (match_operand:SI 2 "register_operand" "r"))))]
2330: ""
2331: "xor.c %0,%1,%2")
2332:
2333: (define_expand "xorsi3"
2334: [(set (match_operand:SI 0 "register_operand" "")
2335: (xor:SI (match_operand:SI 1 "arith32_operand" "")
2336: (match_operand:SI 2 "arith32_operand" "")))]
2337: ""
2338: "
2339: {
2340: if (GET_CODE (operands[2]) == CONST_INT)
2341: {
2342: int value = INTVAL (operands[2]);
2343:
2344: if (! (SMALL_INTVAL (value)
2345: || (value & 0xffff) == 0))
2346: {
2347: emit_insn (gen_xorsi3 (operands[0], operands[1],
2348: gen_rtx (CONST_INT, VOIDmode,
2349: value & 0xffff0000)));
2350: operands[1] = operands[0];
2351: operands[2] = gen_rtx (CONST_INT, VOIDmode, value & 0xffff);
2352: }
2353: }
2354: }")
2355:
2356: (define_insn ""
2357: [(set (match_operand:SI 0 "register_operand" "=r,r,r")
2358: (xor:SI (match_operand:SI 1 "arith32_operand" "%r,r,r")
2359: (match_operand:SI 2 "arith32_operand" "rI,L,n")))]
2360: ""
2361: "@
2362: xor %0,%1,%2
2363: xor.u %0,%1,%X2
2364: xor.u %0,%1,%X2\;xor %0,%0,%x2"
2365: [(set_attr "type" "arith,arith,marith")])
2366:
2367: (define_insn ""
2368: [(set (match_operand:DI 0 "register_operand" "=r")
2369: (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
2370: (match_operand:DI 2 "register_operand" "r"))))]
2371: ""
2372: "xor.c %d0,%d1,%d2\;xor.c %0,%1,%2"
2373: [(set_attr "type" "marith")])
2374:
2375: (define_insn "xordi3"
2376: [(set (match_operand:DI 0 "register_operand" "=r")
2377: (xor:DI (match_operand:DI 1 "arith64_operand" "%r")
2378: (match_operand:DI 2 "arith64_operand" "rn")))]
2379: ""
2380: "*
2381: {
2382: rtx xoperands[10];
2383:
2384: xoperands[0] = operand_subword (operands[0], 1, 0, DImode);
2385: xoperands[1] = operand_subword (operands[1], 1, 0, DImode);
2386: xoperands[2] = operand_subword (operands[2], 1, 0, DImode);
2387:
2388: output_asm_insn (output_xor (xoperands), xoperands);
2389:
2390: operands[0] = operand_subword (operands[0], 0, 0, DImode);
2391: operands[1] = operand_subword (operands[1], 0, 0, DImode);
2392: operands[2] = operand_subword (operands[2], 0, 0, DImode);
2393:
2394: return output_xor (operands);
2395: }"
2396: [(set_attr "type" "marith")
2397: (set_attr "length" "4")]) ; length is 2, 3, or 4.
2398:
2399: ;;- ones complement instructions
2400: (define_insn "one_cmplsi2"
2401: [(set (match_operand:SI 0 "register_operand" "=r")
2402: (not:SI (match_operand:SI 1 "register_operand" "r")))]
2403: ""
2404: "xor.c %0,%1,%#r0")
2405:
2406: (define_insn "one_cmpldi2"
2407: [(set (match_operand:DI 0 "register_operand" "=r")
2408: (not:DI (match_operand:DI 1 "register_operand" "r")))]
2409: ""
2410: "xor.c %d0,%d1,%#r0\;xor.c %0,%1,%#r0"
2411: [(set_attr "type" "marith")])
2412:
2413: ;; Optimized special cases of shifting.
2414: ;; Must precede the general case.
2415:
2416: ;; @@ What about HImode shifted by 8?
2417:
2418: (define_insn ""
2419: [(set (match_operand:SI 0 "register_operand" "=r")
2420: (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
2421: (const_int 24)))]
2422: "! SCALED_ADDRESS_P (XEXP (operands[1], 0))"
2423: "ld.b %0,%1"
2424: [(set_attr "type" "load")])
2425:
2426: (define_insn ""
2427: [(set (match_operand:SI 0 "register_operand" "=r")
2428: (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
2429: (const_int 24)))]
2430: "! SCALED_ADDRESS_P (XEXP (operands[1], 0))"
2431: "ld.bu %0,%1"
2432: [(set_attr "type" "load")])
2433:
2434: (define_insn ""
2435: [(set (match_operand:SI 0 "register_operand" "=r")
2436: (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
2437: (const_int 16)))]
2438: "! SCALED_ADDRESS_P (XEXP (operands[1], 0))"
2439: "ld.h %0,%1"
2440: [(set_attr "type" "load")])
2441:
2442: (define_insn ""
2443: [(set (match_operand:SI 0 "register_operand" "=r")
2444: (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
2445: (const_int 16)))]
2446: "! SCALED_ADDRESS_P (XEXP (operands[1], 0))"
2447: "ld.hu %0,%1"
2448: [(set_attr "type" "load")])
2449:
2450: ;;- arithmetic shift instructions.
2451:
2452: ;; @@ Do the optimized patterns with -1 get used? Perhaps operand 1 should
2453: ;; be arith32_operand?
2454:
2455: ;; Use tbnd to support TARGET_TRAP_LARGE_SHIFT.
2456: (define_insn "tbnd"
2457: [(trap_if (gtu (match_operand:SI 0 "register_operand" "r")
2458: (match_operand:SI 1 "arith_operand" "rI"))
2459: 7)]
2460: ""
2461: "tbnd %r0,%1"
2462: [(set_attr "type" "weird")])
2463:
2464: ;; Just in case the optimizer decides to fold away the test.
2465: (define_insn ""
2466: [(trap_if (const_int 1) 7)]
2467: ""
2468: "tbnd %#r31,0"
2469: [(set_attr "type" "weird")])
2470:
2471: (define_expand "ashlsi3"
2472: [(set (match_operand:SI 0 "register_operand" "")
2473: (ashift:SI (match_operand:SI 1 "register_operand" "")
2474: (match_operand:SI 2 "arith32_operand" "")))]
2475: ""
2476: "
2477: {
2478: if (GET_CODE (operands[2]) == CONST_INT)
2479: {
2480: if ((unsigned) INTVAL (operands[2]) > 31)
2481: {
2482: if (TARGET_TRAP_LARGE_SHIFT)
2483: emit_insn (gen_tbnd (force_reg (SImode, operands[2]),
2484: gen_rtx (CONST_INT, VOIDmode, 31)));
2485: else
2486: emit_move_insn (operands[0], const0_rtx);
2487: DONE;
2488: }
2489: }
2490:
2491: else if (TARGET_TRAP_LARGE_SHIFT)
2492: emit_insn (gen_tbnd (operands[2], gen_rtx (CONST_INT, VOIDmode, 31)));
2493:
2494: else if (TARGET_HANDLE_LARGE_SHIFT)
2495: {
2496: rtx reg = gen_reg_rtx (SImode);
2497: emit_insn (gen_cmpsi (operands[2], gen_rtx (CONST_INT, VOIDmode, 31)));
2498: emit_insn (gen_sleu (reg));
2499: emit_insn (gen_andsi3 (reg, operands[1], reg));
2500: operands[1] = reg;
2501: }
2502: }")
2503:
2504: (define_insn ""
2505: [(set (match_operand:SI 0 "register_operand" "=r,r")
2506: (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
2507: (match_operand:SI 2 "arith5_operand" "r,n")))]
2508: ""
2509: "@
2510: mak %0,%1,%2
2511: mak %0,%1,0<%2>")
2512:
2513: (define_expand "ashrsi3"
2514: [(set (match_operand:SI 0 "register_operand" "")
2515: (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
2516: (match_operand:SI 2 "arith32_operand" "")))]
2517: ""
2518: "
2519: {
2520: if (GET_CODE (operands[2]) == CONST_INT)
2521: {
2522: if ((unsigned) INTVAL (operands[2]) > 31)
2523: {
2524: if (TARGET_TRAP_LARGE_SHIFT)
2525: {
2526: emit_insn (gen_tbnd (force_reg (SImode, operands[2]),
2527: gen_rtx (CONST_INT, VOIDmode, 31)));
2528: DONE;
2529: }
2530: else
2531: operands[2] = gen_rtx (CONST_INT, VOIDmode, 31);
2532: }
2533: }
2534:
2535: else if (TARGET_TRAP_LARGE_SHIFT)
2536: emit_insn (gen_tbnd (operands[2], gen_rtx (CONST_INT, VOIDmode, 31)));
2537:
2538: else if (TARGET_HANDLE_LARGE_SHIFT)
2539: {
2540: rtx reg = gen_reg_rtx (SImode);
2541: emit_insn (gen_cmpsi (operands[2], gen_rtx (CONST_INT, VOIDmode, 31)));
2542: emit_insn (gen_sgtu (reg));
2543: emit_insn (gen_iorsi3 (reg, operands[2], reg));
2544: operands[2] = reg;
2545: }
2546: }")
2547:
2548: (define_insn ""
2549: [(set (match_operand:SI 0 "register_operand" "=r,r")
2550: (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
2551: (match_operand:SI 2 "arith5_operand" "r,n")))]
2552: ""
2553: "@
2554: ext %0,%1,%2
2555: ext %0,%1,0<%2>")
2556:
2557: ;;- logical shift instructions. Logical shift left becomes arithmetic
2558: ;; shift left. LSHIFT is not normally produced, but is supported.
2559:
2560: (define_expand "lshlsi3"
2561: [(set (match_operand:SI 0 "register_operand" "")
2562: (lshift:SI (match_operand:SI 1 "register_operand" "")
2563: (match_operand:SI 2 "arith32_operand" "")))]
2564: ""
2565: "
2566: {
2567: emit_insn (gen_ashlsi3 (operands[0], operands[1], operands[2]));
2568: DONE;
2569: }")
2570:
2571: (define_insn ""
2572: [(set (match_operand:SI 0 "register_operand" "=r,r")
2573: (lshift:SI (match_operand:SI 1 "register_operand" "r,r")
2574: (match_operand:SI 2 "arith5_operand" "r,n")))]
2575: ""
2576: "@
2577: mak %0,%1,%2
2578: mak %0,%1,0<%2>")
2579:
2580: (define_expand "lshrsi3"
2581: [(set (match_operand:SI 0 "register_operand" "")
2582: (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
2583: (match_operand:SI 2 "arith32_operand" "")))]
2584: ""
2585: "
2586: {
2587: if (GET_CODE (operands[2]) == CONST_INT)
2588: {
2589: if ((unsigned) INTVAL (operands[2]) > 31)
2590: {
2591: if (TARGET_TRAP_LARGE_SHIFT)
2592: emit_insn (gen_tbnd (force_reg (SImode, operands[2]),
2593: gen_rtx (CONST_INT, VOIDmode, 31)));
2594: else
2595: emit_move_insn (operands[0], const0_rtx);
2596: DONE;
2597: }
2598: }
2599:
2600: else if (TARGET_TRAP_LARGE_SHIFT)
2601: emit_insn (gen_tbnd (operands[2], gen_rtx (CONST_INT, VOIDmode, 31)));
2602:
2603: else if (TARGET_HANDLE_LARGE_SHIFT)
2604: {
2605: rtx reg = gen_reg_rtx (SImode);
2606: emit_insn (gen_cmpsi (operands[2], gen_rtx (CONST_INT, VOIDmode, 31)));
2607: emit_insn (gen_sleu (reg));
2608: emit_insn (gen_andsi3 (reg, operands[1], reg));
2609: operands[1] = reg;
2610: }
2611: }")
2612:
2613: (define_insn ""
2614: [(set (match_operand:SI 0 "register_operand" "=r,r")
2615: (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
2616: (match_operand:SI 2 "arith5_operand" "r,n")))]
2617: ""
2618: "@
2619: extu %0,%1,%2
2620: extu %0,%1,0<%2>")
2621:
2622: ;;- rotate instructions
2623:
2624: (define_expand "rotlsi3"
2625: [(set (match_operand:SI 0 "register_operand" "")
2626: (rotatert:SI (match_operand:SI 1 "register_operand" "")
2627: (match_operand:SI 2 "arith32_operand" "")))]
2628: ""
2629: "
2630: {
2631: if (GET_CODE (operands[2]) == CONST_INT
2632: && (unsigned) INTVAL (operands[2]) >= 32)
2633: operands[2] = gen_rtx (CONST_INT, VOIDmode,
2634: (32 - INTVAL (operands[2])) % 32);
2635: else
2636: {
2637: rtx op = gen_reg_rtx (SImode);
2638: emit_insn (gen_negsi2 (op, operands[2]));
2639: operands[2] = op;
2640: }
2641: }")
2642:
2643: (define_insn "rotrsi3"
2644: [(set (match_operand:SI 0 "register_operand" "=r")
2645: (rotatert:SI (match_operand:SI 1 "register_operand" "r")
2646: (match_operand:SI 2 "arith_operand" "rI")))]
2647: ""
2648: "rot %0,%1,%2")
2649:
2650: ;; Bit field instructions.
2651:
2652: (define_insn ""
2653: [(set (match_operand:SI 0 "register_operand" "=r")
2654: (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
2655: (const_int 32)
2656: (const_int 0)))]
2657: ""
2658: "or %0,%#r0,%1")
2659:
2660: (define_insn "extv"
2661: [(set (match_operand:SI 0 "register_operand" "=r")
2662: (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
2663: (match_operand:SI 2 "int5_operand" "")
2664: (match_operand:SI 3 "int5_operand" "")))]
2665: ""
1.1.1.2 ! root 2666: "*
! 2667: {
! 2668: operands[4] = gen_rtx (CONST_INT, SImode,
! 2669: (32 - INTVAL (operands[2])) - INTVAL (operands[3]));
! 2670: return \"ext %0,%1,%2<%4>\"; /* <(32-%2-%3)> */
! 2671: }")
1.1 root 2672:
2673: (define_insn ""
2674: [(set (match_operand:SI 0 "register_operand" "=r")
2675: (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
2676: (const_int 32)
2677: (const_int 0)))]
2678: ""
2679: "or %0,%#r0,%1")
2680:
2681: (define_insn "extzv"
2682: [(set (match_operand:SI 0 "register_operand" "=r")
2683: (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
2684: (match_operand:SI 2 "int5_operand" "")
2685: (match_operand:SI 3 "int5_operand" "")))]
2686: ""
1.1.1.2 ! root 2687: "*
! 2688: {
! 2689: operands[4] = gen_rtx (CONST_INT, SImode,
! 2690: (32 - INTVAL (operands[2])) - INTVAL (operands[3]));
! 2691: return \"extu %0,%1,%2<%4>\"; /* <(32-%2-%3)> */
! 2692: }")
1.1 root 2693:
2694: (define_insn ""
1.1.1.2 ! root 2695: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
1.1 root 2696: (match_operand:SI 1 "int5_operand" "")
2697: (match_operand:SI 2 "int5_operand" ""))
2698: (const_int 0))]
2699: ""
1.1.1.2 ! root 2700: "*
! 2701: {
! 2702: operands[3] = gen_rtx (CONST_INT, SImode,
! 2703: (32 - INTVAL (operands[1])) - INTVAL (operands[2]));
! 2704: return \"clr %0,%0,%1<%3>\"; /* <(32-%1-%2)> */
! 2705: }")
1.1 root 2706:
2707: (define_insn ""
1.1.1.2 ! root 2708: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
1.1 root 2709: (match_operand:SI 1 "int5_operand" "")
2710: (match_operand:SI 2 "int5_operand" ""))
2711: (const_int -1))]
2712: ""
1.1.1.2 ! root 2713: "*
! 2714: {
! 2715: operands[3] = gen_rtx (CONST_INT, SImode,
! 2716: (32 - INTVAL (operands[1])) - INTVAL (operands[2]));
! 2717: return \"set %0,%0,%1<%3>\"; /* <(32-%1-%2)> */
! 2718: }")
1.1 root 2719:
2720: (define_insn ""
1.1.1.2 ! root 2721: [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
1.1 root 2722: (match_operand:SI 1 "int5_operand" "")
2723: (match_operand:SI 2 "int5_operand" ""))
2724: (match_operand:SI 3 "int32_operand" "n"))]
2725: ""
2726: "*
2727: {
2728: int value = INTVAL (operands[3]);
2729:
2730: if (INTVAL (operands[1]) < 32)
2731: value &= (1 << INTVAL (operands[1])) - 1;
2732:
2733: operands[2] = gen_rtx (CONST_INT, VOIDmode,
2734: 32 - (INTVAL(operands[1]) + INTVAL(operands[2])));
2735:
2736: value <<= INTVAL (operands[2]);
2737: operands[3] = gen_rtx (CONST_INT, VOIDmode, value);
2738:
2739: if (SMALL_INTVAL (value))
2740: return \"clr %0,%0,%1<%2>\;or %0,%0,%3\";
2741: else if ((value & 0x0000ffff) == 0)
2742: return \"clr %0,%0,%1<%2>\;or.u %0,%0,%X3\";
2743: else
2744: return \"clr %0,%0,%1<%2>\;or.u %0,%0,%X3\;or %0,%0,%x3\";
2745: }"
2746: [(set_attr "type" "marith")
2747: (set_attr "length" "3")]) ; may be 2 or 3.
2748:
2749: ;; negate insns
2750: (define_insn "negsi2"
2751: [(set (match_operand:SI 0 "register_operand" "=r")
2752: (neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
2753: ""
2754: "subu %0,%#r0,%1")
2755:
2756: (define_insn ""
2757: [(set (match_operand:SF 0 "register_operand" "=r")
2758: (float_truncate:SF (neg:DF (match_operand:DF 1 "register_operand" "r"))))]
2759: ""
2760: "fsub.ssd %0,%#r0,%1"
2761: [(set_attr "type" "dpadd")])
2762:
2763: (define_insn ""
2764: [(set (match_operand:DF 0 "register_operand" "+r")
2765: (neg:DF (match_dup 0)))]
2766: ""
2767: "xor.u %0,%0,0x8000")
2768:
2769: (define_insn "negdf2"
2770: [(set (match_operand:DF 0 "register_operand" "=&r")
2771: (neg:DF (match_operand:DF 1 "register_operand" "r")))]
2772: ""
2773: "xor.u %0,%1,0x8000\;or %d0,%#r0,%d1"
2774: [(set_attr "type" "marith")])
2775:
2776: (define_insn "negsf2"
2777: [(set (match_operand:SF 0 "register_operand" "=r")
2778: (neg:SF (match_operand:SF 1 "register_operand" "r")))]
2779: ""
2780: "xor.u %0,%1,0x8000")
2781:
2782: ;; absolute value insns for floating-point (integer abs can be done using the
2783: ;; machine-independent sequence).
2784:
2785: (define_insn ""
2786: [(set (match_operand:DF 0 "register_operand" "+r")
2787: (abs:DF (match_dup 0)))]
2788: ""
2789: "and.u %0,%0,0x7fff")
2790:
2791: (define_insn "absdf2"
2792: [(set (match_operand:DF 0 "register_operand" "=&r")
2793: (abs:DF (match_operand:DF 1 "register_operand" "r")))]
2794: ""
2795: "and.u %0,%1,0x7fff\;or %d0,%#r0,%d1"
2796: [(set_attr "type" "marith")])
2797:
2798: (define_insn "abssf2"
2799: [(set (match_operand:SF 0 "register_operand" "=r")
2800: (abs:SF (match_operand:SF 1 "register_operand" "r")))]
2801: ""
2802: "and.u %0,%1,0x7fff")
2803:
2804: ;; Subroutines of "casesi".
2805:
2806: ;; Operand 0 is index
2807: ;; operand 1 is the minimum bound
2808: ;; operand 2 is the maximum bound - minimum bound + 1
2809: ;; operand 3 is CODE_LABEL for the table;
2810: ;; operand 4 is the CODE_LABEL to go to if index out of range.
2811:
2812: (define_expand "casesi"
2813: ;; We don't use these for generating the RTL, but we must describe
2814: ;; the operands here.
2815: [(match_operand:SI 0 "general_operand" "")
2816: (match_operand:SI 1 "immediate_operand" "")
2817: (match_operand:SI 2 "immediate_operand" "")
2818: (match_operand 3 "" "")
2819: (match_operand 4 "" "")]
2820: ""
2821: "
2822: {
2823: register rtx index_diff = gen_reg_rtx (SImode);
2824: register rtx low = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[1]));
2825:
2826: /* Compute the index difference and handle the default case. */
2827: emit_insn (gen_addsi3 (index_diff,
2828: force_reg (SImode, operands[0]),
2829: ADD_INT (low) ? low : force_reg (SImode, low)));
2830: emit_insn (gen_cmpsi (index_diff, operands[2]));
2831: emit_jump_insn (gen_bgtu (operands[4]));
2832:
2833: /* Call the jump that will branch to the appropriate case. */
2834: emit_jump_insn (gen_casesi_enter (gen_rtx (LABEL_REF, VOIDmode, operands[3]),
2835: index_diff,
2836: operands[3]));
2837: /* Claim that flow drops into the table so it will be adjacent. */
2838: DONE;
2839: }")
2840:
2841: ;; The bsr.n instruction is directed to the END of the table. See
2842: ;; ASM_OUTPUT_CASE_END.
2843:
2844: (define_insn "casesi_enter"
2845: [(set (pc) (match_operand 0 "" ""))
2846: (use (match_operand:SI 1 "register_operand" "r"))
2847: ;; The USE here is so that at least one jump-insn will refer to the label,
2848: ;; to keep it alive in jump_optimize.
2849: (use (label_ref (match_operand 2 "" "")))
2850: (clobber (reg:SI 1))]
2851: ""
2852: "*
2853: {
2854: if (flag_delayed_branch)
2855: return \"bsr.n %0e\;lda %#r1,%#r1[%1]\";
2856: m88k_case_index = REGNO (operands[1]);
2857: return \"bsr %0e\";
2858: }"
2859: [(set_attr "type" "weird")
2860: (set_attr "length" "3")]) ; Including the "jmp r1".
2861:
2862: ;;- jump to subroutine
2863: (define_expand "call"
2864: [(parallel [(call (match_operand:SI 0 "" "")
2865: (match_operand 1 "" ""))
2866: (use (reg:SI 1))])]
2867: ""
2868: "
2869: {
2870: if (GET_CODE (operands[0]) == MEM
2871: && ! call_address_operand (XEXP (operands[0], 0), SImode))
2872: operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
2873: force_reg (Pmode, XEXP (operands[0], 0)));
2874: }")
2875:
2876: (define_insn ""
2877: [(parallel [(call (mem:SI (match_operand:SI 0 "call_address_operand" "rQ"))
2878: (match_operand 1 "" ""))
2879: (use (reg:SI 1))])]
2880: ""
2881: "* return output_call (operands, operands[0]);"
2882: [(set_attr "type" "call")])
2883:
2884: (define_expand "call_value"
2885: [(parallel [(set (match_operand 0 "register_operand" "")
2886: (call (match_operand:SI 1 "" "")
2887: (match_operand 2 "" "")))
2888: (use (reg:SI 1))])]
2889: ""
2890: "
2891: {
2892: if (GET_CODE (operands[1]) == MEM
2893: && ! call_address_operand (XEXP (operands[1], 0), SImode))
2894: operands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
2895: force_reg (Pmode, XEXP (operands[1], 0)));
2896: }")
2897:
2898: (define_insn ""
2899: [(parallel [(set (match_operand 0 "register_operand" "=r")
2900: (call (mem:SI
2901: (match_operand:SI 1 "call_address_operand" "rQ"))
2902: (match_operand 2 "" "")))
2903: (use (reg:SI 1))])]
2904: ""
2905: "* return output_call (operands, operands[1]);"
2906: [(set_attr "type" "call")])
2907:
2908: ;; Nop instruction and others
2909:
2910: (define_insn "nop"
2911: [(const_int 0)]
2912: ""
2913: "ff0 %#r0,%#r0")
2914:
2915: (define_insn "return"
2916: [(return)]
2917: "null_epilogue ()"
2918: "jmp%. %#r1"
2919: [(set_attr "type" "branch")])
2920:
2921: (define_insn "indirect_jump"
2922: [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
2923: ""
2924: "jmp%. %0"
2925: [(set_attr "type" "branch")])
2926:
2927: (define_insn "jump"
2928: [(set (pc)
2929: (label_ref (match_operand 0 "" "")))]
2930: ""
2931: "br%. %l0"
2932: [(set_attr "type" "jump")])
2933:
2934: ;; This insn is used for some loop tests, typically loops reversed when
2935: ;; strength reduction is used. It is actually created when the instruction
2936: ;; combination phase combines the special loop test. Since this insn
2937: ;; is both a jump insn and has an output, it must deal with it's own
2938: ;; reloads, hence the `m' constraints. The `!' constraints direct reload
2939: ;; to not choose the register alternatives in the event a reload is needed.
2940:
2941: (define_insn "decrement_and_branch_until_zero"
2942: [(set (pc)
2943: (if_then_else
2944: (match_operator 0 "relop_no_unsigned"
2945: [(match_operand:SI 1 "register_operand" "+!r,!r,m,m")
2946: (const_int 0)])
2947: (label_ref (match_operand 2 "" ""))
2948: (pc)))
2949: (set (match_dup 1)
2950: (plus:SI (match_dup 1)
2951: (match_operand:SI 3 "add_operand" "rI,J,rI,J")))
2952: (clobber (match_scratch:SI 4 "=X,X,&r,&r"))
2953: (clobber (match_scratch:SI 5 "=X,X,&r,&r"))]
2954: "find_reg_note (insn, REG_NONNEG, 0)"
2955: "@
2956: bcnd.n %B0,%1,%2\;addu %1,%1,%3
2957: bcnd.n %B0,%1,%2\;subu %1,%1,%n3
2958: ld %4,%1\;addu %5,%4,%3\;bcnd.n %B0,%4,%2\;st %5,%1
2959: ld %4,%1\;subu %5,%4,%n3\;bcnd.n %B0,%4,%2\;st %5,%1"
2960: [(set_attr "type" "weird")
2961: (set_attr "length" "2,2,4,4")])
2962:
2963: ;; Special insn to serve as the last insn of a define_expand. This insn
2964: ;; will generate no code.
2965:
2966: (define_expand "dummy"
2967: [(set (match_operand 0 "" "") (match_dup 0))]
2968: ""
2969: "")
2970:
2971: ;;- Local variables:
2972: ;;- mode:emacs-lisp
2973: ;;- comment-start: ";;- "
2974: ;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
2975: ;;- eval: (modify-syntax-entry ?[ "(]")
2976: ;;- eval: (modify-syntax-entry ?] ")[")
2977: ;;- eval: (modify-syntax-entry ?{ "(}")
2978: ;;- eval: (modify-syntax-entry ?} "){")
2979: ;;- End:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.