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