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