|
|
1.1 root 1: ;;- Machine description Acorn RISC Machine for GNU compiler
2: ;; Copyright (C) 1991, 1993 Free Software Foundation, Inc.
3: ;; Contributed by Pieter `Tiggr' Schoenmakers ([email protected])
4: ;; and Martin Simmons (@harleqn.co.uk).
5: ;; More major hacks by Richard Earnshaw ([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: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24:
25: ;; Every template must be output by arm_output_asm_insn, since this keeps
26: ;; track of the offset of labels within the text segment. This is needed to
27: ;; to be able to (correctly) output instructions for loading a value from a
28: ;; function's constant pool, since different instructions are needed when the
29: ;; constant pool is more than 4095 bytes away from the PC.
30:
31: ;; There are patterns in this file to support XFmode arithmetic.
32: ;; Unfortunately RISCiX doesn't work well with these so they are disabled.
33: ;; (See arm.h)
34:
35: ;; UNSPEC Usage:
36: ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
37: ;; the mode is MODE_FLOAT
38: ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
39: ;; the mode is MODE_FLOAT
40:
41: ;; Attributes
42:
43: ; condition codes: this one is used by final_prescan_insn to speed up
44: ; conditionalizing instructions. It saves having to scan the rtl to see if
45: ; it uses or alters the condition codes.
46:
47: ; USE means that the condition codes are used by the insn in the process of
48: ; outputting code, this means (at present) that we can't use the insn in
49: ; inlined branches
50:
51: ; SET means that the purpose of the insn is to set the condition codes in a
52: ; well defined manner.
53:
54: ; CLOB means that the condition codes are altered in an undefined manner, if
55: ; they are altered at all
56:
57: ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
58: ; but are if the branch wasn't taken; the effect is to limit the branch
59: ; elimination scanning.
60:
61: ; NOCOND means that the condition codes are niether altered nor affect the
62: ; output of this insn
63:
64: (define_attr "conds" "use,set,clob,jump_clob,nocond"
65: (const_string "nocond"))
66:
67: ; CPU attribute is used to determine whether condition codes are clobbered
68: ; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the
69: ; arm2 and arm3 the condition codes are restored by the return.
70:
71: (define_attr "cpu" "arm2,arm3,arm6" (const (symbol_ref "arm_cpu_attr")))
72:
73: ; LENGTH, all instructions are 4 bytes
74: (define_attr "length" "" (const_int 1))
75:
76: ; An assembler sequence may clobber the condition codes without us knowing
77: (define_asm_attributes
78: [(set_attr "conds" "clob")
79: (set_attr "length" "1")])
80:
81: ; TYPE attribute is used to detect floating point instructions which, if
82: ; running on a co-processor can run in parallel with other, basic instructions
83: ; If write-buffer scheduling is enabled then it can also be used in the
84: ; scheduling of writes.
85:
86: ; Classification of each insn
87: ; normal any data instruction that doesn't hit memory or fp regs
88: ; block blockage insn, this blocks all functional units
89: ; float a floating point arithmetic operation (subject to expansion)
90: ; float_em a floating point arithmetic operation that is normally emulated
91: ; f_load a floating point load from memory
92: ; f_store a floating point store to memory
93: ; f_mem_r a transfer of a floating point register to a real reg via mem
94: ; r_mem_f the reverse of f_mem_r
95: ; f_2_r fast transfer float to arm (no memory needed)
96: ; r_2_f fast transfer arm to float
97: ; call a subroutine call
98: ; load any load from memory
99: ; store1 store 1 word to memory from arm registers
100: ; store2 store 2 words
101: ; store3 store 3 words
102: ; store4 store 4 words
103: ;
104: (define_attr "type"
105: "normal,block,float,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4"
106: (const_string "normal"))
107:
108: (define_attr "write_conflict" "no,yes"
109: (if_then_else (eq_attr "type"
110: "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
111: (const_string "yes")
112: (const_string "no")))
113:
114: ; The write buffer on some of the arm6 processors is hard to model exactly.
115: ; There is room in the buffer for up to two addresses and up to eight words
116: ; of memory, but the two needn't be split evenly. When writing the two
117: ; addresses are fully pipelined. However, a read from memory that is not
118: ; currently in the cache will block until the writes have completed.
119: ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
120: ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
121: ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
122: ; cycle to add as well.
123:
124: ;; (define_function_unit {name} {num-units} {n-users} {test}
125: ;; {ready-delay} {issue-delay} [{conflict-list}])
126: ;; This is not well tuned, but I don't have all the details.
127: (define_function_unit "fpa" 1 1 (eq_attr "type" "float") 5 0)
128:
129: (define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 3 3
130: [(eq_attr "write_conflict" "yes")])
131: (define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 5 5
132: [(eq_attr "write_conflict" "yes")])
133: (define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 7 7
134: [(eq_attr "write_conflict" "yes")])
135: (define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 9 9
136: [(eq_attr "write_conflict" "yes")])
137: (define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 3 3
138: [(eq_attr "write_conflict" "yes")])
139:
140: ;; Note: For DImode insns, there is normally no reason why operands should
141: ;; not be in the same register, what we don't want is for something being
142: ;; written to partially overlap something that is an input.
143:
144: ;; Addition insns.
145:
146: (define_insn "adddi3"
147: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
148: (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
149: (match_operand:DI 2 "s_register_operand" "r,0")))
150: (clobber (reg:CC 24))]
151: ""
152: "*
153: arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands);
154: return (arm_output_asm_insn (\"adc\\t%R0, %R1, %R2\", operands));
155: "
156: [(set_attr "conds" "clob")
157: (set_attr "length" "2")])
158:
159: (define_insn ""
160: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
161: (plus:DI (sign_extend:DI
162: (match_operand:SI 1 "s_register_operand" "r,r"))
163: (match_operand:DI 2 "s_register_operand" "r,0")))
164: (clobber (reg:CC 24))]
165: ""
166: "*
167: arm_output_asm_insn (\"adds\\t%0, %2, %1\", operands);
168: return (arm_output_asm_insn (\"adc\\t%R0, %R2, %1, asr #31\", operands));
169: "
170: [(set_attr "conds" "clob")
171: (set_attr "length" "2")])
172:
173: (define_insn ""
174: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
175: (plus:DI (zero_extend:DI
176: (match_operand:SI 1 "s_register_operand" "r,r"))
177: (match_operand:DI 2 "s_register_operand" "r,0")))
178: (clobber (reg:CC 24))]
179: ""
180: "*
181: arm_output_asm_insn (\"adds\\t%0, %2, %1\", operands);
182: return (arm_output_asm_insn (\"adc\\t%R0, %R2, #0\", operands));
183: "
184: [(set_attr "conds" "clob")
185: (set_attr "length" "2")])
186:
187: (define_insn "addsi3"
188: [(set (match_operand:SI 0 "s_register_operand" "=r")
189: (plus:SI (match_operand:SI 1 "s_register_operand" "r")
190: (match_operand:SI 2 "arm_add_operand" "rL")))]
191: ""
192: "*
193: if (GET_CODE (operands[2]) == CONST_INT
194: && !const_ok_for_arm (INTVAL (operands[2])))
195: {
196: operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2]));
197: return arm_output_asm_insn (\"sub\\t%0, %1, %2\", operands);
198: }
199: return arm_output_asm_insn (\"add\\t%0, %1, %2\", operands);
200: ")
201:
202: (define_insn ""
203: [(set (reg:CC_NOOV 24)
204: (compare:CC_NOOV (plus:SI (match_operand:SI 1 "s_register_operand" "r")
205: (match_operand:SI 2 "arm_add_operand" "rL"))
206: (const_int 0)))
207: (set (match_operand:SI 0 "s_register_operand" "=r")
208: (plus:SI (match_dup 1) (match_dup 2)))]
209: ""
210: "*
211: if (GET_CODE (operands[2]) == CONST_INT
212: && !const_ok_for_arm (INTVAL (operands[2])))
213: {
214: operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2]));
215: return arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
216: }
217: return (arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands));
218: "
219: [(set_attr "conds" "set")])
220:
221: (define_insn ""
222: [(set (reg:CC 24)
223: (compare:CC (match_operand:SI 1 "s_register_operand" "r")
224: (neg:SI (match_operand:SI 2 "arm_add_operand" "rL"))))
225: (set (match_operand:SI 0 "s_register_operand" "=r")
226: (plus:SI (match_dup 1) (match_dup 2)))]
227: ""
228: "*
229: if (GET_CODE (operands[2]) == CONST_INT
230: && !const_ok_for_arm (INTVAL (operands[2])))
231: {
232: operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2]));
233: return arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
234: }
235: return (arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands));
236: "
237: [(set_attr "conds" "set")])
238:
239: (define_insn "incscc"
240: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
241: (plus:SI (match_operator:SI 2 "comparison_operator"
242: [(reg 24) (const_int 0)])
243: (match_operand:SI 1 "s_register_operand" "0,?r")))]
244: ""
245: "*
246: if (which_alternative == 1)
247: arm_output_asm_insn (\"mov%D2\\t%0, %1\", operands);
248: return arm_output_asm_insn (\"add%d2\\t%0, %1, #1\", operands);
249: "
250: [(set_attr "conds" "use")
251: (set_attr "length" "*,2")])
252:
253: ; If a constant is too big to fit in a single instruction then the constant
254: ; will be pre-loaded into a register taking at least two insns, we might be
255: ; able to merge it with an add, but it depends on the exact value.
256:
257: (define_split
258: [(set (match_operand:SI 0 "s_register_operand" "=r")
259: (plus:SI (match_operand:SI 1 "s_register_operand" "r")
260: (match_operand:SI 2 "immediate_operand" "n")))]
261: "!(const_ok_for_arm (INTVAL (operands[2]))
262: || const_ok_for_arm (-INTVAL (operands[2])))"
263: [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
264: (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
265: "
266: {
267: unsigned int val = (unsigned) INTVAL (operands[2]);
268: int i;
269: unsigned int temp;
270:
271: /* this code is similar to the approach followed in movsi, but it must
272: generate exactly two insns */
273:
274: for (i = 30; i >= 0; i -= 2)
275: {
276: if (val & (3 << i))
277: {
278: i -= 6;
279: if (i < 0) i = 0;
280: if (const_ok_for_arm (temp = (val & ~(255 << i))))
281: {
282: val &= 255 << i;
283: break;
284: }
285: /* we might be able to do this as (larger number - small number) */
286: temp = ((val >> i) & 255) + 1;
287: if (temp > 255 && i < 24)
288: {
289: i += 2;
290: temp = ((val >> i) & 255) + 1;
291: }
292: if (const_ok_for_arm ((temp << i) - val))
293: {
294: i = temp << i;
295: temp = (unsigned) - (int) (i - val);
296: val = i;
297: break;
298: }
299: FAIL;
300: }
301: }
302: /* if we got here, we have found a way of doing it in two instructions.
303: the two constants are in val and temp */
304: operands[2] = GEN_INT ((int)val);
305: operands[3] = GEN_INT ((int)temp);
306: }
307: ")
308:
309: (define_insn "addsf3"
310: [(set (match_operand:SF 0 "s_register_operand" "=f,f")
311: (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
312: (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
313: ""
314: "*
315: {
316: REAL_VALUE_TYPE r;
317:
318: switch (which_alternative)
319: {
320: case 0:
321: return arm_output_asm_insn (\"adfs\\t%0, %1, %2\", operands);
322: case 1:
323: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
324: r = REAL_VALUE_NEGATE (r);
325: operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[2]));
326: return arm_output_asm_insn (\"sufs\\t%0, %1, %2\", operands);
327: }
328: }
329: "
330: [(set_attr "type" "float")])
331:
332: (define_insn "adddf3"
333: [(set (match_operand:DF 0 "s_register_operand" "=f,f")
334: (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
335: (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
336: ""
337: "*
338: {
339: REAL_VALUE_TYPE r;
340:
341: switch (which_alternative)
342: {
343: case 0:
344: return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
345: case 1:
346: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
347: r = REAL_VALUE_NEGATE (r);
348: operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[2]));
349: return arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands);
350: }
351: }
352: "
353: [(set_attr "type" "float")])
354:
355: (define_insn ""
356: [(set (match_operand:DF 0 "s_register_operand" "=f,f")
357: (plus:DF (float_extend:DF
358: (match_operand:SF 1 "s_register_operand" "f,f"))
359: (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
360: ""
361: "*
362: {
363: REAL_VALUE_TYPE r;
364:
365: switch (which_alternative)
366: {
367: case 0:
368: return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
369: case 1:
370: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
371: r = REAL_VALUE_NEGATE (r);
372: operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[2]));
373: return arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands);
374: }
375: }
376: "
377: [(set_attr "type" "float")])
378:
379: (define_insn ""
380: [(set (match_operand:DF 0 "s_register_operand" "=f")
381: (plus:DF (match_operand:DF 1 "s_register_operand" "f")
382: (float_extend:DF
383: (match_operand:SF 2 "s_register_operand" "f"))))]
384: ""
385: "*
386: return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
387: "
388: [(set_attr "type" "float")])
389:
390: (define_insn ""
391: [(set (match_operand:DF 0 "s_register_operand" "=f")
392: (plus:DF (float_extend:DF
393: (match_operand:SF 1 "s_register_operand" "f"))
394: (float_extend:DF
395: (match_operand:SF 2 "s_register_operand" "f"))))]
396: ""
397: "*
398: return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
399: "
400: [(set_attr "type" "float")])
401:
402: (define_insn "addxf3"
403: [(set (match_operand:XF 0 "s_register_operand" "=f,f")
404: (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
405: (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
406: "ENABLE_XF_PATTERNS"
407: "*
408: {
409: REAL_VALUE_TYPE r;
410:
411: switch (which_alternative)
412: {
413: case 0:
414: return (arm_output_asm_insn (\"adfe\\t%0, %1, %2\", operands));
415: case 1:
416: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
417: r = REAL_VALUE_NEGATE (r);
418: operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[2]));
419: return arm_output_asm_insn (\"sufe\\t%0, %1, %2\", operands);
420: }
421: }
422: "
423: [(set_attr "type" "float")])
424:
425: (define_insn "subdi3"
426: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
427: (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
428: (match_operand:DI 2 "s_register_operand" "r,0,0")))
429: (clobber (reg:CC 24))]
430: ""
431: "*
432: arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
433: return (arm_output_asm_insn (\"sbc\\t%R0, %R1, %R2\", operands));
434: "
435: [(set_attr "conds" "clob")
436: (set_attr "length" "2")])
437:
438: (define_insn ""
439: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
440: (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
441: (zero_extend:DI
442: (match_operand:SI 2 "s_register_operand" "r,r"))))
443: (clobber (reg:CC 24))]
444: ""
445: "*
446: arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
447: return (arm_output_asm_insn (\"sbc\\t%R0, %R1, #0\", operands));
448: "
449: [(set_attr "conds" "clob")
450: (set_attr "length" "2")])
451:
452: (define_insn ""
453: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
454: (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
455: (sign_extend:DI
456: (match_operand:SI 2 "s_register_operand" "r,r"))))
457: (clobber (reg:CC 24))]
458: ""
459: "*
460: arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
461: return (arm_output_asm_insn (\"sbc\\t%R0, %R1, %2, asr #31\", operands));
462: "
463: [(set_attr "conds" "clob")
464: (set_attr "length" "2")])
465:
466: (define_insn ""
467: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
468: (minus:DI (zero_extend:DI
469: (match_operand:SI 2 "s_register_operand" "r,r"))
470: (match_operand:DI 1 "s_register_operand" "?r,0")))
471: (clobber (reg:CC 24))]
472: ""
473: "*
474: arm_output_asm_insn (\"rsbs\\t%0, %1, %2\", operands);
475: return (arm_output_asm_insn (\"rsc\\t%R0, %R1, #0\", operands));
476: "
477: [(set_attr "conds" "clob")
478: (set_attr "length" "2")])
479:
480: (define_insn ""
481: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
482: (minus:DI (sign_extend:DI
483: (match_operand:SI 2 "s_register_operand" "r,r"))
484: (match_operand:DI 1 "s_register_operand" "?r,0")))
485: (clobber (reg:CC 24))]
486: ""
487: "*
488: arm_output_asm_insn (\"rsbs\\t%0, %1, %2\", operands);
489: return (arm_output_asm_insn (\"rsc\\t%R0, %R1, %2, asr #31\", operands));
490: "
491: [(set_attr "conds" "clob")
492: (set_attr "length" "2")])
493:
494: (define_insn ""
495: [(set (match_operand:DI 0 "s_register_operand" "=r")
496: (minus:DI (zero_extend:DI
497: (match_operand:SI 1 "s_register_operand" "r"))
498: (zero_extend:DI
499: (match_operand:SI 2 "s_register_operand" "r"))))
500: (clobber (reg:CC 24))]
501: ""
502: "*
503: arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
504: return (arm_output_asm_insn (\"rsc\\t%R0, %1, %1 @ extend carry\",
505: operands));
506: "
507: [(set_attr "conds" "clob")
508: (set_attr "length" "2")])
509:
510: (define_insn "subsi3"
511: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
512: (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
513: (match_operand:SI 2 "arm_rhs_operand" "rI,r")))]
514: ""
515: "*
516: switch (which_alternative)
517: {
518: case 0:
519: return (arm_output_asm_insn (\"sub\\t%0, %1, %2\", operands));
520: case 1:
521: return (arm_output_asm_insn (\"rsb\\t%0, %2, %1\", operands));
522: }
523: ")
524:
525: (define_insn ""
526: [(set (reg:CC_NOOV 24)
527: (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
528: (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
529: (const_int 0)))
530: (set (match_operand:SI 0 "s_register_operand" "=r,r")
531: (minus:SI (match_dup 1) (match_dup 2)))]
532: ""
533: "*
534: switch (which_alternative)
535: {
536: case 0:
537: return arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
538: case 1:
539: return arm_output_asm_insn (\"rsbs\\t%0, %2, %1\", operands);
540: }
541: "
542: [(set_attr "conds" "set")])
543:
544: (define_insn "decscc"
545: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
546: (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
547: (match_operator:SI 2 "comparison_operator"
548: [(reg 24) (const_int 0)])))]
549: ""
550: "*
551: if (which_alternative == 1)
552: arm_output_asm_insn (\"mov%D2\\t%0, %1\", operands);
553: return arm_output_asm_insn (\"sub%d2\\t%0, %1, #1\", operands);
554: "
555: [(set_attr "conds" "use")
556: (set_attr "length" "*,2")])
557:
558: (define_insn "subsf3"
559: [(set (match_operand:SF 0 "s_register_operand" "=f,f")
560: (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
561: (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
562: ""
563: "*
564: switch (which_alternative)
565: {
566: case 0:
567: return (arm_output_asm_insn (\"sufs\\t%0, %1, %2\", operands));
568: case 1:
569: return (arm_output_asm_insn (\"rsfs\\t%0, %2, %1\", operands));
570: }
571: "
572: [(set_attr "type" "float")])
573:
574: (define_insn "subdf3"
575: [(set (match_operand:DF 0 "s_register_operand" "=f,f")
576: (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
577: (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
578: ""
579: "*
580: switch (which_alternative)
581: {
582: case 0:
583: return (arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands));
584: case 1:
585: return (arm_output_asm_insn (\"rsfd\\t%0, %2, %1\", operands));
586: }
587: "
588: [(set_attr "type" "float")])
589:
590: (define_insn ""
591: [(set (match_operand:DF 0 "s_register_operand" "=f")
592: (minus:DF (float_extend:DF
593: (match_operand:SF 1 "s_register_operand" "f"))
594: (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
595: ""
596: "*
597: return arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands);
598: "
599: [(set_attr "type" "float")])
600:
601: (define_insn ""
602: [(set (match_operand:DF 0 "s_register_operand" "=f,f")
603: (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
604: (float_extend:DF
605: (match_operand:SF 2 "s_register_operand" "f,f"))))]
606: ""
607: "*
608: switch (which_alternative)
609: {
610: case 0:
611: return (arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands));
612: case 1:
613: return (arm_output_asm_insn (\"rsfd\\t%0, %2, %1\", operands));
614: }
615: "
616: [(set_attr "type" "float")])
617:
618: (define_insn ""
619: [(set (match_operand:DF 0 "s_register_operand" "=f")
620: (minus:DF (float_extend:DF
621: (match_operand:SF 1 "s_register_operand" "f"))
622: (float_extend:DF
623: (match_operand:SF 2 "s_register_operand" "f"))))]
624: ""
625: "*
626: return arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands);
627: "
628: [(set_attr "type" "float")])
629:
630: (define_insn "subxf3"
631: [(set (match_operand:XF 0 "s_register_operand" "=f,f")
632: (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
633: (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
634: "ENABLE_XF_PATTERNS"
635: "*
636: switch (which_alternative)
637: {
638: case 0:
639: return (arm_output_asm_insn (\"sufe\\t%0, %1, %2\", operands));
640: case 1:
641: return (arm_output_asm_insn (\"rsfe\\t%0, %2, %1\", operands));
642: }
643: "
644: [(set_attr "type" "float")])
645:
646: ;; Multiplication insns
647:
648: ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
649: (define_insn "mulsi3"
650: [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
651: (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
652: (match_operand:SI 1 "s_register_operand" "%?r,0")))]
653: ""
654: "*
655: return (arm_output_asm_insn (\"mul\\t%0, %2, %1\", operands));
656: ")
657:
658: (define_insn ""
659: [(set (reg:CC_NOOV 24)
660: (compare:CC_NOOV (mult:SI
661: (match_operand:SI 2 "s_register_operand" "r,r")
662: (match_operand:SI 1 "s_register_operand" "%?r,0"))
663: (const_int 0)))
664: (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
665: (mult:SI (match_dup 2) (match_dup 1)))]
666: ""
667: "*
668: return (arm_output_asm_insn (\"muls\\t%0, %2, %1\", operands));
669: "
670: [(set_attr "conds" "set")])
671:
672: (define_insn ""
673: [(set (reg:CC_NOOV 24)
674: (compare:CC_NOOV (mult:SI
675: (match_operand:SI 2 "s_register_operand" "r,r")
676: (match_operand:SI 1 "s_register_operand" "%?r,0"))
677: (const_int 0)))
678: (clobber (match_scratch:SI 0 "=&r,&r"))]
679: ""
680: "*
681: return (arm_output_asm_insn (\"muls\\t%0, %2, %1\", operands));
682: "
683: [(set_attr "conds" "set")])
684:
685: ;; Unnamed templates to match MLA instruction.
686:
687: (define_insn ""
688: [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
689: (plus:SI
690: (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
691: (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
692: (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
693: ""
694: "*
695: return (arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands));
696: ")
697:
698: (define_insn ""
699: [(set (reg:CC_NOOV 24)
700: (compare:CC_NOOV (plus:SI
701: (mult:SI
702: (match_operand:SI 2 "s_register_operand" "r,r,r,r")
703: (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
704: (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
705: (const_int 0)))
706: (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
707: (plus:SI (mult:SI (match_dup 2) (match_dup 1))
708: (match_dup 3)))]
709: ""
710: "*
711: return (arm_output_asm_insn (\"mlas\\t%0, %2, %1, %3\", operands));
712: "
713: [(set_attr "conds" "set")])
714:
715: (define_insn ""
716: [(set (reg:CC_NOOV 24)
717: (compare:CC_NOOV (plus:SI
718: (mult:SI
719: (match_operand:SI 2 "s_register_operand" "r,r,r,r")
720: (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
721: (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
722: (const_int 0)))
723: (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
724: ""
725: "*
726: return (arm_output_asm_insn (\"mlas\\t%0, %2, %1, %3\", operands));
727: "
728: [(set_attr "conds" "set")])
729:
730: (define_insn "mulsf3"
731: [(set (match_operand:SF 0 "s_register_operand" "=f")
732: (mult:SF (match_operand:SF 1 "s_register_operand" "f")
733: (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
734: ""
735: "*
736: return (arm_output_asm_insn (\"fmls\\t%0, %1, %2\", operands));
737: "
738: [(set_attr "type" "float")])
739:
740: (define_insn "muldf3"
741: [(set (match_operand:DF 0 "s_register_operand" "=f")
742: (mult:DF (match_operand:DF 1 "s_register_operand" "f")
743: (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
744: ""
745: "*
746: return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
747: "
748: [(set_attr "type" "float")])
749:
750: (define_insn ""
751: [(set (match_operand:DF 0 "s_register_operand" "=f")
752: (mult:DF (float_extend:DF
753: (match_operand:SF 1 "s_register_operand" "f"))
754: (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
755: ""
756: "*
757: return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
758: "
759: [(set_attr "type" "float")])
760:
761: (define_insn ""
762: [(set (match_operand:DF 0 "s_register_operand" "=f")
763: (mult:DF (match_operand:DF 1 "s_register_operand" "f")
764: (float_extend:DF
765: (match_operand:SF 2 "s_register_operand" "f"))))]
766: ""
767: "*
768: return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
769: "
770: [(set_attr "type" "float")])
771:
772: (define_insn ""
773: [(set (match_operand:DF 0 "s_register_operand" "=f")
774: (mult:DF (float_extend:DF
775: (match_operand:SF 1 "s_register_operand" "f"))
776: (float_extend:DF
777: (match_operand:SF 2 "s_register_operand" "f"))))]
778: ""
779: "*
780: return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
781: "
782: [(set_attr "type" "float")])
783:
784: (define_insn "mulxf3"
785: [(set (match_operand:XF 0 "s_register_operand" "=f")
786: (mult:XF (match_operand:XF 1 "s_register_operand" "f")
787: (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
788: "ENABLE_XF_PATTERNS"
789: "*
790: return (arm_output_asm_insn (\"mufe\\t%0, %1, %2\", operands));
791: "
792: [(set_attr "type" "float")])
793:
794: ;; Division insns
795:
796: (define_insn "divsf3"
797: [(set (match_operand:SF 0 "s_register_operand" "=f,f")
798: (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
799: (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
800: ""
801: "*
802: switch (which_alternative)
803: {
804: case 0:
805: return (arm_output_asm_insn (\"fdvs\\t%0, %1, %2\", operands));
806: case 1:
807: return (arm_output_asm_insn (\"frds\\t%0, %2, %1\", operands));
808: }
809: "
810: [(set_attr "type" "float")])
811:
812: (define_insn "divdf3"
813: [(set (match_operand:DF 0 "s_register_operand" "=f,f")
814: (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
815: (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
816: ""
817: "*
818: switch (which_alternative)
819: {
820: case 0:
821: return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands));
822: case 1:
823: return (arm_output_asm_insn (\"rdfd\\t%0, %2, %1\", operands));
824: }
825: "
826: [(set_attr "type" "float")])
827:
828: (define_insn ""
829: [(set (match_operand:DF 0 "s_register_operand" "=f")
830: (div:DF (float_extend:DF
831: (match_operand:SF 1 "s_register_operand" "f"))
832: (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
833: ""
834: "*
835: return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands));
836: "
837: [(set_attr "type" "float")])
838:
839: (define_insn ""
840: [(set (match_operand:DF 0 "s_register_operand" "=f")
841: (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
842: (float_extend:DF
843: (match_operand:SF 2 "s_register_operand" "f"))))]
844: ""
845: "*
846: return (arm_output_asm_insn (\"rdfd\\t%0, %2, %1\", operands));
847: "
848: [(set_attr "type" "float")])
849:
850: (define_insn ""
851: [(set (match_operand:DF 0 "s_register_operand" "=f")
852: (div:DF (float_extend:DF
853: (match_operand:SF 1 "s_register_operand" "f"))
854: (float_extend:DF
855: (match_operand:SF 2 "s_register_operand" "f"))))]
856: ""
857: "*
858: return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands));
859: "
860: [(set_attr "type" "float")])
861:
862: (define_insn "divxf3"
863: [(set (match_operand:XF 0 "s_register_operand" "=f,f")
864: (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
865: (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
866: "ENABLE_XF_PATTERNS"
867: "*
868: switch (which_alternative)
869: {
870: case 0:
871: return (arm_output_asm_insn (\"dvfe\\t%0, %1, %2\", operands));
872: case 1:
873: return (arm_output_asm_insn (\"rdfe\\t%0, %2, %1\", operands));
874: }
875: "
876: [(set_attr "type" "float")])
877:
878: ;; Modulo insns
879:
880: (define_insn "modsf3"
881: [(set (match_operand:SF 0 "s_register_operand" "=f")
882: (mod:SF (match_operand:SF 1 "s_register_operand" "f")
883: (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
884: ""
885: "*
886: return (arm_output_asm_insn (\"rmfs\\t%0, %1, %2\", operands));
887: "
888: [(set_attr "type" "float")])
889:
890: (define_insn "moddf3"
891: [(set (match_operand:DF 0 "s_register_operand" "=f")
892: (mod:DF (match_operand:DF 1 "s_register_operand" "f")
893: (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
894: ""
895: "*
896: return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
897: "
898: [(set_attr "type" "float")])
899:
900: (define_insn ""
901: [(set (match_operand:DF 0 "s_register_operand" "=f")
902: (mod:DF (float_extend:DF
903: (match_operand:SF 1 "s_register_operand" "f"))
904: (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
905: ""
906: "*
907: return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
908: "
909: [(set_attr "type" "float")])
910:
911: (define_insn ""
912: [(set (match_operand:DF 0 "s_register_operand" "=f")
913: (mod:DF (match_operand:DF 1 "s_register_operand" "f")
914: (float_extend:DF
915: (match_operand:SF 2 "s_register_operand" "f"))))]
916: ""
917: "*
918: return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
919: "
920: [(set_attr "type" "float")])
921:
922: (define_insn ""
923: [(set (match_operand:DF 0 "s_register_operand" "=f")
924: (mod:DF (float_extend:DF
925: (match_operand:SF 1 "s_register_operand" "f"))
926: (float_extend:DF
927: (match_operand:SF 2 "s_register_operand" "f"))))]
928: ""
929: "*
930: return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
931: "
932: [(set_attr "type" "float")])
933:
934: (define_insn "modxf3"
935: [(set (match_operand:XF 0 "s_register_operand" "=f")
936: (mod:XF (match_operand:XF 1 "s_register_operand" "f")
937: (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
938: "ENABLE_XF_PATTERNS"
939: "*
940: return (arm_output_asm_insn (\"rmfe\\t%0, %1, %2\", operands));
941: "
942: [(set_attr "type" "float")])
943:
944: ;; Boolean and,ior,xor insns
945:
946: (define_insn "anddi3"
947: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
948: (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
949: (match_operand:DI 2 "s_register_operand" "r,0")))]
950: ""
951: "*
952: arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
953: return (arm_output_asm_insn (\"and\\t%R0, %R1, %R2\", operands));
954: "
955: [(set_attr "length" "2")])
956:
957: (define_insn ""
958: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
959: (and:DI (zero_extend:DI
960: (match_operand:SI 2 "s_register_operand" "r,r"))
961: (match_operand:DI 1 "s_register_operand" "?r,0")))]
962: ""
963: "*
964: arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
965: return arm_output_asm_insn (\"mov\\t%R0, #0\", operands);
966: "
967: [(set_attr "length" "2")])
968:
969: (define_insn ""
970: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
971: (and:DI (sign_extend:DI
972: (match_operand:SI 2 "s_register_operand" "r,r"))
973: (match_operand:DI 1 "s_register_operand" "?r,0")))]
974: ""
975: "*
976: arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
977: return arm_output_asm_insn (\"and\\t%R0, %R1, %2, asr #31\", operands);
978: "
979: [(set_attr "length" "2")])
980:
981: (define_insn "andsi3"
982: [(set (match_operand:SI 0 "s_register_operand" "=r")
983: (and:SI (match_operand:SI 1 "s_register_operand" "r")
984: (match_operand:SI 2 "arm_not_operand" "rK")))]
985: ""
986: "*
987: if (GET_CODE (operands[2]) == CONST_INT
988: && !const_ok_for_arm (INTVAL (operands[2])))
989: {
990: operands[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
991: return arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands);
992: }
993: return arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
994: ")
995:
996: (define_insn ""
997: [(set (reg:CC_NOOV 24)
998: (compare:CC_NOOV (and:SI (match_operand:SI 1 "s_register_operand" "r")
999: (match_operand:SI 2 "arm_not_operand" "rK"))
1000: (const_int 0)))
1001: (set (match_operand:SI 0 "s_register_operand" "=r")
1002: (and:SI (match_dup 1) (match_dup 2)))]
1003: ""
1004: "*
1005: if (GET_CODE (operands[2]) == CONST_INT
1006: && !const_ok_for_arm (INTVAL (operands[2])))
1007: {
1008: operands[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
1009: return arm_output_asm_insn (\"bics\\t%0, %1, %2\", operands);
1010: }
1011: return arm_output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1012: "
1013: [(set_attr "conds" "set")])
1014:
1015: (define_insn ""
1016: [(set (reg:CC_NOOV 24)
1017: (compare:CC_NOOV (and:SI (match_operand:SI 0 "s_register_operand" "r")
1018: (match_operand:SI 1 "arm_rhs_operand" "rI"))
1019: (const_int 0)))]
1020: ""
1021: "*
1022: return arm_output_asm_insn (\"tst\\t%0, %1\", operands);
1023: "
1024: [(set_attr "conds" "set")])
1025:
1026: (define_insn ""
1027: [(set (reg:CC_NOOV 24)
1028: (compare:CC_NOOV (and:SI (match_operand:SI 0 "s_register_operand" "r")
1029: (match_operand:SI 1 "immediate_operand" "K"))
1030: (const_int 0)))
1031: (clobber (match_scratch:SI 3 "=r"))]
1032: "const_ok_for_arm (~INTVAL (operands[1]))"
1033: "*
1034: operands[1] = GEN_INT (~INTVAL (operands[1]));
1035: return arm_output_asm_insn (\"bics\\t%3, %0, %1\", operands);
1036: "
1037: [(set_attr "conds" "set")])
1038:
1039: (define_insn ""
1040: [(set (reg:CC_NOOV 24)
1041: (compare:CC_NOOV (zero_extract:SI
1042: (match_operand:SI 0 "s_register_operand" "r")
1043: (match_operand:SI 1 "immediate_operand" "n")
1044: (match_operand:SI 2 "immediate_operand" "n"))
1045: (const_int 0)))]
1046: "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1047: && INTVAL (operands[1]) > 0
1048: && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1049: && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1050: "*
1051: {
1052: unsigned int mask = 0;
1053: int cnt = INTVAL (operands[1]);
1054:
1055: while (cnt--)
1056: mask = (mask << 1) | 1;
1057: operands[1] = gen_rtx (CONST_INT, VOIDmode, mask << INTVAL (operands[2]));
1058: return arm_output_asm_insn (\"tst\\t%0, %1\", operands);
1059: }
1060: "
1061: [(set_attr "conds" "set")])
1062:
1063: (define_insn ""
1064: [(set (reg:CC_NOOV 24)
1065: (compare:CC_NOOV (zero_extract:SI
1066: (match_operand:QI 0 "memory_operand" "m")
1067: (match_operand 1 "immediate_operand" "n")
1068: (match_operand 2 "immediate_operand" "n"))
1069: (const_int 0)))
1070: (clobber (match_scratch:QI 3 "=r"))]
1071: "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1072: && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1073: "*
1074: {
1075: unsigned int mask = 0;
1076: int cnt = INTVAL (operands[1]);
1077:
1078: while (cnt--)
1079: mask = (mask << 1) | 1;
1080: operands[1] = gen_rtx (CONST_INT, VOIDmode, mask << INTVAL (operands[2]));
1081: arm_output_asm_insn (\"ldrb\\t%3, %0\", operands);
1082: return arm_output_asm_insn (\"tst\\t%3, %1\", operands);
1083: }
1084: "
1085: [(set_attr "conds" "set")
1086: (set_attr "length" "2")])
1087:
1088: ;; constants for op 2 will never be given to these patterns.
1089: (define_insn ""
1090: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1091: (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1092: (match_operand:DI 1 "s_register_operand" "0,r")))]
1093: ""
1094: "*
1095: arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands);
1096: return arm_output_asm_insn (\"bic\\t%R0, %R1, %R2\", operands);
1097: "
1098: [(set_attr "length" "2")])
1099:
1100: (define_insn ""
1101: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1102: (and:DI (not:DI (zero_extend:DI
1103: (match_operand:SI 2 "s_register_operand" "r,r")))
1104: (match_operand:DI 1 "s_register_operand" "?r,0")))]
1105: ""
1106: "*
1107: arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands);
1108: if (REGNO (operands[1]) != REGNO (operands[0]))
1109: return arm_output_asm_insn (\"mov\\t%R0, %R1\", operands);
1110: return \"\";
1111: "
1112: [(set_attr "length" "2,1")])
1113:
1114: (define_insn ""
1115: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1116: (and:DI (not:DI (sign_extend:DI
1117: (match_operand:SI 2 "s_register_operand" "r,r")))
1118: (match_operand:DI 1 "s_register_operand" "?r,0")))]
1119: ""
1120: "*
1121: arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands);
1122: return arm_output_asm_insn (\"bic\\t%R0, %R1, %2, asr #31\", operands);
1123: "
1124: [(set_attr "length" "2")])
1125:
1126: (define_insn ""
1127: [(set (match_operand:SI 0 "s_register_operand" "=r")
1128: (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1129: (match_operand:SI 1 "s_register_operand" "r")))]
1130: ""
1131: "*
1132: return (arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands));
1133: ")
1134:
1135: (define_insn ""
1136: [(set (reg:CC_NOOV 24)
1137: (compare:CC_NOOV (and:SI
1138: (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1139: (match_operand:SI 1 "s_register_operand" "r"))
1140: (const_int 0)))
1141: (set (match_operand:SI 0 "s_register_operand" "=r")
1142: (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1143: ""
1144: "*
1145: return (arm_output_asm_insn (\"bics\\t%0, %1, %2\", operands));
1146: "
1147: [(set_attr "conds" "set")])
1148:
1149: (define_insn ""
1150: [(set (reg:CC_NOOV 24)
1151: (compare:CC_NOOV (and:SI
1152: (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1153: (match_operand:SI 1 "s_register_operand" "r"))
1154: (const_int 0)))
1155: (clobber (match_scratch:SI 0 "=r"))]
1156: ""
1157: "*
1158: return (arm_output_asm_insn (\"bics\\t%0, %1, %2\", operands));
1159: "
1160: [(set_attr "conds" "set")])
1161:
1162: (define_insn "iordi3"
1163: [(set (match_operand:DI 0 "s_register_operand" "=&r")
1164: (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1165: (match_operand:DI 2 "s_register_operand" "r")))]
1166: ""
1167: "*
1168: arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
1169: return (arm_output_asm_insn (\"orr\\t%R0, %R1, %R2\", operands));
1170: "
1171: [(set_attr "length" "2")])
1172:
1173: (define_insn ""
1174: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1175: (ior:DI (zero_extend:DI
1176: (match_operand:SI 2 "s_register_operand" "r,r"))
1177: (match_operand:DI 1 "s_register_operand" "?r,0")))]
1178: ""
1179: "*
1180: arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
1181: if (REGNO (operands[0]) != REGNO (operands[1]))
1182: return (arm_output_asm_insn (\"mov\\t%R0, %R1\", operands));
1183: return \"\";
1184: "
1185: [(set_attr "length" "2,1")])
1186:
1187: (define_insn ""
1188: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1189: (ior:DI (sign_extend:DI
1190: (match_operand:SI 2 "s_register_operand" "r,r"))
1191: (match_operand:DI 1 "s_register_operand" "?r,0")))]
1192: ""
1193: "*
1194: arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
1195: return (arm_output_asm_insn (\"orr\\t%R0, %R1, %2, asr #31\", operands));
1196: "
1197: [(set_attr "length" "2")])
1198:
1199: (define_insn "iorsi3"
1200: [(set (match_operand:SI 0 "s_register_operand" "=r")
1201: (ior:SI (match_operand:SI 1 "s_register_operand" "r")
1202: (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1203: ""
1204: "*
1205: return (arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands));
1206: ")
1207:
1208: (define_insn ""
1209: [(set (reg:CC_NOOV 24)
1210: (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1211: (match_operand:SI 2 "arm_rhs_operand" "rI"))
1212: (const_int 0)))
1213: (set (match_operand:SI 0 "s_register_operand" "=r")
1214: (ior:SI (match_dup 1) (match_dup 2)))]
1215: ""
1216: "*
1217: return arm_output_asm_insn (\"orrs\\t%0, %1, %2\", operands);
1218: "
1219: [(set_attr "conds" "set")])
1220:
1221: (define_insn ""
1222: [(set (reg:CC_NOOV 24)
1223: (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1224: (match_operand:SI 2 "arm_rhs_operand" "rI"))
1225: (const_int 0)))
1226: (clobber (match_scratch:SI 0 "=r"))]
1227: ""
1228: "*
1229: return arm_output_asm_insn (\"orrs\\t%0, %1, %2\", operands);
1230: "
1231: [(set_attr "conds" "set")])
1232:
1233: (define_insn "xordi3"
1234: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1235: (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1236: (match_operand:DI 2 "s_register_operand" "r,0")))]
1237: ""
1238: "*
1239: arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands);
1240: return arm_output_asm_insn (\"eor\\t%R0, %R1, %R2\", operands);
1241: "
1242: [(set_attr "length" "2")])
1243:
1244: (define_insn ""
1245: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1246: (xor:DI (zero_extend:DI
1247: (match_operand:SI 2 "s_register_operand" "r,r"))
1248: (match_operand:DI 1 "s_register_operand" "?r,0")))]
1249: ""
1250: "*
1251: arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands);
1252: if (REGNO (operands[0]) != REGNO (operands[1]))
1253: return arm_output_asm_insn (\"mov\\t%R0, %R1\", operands);
1254: return \"\";
1255: "
1256: [(set_attr "length" "2,1")])
1257:
1258: (define_insn ""
1259: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1260: (xor:DI (sign_extend:DI
1261: (match_operand:SI 2 "s_register_operand" "r,r"))
1262: (match_operand:DI 1 "s_register_operand" "?r,0")))]
1263: ""
1264: "*
1265: arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands);
1266: return arm_output_asm_insn (\"eor\\t%R0, %R1, %2, asr #31\", operands);
1267: "
1268: [(set_attr "length" "2")])
1269:
1270: (define_insn "xorsi3"
1271: [(set (match_operand:SI 0 "s_register_operand" "=r")
1272: (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1273: (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1274: ""
1275: "*
1276: return (arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands));
1277: ")
1278:
1279: (define_insn ""
1280: [(set (reg:CC_NOOV 24)
1281: (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1282: (match_operand:SI 2 "arm_rhs_operand" "rI"))
1283: (const_int 0)))
1284: (set (match_operand:SI 0 "s_register_operand" "=r")
1285: (xor:SI (match_dup 1) (match_dup 2)))]
1286: ""
1287: "*
1288: return arm_output_asm_insn (\"eors\\t%0, %1, %2\", operands);
1289: "
1290: [(set_attr "conds" "set")])
1291:
1292: (define_insn ""
1293: [(set (reg:CC_NOOV 24)
1294: (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1295: (match_operand:SI 1 "arm_rhs_operand" "rI"))
1296: (const_int 0)))]
1297: ""
1298: "*
1299: return arm_output_asm_insn (\"teq\\t%0, %1\", operands);
1300: "
1301: [(set_attr "conds" "set")])
1302:
1303: ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
1304: ;; (NOT D) we can sometimes merge the final NOT into one of the following
1305: ;; insns
1306:
1307: (define_split
1308: [(set (match_operand:SI 0 "s_register_operand" "=r")
1309: (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1310: (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1311: (match_operand:SI 3 "arm_rhs_operand" "rI")))
1312: (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1313: ""
1314: [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1315: (not:SI (match_dup 3))))
1316: (set (match_dup 0) (not:SI (match_dup 4)))]
1317: ""
1318: )
1319:
1320: (define_insn ""
1321: [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1322: (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1323: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1324: (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1325: ""
1326: "*
1327: arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
1328: return arm_output_asm_insn (\"bic\\t%0, %0, %3\", operands);
1329: "
1330: [(set_attr "length" "2")])
1331:
1332:
1333:
1334: ;; Minimum and maximum insns
1335:
1336: (define_insn "smaxsi3"
1337: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1338: (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1339: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1340: (clobber (reg:CC 24))]
1341: ""
1342: "*
1343: arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1344: if (which_alternative != 0)
1345: arm_output_asm_insn (\"movge\\t%0, %1\", operands);
1346: if (which_alternative != 1)
1347: return arm_output_asm_insn (\"movlt\\t%0, %2\", operands);
1348: return \"\";
1349: "
1350: [(set_attr "conds" "clob")
1351: (set_attr "length" "2,2,3")])
1352:
1353: (define_insn "sminsi3"
1354: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1355: (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1356: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1357: (clobber (reg:CC 24))]
1358: ""
1359: "*
1360: arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1361: if (which_alternative != 0)
1362: arm_output_asm_insn (\"movle\\t%0, %1\", operands);
1363: if (which_alternative != 1)
1364: return arm_output_asm_insn (\"movgt\\t%0, %2\", operands);
1365: return \"\";
1366: "
1367: [(set_attr "conds" "clob")
1368: (set_attr "length" "2,2,3")])
1369:
1370: (define_insn "umaxsi3"
1371: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1372: (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1373: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1374: (clobber (reg:CC 24))]
1375: ""
1376: "*
1377: arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1378: if (which_alternative != 0)
1379: arm_output_asm_insn (\"movcs\\t%0, %1\", operands);
1380: if (which_alternative != 1)
1381: return arm_output_asm_insn (\"movcc\\t%0, %2\", operands);
1382: return \"\";
1383: "
1384: [(set_attr "conds" "clob")
1385: (set_attr "length" "2,2,3")])
1386:
1387: (define_insn "uminsi3"
1388: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1389: (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1390: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1391: (clobber (reg:CC 24))]
1392: ""
1393: "*
1394: arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1395: if (which_alternative != 0)
1396: arm_output_asm_insn (\"movcc\\t%0, %1\", operands);
1397: if (which_alternative != 1)
1398: return arm_output_asm_insn (\"movcs\\t%0, %2\", operands);
1399: return \"\";
1400: "
1401: [(set_attr "conds" "clob")
1402: (set_attr "length" "2,2,3")])
1403:
1404: (define_insn ""
1405: [(set (match_operand:SI 0 "memory_operand" "=m")
1406: (match_operator:SI 3 "minmax_operator"
1407: [(match_operand:SI 1 "s_register_operand" "r")
1408: (match_operand:SI 2 "s_register_operand" "r")]))
1409: (clobber (reg:CC 24))]
1410: ""
1411: "*
1412: operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1413: operands[2]);
1414: arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1415: arm_output_asm_insn (\"str%d3\\t%1, %0\", operands);
1416: return arm_output_asm_insn (\"str%D3\\t%2, %0\", operands);
1417: "
1418: [(set_attr "conds" "clob")
1419: (set_attr "length" "3")
1420: (set_attr "type" "store1")])
1421:
1422: (define_insn ""
1423: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1424: (match_operator:SI 4 "shiftable_operator"
1425: [(match_operator:SI 5 "minmax_operator"
1426: [(match_operand:SI 2 "s_register_operand" "r,r")
1427: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1428: (match_operand:SI 1 "s_register_operand" "0,?r")]))
1429: (clobber (reg:CC 24))]
1430: ""
1431: "*
1432: {
1433: char buf[100];
1434: enum rtx_code code = GET_CODE (operands[4]);
1435: char *inst = arithmetic_instr (operands[4], TRUE);
1436:
1437: operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1438: operands[3]);
1439: arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
1440: sprintf (buf, \"%s%%d5\\t%%0, %%1, %%2\", inst);
1441: arm_output_asm_insn (buf, operands);
1442: if (which_alternative != 0 || operands[3] != const0_rtx
1443: || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1444: {
1445: sprintf (buf, \"%s%%D5\\t%%0, %%1, %%3\", inst);
1446: return arm_output_asm_insn (buf, operands);
1447: }
1448: return \"\";
1449: }
1450: "
1451: [(set_attr "conds" "clob")
1452: (set_attr "length" "3")])
1453:
1454:
1455: ;; Shift and rotation insns
1456:
1457: (define_insn "ashlsi3"
1458: [(set (match_operand:SI 0 "s_register_operand" "=r")
1459: (ashift:SI (match_operand:SI 1 "s_register_operand" "r")
1460: (match_operand:SI 2 "arm_rhs_operand" "rn")))]
1461: ""
1462: "*
1463: return (output_shifted_move (ASHIFT, operands));
1464: ")
1465:
1466: (define_insn "ashrsi3"
1467: [(set (match_operand:SI 0 "s_register_operand" "=r")
1468: (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "r")
1469: (match_operand:SI 2 "arm_rhs_operand" "rn")))]
1470: ""
1471: "*
1472: return (output_shifted_move (ASHIFTRT, operands));
1473: ")
1474:
1475: ;; lshlsi3 is not defined because shift counts cannot be negative
1476: ;; An unnamed pattern is needed for expansion of zero_extend.
1477:
1478: (define_insn ""
1479: [(set (match_operand:SI 0 "s_register_operand" "=r")
1480: (lshift:SI (match_operand:SI 1 "s_register_operand" "r")
1481: (match_operand:SI 2 "arm_rhs_operand" "rn")))]
1482: ""
1483: "*
1484: return (output_shifted_move (LSHIFT, operands));
1485: ")
1486:
1487: (define_insn "lshrsi3"
1488: [(set (match_operand:SI 0 "s_register_operand" "=r")
1489: (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "r")
1490: (match_operand:SI 2 "arm_rhs_operand" "rn")))]
1491: ""
1492: "*
1493: return (output_shifted_move (LSHIFTRT, operands));
1494: ")
1495:
1496: ;; rotlsi3 is not defined yet to see what happens
1497:
1498: (define_insn "rotrsi3"
1499: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1500: (rotatert:SI (match_operand:SI 1 "s_register_operand" "r,r")
1501: (match_operand:SI 2 "arm_rhs_operand" "r,n")))]
1502: ""
1503: "*
1504: switch (which_alternative)
1505: {
1506: case 0:
1507: return (arm_output_asm_insn (\"mov\\t%0, %1, ror %2\", operands));
1508: case 1:
1509: if (INTVAL(operands[2]) > 31)
1510: operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 32);
1511: return (arm_output_asm_insn (\"mov\\t%0, %1, ror %2\", operands));
1512: }
1513: ")
1514:
1515: (define_insn ""
1516: [(set (reg:CC_NOOV 24)
1517: (compare:CC_NOOV (match_operator:SI 1 "shift_operator"
1518: [(match_operand:SI 2 "s_register_operand" "r")
1519: (match_operand:SI 3 "arm_rhs_operand" "rn")])
1520: (const_int 0)))
1521: (set (match_operand:SI 0 "s_register_operand" "=r")
1522: (match_op_dup 1 [(match_dup 2) (match_dup 3)]))]
1523: ""
1524: "*
1525: {
1526: char buf[100];
1527:
1528: sprintf (buf, \"movs\\t%%0, %%2, %s %%3\",
1529: shift_instr (GET_CODE (operands[1]), &operands[3]));
1530: return arm_output_asm_insn (buf, operands);
1531: }
1532: "
1533: [(set_attr "conds" "set")])
1534:
1535: (define_insn ""
1536: [(set (reg:CC_NOOV 24)
1537: (compare:CC_NOOV (match_operator:SI 1 "shift_operator"
1538: [(match_operand:SI 2 "s_register_operand" "r")
1539: (match_operand:SI 3 "arm_rhs_operand" "rn")])
1540: (const_int 0)))
1541: (clobber (match_scratch:SI 0 "=r"))]
1542: ""
1543: "*
1544: {
1545: char buf[100];
1546:
1547: sprintf (buf, \"movs\\t%%0, %%2, %s %%3\",
1548: shift_instr (GET_CODE (operands[1]), &operands[3]));
1549: return arm_output_asm_insn (buf, operands);
1550: }
1551: "
1552: [(set_attr "conds" "set")])
1553:
1554: (define_insn ""
1555: [(set (match_operand:SI 0 "s_register_operand" "=r")
1556: (not:SI (match_operator:SI 1 "shift_operator"
1557: [(match_operand:SI 2 "s_register_operand" "r")
1558: (match_operand:SI 3 "arm_rhs_operand" "rn")])))]
1559: ""
1560: "*
1561: {
1562: char buf[100];
1563: sprintf (buf, \"mvn\\t%%0, %%2, %s %%3\",
1564: shift_instr (GET_CODE (operands[1]), &operands[3]));
1565: return arm_output_asm_insn (buf, operands);
1566: }
1567: ")
1568:
1569: (define_insn ""
1570: [(set (reg:CC_NOOV 24)
1571: (compare:CC_NOOV (not:SI (match_operator:SI 1 "shift_operator"
1572: [(match_operand:SI 2 "s_register_operand" "r")
1573: (match_operand:SI 3 "arm_rhs_operand" "rn")]))
1574: (const_int 0)))
1575: (set (match_operand:SI 0 "s_register_operand" "=r")
1576: (not:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])))]
1577: ""
1578: "*
1579: {
1580: char buf[100];
1581: sprintf (buf, \"mvns\\t%%0, %%2, %s %%3\",
1582: shift_instr (GET_CODE (operands[1]), &operands[3]));
1583: return arm_output_asm_insn (buf, operands);
1584: }
1585: "
1586: [(set_attr "conds" "set")])
1587:
1588: (define_insn ""
1589: [(set (reg:CC_NOOV 24)
1590: (compare:CC_NOOV (not:SI (match_operator:SI 1 "shift_operator"
1591: [(match_operand:SI 2 "s_register_operand" "r")
1592: (match_operand:SI 3 "arm_rhs_operand" "rn")]))
1593: (const_int 0)))
1594: (clobber (match_scratch:SI 0 "=r"))]
1595: ""
1596: "*
1597: {
1598: char buf[100];
1599: sprintf (buf, \"mvns\\t%%0, %%2, %s %%3\",
1600: shift_instr (GET_CODE (operands[1]), &operands[3]));
1601: return arm_output_asm_insn (buf, operands);
1602: }
1603: "
1604: [(set_attr "conds" "set")])
1605:
1606:
1607: ;; Unary arithmetic insns
1608:
1609: (define_insn "negdi2"
1610: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1611: (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1612: ""
1613: "*
1614: arm_output_asm_insn (\"rsbs\\t%0, %1, #0\", operands);
1615: return (arm_output_asm_insn (\"rsc\\t%R0, %R1, #0\", operands));
1616: "
1617: [(set_attr "conds" "clob")
1618: (set_attr "length" "2")])
1619:
1620: (define_insn "negsi2"
1621: [(set (match_operand:SI 0 "s_register_operand" "=r")
1622: (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1623: ""
1624: "*
1625: return (arm_output_asm_insn (\"rsb\\t%0, %1, #0\", operands));
1626: ")
1627:
1628: (define_insn "negsf2"
1629: [(set (match_operand:SF 0 "s_register_operand" "=f")
1630: (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1631: ""
1632: "*
1633: return (arm_output_asm_insn (\"mnfs\\t%0, %1\", operands));
1634: "
1635: [(set_attr "type" "float")])
1636:
1637: (define_insn "negdf2"
1638: [(set (match_operand:DF 0 "s_register_operand" "=f")
1639: (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1640: ""
1641: "*
1642: return (arm_output_asm_insn (\"mnfd\\t%0, %1\", operands));
1643: "
1644: [(set_attr "type" "float")])
1645:
1646: (define_insn ""
1647: [(set (match_operand:DF 0 "s_register_operand" "=f")
1648: (neg:DF (float_extend:DF
1649: (match_operand:SF 1 "s_register_operand" "f"))))]
1650: ""
1651: "*
1652: return (arm_output_asm_insn (\"mnfd\\t%0, %1\", operands));
1653: "
1654: [(set_attr "type" "float")])
1655:
1656: (define_insn "negxf2"
1657: [(set (match_operand:XF 0 "s_register_operand" "=f")
1658: (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1659: "ENABLE_XF_PATTERNS"
1660: "*
1661: return (arm_output_asm_insn (\"mnfe\\t%0, %1\", operands));
1662: "
1663: [(set_attr "type" "float")])
1664:
1665: ;; abssi2 doesn't really clobber the condition codes if a different register
1666: ;; is being set. To keep things simple, assume during rtl manipulations that
1667: ;; it does, but tell the final scan operator the truth. Similarly for
1668: ;; (neg (abs...))
1669:
1670: (define_insn "abssi2"
1671: [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1672: (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1673: (clobber (reg 24))]
1674: ""
1675: "*
1676: switch (which_alternative)
1677: {
1678: case 0:
1679: arm_output_asm_insn (\"cmp\\t%0, #0\", operands);
1680: return arm_output_asm_insn (\"rsblt\\t%0, %0, #0\", operands);
1681: case 1:
1682: arm_output_asm_insn (\"eor\\t%0, %1, %1, asr #31\", operands);
1683: return arm_output_asm_insn (\"sub\\t%0, %0, %1, asr #31\", operands);
1684: }
1685: "
1686: [(set_attr "conds" "clob,*")
1687: (set_attr "length" "2")])
1688:
1689: (define_insn ""
1690: [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1691: (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1692: (clobber (reg 24))]
1693: ""
1694: "*
1695: switch (which_alternative)
1696: {
1697: case 0:
1698: arm_output_asm_insn (\"cmp\\t%0, #0\", operands);
1699: return arm_output_asm_insn (\"rsbgt\\t%0, %0, #0\", operands);
1700: case 1:
1701: arm_output_asm_insn (\"eor\\t%0, %1, %1, asr #31\", operands);
1702: return arm_output_asm_insn (\"rsb\\t%0, %0, %1, asr #31\", operands);
1703: }
1704: "
1705: [(set_attr "conds" "clob,*")
1706: (set_attr "length" "2")])
1707:
1708: (define_insn "abssf2"
1709: [(set (match_operand:SF 0 "s_register_operand" "=f")
1710: (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1711: ""
1712: "*
1713: return (arm_output_asm_insn (\"abss\\t%0, %1\", operands));
1714: "
1715: [(set_attr "type" "float")])
1716:
1717: (define_insn "absdf2"
1718: [(set (match_operand:DF 0 "s_register_operand" "=f")
1719: (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1720: ""
1721: "*
1722: return (arm_output_asm_insn (\"absd\\t%0, %1\", operands));
1723: "
1724: [(set_attr "type" "float")])
1725:
1726: (define_insn ""
1727: [(set (match_operand:DF 0 "s_register_operand" "=f")
1728: (abs:DF (float_extend:DF
1729: (match_operand:SF 1 "s_register_operand" "f"))))]
1730: ""
1731: "*
1732: return (arm_output_asm_insn (\"absd\\t%0, %1\", operands));
1733: "
1734: [(set_attr "type" "float")])
1735:
1736: (define_insn "absxf2"
1737: [(set (match_operand:XF 0 "s_register_operand" "=f")
1738: (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1739: "ENABLE_XF_PATTERNS"
1740: "*
1741: return (arm_output_asm_insn (\"abse\\t%0, %1\", operands));
1742: "
1743: [(set_attr "type" "float")])
1744:
1745: (define_insn "sqrtsf2"
1746: [(set (match_operand:SF 0 "s_register_operand" "=f")
1747: (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1748: ""
1749: "*
1750: return (arm_output_asm_insn (\"sqts\\t%0, %1\", operands));
1751: "
1752: [(set_attr "type" "float_em")])
1753:
1754: (define_insn "sqrtdf2"
1755: [(set (match_operand:DF 0 "s_register_operand" "=f")
1756: (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1757: ""
1758: "*
1759: return (arm_output_asm_insn (\"sqtd\\t%0, %1\", operands));
1760: "
1761: [(set_attr "type" "float_em")])
1762:
1763: (define_insn ""
1764: [(set (match_operand:DF 0 "s_register_operand" "=f")
1765: (sqrt:DF (float_extend:DF
1766: (match_operand:SF 1 "s_register_operand" "f"))))]
1767: ""
1768: "*
1769: return (arm_output_asm_insn (\"sqtd\\t%0, %1\", operands));
1770: "
1771: [(set_attr "type" "float_em")])
1772:
1773: (define_insn "sqrtxf2"
1774: [(set (match_operand:XF 0 "s_register_operand" "=f")
1775: (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1776: "ENABLE_XF_PATTERNS"
1777: "*
1778: return (arm_output_asm_insn (\"sqte\\t%0, %1\", operands));
1779: "
1780: [(set_attr "type" "float_em")])
1781:
1782: (define_insn "sinsf2"
1783: [(set (match_operand:SF 0 "s_register_operand" "=f")
1784: (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1785: ""
1786: "*
1787: return arm_output_asm_insn (\"sins\\t%0, %1\", operands);
1788: "
1789: [(set_attr "type" "float_em")])
1790:
1791: (define_insn "sindf2"
1792: [(set (match_operand:DF 0 "s_register_operand" "=f")
1793: (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1794: ""
1795: "*
1796: return arm_output_asm_insn (\"sind\\t%0, %1\", operands);
1797: "
1798: [(set_attr "type" "float_em")])
1799:
1800: (define_insn ""
1801: [(set (match_operand:DF 0 "s_register_operand" "=f")
1802: (unspec:DF [(float_extend:DF
1803: (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1804: ""
1805: "*
1806: return arm_output_asm_insn (\"sind\\t%0, %1\", operands);
1807: "
1808: [(set_attr "type" "float_em")])
1809:
1810: (define_insn "sinxf2"
1811: [(set (match_operand:XF 0 "s_register_operand" "=f")
1812: (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1813: "ENABLE_XF_PATTERNS"
1814: "*
1815: return arm_output_asm_insn (\"sine\\t%0, %1\", operands);
1816: "
1817: [(set_attr "type" "float_em")])
1818:
1819: (define_insn "cossf2"
1820: [(set (match_operand:SF 0 "s_register_operand" "=f")
1821: (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1822: ""
1823: "*
1824: return arm_output_asm_insn (\"coss\\t%0, %1\", operands);
1825: "
1826: [(set_attr "type" "float_em")])
1827:
1828: (define_insn "cosdf2"
1829: [(set (match_operand:DF 0 "s_register_operand" "=f")
1830: (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1831: ""
1832: "*
1833: return arm_output_asm_insn (\"cosd\\t%0, %1\", operands);
1834: "
1835: [(set_attr "type" "float_em")])
1836:
1837: (define_insn ""
1838: [(set (match_operand:DF 0 "s_register_operand" "=f")
1839: (unspec:DF [(float_extend:DF
1840: (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1841: ""
1842: "*
1843: return arm_output_asm_insn (\"cosd\\t%0, %1\", operands);
1844: "
1845: [(set_attr "type" "float_em")])
1846:
1847: (define_insn "cosxf2"
1848: [(set (match_operand:XF 0 "s_register_operand" "=f")
1849: (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1850: "ENABLE_XF_PATTERNS"
1851: "*
1852: return arm_output_asm_insn (\"cose\\t%0, %1\", operands);
1853: "
1854: [(set_attr "type" "float_em")])
1855:
1856: (define_insn "one_cmpldi2"
1857: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1858: (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1859: ""
1860: "*
1861: arm_output_asm_insn (\"mvn\\t%0, %1\", operands);
1862: return arm_output_asm_insn (\"mvn\\t%R0, %R1\", operands);
1863: "
1864: [(set_attr "length" "2")])
1865:
1866: (define_insn "one_cmplsi2"
1867: [(set (match_operand:SI 0 "s_register_operand" "=r")
1868: (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
1869: ""
1870: "*
1871: return (arm_output_asm_insn (\"mvn\\t%0, %1\", operands));
1872: ")
1873:
1874: (define_insn ""
1875: [(set (reg:CC_NOOV 24)
1876: (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1877: (const_int 0)))
1878: (set (match_operand:SI 0 "s_register_operand" "=r")
1879: (not:SI (match_dup 1)))]
1880: ""
1881: "*
1882: return (arm_output_asm_insn (\"mvns\\t%0, %1\", operands));
1883: "
1884: [(set_attr "conds" "set")])
1885:
1886: (define_insn ""
1887: [(set (reg:CC_NOOV 24)
1888: (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1889: (const_int 0)))
1890: (clobber (match_scratch:SI 0 "=r"))]
1891: ""
1892: "*
1893: return (arm_output_asm_insn (\"mvns\\t%0, %1\", operands));
1894: "
1895: [(set_attr "conds" "set")])
1896:
1897: ;; Fixed <--> Floating conversion insns
1898:
1899: (define_insn "floatsisf2"
1900: [(set (match_operand:SF 0 "s_register_operand" "=f")
1901: (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
1902: ""
1903: "*
1904: return (arm_output_asm_insn (\"flts\\t%0, %1\", operands));
1905: "
1906: [(set_attr "type" "r_2_f")])
1907:
1908: (define_insn "floatsidf2"
1909: [(set (match_operand:DF 0 "s_register_operand" "=f")
1910: (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
1911: ""
1912: "*
1913: return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands));
1914: "
1915: [(set_attr "type" "r_2_f")])
1916:
1917: (define_insn "floatsixf2"
1918: [(set (match_operand:XF 0 "s_register_operand" "=f")
1919: (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
1920: "ENABLE_XF_PATTERNS"
1921: "*
1922: return (arm_output_asm_insn (\"flte\\t%0, %1\", operands));
1923: "
1924: [(set_attr "type" "r_2_f")])
1925:
1926: (define_insn "fix_truncsfsi2"
1927: [(set (match_operand:SI 0 "s_register_operand" "=r")
1928: (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
1929: ""
1930: "*
1931: return arm_output_asm_insn (\"fixz\\t%0, %1\", operands);
1932: "
1933: [(set_attr "type" "f_2_r")])
1934:
1935: (define_insn "fix_truncdfsi2"
1936: [(set (match_operand:SI 0 "s_register_operand" "=r")
1937: (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
1938: ""
1939: "*
1940: return arm_output_asm_insn (\"fixz\\t%0, %1\", operands);
1941: "
1942: [(set_attr "type" "f_2_r")])
1943:
1944: (define_insn "fix_truncxfsi2"
1945: [(set (match_operand:SI 0 "s_register_operand" "=r")
1946: (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
1947: "ENABLE_XF_PATTERNS"
1948: "*
1949: return arm_output_asm_insn (\"fixz\\t%0, %1\", operands);
1950: "
1951: [(set_attr "type" "f_2_r")])
1952:
1953: ;; Truncation insns
1954:
1955: (define_insn "truncdfsf2"
1956: [(set (match_operand:SF 0 "s_register_operand" "=f")
1957: (float_truncate:SF
1958: (match_operand:DF 1 "s_register_operand" "f")))]
1959: ""
1960: "*
1961: return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
1962: "
1963: [(set_attr "type" "float")])
1964:
1965: (define_insn "truncxfsf2"
1966: [(set (match_operand:SF 0 "s_register_operand" "=f")
1967: (float_truncate:SF
1968: (match_operand:XF 1 "s_register_operand" "f")))]
1969: "ENABLE_XF_PATTERNS"
1970: "*
1971: return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
1972: "
1973: [(set_attr "type" "float")])
1974:
1975: (define_insn "truncxfdf2"
1976: [(set (match_operand:DF 0 "s_register_operand" "=f")
1977: (float_truncate:DF
1978: (match_operand:XF 1 "s_register_operand" "f")))]
1979: "ENABLE_XF_PATTERNS"
1980: "*
1981: return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands));
1982: "
1983: [(set_attr "type" "float")])
1984:
1985: ;; Zero and sign extension instructions.
1986:
1987: (define_insn "zero_extendsidi2"
1988: [(set (match_operand:DI 0 "s_register_operand" "=r")
1989: (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1990: ""
1991: "*
1992: if (REGNO (operands[1]) != REGNO (operands[0]))
1993: arm_output_asm_insn (\"mov\\t%0, %1\", operands);
1994: return arm_output_asm_insn (\"mov\\t%R0, #0\", operands);
1995: "
1996: [(set_attr "length" "2")])
1997:
1998: (define_insn "zero_extendqidi2"
1999: [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2000: (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2001: ""
2002: "*
2003: switch (which_alternative)
2004: {
2005: case 0:
2006: arm_output_asm_insn (\"and\\t%0, %1, #255\", operands);
2007: break;
2008: case 1:
2009: arm_output_asm_insn (\"ldrb\\t%0, %1\",operands);
2010: break;
2011: }
2012: return arm_output_asm_insn (\"mov\\t%R0, #0\", operands);
2013: "
2014: [(set_attr "length" "2")
2015: (set_attr "type" "*,load")])
2016:
2017: (define_insn "extendsidi2"
2018: [(set (match_operand:DI 0 "s_register_operand" "=r")
2019: (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2020: ""
2021: "*
2022: if (REGNO (operands[1]) != REGNO (operands[0]))
2023: arm_output_asm_insn (\"mov\\t%0, %1\", operands);
2024: return arm_output_asm_insn (\"mov\\t%R0, %0, asr #31\", operands);
2025: "
2026: [(set_attr "length" "2")])
2027:
2028: (define_expand "zero_extendhisi2"
2029: [(set (match_dup 2)
2030: (ashift:SI (match_operand:HI 1 "s_register_operand" "")
2031: (const_int 16)))
2032: (set (match_operand:SI 0 "s_register_operand" "")
2033: (lshiftrt:SI (match_dup 2)
2034: (const_int 16)))]
2035: ""
2036: "
2037: { operands[1] = gen_lowpart (SImode, operands[1]);
2038: operands[2] = gen_reg_rtx (SImode); }")
2039:
2040: (define_insn "zero_extendqihi2"
2041: [(set (match_operand:HI 0 "s_register_operand" "=r")
2042: (zero_extend:HI
2043: (match_operand:QI 1 "s_register_operand" "r")))]
2044: ""
2045: "*
2046: return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqihi2\", operands));
2047: ")
2048:
2049: (define_insn ""
2050: [(set (reg:CC_NOOV 24)
2051: (compare:CC_NOOV (match_operand:QI 1 "s_register_operand" "r")
2052: (const_int 0)))
2053: (set (match_operand:SI 0 "s_register_operand" "=r")
2054: (zero_extend:HI (match_dup 1)))]
2055: ""
2056: "*
2057: return arm_output_asm_insn (\"ands\\t%0, %1, #255\", operands);
2058: "
2059: [(set_attr "conds" "set")])
2060:
2061: (define_insn ""
2062: [(set (reg:CC_NOOV 24)
2063: (compare:CC_NOOV (match_operand:QI 0 "s_register_operand" "r")
2064: (const_int 0)))]
2065: ""
2066: "*
2067: return arm_output_asm_insn (\"tst\\t%0, #255\", operands);
2068: "
2069: [(set_attr "conds" "set")])
2070:
2071: (define_insn "zero_extendqisi2"
2072: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2073: (zero_extend:SI
2074: (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2075: ""
2076: "*
2077: switch (which_alternative)
2078: {
2079: case 0:
2080: return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqisi2\", operands));
2081: case 1:
2082: return (arm_output_asm_insn (\"ldrb\\t%0, %1\\t@ zero_extendqisi2\", operands));
2083: }
2084: "
2085: [(set_attr "type" "*,load")])
2086:
2087: (define_insn ""
2088: [(set (reg:CC_NOOV 24)
2089: (compare:CC_NOOV (match_operand:QI 1 "s_register_operand" "r")
2090: (const_int 0)))
2091: (set (match_operand:SI 0 "s_register_operand" "=r")
2092: (zero_extend:SI (match_dup 1)))]
2093: ""
2094: "*
2095: return arm_output_asm_insn (\"ands\\t%0, %1, #255\", operands);
2096: "
2097: [(set_attr "conds" "set")])
2098:
2099: (define_insn ""
2100: [(set (reg:CC_NOOV 24)
2101: (compare:CC_NOOV (match_operand:QI 1 "s_register_operand" "r")
2102: (const_int 0)))
2103: (set (match_operand:QI 0 "s_register_operand" "=r")
2104: (match_dup 1))]
2105: ""
2106: "*
2107: return arm_output_asm_insn (\"ands\\t%0, %1, #255\", operands);
2108: "
2109: [(set_attr "conds" "set")])
2110:
2111: (define_expand "extendhisi2"
2112: [(set (match_dup 2)
2113: (ashift:SI (match_operand:HI 1 "s_register_operand" "")
2114: (const_int 16)))
2115: (set (match_operand:SI 0 "s_register_operand" "")
2116: (ashiftrt:SI (match_dup 2)
2117: (const_int 16)))]
2118: ""
2119: "
2120: { operands[1] = gen_lowpart (SImode, operands[1]);
2121: operands[2] = gen_reg_rtx (SImode); }")
2122:
2123: (define_expand "extendqihi2"
2124: [(set (match_dup 2)
2125: (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2126: (const_int 24)))
2127: (set (match_operand:HI 0 "s_register_operand" "")
2128: (ashiftrt:SI (match_dup 2)
2129: (const_int 24)))]
2130: ""
2131: "
2132: { operands[0] = gen_lowpart (SImode, operands[0]);
2133: operands[1] = gen_lowpart (SImode, operands[1]);
2134: operands[2] = gen_reg_rtx (SImode); }")
2135:
2136: (define_expand "extendqisi2"
2137: [(set (match_dup 2)
2138: (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2139: (const_int 24)))
2140: (set (match_operand:SI 0 "s_register_operand" "")
2141: (ashiftrt:SI (match_dup 2)
2142: (const_int 24)))]
2143: ""
2144: "
2145: { operands[1] = gen_lowpart (SImode, operands[1]);
2146: operands[2] = gen_reg_rtx (SImode); }")
2147:
2148: (define_insn "extendsfdf2"
2149: [(set (match_operand:DF 0 "s_register_operand" "=f")
2150: (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2151: ""
2152: "*
2153: return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands));
2154: "
2155: [(set_attr "type" "float")])
2156:
2157: (define_insn "extendsfxf2"
2158: [(set (match_operand:XF 0 "s_register_operand" "=f")
2159: (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2160: "ENABLE_XF_PATTERNS"
2161: "*
2162: return (arm_output_asm_insn (\"mvfe\\t%0, %1\", operands));
2163: ")
2164:
2165: (define_insn "extenddfxf2"
2166: [(set (match_operand:XF 0 "s_register_operand" "=f")
2167: (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2168: "ENABLE_XF_PATTERNS"
2169: "*
2170: return (arm_output_asm_insn (\"mvfe\\t%0, %1\", operands));
2171: "
2172: [(set_attr "type" "float")])
2173:
2174:
2175: ;; Move insns (including loads and stores)
2176:
2177: ;; XXX Just some ideas about movti.
2178: ;; I don't think these are a good idea on the arm, there just aren't enough
2179: ;; registers
2180: ;;(define_expand "loadti"
2181: ;; [(set (match_operand:TI 0 "s_register_operand" "")
2182: ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2183: ;; "" "")
2184:
2185: ;;(define_expand "storeti"
2186: ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2187: ;; (match_operand:TI 1 "s_register_operand" ""))]
2188: ;; "" "")
2189:
2190: ;;(define_expand "movti"
2191: ;; [(set (match_operand:TI 0 "general_operand" "")
2192: ;; (match_operand:TI 1 "general_operand" ""))]
2193: ;; ""
2194: ;; "
2195: ;;{
2196: ;; rtx insn;
2197: ;;
2198: ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2199: ;; operands[1] = copy_to_reg (operands[1]);
2200: ;; if (GET_CODE (operands[0]) == MEM)
2201: ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2202: ;; else if (GET_CODE (operands[1]) == MEM)
2203: ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2204: ;; else
2205: ;; FAIL;
2206: ;;
2207: ;; emit_insn (insn);
2208: ;; DONE;
2209: ;;}")
2210:
2211: ;; Recognise garbage generated above.
2212:
2213: ;;(define_insn ""
2214: ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2215: ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2216: ;; ""
2217: ;; "*
2218: ;; {
2219: ;; register mem = (which_alternative < 3);
2220: ;; register char *template;
2221: ;;
2222: ;; operands[mem] = XEXP (operands[mem], 0);
2223: ;; switch (which_alternative)
2224: ;; {
2225: ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2226: ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2227: ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2228: ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2229: ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2230: ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2231: ;; }
2232: ;; return (arm_output_asm_insn (template, operands));
2233: ;; }")
2234:
2235:
2236: (define_insn "movdi"
2237: [(set (match_operand:DI 0 "di_operand" "=r,r,r,o<>,r")
2238: (match_operand:DI 1 "di_operand" "rK,n,o<>,r,F"))]
2239: ""
2240: "*
2241: return (output_move_double (operands));
2242: "
2243: [(set_attr "length" "2,8,2,2,8")
2244: (set_attr "type" "*,*,load,store2,*")])
2245:
2246: (define_expand "movsi"
2247: [(set (match_operand:SI 0 "general_operand" "")
2248: (match_operand:SI 1 "general_operand" ""))]
2249: ""
2250: "
2251: /* Everything except mem = const or mem = mem can be done easily */
2252: if (GET_CODE (operands[0]) == MEM)
2253: operands[1] = force_reg (SImode, operands[1]);
2254: if (GET_CODE (operands[1]) == CONST_INT
2255: && !(const_ok_for_arm (INTVAL (operands[1]))
2256: || const_ok_for_arm (~INTVAL (operands[1]))))
2257: {
2258: int n = INTVAL (operands[1]);
2259: rtx tmpreg, tmpreg2;
2260: int i, n_ones = 0, first = 1, last = 0;
2261:
2262: if (GET_CODE (operands[0]) != REG
2263: && GET_CODE (operands[0]) != SUBREG)
2264: abort ();
2265: for (i = 0; i < 32; i++)
2266: if (n & 1 << i)
2267: n_ones++;
2268: /* These loops go the opposite way around to those in arm.c so that
2269: the last constant may be more likely to be eliminted into the
2270: next instruction */
2271:
2272: if (n_ones > 16)
2273: {
2274: n = (~n) & 0xffffffff;
2275: for (i = 30; i >= 0; i -= 2)
2276: {
2277: if (n & (3 << i))
2278: {
2279: i -= 6;
2280: if (i < 0)
2281: i = 0;
2282: if ((n & (255 << i)) == n)
2283: last = 1;
2284: if (first)
2285: {
2286: rtx equal;
2287: rtx insn =
2288: emit_insn (gen_movsi (tmpreg = (reload_in_progress
2289: || reload_completed)
2290: ? operands[0]
2291: : gen_reg_rtx (SImode),
2292: equal = gen_rtx (CONST_INT, VOIDmode,
2293: ~(n & (255 << i)))));
2294: first = 0;
2295: }
2296: else
2297: {
2298: rtx constant;
2299: rtx insn =
2300: emit_insn (gen_subsi3 (tmpreg2 = (reload_in_progress
2301: || reload_completed
2302: || last)
2303: ? operands[0]
2304: : gen_reg_rtx (SImode),
2305: tmpreg,
2306: constant = gen_rtx (CONST_INT, VOIDmode,
2307: n & (255 << i))));
2308: tmpreg = tmpreg2;
2309: }
2310: n &= ~(255 << i);
2311: }
2312: }
2313: }
2314: else
2315: {
2316: for (i = 30; i >= 0; i -= 2)
2317: {
2318: if (n & (3 << i))
2319: {
2320: i -= 6;
2321: if (i < 0)
2322: i = 0;
2323: if ((n & (255 << i)) == n)
2324: last = 1;
2325: if (first)
2326: {
2327: rtx equal;
2328: rtx insn =
2329: emit_insn (gen_movsi (tmpreg = (reload_in_progress
2330: || reload_completed)
2331: ? operands[0]
2332: : gen_reg_rtx (SImode),
2333: equal = gen_rtx (CONST_INT, VOIDmode,
2334: n & (255 << i))));
2335: first = 0;
2336: }
2337: else
2338: {
2339: rtx constant;
2340: rtx insn =
2341: emit_insn (gen_addsi3 (tmpreg2 = (reload_in_progress
2342: || reload_completed
2343: || last)
2344: ? operands[0]
2345: : gen_reg_rtx (SImode),
2346: tmpreg,
2347: constant = gen_rtx (CONST_INT, VOIDmode,
2348: n & (255 << i))));
2349: tmpreg = tmpreg2;
2350: }
2351: n &= ~(255 << i);
2352: }
2353: }
2354: }
2355: DONE;
2356: }
2357: ")
2358:
2359: (define_insn ""
2360: [(set (match_operand:SI 0 "general_operand" "=r,r,r,m,r")
2361: (match_operand:SI 1 "general_operand" "m,K,r,r,S"))]
2362: "(register_operand (operands[0], SImode)
2363: && (GET_CODE (operands[1]) != CONST_INT
2364: || const_ok_for_arm (INTVAL (operands[1]))
2365: || const_ok_for_arm (~INTVAL (operands[1])))
2366: && (GET_CODE (operands[1]) != SYMBOL_REF
2367: || CONSTANT_ADDRESS_P (operands[1])))
2368: || register_operand (operands[1], SImode)"
2369: "*
2370: switch (which_alternative)
2371: {
2372: case 2:
2373: return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
2374: case 1:
2375: if (!const_ok_for_arm (INTVAL (operands[1])))
2376: {
2377: operands[1] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[1]));
2378: return arm_output_asm_insn (\"mvn\\t%0, %1\", operands);
2379: }
2380: return arm_output_asm_insn (\"mov\\t%0, %1\", operands);
2381: case 0:
2382: if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
2383: && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
2384: return (arm_output_llc (operands));
2385: else
2386: return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands));
2387: case 3:
2388: return (arm_output_asm_insn (\"str\\t%1, %0\", operands));
2389: case 4:
2390: return output_load_symbol (operands);
2391: }
2392: "
2393: [(set_attr "length" "2,*,*,*,4")
2394: (set_attr "type" "load,*,*,store1,*")])
2395:
2396: ;; If copying one reg to another we can set the condition codes according to
2397: ;; its value. Such a move is common after a return from subroutine and the
2398: ;; result is being tested against zero.
2399:
2400: (define_insn ""
2401: [(set (reg:CC 24) (compare (match_operand:SI 1 "s_register_operand" "r")
2402: (const_int 0)))
2403: (set (match_operand:SI 0 "s_register_operand" "=r") (match_dup 1))]
2404: ""
2405: "*
2406: if (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
2407: && REGNO (operands[0]) == REGNO (operands[1]))
2408: return arm_output_asm_insn (\"cmp\\t%0, #0\", operands);
2409: return arm_output_asm_insn (\"subs\\t%0, %1, #0\", operands);
2410: "
2411: [(set_attr "conds" "set")])
2412:
2413: ;; Subroutine to store a half word from a register into memory.
2414: ;; Operand 0 is the source register (HImode)
2415: ;; Operand 1 is the destination address in a register (SImode)
2416:
2417: ;; In both this routine and the next, we must be careful not to spill
2418: ;; a memory address of reg+large_const into a seperate PLUS insn, since this
2419: ;; can generate unrecognizable rtl.
2420:
2421: (define_expand "storehi"
2422: [;; store the low byte
2423: (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
2424: ;; extract the high byte
2425: (set (match_dup 2)
2426: (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2427: ;; store the high byte
2428: (set (mem:QI (match_dup 4))
2429: (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
2430: ""
2431: "
2432: {
2433: enum rtx_code code = GET_CODE (operands[1]);
2434:
2435: if ((code == PLUS || code == MINUS)
2436: && (GET_CODE (XEXP (operands[1], 1)) == REG
2437: || GET_CODE (XEXP (operands[1], 0)) != REG))
2438: operands[1] = force_reg (SImode, operands[1]);
2439: operands[4] = plus_constant (operands[1], 1);
2440: operands[3] = gen_lowpart (QImode, operands[0]);
2441: operands[0] = gen_lowpart (SImode, operands[0]);
2442: operands[2] = gen_reg_rtx (SImode);
2443: }
2444: ")
2445:
2446: ;; Subroutine to store a half word integer constant into memory.
2447: ;; Operand 0 is the constant
2448: ;; Operand 1 is the destination address in a register (SImode)
2449:
2450: (define_expand "storeinthi"
2451: [;; store the low byte
2452: (set (mem:QI (match_operand:SI 1 "" "")) (match_operand 0 "" ""))
2453: ;; store the high byte
2454: (set (mem:QI (match_dup 3)) (match_dup 2))]
2455: ""
2456: "
2457: {
2458: int value = INTVAL (operands[0]);
2459: enum rtx_code code = GET_CODE (operands[1]);
2460:
2461: if ((code == PLUS || code == MINUS)
2462: && (GET_CODE (XEXP (operands[1], 1)) == REG
2463: || GET_CODE (XEXP (operands[1], 0)) != REG))
2464: operands[1] = force_reg (SImode, operands[1]);
2465:
2466: operands[0] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode, value & 255));
2467: operands[2] = force_reg (QImode,
2468: gen_rtx (CONST_INT, VOIDmode,(value>>8) & 255));
2469: operands[3] = plus_constant (operands[1], 1);
2470: }
2471: ")
2472:
2473: (define_expand "movhi"
2474: [(set (match_operand:HI 0 "general_operand" "")
2475: (match_operand:HI 1 "general_operand" ""))]
2476: ""
2477: "
2478: {
2479: rtx insn;
2480:
2481: if (reload_in_progress || reload_completed)
2482: insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
2483: else
2484: {
2485: if (GET_CODE (operands[0]) == MEM)
2486: {
2487: if (GET_CODE (operands[1]) == CONST_INT)
2488: {
2489: insn = gen_storeinthi (operands[1], XEXP (operands[0],0));
2490: }
2491: else
2492: {
2493: if (GET_CODE (operands[1]) == MEM)
2494: operands[1] = force_reg (HImode, operands[1]);
2495: insn = gen_storehi (operands[1], XEXP (operands[0], 0));
2496: }
2497: }
2498: else if (GET_CODE (operands[1]) == CONST_INT
2499: && !(const_ok_for_arm (INTVAL (operands[1]))
2500: || const_ok_for_arm (~INTVAL (operands[1]))))
2501: {
2502: rtx reg, reg2;
2503:
2504: /* no need to be clever, this will always take two insns.
2505: The top sixteen bits should be all zeros or all ones. */
2506: if (INTVAL (operands[1]) < 0)
2507: {
2508: emit_insn (gen_movsi (reg = gen_reg_rtx (SImode),
2509: GEN_INT (INTVAL (operands[1])
2510: | ~(0x0ff00))));
2511: emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg,
2512: GEN_INT (-((~INTVAL (operands[1]))
2513: & 0xff))));
2514: }
2515: else
2516: {
2517: emit_insn (gen_movsi (reg = gen_reg_rtx (SImode),
2518: GEN_INT (INTVAL (operands[1]) & 0xff00)));
2519: emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg,
2520: GEN_INT (INTVAL (operands[1]) & 0x00ff)));
2521: }
2522: insn = gen_rtx (SET, HImode, operands[0],
2523: gen_rtx (SUBREG, HImode, reg2, 0));
2524: }
2525: else
2526: insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
2527: }
2528:
2529: emit_insn (insn);
2530: DONE;
2531: }")
2532:
2533: ;; Pattern to recognise insn generated default case above
2534:
2535: (define_insn ""
2536: [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
2537: (match_operand:HI 1 "general_operand" "r,K,m,r"))]
2538: "(register_operand (operands[0], HImode)
2539: && (GET_CODE (operands[1]) != CONST_INT
2540: || const_ok_for_arm (INTVAL (operands[1]))
2541: || const_ok_for_arm (~INTVAL (operands[1]))))
2542: || register_operand (operands[1], HImode)"
2543: "*
2544: switch (which_alternative)
2545: {
2546: case 1:
2547: if (!const_ok_for_arm (INTVAL (operands[1])))
2548: {
2549: operands[1] = GEN_INT (~INTVAL (operands[1]));
2550: return arm_output_asm_insn (\"mvn\\t%0, %1\", operands);
2551: }
2552: /* fall through */
2553: case 0:
2554: return arm_output_asm_insn (\"mov\\t%0, %1\\t@movhi\", operands);
2555: case 2:
2556: return arm_output_asm_insn (\"ldr\\t%0, %1\\t@movhi\", operands);
2557: case 3:
2558: return arm_output_asm_insn (\"str\\t%1, %0\\t@movhi\", operands);
2559: }
2560: "
2561: [(set_attr "type" "*,*,load,store1")])
2562:
2563: (define_expand "reload_outhi"
2564: [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2565: (match_operand:HI 1 "s_register_operand" "r")
2566: (match_operand:SI 2 "s_register_operand" "=&r")])]
2567: ""
2568: "
2569: arm_reload_out_hi (operands);
2570: DONE;
2571: ")
2572:
2573: (define_expand "movqi"
2574: [(set (match_operand:QI 0 "general_operand" "")
2575: (match_operand:QI 1 "general_operand" ""))]
2576: ""
2577: "
2578: /* Everything except mem = const or mem = mem can be done easily */
2579:
2580: if (!(reload_in_progress || reload_completed))
2581: {
2582: rtx reg;
2583: if (GET_CODE (operands[1]) == CONST_INT)
2584: {
2585: emit_insn (gen_movsi (reg = gen_reg_rtx (SImode), operands[1]));
2586: operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
2587: }
2588: }
2589: if (GET_CODE (operands[0]) == MEM)
2590: operands[1] = force_reg (QImode, operands[1]);
2591: ")
2592:
2593:
2594: (define_insn ""
2595: [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
2596: (match_operand:QI 1 "general_operand" "r,K,m,r"))]
2597: "register_operand (operands[0], QImode)
2598: || register_operand (operands[1], QImode)"
2599: "*
2600: switch (which_alternative)
2601: {
2602: case 1:
2603: if (INTVAL (operands[1]) < 0)
2604: {
2605: operands[1] = GEN_INT (~INTVAL (operands[1]));
2606: return arm_output_asm_insn (\"mvn\\t%0, %1\", operands);
2607: }
2608: case 0:
2609: return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
2610: case 2:
2611: return (arm_output_asm_insn (\"ldrb\\t%0, %1\", operands));
2612: case 3:
2613: return (arm_output_asm_insn (\"strb\\t%1, %0\", operands));
2614: }
2615: "
2616: [(set_attr "type" "*,*,load,store1")])
2617:
2618: (define_insn "movsf"
2619: [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
2620: (match_operand:SF 1 "general_operand" "fG,H,m,f,r,f,r,m,r"))]
2621: ""
2622: "*
2623: {
2624: REAL_VALUE_TYPE r;
2625:
2626: switch (which_alternative)
2627: {
2628: case 0:
2629: return arm_output_asm_insn (\"mvfs\\t%0, %1\", operands);
2630: case 1:
2631: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2632: r = REAL_VALUE_NEGATE (r);
2633: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
2634: return arm_output_asm_insn (\"mnfs\\t%0, %1\", operands);
2635: case 2:
2636: return arm_output_asm_insn (\"ldfs\\t%0, %1\", operands);
2637: case 3:
2638: return arm_output_asm_insn (\"stfs\\t%1, %0\", operands);
2639: case 4:
2640: arm_output_asm_insn(\"stmfd\\tsp!, {%1}\", operands);
2641: return arm_output_asm_insn (\"ldfs\\t%0, [sp],#4\", operands);
2642: case 5:
2643: arm_output_asm_insn(\"stfs\\t%1, [sp,#-4]!\", operands);
2644: return arm_output_asm_insn (\"ldmfd\\tsp!, {%0}\", operands);
2645: case 6:
2646: return arm_output_asm_insn (\"mov\\t%0, %1\", operands);
2647: case 7:
2648: return arm_output_asm_insn (\"ldr\\t%0, %1\\t@ float\", operands);
2649: case 8:
2650: return arm_output_asm_insn (\"str\\t%1, %0\\t@ float\", operands);
2651: }
2652: }
2653: "
2654: [(set_attr "length" "1,1,1,1,2,2,1,1,1")
2655: (set_attr "type" "float,float,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
2656:
2657: (define_expand "movdf"
2658: [(parallel [(set (match_operand:DF 0 "general_operand" "")
2659: (match_operand:DF 1 "general_operand" ""))
2660: (clobber (match_scratch:SI 2 ""))])]
2661: ""
2662: "
2663: if (GET_CODE (operands[0]) == MEM)
2664: operands[1] = force_reg (DFmode, operands[1]);
2665: ")
2666:
2667: ;; Reloading a df mode value stored in integer regs to memory can require a
2668: ;; scratch reg.
2669: (define_expand "reload_outdf"
2670: [(parallel [(set (match_operand:DF 0 "reload_memory_operand" "=o")
2671: (match_operand:DF 1 "s_register_operand" "r"))
2672: (clobber (match_operand:SI 2 "s_register_operand" "=&r"))])]
2673: ""
2674: "")
2675:
2676: (define_insn ""
2677: [(set (match_operand:DF 0 "general_operand" "=r,Q,r,o,f,f,f,f,m,!f,!r,r")
2678: (match_operand:DF 1 "general_operand"
2679: "Q,r,?o,?r,?f,!G,!H,m,f,r,f,??r"))
2680: (clobber (match_scratch:SI 2 "=X,X,X,&r,X,X,X,X,X,X,X,X"))]
2681: "GET_CODE (operands[0]) != MEM || register_operand (operands[1], DFmode)"
2682: "*
2683: {
2684: REAL_VALUE_TYPE r;
2685: rtx ops[3];
2686:
2687: switch (which_alternative)
2688: {
2689: case 0:
2690: operands[1] = XEXP (operands[1], 0);
2691: return arm_output_asm_insn (\"ldmia\\t%1, {%0, %R0}\\t@ double\",
2692: operands);
2693: case 1:
2694: operands[0] = XEXP (operands[0], 0);
2695: return arm_output_asm_insn (\"stmia\\t%0, {%1, %R1}\\t@ double\",
2696: operands);
2697: case 2:
2698: ops[0] = operands[0];
2699: ops[1] = XEXP (XEXP (operands[1], 0), 0);
2700: ops[2] = XEXP (XEXP (operands[1], 0), 1);
2701: if (!INTVAL (ops[2]) || const_ok_for_arm (INTVAL (ops[2])))
2702: arm_output_asm_insn (\"add\\t%0, %1, %2\", ops);
2703: else
2704: arm_output_asm_insn (\"sub\\t%0, %1, #%n2\", ops);
2705: return arm_output_asm_insn (\"ldmia\\t%0, {%0, %R0}\\t@ double\",
2706: operands);
2707: case 3:
2708:
2709: ops[0] = operands[2];
2710: ops[1] = XEXP (XEXP (operands[0], 0), 0);
2711: ops[2] = XEXP (XEXP (operands[0], 0), 1);
2712: if (!INTVAL (ops[2]) || const_ok_for_arm (INTVAL (ops[2])))
2713: arm_output_asm_insn (\"add\\t%0, %1, %2\", ops);
2714: else
2715: arm_output_asm_insn (\"sub\\t%0, %1, #%n2\", ops);
2716: return arm_output_asm_insn (\"stmia\\t%2, {%1, %R1}\\t@ double\",
2717: operands);
2718: case 4:
2719: case 5:
2720: return arm_output_asm_insn (\"mvfd\\t%0, %1\", operands);
2721: case 6:
2722: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2723: r = REAL_VALUE_NEGATE (r);
2724: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
2725: return arm_output_asm_insn (\"mnfd\\t%0, %1\", operands);
2726: case 7: return arm_output_asm_insn (\"ldfd\\t%0, %1\", operands);
2727: case 8: return arm_output_asm_insn (\"stfd\\t%1, %0\", operands);
2728: case 9: return output_mov_double_fpu_from_arm (operands);
2729: case 10: return output_mov_double_arm_from_fpu (operands);
2730: case 11: return output_move_double (operands);
2731: }
2732: }
2733: "
2734: [(set_attr "length" "1,1,2,2,1,1,1,1,1,2,2,2")
2735: (set_attr "type"
2736: "load,store2,load,store2,float,float,float,f_load,f_store,r_mem_f,f_mem_r,*")])
2737:
2738: (define_insn "movxf"
2739: [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
2740: (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
2741: "ENABLE_XF_PATTERNS"
2742: "*
2743: {
2744: REAL_VALUE_TYPE r;
2745:
2746: switch (which_alternative)
2747: {
2748: case 0: return arm_output_asm_insn (\"mvfe\\t%0, %1\", operands);
2749: case 1:
2750: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2751: r = REAL_VALUE_NEGATE (r);
2752: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
2753: return arm_output_asm_insn (\"mnfe\\t%0, %1\", operands);
2754: case 2: return arm_output_asm_insn (\"ldfe\\t%0, %1\", operands);
2755: case 3: return arm_output_asm_insn (\"stfe\\t%1, %0\", operands);
2756: case 4: return output_mov_long_double_fpu_from_arm (operands);
2757: case 5: return output_mov_long_double_arm_from_fpu (operands);
2758: case 6: return output_mov_long_double_arm_from_arm (operands);
2759: }
2760: }
2761: "
2762: [(set_attr "length" "1,1,1,1,2,2,3")
2763: (set_attr "type" "float,float,f_load,f_store,r_mem_f,f_mem_r,*")])
2764:
2765:
2766: ;; load- and store-multiple insns
2767: ;; The arm can load/store any set of registers, provided that they are in
2768: ;; ascending order; but that is beyond GCC so stick with what it knows.
2769:
2770: (define_expand "load_multiple"
2771: [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2772: (match_operand:SI 1 "" ""))
2773: (use (match_operand:SI 2 "" ""))])]
2774: ""
2775: "
2776: /* Support only fixed point registers */
2777: if (GET_CODE (operands[2]) != CONST_INT
2778: || INTVAL (operands[2]) > 14
2779: || INTVAL (operands[2]) < 2
2780: || GET_CODE (operands[1]) != MEM
2781: || GET_CODE (operands[0]) != REG
2782: || REGNO (operands[0]) > 14
2783: || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
2784: FAIL;
2785:
2786: operands[3]
2787: = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
2788: force_reg (SImode, XEXP (operands[1], 0)),
2789: TRUE, FALSE);
2790: ")
2791:
2792: ;; Load multiple with write-back
2793:
2794: (define_insn ""
2795: [(match_parallel 0 "load_multiple_operation"
2796: [(set (match_operand:SI 1 "s_register_operand" "+r")
2797: (plus:SI (match_dup 1)
2798: (match_operand:SI 2 "immediate_operand" "n")))
2799: (set (match_operand:SI 3 "s_register_operand" "=r")
2800: (mem:SI (match_dup 1)))])]
2801: "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2802: "*
2803: {
2804: rtx ops[3];
2805: int count = XVECLEN (operands[0], 0);
2806:
2807: ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2808: ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
2809: ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
2810:
2811: return arm_output_asm_insn (\"ldmia\\t%0!, {%1-%2}\\t@ load multiple\", ops);
2812: }
2813: "
2814: [(set_attr "type" "load")])
2815:
2816: ;; Ordinary load multiple
2817:
2818: (define_insn ""
2819: [(match_parallel 0 "load_multiple_operation"
2820: [(set (match_operand:SI 1 "s_register_operand" "=r")
2821: (match_operand:SI 2 "indirect_operand" "Q"))])]
2822: ""
2823: "*
2824: {
2825: rtx ops[3];
2826: int count = XVECLEN (operands[0], 0);
2827:
2828: ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2829: ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
2830: ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
2831:
2832: return arm_output_asm_insn (\"ldmia\\t%0, {%1-%2}\\t@ load multiple\", ops);
2833: }
2834: "
2835: [(set_attr "type" "load")])
2836:
2837: (define_expand "store_multiple"
2838: [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2839: (match_operand:SI 1 "" ""))
2840: (use (match_operand:SI 2 "" ""))])]
2841: ""
2842: "
2843: /* Support only fixed point registers */
2844: if (GET_CODE (operands[2]) != CONST_INT
2845: || INTVAL (operands[2]) > 14
2846: || INTVAL (operands[2]) < 2
2847: || GET_CODE (operands[1]) != REG
2848: || GET_CODE (operands[0]) != MEM
2849: || REGNO (operands[1]) > 14
2850: || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
2851: FAIL;
2852:
2853: operands[3]
2854: = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
2855: force_reg (SImode, XEXP (operands[0], 0)),
2856: TRUE, FALSE);
2857: ")
2858:
2859: ;; Store multiple with write-back
2860:
2861: (define_insn ""
2862: [(match_parallel 0 "store_multiple_operation"
2863: [(set (match_operand:SI 1 "s_register_operand" "+r")
2864: (plus:SI (match_dup 1)
2865: (match_operand:SI 2 "immediate_operand" "n")))
2866: (set (mem:SI (match_dup 1))
2867: (match_operand:SI 3 "s_register_operand" "r"))])]
2868: "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2869: "*
2870: {
2871: rtx ops[3];
2872: int count = XVECLEN (operands[0], 0);
2873:
2874: ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2875: ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
2876: ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
2877:
2878: return arm_output_asm_insn (\"stmia\\t%0!, {%1-%2}\\t@ str multiple\", ops);
2879: }
2880: "
2881: [(set (attr "type")
2882: (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2883: (const_string "store2")
2884: (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
2885: (const_string "store3")]
2886: (const_string "store4")))])
2887:
2888: ;; Ordinary store multiple
2889:
2890: (define_insn ""
2891: [(match_parallel 0 "store_multiple_operation"
2892: [(set (match_operand:SI 2 "indirect_operand" "=Q")
2893: (match_operand:SI 1 "s_register_operand" "r"))])]
2894: ""
2895: "*
2896: {
2897: rtx ops[3];
2898: int count = XVECLEN (operands[0], 0);
2899:
2900: ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
2901: ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
2902: ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
2903:
2904: return arm_output_asm_insn (\"stmia\\t%0, {%1-%2}\\t@ str multiple\", ops);
2905: }
2906: "
2907: [(set (attr "type")
2908: (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
2909: (const_string "store2")
2910: (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2911: (const_string "store3")]
2912: (const_string "store4")))])
2913:
2914: ;; Move a block of memory if it is word aligned and MORE than 2 words long.
2915: ;; We could let this apply for blocks of less than this, but it clobbers so
2916: ;; many registers that there is then probably a better way.
2917:
2918: ;; If optimizing, output redundant moves with REG_NOTES on them, this
2919: ;; produces better code.
2920:
2921: (define_expand "movstrsi"
2922: [(set (match_operand:BLK 0 "general_operand" "=m")
2923: (match_operand:BLK 1 "general_operand" "m"))
2924: (use (match_operand:SI 2 "immediate_operand" "n"))
2925: (use (match_operand:SI 3 "immediate_operand" "n"))
2926: (clobber (reg:SI 0))
2927: (clobber (reg:SI 1))
2928: (clobber (reg:SI 2))
2929: (clobber (reg:SI 3))
2930: (clobber (match_scratch:SI 4 "=+r"))
2931: (clobber (match_scratch:SI 5 "=+r"))]
2932: ""
2933: "
2934: {
2935: int words_to_go;
2936: int i, r;
2937: rtx const_sxteen = gen_rtx (CONST_INT, SImode, 16);
2938: rtx src = gen_reg_rtx (SImode);
2939: rtx dst = gen_reg_rtx (SImode);
2940: rtx st_src, st_dst, end_src, end_dst, fin_src, fin_dst;
2941: extern int optimize;
2942:
2943: if (GET_CODE (operands[2]) != CONST_INT
2944: || GET_CODE (operands[3]) != CONST_INT
2945: || INTVAL (operands[2]) % 4 != 0
2946: || INTVAL (operands[2]) < 4
2947: || INTVAL (operands[2]) > 64
2948: || INTVAL (operands[3]) < 4
2949: || INTVAL (operands[3]) % 4 != 0)
2950: FAIL;
2951: emit_move_insn (dst, st_dst = force_reg (SImode, XEXP (operands[0], 0)));
2952: emit_move_insn (src, st_src = force_reg (SImode, XEXP (operands[1], 0)));
2953: fin_src = src;
2954: fin_dst = dst;
2955:
2956: for (i = 0, words_to_go = INTVAL (operands[2]) / 4; words_to_go >= 2; i+=4)
2957: {
2958: emit_insn (arm_gen_load_multiple (0, words_to_go > 4 ? 4 : words_to_go,
2959: src, TRUE, TRUE));
2960: emit_insn (arm_gen_store_multiple (0, words_to_go > 4 ? 4 : words_to_go,
2961: dst, TRUE, TRUE));
2962: if (optimize)
2963: for (r = (words_to_go > 4) ? 3 : words_to_go - 1; r >= 0; r--)
2964: {
2965: rtx note;
2966: note = emit_move_insn (gen_reg_rtx (SImode),
2967: gen_rtx (REG, SImode, r));
2968: REG_NOTES (note) = gen_rtx (EXPR_LIST, REG_EQUIV,
2969: gen_rtx (MEM, SImode,
2970: plus_constant (st_src, 4*(i+r))),
2971: REG_NOTES (note));
2972: REG_NOTES (note) = gen_rtx (EXPR_LIST, REG_EQUIV,
2973: gen_rtx (MEM, SImode,
2974: plus_constant (st_dst, 4*(i+r))),
2975: REG_NOTES (note));
2976: }
2977: words_to_go -= words_to_go < 4 ? words_to_go : 4;
2978: }
2979: if (words_to_go)
2980: {
2981: rtx sreg;
2982:
2983: emit_move_insn (sreg = gen_reg_rtx (SImode), gen_rtx (MEM, SImode, src));
2984: emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
2985: emit_move_insn (gen_rtx (MEM, SImode, dst), sreg);
2986: emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
2987: }
2988: if (optimize)
2989: {
2990: /* Insns for the REG_NOTES: These notes tell the optimiser where the
2991: index registers have got to so that consecutive block moves of
2992: contiguous data work efficiently */
2993:
2994: end_src = emit_move_insn (fin_src, fin_src);
2995: REG_NOTES (end_src) = gen_rtx(EXPR_LIST, REG_EQUAL,
2996: plus_constant (st_src, INTVAL (operands[2])),
2997: REG_NOTES (end_src));
2998: end_dst = emit_move_insn (fin_dst, fin_dst);
2999: REG_NOTES (end_dst) = gen_rtx(EXPR_LIST, REG_EQUAL,
3000: plus_constant (st_dst, INTVAL (operands[2])),
3001: REG_NOTES (end_dst));
3002: }
3003: DONE;
3004: }
3005: ")
3006:
3007:
3008: ;; Comparison and test insns
3009:
3010: (define_expand "cmpsi"
3011: [(set (reg:CC 24)
3012: (compare:CC (match_operand:SI 0 "s_register_operand" "")
3013: (match_operand:SI 1 "arm_add_operand" "")))]
3014: ""
3015: "
3016: {
3017: arm_compare_op0 = operands[0];
3018: arm_compare_op1 = operands[1];
3019: arm_compare_fp = 0;
3020: DONE;
3021: }
3022: ")
3023:
3024: (define_expand "cmpsf"
3025: [(set (reg:CC 24)
3026: (compare:CC (match_operand:SF 0 "s_register_operand" "")
3027: (match_operand:SF 1 "fpu_rhs_operand" "")))]
3028: ""
3029: "
3030: {
3031: arm_compare_op0 = operands[0];
3032: arm_compare_op1 = operands[1];
3033: arm_compare_fp = 1;
3034: DONE;
3035: }
3036: ")
3037:
3038: (define_expand "cmpdf"
3039: [(set (reg:CC 24)
3040: (compare:CC (match_operand:DF 0 "s_register_operand" "")
3041: (match_operand:DF 1 "fpu_rhs_operand" "")))]
3042: ""
3043: "
3044: {
3045: arm_compare_op0 = operands[0];
3046: arm_compare_op1 = operands[1];
3047: arm_compare_fp = 1;
3048: DONE;
3049: }
3050: ")
3051:
3052: (define_expand "cmpxf"
3053: [(set (reg:CC 24)
3054: (compare:CC (match_operand:XF 0 "s_register_operand" "")
3055: (match_operand:XF 1 "fpu_rhs_operand" "")))]
3056: "ENABLE_XF_PATTERNS"
3057: "
3058: {
3059: arm_compare_op0 = operands[0];
3060: arm_compare_op1 = operands[1];
3061: arm_compare_fp = 1;
3062: DONE;
3063: }
3064: ")
3065:
3066: (define_insn ""
3067: [(set (match_operand 0 "cc_register" "")
3068: (compare (match_operand:SI 1 "s_register_operand" "r")
3069: (match_operand:SI 2 "arm_add_operand" "rL")))]
3070: ""
3071: "*
3072: if (GET_CODE (operands[2]) == CONST_INT
3073: && !const_ok_for_arm (INTVAL (operands[2])))
3074: return arm_output_asm_insn (\"cmn\\t%1, #%n2\", operands);
3075: return arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
3076: "
3077: [(set_attr "conds" "set")])
3078:
3079: (define_insn ""
3080: [(set (match_operand 0 "cc_register" "")
3081: (compare (match_operand:SI 1 "s_register_operand" "r")
3082: (neg:SI (match_operand:SI 2 "s_register_operand" "r"))))]
3083: ""
3084: "*
3085: return arm_output_asm_insn (\"cmn\\t%1, %2\", operands);
3086: "
3087: [(set_attr "conds" "set")])
3088:
3089: (define_insn ""
3090: [(set (match_operand 0 "cc_register" "")
3091: (compare (match_operand:SI 1 "s_register_operand" "r")
3092: (match_operator:SI 2 "shift_operator"
3093: [(match_operand:SI 3 "s_register_operand" "r")
3094: (match_operand:SI 4 "arm_rhs_operand" "rn")])))]
3095: ""
3096: "*
3097: return output_shift_compare (operands, FALSE);
3098: "
3099: [(set_attr "conds" "set")])
3100:
3101: (define_insn ""
3102: [(set (match_operand 0 "cc_register" "")
3103: (compare (match_operand:SI 1 "s_register_operand" "r")
3104: (neg:SI (match_operator:SI 2 "shift_operator"
3105: [(match_operand:SI 3 "s_register_operand" "r")
3106: (match_operand:SI 4 "arm_rhs_operand" "rn")]))))]
3107: ""
3108: "*
3109: return output_shift_compare (operands, TRUE);
3110: "
3111: [(set_attr "conds" "set")])
3112:
3113: (define_insn ""
3114: [(set (reg:CCFP 24)
3115: (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3116: (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3117: ""
3118: "*
3119: {
3120: REAL_VALUE_TYPE r;
3121:
3122: switch (which_alternative)
3123: {
3124: case 0:
3125: return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3126: case 1:
3127: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3128: r = REAL_VALUE_NEGATE (r);
3129: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3130: return arm_output_asm_insn (\"cnf\\t%0, %1\", operands);
3131: }
3132: }
3133: "
3134: [(set_attr "conds" "set")
3135: (set_attr "type" "f_2_r")])
3136:
3137: (define_insn ""
3138: [(set (reg:CCFP 24)
3139: (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3140: (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3141: ""
3142: "*
3143: {
3144: REAL_VALUE_TYPE r;
3145:
3146: switch (which_alternative)
3147: {
3148: case 0:
3149: return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3150: case 1:
3151: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3152: r = REAL_VALUE_NEGATE (r);
3153: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3154: return arm_output_asm_insn (\"cnf\\t%0, %1\", operands);
3155: }
3156: }
3157: "
3158: [(set_attr "conds" "set")
3159: (set_attr "type" "f_2_r")])
3160:
3161: (define_insn ""
3162: [(set (reg:CCFP 24)
3163: (compare:CCFP (float_extend:DF
3164: (match_operand:SF 0 "s_register_operand" "f,f"))
3165: (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3166: ""
3167: "*
3168: {
3169: REAL_VALUE_TYPE r;
3170:
3171: switch (which_alternative)
3172: {
3173: case 0:
3174: return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3175: case 1:
3176: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3177: r = REAL_VALUE_NEGATE (r);
3178: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3179: return arm_output_asm_insn (\"cnf\\t%0, %1\", operands);
3180: }
3181: }
3182: "
3183: [(set_attr "conds" "set")
3184: (set_attr "type" "f_2_r")])
3185:
3186: (define_insn ""
3187: [(set (reg:CCFP 24)
3188: (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3189: (float_extend:DF
3190: (match_operand:SF 1 "s_register_operand" "f"))))]
3191: ""
3192: "*
3193: return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3194: "
3195: [(set_attr "conds" "set")
3196: (set_attr "type" "f_2_r")])
3197:
3198: (define_insn ""
3199: [(set (reg:CCFP 24)
3200: (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3201: (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3202: "ENABLE_XF_PATTERNS"
3203: "*
3204: {
3205: REAL_VALUE_TYPE r;
3206:
3207: switch (which_alternative)
3208: {
3209: case 0:
3210: return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3211: case 1:
3212: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3213: r = REAL_VALUE_NEGATE (r);
3214: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3215: return arm_output_asm_insn (\"cnf\\t%0, %1\", operands);
3216: }
3217: }
3218: "
3219: [(set_attr "conds" "set")
3220: (set_attr "type" "f_2_r")])
3221:
3222: (define_insn ""
3223: [(set (reg:CCFPE 24)
3224: (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3225: (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3226: ""
3227: "*
3228: {
3229: REAL_VALUE_TYPE r;
3230:
3231: switch (which_alternative)
3232: {
3233: case 0:
3234: return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3235: case 1:
3236: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3237: r = REAL_VALUE_NEGATE (r);
3238: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3239: return arm_output_asm_insn (\"cnfe\\t%0, %1\", operands);
3240: }
3241: }
3242: "
3243: [(set_attr "conds" "set")
3244: (set_attr "type" "f_2_r")])
3245:
3246: (define_insn ""
3247: [(set (reg:CCFPE 24)
3248: (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3249: (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3250: ""
3251: "*
3252: {
3253: REAL_VALUE_TYPE r;
3254:
3255: switch (which_alternative)
3256: {
3257: case 0:
3258: return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3259: case 1:
3260: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3261: r = REAL_VALUE_NEGATE (r);
3262: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3263: return arm_output_asm_insn (\"cnfe\\t%0, %1\", operands);
3264: }
3265: }
3266: "
3267: [(set_attr "conds" "set")
3268: (set_attr "type" "f_2_r")])
3269:
3270: (define_insn ""
3271: [(set (reg:CCFPE 24)
3272: (compare:CCFPE (float_extend:DF
3273: (match_operand:SF 0 "s_register_operand" "f,f"))
3274: (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3275: ""
3276: "*
3277: {
3278: REAL_VALUE_TYPE r;
3279:
3280: switch (which_alternative)
3281: {
3282: case 0:
3283: return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3284: case 1:
3285: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3286: r = REAL_VALUE_NEGATE (r);
3287: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3288: return arm_output_asm_insn (\"cnfe\\t%0, %1\", operands);
3289: }
3290: }
3291: "
3292: [(set_attr "conds" "set")
3293: (set_attr "type" "f_2_r")])
3294:
3295: (define_insn ""
3296: [(set (reg:CCFPE 24)
3297: (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3298: (float_extend:DF
3299: (match_operand:SF 1 "s_register_operand" "f"))))]
3300: ""
3301: "*
3302: return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3303: "
3304: [(set_attr "conds" "set")
3305: (set_attr "type" "f_2_r")])
3306:
3307: (define_insn ""
3308: [(set (reg:CCFPE 24)
3309: (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3310: (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3311: "ENABLE_XF_PATTERNS"
3312: "*
3313: {
3314: REAL_VALUE_TYPE r;
3315:
3316: switch (which_alternative)
3317: {
3318: case 0:
3319: return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3320: case 1:
3321: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3322: r = REAL_VALUE_NEGATE (r);
3323: operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3324: return arm_output_asm_insn (\"cnfe\\t%0, %1\", operands);
3325: }
3326: }
3327: "
3328: [(set_attr "conds" "set")
3329: (set_attr "type" "f_2_r")])
3330:
3331: ; This insn allows redundant compares to be removed by cse, nothing should
3332: ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3333: ; is deleted later on. The match_dup will match the mode here, so that
3334: ; mode changes of the condition codes aren't lost by this even though we don't
3335: ; specify what they are.
3336:
3337: (define_insn ""
3338: [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3339: ""
3340: "\\t@ deleted compare"
3341: [(set_attr "conds" "set")
3342: (set_attr "length" "0")])
3343:
3344:
3345: ;; Conditional branch insns
3346:
3347: (define_expand "beq"
3348: [(set (pc)
3349: (if_then_else (eq (match_dup 1) (const_int 0))
3350: (label_ref (match_operand 0 "" ""))
3351: (pc)))]
3352: ""
3353: "
3354: {
3355: operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3356: arm_compare_fp);
3357: }
3358: ")
3359:
3360: (define_expand "bne"
3361: [(set (pc)
3362: (if_then_else (ne (match_dup 1) (const_int 0))
3363: (label_ref (match_operand 0 "" ""))
3364: (pc)))]
3365: ""
3366: "
3367: {
3368: operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3369: arm_compare_fp);
3370: }
3371: ")
3372:
3373: (define_expand "bgt"
3374: [(set (pc)
3375: (if_then_else (gt (match_dup 1) (const_int 0))
3376: (label_ref (match_operand 0 "" ""))
3377: (pc)))]
3378: ""
3379: "
3380: {
3381: operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3382: arm_compare_fp);
3383: }
3384: ")
3385:
3386: (define_expand "ble"
3387: [(set (pc)
3388: (if_then_else (le (match_dup 1) (const_int 0))
3389: (label_ref (match_operand 0 "" ""))
3390: (pc)))]
3391: ""
3392: "
3393: {
3394: operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3395: arm_compare_fp);
3396: }
3397: ")
3398:
3399: (define_expand "bge"
3400: [(set (pc)
3401: (if_then_else (ge (match_dup 1) (const_int 0))
3402: (label_ref (match_operand 0 "" ""))
3403: (pc)))]
3404: ""
3405: "
3406: {
3407: operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3408: arm_compare_fp);
3409: }
3410: ")
3411:
3412: (define_expand "blt"
3413: [(set (pc)
3414: (if_then_else (lt (match_dup 1) (const_int 0))
3415: (label_ref (match_operand 0 "" ""))
3416: (pc)))]
3417: ""
3418: "
3419: {
3420: operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3421: arm_compare_fp);
3422: }
3423: ")
3424:
3425: (define_expand "bgtu"
3426: [(set (pc)
3427: (if_then_else (gtu (match_dup 1) (const_int 0))
3428: (label_ref (match_operand 0 "" ""))
3429: (pc)))]
3430: ""
3431: "
3432: {
3433: operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3434: arm_compare_fp);
3435: }
3436: ")
3437:
3438: (define_expand "bleu"
3439: [(set (pc)
3440: (if_then_else (leu (match_dup 1) (const_int 0))
3441: (label_ref (match_operand 0 "" ""))
3442: (pc)))]
3443: ""
3444: "
3445: {
3446: operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3447: arm_compare_fp);
3448: }
3449: ")
3450:
3451: (define_expand "bgeu"
3452: [(set (pc)
3453: (if_then_else (geu (match_dup 1) (const_int 0))
3454: (label_ref (match_operand 0 "" ""))
3455: (pc)))]
3456: ""
3457: "
3458: {
3459: operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3460: arm_compare_fp);
3461: }
3462: ")
3463:
3464: (define_expand "bltu"
3465: [(set (pc)
3466: (if_then_else (ltu (match_dup 1) (const_int 0))
3467: (label_ref (match_operand 0 "" ""))
3468: (pc)))]
3469: ""
3470: "
3471: {
3472: operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3473: arm_compare_fp);
3474: }
3475: ")
3476:
3477: ;; patterns to match conditional branch insns
3478:
3479: (define_insn ""
3480: [(set (pc)
3481: (if_then_else (match_operator 1 "comparison_operator"
3482: [(reg 24) (const_int 0)])
3483: (label_ref (match_operand 0 "" ""))
3484: (pc)))]
3485: ""
3486: "*
3487: {
3488: extern int arm_ccfsm_state;
3489:
3490: if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3491: {
3492: arm_ccfsm_state += 2;
3493: return \"\";
3494: }
3495: return (arm_output_asm_insn (\"b%d1\\t%l0\", operands));
3496: }"
3497: [(set_attr "conds" "use")])
3498:
3499: (define_insn ""
3500: [(set (pc)
3501: (if_then_else (match_operator 1 "comparison_operator"
3502: [(reg 24) (const_int 0)])
3503: (pc)
3504: (label_ref (match_operand 0 "" ""))))]
3505: ""
3506: "*
3507: {
3508: extern int arm_ccfsm_state;
3509:
3510: if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3511: {
3512: arm_ccfsm_state += 2;
3513: return \"\";
3514: }
3515: return (arm_output_asm_insn (\"b%D1\\t%l0\", operands));
3516: }"
3517: [(set_attr "conds" "use")])
3518:
3519:
3520: ; scc insns
3521:
3522: (define_expand "seq"
3523: [(set (match_operand:SI 0 "s_register_operand" "=r")
3524: (eq:SI (match_dup 1) (const_int 0)))]
3525: ""
3526: "
3527: {
3528: operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3529: arm_compare_fp);
3530: }
3531: ")
3532:
3533: (define_expand "sne"
3534: [(set (match_operand:SI 0 "s_register_operand" "=r")
3535: (ne:SI (match_dup 1) (const_int 0)))]
3536: ""
3537: "
3538: {
3539: operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3540: arm_compare_fp);
3541: }
3542: ")
3543:
3544: (define_expand "sgt"
3545: [(set (match_operand:SI 0 "s_register_operand" "=r")
3546: (gt:SI (match_dup 1) (const_int 0)))]
3547: ""
3548: "
3549: {
3550: operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3551: arm_compare_fp);
3552: }
3553: ")
3554:
3555: (define_expand "sle"
3556: [(set (match_operand:SI 0 "s_register_operand" "=r")
3557: (le:SI (match_dup 1) (const_int 0)))]
3558: ""
3559: "
3560: {
3561: operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3562: arm_compare_fp);
3563: }
3564: ")
3565:
3566: (define_expand "sge"
3567: [(set (match_operand:SI 0 "s_register_operand" "=r")
3568: (ge:SI (match_dup 1) (const_int 0)))]
3569: ""
3570: "
3571: {
3572: operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3573: arm_compare_fp);
3574: }
3575: ")
3576:
3577: (define_expand "slt"
3578: [(set (match_operand:SI 0 "s_register_operand" "=r")
3579: (lt:SI (match_dup 1) (const_int 0)))]
3580: ""
3581: "
3582: {
3583: operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3584: arm_compare_fp);
3585: }
3586: ")
3587:
3588: (define_expand "sgtu"
3589: [(set (match_operand:SI 0 "s_register_operand" "=r")
3590: (gtu:SI (match_dup 1) (const_int 0)))]
3591: ""
3592: "
3593: {
3594: operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3595: arm_compare_fp);
3596: }
3597: ")
3598:
3599: (define_expand "sleu"
3600: [(set (match_operand:SI 0 "s_register_operand" "=r")
3601: (leu:SI (match_dup 1) (const_int 0)))]
3602: ""
3603: "
3604: {
3605: operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3606: arm_compare_fp);
3607: }
3608: ")
3609:
3610: (define_expand "sgeu"
3611: [(set (match_operand:SI 0 "s_register_operand" "=r")
3612: (geu:SI (match_dup 1) (const_int 0)))]
3613: ""
3614: "
3615: {
3616: operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3617: arm_compare_fp);
3618: }
3619: ")
3620:
3621: (define_expand "sltu"
3622: [(set (match_operand:SI 0 "s_register_operand" "=r")
3623: (ltu:SI (match_dup 1) (const_int 0)))]
3624: ""
3625: "
3626: {
3627: operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3628: arm_compare_fp);
3629: }
3630: ")
3631:
3632: (define_insn ""
3633: [(set (match_operand:SI 0 "s_register_operand" "=r")
3634: (match_operator:SI 1 "comparison_operator" [(reg 24) (const_int 0)]))]
3635: ""
3636: "*
3637: arm_output_asm_insn (\"mov%d1\\t%0, #1\", operands);
3638: return arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
3639: "
3640: [(set_attr "conds" "use")
3641: (set_attr "length" "2")])
3642:
3643: (define_insn ""
3644: [(set (match_operand:SI 0 "s_register_operand" "=r")
3645: (neg:SI (match_operator:SI 1 "comparison_operator"
3646: [(reg 24) (const_int 0)])))]
3647: ""
3648: "*
3649: arm_output_asm_insn (\"mvn%d1\\t%0, #0\", operands);
3650: return arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
3651: "
3652: [(set_attr "conds" "use")
3653: (set_attr "length" "2")])
3654:
3655: (define_insn ""
3656: [(set (match_operand:SI 0 "s_register_operand" "=r")
3657: (not:SI (match_operator:SI 1 "comparison_operator"
3658: [(reg 24) (const_int 0)])))]
3659: ""
3660: "*
3661: arm_output_asm_insn (\"mvn%d1\\t%0, #1\", operands);
3662: return arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
3663: "
3664: [(set_attr "conds" "use")
3665: (set_attr "length" "2")])
3666:
3667:
3668: ;; Jump and linkage insns
3669:
3670: (define_insn "jump"
3671: [(set (pc)
3672: (label_ref (match_operand 0 "" "")))]
3673: ""
3674: "*
3675: {
3676: extern int arm_ccfsm_state;
3677:
3678: if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3679: {
3680: arm_ccfsm_state += 2;
3681: return \"\";
3682: }
3683: return (arm_output_asm_insn (\"b\\t%l0\", operands));
3684: }")
3685:
3686: (define_expand "call"
3687: [(parallel [(call (match_operand 0 "memory_operand" "")
3688: (match_operand 1 "general_operand" ""))
3689: (clobber (reg:SI 14))])]
3690: ""
3691: "")
3692:
3693: (define_insn ""
3694: [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
3695: (match_operand 1 "" "g"))
3696: (clobber (reg:SI 14))]
3697: ""
3698: "*
3699: return (output_call (operands));
3700: "
3701: [(set (attr "conds")
3702: (if_then_else (eq_attr "cpu" "arm6")
3703: (const_string "clob")
3704: (const_string "nocond")))
3705: ;; length is worst case, normally it is only two
3706: (set_attr "length" "3")
3707: (set_attr "type" "call")])
3708:
3709: (define_insn ""
3710: [(call (mem:SI (match_operand 0 "memory_operand" "m"))
3711: (match_operand 1 "general_operand" "g"))
3712: (clobber (reg:SI 14))]
3713: ""
3714: "*
3715: return (output_call_mem (operands));
3716: "
3717: [(set (attr "conds")
3718: (if_then_else (eq_attr "cpu" "arm6")
3719: (const_string "clob")
3720: (const_string "nocond")))
3721: (set_attr "length" "3")
3722: (set_attr "type" "call")])
3723:
3724: (define_expand "call_value"
3725: [(parallel [(set (match_operand 0 "" "=rf")
3726: (call (match_operand 1 "memory_operand" "m")
3727: (match_operand 2 "general_operand" "g")))
3728: (clobber (reg:SI 14))])]
3729: ""
3730: "")
3731:
3732: (define_insn ""
3733: [(set (match_operand 0 "" "=rf")
3734: (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
3735: (match_operand 2 "general_operand" "g")))
3736: (clobber (reg:SI 14))]
3737: ""
3738: "*
3739: return (output_call (&operands[1]));
3740: "
3741: [(set (attr "conds")
3742: (if_then_else (eq_attr "cpu" "arm6")
3743: (const_string "clob")
3744: (const_string "nocond")))
3745: (set_attr "length" "3")
3746: (set_attr "type" "call")])
3747:
3748: (define_insn ""
3749: [(set (match_operand 0 "" "=rf")
3750: (call (mem:SI (match_operand 1 "memory_operand" "m"))
3751: (match_operand 2 "general_operand" "g")))
3752: (clobber (reg:SI 14))]
3753: "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
3754: "*
3755: return (output_call_mem (&operands[1]));
3756: "
3757: [(set (attr "conds")
3758: (if_then_else (eq_attr "cpu" "arm6")
3759: (const_string "clob")
3760: (const_string "nocond")))
3761: (set_attr "length" "3")
3762: (set_attr "type" "call")])
3763:
3764: ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
3765: ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
3766:
3767: (define_insn ""
3768: [(call (mem:SI (match_operand:SI 0 "" "i"))
3769: (match_operand:SI 1 "general_operand" "g"))
3770: (clobber (reg:SI 14))]
3771: "GET_CODE (operands[0]) == SYMBOL_REF"
3772: "*
3773: return (arm_output_asm_insn (\"bl\\t%a0\", operands));
3774: "
3775: [(set (attr "conds")
3776: (if_then_else (eq_attr "cpu" "arm6")
3777: (const_string "clob")
3778: (const_string "nocond")))
3779: (set_attr "type" "call")])
3780:
3781: (define_insn ""
3782: [(set (match_operand 0 "s_register_operand" "=rf")
3783: (call (mem:SI (match_operand:SI 1 "" "i"))
3784: (match_operand:SI 2 "general_operand" "g")))
3785: (clobber (reg:SI 14))]
3786: "GET_CODE(operands[1]) == SYMBOL_REF"
3787: "*
3788: return (arm_output_asm_insn (\"bl\\t%a1\", operands));
3789: "
3790: [(set (attr "conds")
3791: (if_then_else (eq_attr "cpu" "arm6")
3792: (const_string "clob")
3793: (const_string "nocond")))
3794: (set_attr "type" "call")])
3795:
3796: ;; Often the return insn will be the same as loading from memory, so set attr
3797: (define_insn "return"
3798: [(return)]
3799: "USE_RETURN_INSN"
3800: "*
3801: {
3802: extern int arm_ccfsm_state;
3803:
3804: if (arm_ccfsm_state == 2)
3805: {
3806: arm_ccfsm_state += 2;
3807: return \"\";
3808: }
3809: return output_return_instruction (NULL, TRUE);
3810: }"
3811: [(set_attr "type" "load")])
3812:
3813: (define_insn ""
3814: [(set (pc)
3815: (if_then_else (match_operator 0 "comparison_operator"
3816: [(reg 24) (const_int 0)])
3817: (return)
3818: (pc)))]
3819: "USE_RETURN_INSN"
3820: "*
3821: {
3822: extern int arm_ccfsm_state;
3823:
3824: if (arm_ccfsm_state == 2)
3825: {
3826: arm_ccfsm_state += 2;
3827: return \"\";
3828: }
3829: return output_return_instruction (operands[0], TRUE);
3830: }"
3831: [(set_attr "conds" "use")
3832: (set_attr "type" "load")])
3833:
3834: (define_insn ""
3835: [(set (pc)
3836: (if_then_else (match_operator 0 "comparison_operator"
3837: [(reg 24) (const_int 0)])
3838: (pc)
3839: (return)))]
3840: "USE_RETURN_INSN"
3841: "*
3842: {
3843: extern int arm_ccfsm_state;
3844:
3845: if (arm_ccfsm_state == 2)
3846: {
3847: arm_ccfsm_state += 2;
3848: return \"\";
3849: }
3850: return output_return_instruction
3851: (gen_rtx (reverse_condition (GET_CODE (operands[0])),
3852: GET_MODE (operands[0]), XEXP (operands[0], 0),
3853: XEXP (operands[0], 1)),
3854: TRUE);
3855: }"
3856: [(set_attr "conds" "use")
3857: (set_attr "type" "load")])
3858:
3859: ;; Call subroutine returning any type.
3860:
3861: (define_expand "untyped_call"
3862: [(parallel [(call (match_operand 0 "" "")
3863: (const_int 0))
3864: (match_operand 1 "" "")
3865: (match_operand 2 "" "")])]
3866: ""
3867: "
3868: {
3869: int i;
3870:
3871: emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
3872:
3873: for (i = 0; i < XVECLEN (operands[2], 0); i++)
3874: {
3875: rtx set = XVECEXP (operands[2], 0, i);
3876: emit_move_insn (SET_DEST (set), SET_SRC (set));
3877: }
3878:
3879: /* The optimizer does not know that the call sets the function value
3880: registers we stored in the result block. We avoid problems by
3881: claiming that all hard registers are used and clobbered at this
3882: point. */
3883: emit_insn (gen_blockage ());
3884:
3885: DONE;
3886: }")
3887:
3888: ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
3889: ;; all of memory. This blocks insns from being moved across this point.
3890:
3891: (define_insn "blockage"
3892: [(unspec_volatile [(const_int 0)] 0)]
3893: ""
3894: ""
3895: [(set_attr "length" "0")
3896: (set_attr "type" "block")])
3897:
3898: (define_insn "tablejump"
3899: [(set (pc)
3900: (match_operand:SI 0 "s_register_operand" "r"))
3901: (use (label_ref (match_operand 1 "" "")))]
3902: ""
3903: "*
3904: return arm_output_asm_insn (\"mov\\tpc, %0\\t@ table jump, label %l1\",
3905: operands);
3906: ")
3907:
3908: (define_insn ""
3909: [(set (pc)
3910: (match_operand:SI 0 "memory_operand" "m"))
3911: (use (label_ref (match_operand 1 "" "")))]
3912: ""
3913: "*
3914: return arm_output_asm_insn (\"ldr\\tpc, %0\\t@ table jump, label %l1\",
3915: operands);
3916: "
3917: [(set_attr "type" "load")])
3918:
3919: (define_insn "indirect_jump"
3920: [(set (pc)
3921: (match_operand:SI 0 "s_register_operand" "r"))]
3922: ""
3923: "*
3924: return arm_output_asm_insn (\"mov\\tpc, %0\\t@ indirect jump\", operands);
3925: ")
3926:
3927: (define_insn ""
3928: [(set (pc)
3929: (match_operand:SI 0 "memory_operand" "m"))]
3930: ""
3931: "*
3932: return arm_output_asm_insn (\"ldr\\tpc, %0\\t@ indirect jump\", operands);
3933: "
3934: [(set_attr "type" "load")])
3935:
3936: ;; Misc insns
3937:
3938: (define_insn "nop"
3939: [(const_int 0)]
3940: ""
3941: "*
3942: return arm_output_asm_insn (\"mov\\tr0, r0\\t@ nop\", operands);
3943: ")
3944:
3945: ;; Patterns to allow combination of arithmetic, cond code and shifts
3946:
3947: (define_insn ""
3948: [(set (match_operand:SI 0 "s_register_operand" "=r")
3949: (match_operator:SI 1 "shiftable_operator"
3950: [(match_operator:SI 3 "shift_operator"
3951: [(match_operand:SI 4 "s_register_operand" "r")
3952: (match_operand:SI 5 "nonmemory_operand" "rI")])
3953: (match_operand:SI 2 "s_register_operand" "r")]))]
3954: ""
3955: "*
3956: return (output_arithmetic_with_shift (operands, TRUE, FALSE));
3957: ")
3958:
3959: (define_insn ""
3960: [(set (reg:CC_NOOV 24)
3961: (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3962: [(match_operator:SI 3 "shift_operator"
3963: [(match_operand:SI 4 "s_register_operand" "r")
3964: (match_operand:SI 5 "nonmemory_operand" "rI")])
3965: (match_operand:SI 2 "s_register_operand" "r")])
3966: (const_int 0)))
3967: (set (match_operand:SI 0 "s_register_operand" "=r")
3968: (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
3969: (match_dup 2)]))]
3970: ""
3971: "*
3972: return (output_arithmetic_with_shift (operands, TRUE, TRUE));
3973: "
3974: [(set_attr "conds" "set")])
3975:
3976: (define_insn ""
3977: [(set (reg:CC_NOOV 24)
3978: (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3979: [(match_operator:SI 3 "shift_operator"
3980: [(match_operand:SI 4 "s_register_operand" "r")
3981: (match_operand:SI 5 "nonmemory_operand" "rI")])
3982: (match_operand:SI 2 "s_register_operand" "r")])
3983: (const_int 0)))
3984: (clobber (match_scratch:SI 0 "=r"))]
3985: ""
3986: "*
3987: return (output_arithmetic_with_shift (operands, TRUE, TRUE));
3988: "
3989: [(set_attr "conds" "set")])
3990:
3991: (define_insn ""
3992: [(set (match_operand:SI 0 "s_register_operand" "=r")
3993: (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3994: (match_operator:SI 2 "shift_operator"
3995: [(match_operand:SI 3 "s_register_operand" "r")
3996: (match_operand:SI 4 "nonmemory_operand" "rn")])))]
3997: ""
3998: "*
3999: {
4000: rtx ops[6];
4001:
4002: ops[0] = operands[0];
4003: ops[1] = gen_rtx (MINUS, SImode, operands[1], operands[2]);
4004: ops[2] = operands[1];
4005: ops[3] = operands[2];
4006: ops[4] = operands[3];
4007: ops[5] = operands[4];
4008: return output_arithmetic_with_shift (ops, FALSE, FALSE);
4009: }
4010: ")
4011:
4012: (define_insn ""
4013: [(set (reg:CC_NOOV 24)
4014: (compare:CC_NOOV (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4015: (match_operator:SI 2 "shift_operator"
4016: [(match_operand:SI 3 "s_register_operand" "r")
4017: (match_operand:SI 4 "nonmemory_operand" "rn")]))
4018: (const_int 0)))
4019: (set (match_operand:SI 0 "s_register_operand" "=r")
4020: (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4021: (match_dup 4)])))]
4022: ""
4023: "*
4024: {
4025: rtx ops[6];
4026:
4027: ops[0] = operands[0];
4028: ops[1] = gen_rtx (MINUS, SImode, operands[1], operands[2]);
4029: ops[2] = operands[1];
4030: ops[3] = operands[2];
4031: ops[4] = operands[3];
4032: ops[5] = operands[4];
4033: return output_arithmetic_with_shift (ops, FALSE, TRUE);
4034: }
4035: "
4036: [(set_attr "conds" "set")])
4037:
4038: (define_insn ""
4039: [(set (reg:CC_NOOV 24)
4040: (compare:CC_NOOV (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4041: (match_operator:SI 2 "shift_operator"
4042: [(match_operand:SI 3 "s_register_operand" "r")
4043: (match_operand:SI 4 "nonmemory_operand" "rn")]))
4044: (const_int 0)))
4045: (clobber (match_scratch:SI 0 "=r"))]
4046: ""
4047: "*
4048: {
4049: rtx ops[6];
4050:
4051: ops[0] = operands[0];
4052: ops[1] = gen_rtx (MINUS, SImode, operands[1], operands[2]);
4053: ops[2] = operands[1];
4054: ops[3] = operands[2];
4055: ops[4] = operands[3];
4056: ops[5] = operands[4];
4057: return output_arithmetic_with_shift (ops, FALSE, TRUE);
4058: }
4059: "
4060: [(set_attr "conds" "set")])
4061:
4062: ;; These variants of the above insns can occur if the first operand is the
4063: ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
4064: ;; seem to be a way around it. Most of the predicates have to be null
4065: ;; because the format can be generated part way through reload, so
4066: ;; if we don't match it as soon as it becomes available, reload doesn't know
4067: ;; how to reload pseudos that haven't got hard registers; the constraints will
4068: ;; sort everything out.
4069:
4070: (define_insn ""
4071: [(set (match_operand:SI 0 "" "=&r")
4072: (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4073: [(match_operand:SI 3 "" "r")
4074: (match_operand:SI 4 "" "rn")])
4075: (match_operand:SI 2 "" "r"))
4076: (match_operand:SI 1 "const_int_operand" "n")))]
4077: "reload_in_progress"
4078: "*
4079: {
4080: char instr[100];
4081: sprintf (instr, \"add\\t%%0, %%2, %%3, %s %%4\",
4082: shift_instr (GET_CODE (operands[5]), &operands[4]));
4083: arm_output_asm_insn (instr, operands);
4084: operands[2] = operands[1];
4085: operands[1] = operands[0];
4086: return output_add_immediate (operands);
4087: }"
4088: ; we have no idea how long the add_immediate is, it could be up to 4.
4089: [(set_attr "length" "5")])
4090:
4091: (define_insn ""
4092: [(set (reg:CC_NOOV 24)
4093: (compare:CC_NOOV (plus:SI
4094: (plus:SI
4095: (match_operator:SI 5 "shift_operator"
4096: [(match_operand:SI 3 "" "r")
4097: (match_operand:SI 4 "" "rn")])
4098: (match_operand:SI 1 "" "r"))
4099: (match_operand:SI 2 "const_int_operand" "n"))
4100: (const_int 0)))
4101: (set (match_operand:SI 0 "" "=&r")
4102: (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4103: (match_dup 1))
4104: (match_dup 2)))]
4105: "reload_in_progress"
4106: "*
4107: {
4108: char instr[100];
4109: sprintf (instr, \"adds\\t%%0, %%0, %%3, %s %%4\",
4110: shift_instr (GET_CODE (operands[5]), &operands[4]));
4111: output_add_immediate (operands);
4112: return arm_output_asm_insn (instr, operands);
4113: }"
4114: [(set_attr "conds" "set")
4115: (set_attr "length" "5")])
4116:
4117: (define_insn ""
4118: [(set (reg:CC_NOOV 24)
4119: (compare:CC_NOOV (plus:SI
4120: (plus:SI
4121: (match_operator:SI 5 "shift_operator"
4122: [(match_operand:SI 3 "" "r")
4123: (match_operand:SI 4 "" "rn")])
4124: (match_operand:SI 1 "" "r"))
4125: (match_operand:SI 2 "const_int_operand" "n"))
4126: (const_int 0)))
4127: (clobber (match_scratch:SI 0 "=&r"))]
4128: "reload_in_progress"
4129: "*
4130: {
4131: char instr[100];
4132: sprintf (instr, \"adds\\t%%0, %%0, %%3, %s %%4\",
4133: shift_instr (GET_CODE (operands[5]), &operands[4]));
4134: output_add_immediate (operands);
4135: return arm_output_asm_insn (instr, operands);
4136: }"
4137: [(set_attr "conds" "set")
4138: (set_attr "length" "5")])
4139:
4140: ;; These are similar, but are needed when the mla pattern contains the
4141: ;; eliminated register as operand 3.
4142:
4143: (define_insn ""
4144: [(set (match_operand:SI 0 "" "=&r,&r")
4145: (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4146: (match_operand:SI 2 "" "r,r"))
4147: (match_operand:SI 3 "" "r,r"))
4148: (match_operand:SI 4 "const_int_operand" "n,n")))]
4149: "reload_in_progress"
4150: "*
4151: arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands);
4152: operands[2] = operands[4];
4153: operands[1] = operands[0];
4154: return output_add_immediate (operands);
4155: "
4156: [(set_attr "length" "5")])
4157:
4158: (define_insn ""
4159: [(set (reg:CC_NOOV 24)
4160: (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4161: (match_operand:SI 3 "" "r")
4162: (match_operand:SI 4 "" "r"))
4163: (match_operand:SI 1 "" "r"))
4164: (match_operand:SI 2 "const_int_operand" "n"))
4165: (const_int 0)))
4166: (set (match_operand:SI 0 "" "=&r")
4167: (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4168: (match_dup 2)))]
4169: "reload_in_progress"
4170: "*
4171: output_add_immediate (operands);
4172: return arm_output_asm_insn (\"mlas\\t%0, %3, %4, %0\", operands);
4173: "
4174: [(set_attr "length" "5")
4175: (set_attr "conds" "set")])
4176:
4177: (define_insn ""
4178: [(set (reg:CC_NOOV 24)
4179: (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4180: (match_operand:SI 3 "" "r")
4181: (match_operand:SI 4 "" "r"))
4182: (match_operand:SI 1 "" "r"))
4183: (match_operand:SI 2 "const_int_operand" "n"))
4184: (const_int 0)))
4185: (clobber (match_scratch:SI 0 "=&r"))]
4186: "reload_in_progress"
4187: "*
4188: output_add_immediate (operands);
4189: return arm_output_asm_insn (\"mlas\\t%0, %3, %4, %0\", operands);
4190: "
4191: [(set_attr "length" "5")
4192: (set_attr "conds" "set")])
4193:
4194:
4195:
4196:
4197: (define_insn ""
4198: [(set (match_operand:SI 0 "s_register_operand" "=r")
4199: (and:SI (match_operator 1 "comparison_operator"
4200: [(reg 24) (const_int 0)])
4201: (match_operand:SI 2 "s_register_operand" "r")))]
4202: ""
4203: "*
4204: arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
4205: return arm_output_asm_insn (\"and%d1\\t%0, %2, #1\", operands);
4206: "
4207: [(set_attr "conds" "use")
4208: (set_attr "length" "2")])
4209:
4210: (define_insn ""
4211: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4212: (ior:SI (match_operator 2 "comparison_operator"
4213: [(reg 24) (const_int 0)])
4214: (match_operand:SI 1 "s_register_operand" "0,?r")))]
4215: ""
4216: "*
4217: if (which_alternative != 0)
4218: arm_output_asm_insn (\"mov%D2\\t%0, %1\", operands);
4219: return arm_output_asm_insn (\"orr%d2\\t%0, %1, #1\", operands);
4220: "
4221: [(set_attr "conds" "use")
4222: (set_attr "length" "1,2")])
4223:
4224: (define_insn ""
4225: [(set (match_operand:SI 0 "s_register_operand" "=r")
4226: (match_operator 1 "comparison_operator"
4227: [(match_operand:SI 2 "s_register_operand" "r")
4228: (match_operand:SI 3 "arm_add_operand" "rL")]))
4229: (clobber (reg 24))]
4230: ""
4231: "*
4232: if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4233: return arm_output_asm_insn (\"mov\\t%0, %2, lsr #31\", operands);
4234: if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4235: {
4236: arm_output_asm_insn (\"mvn\\t%0, %2\", operands);
4237: return arm_output_asm_insn (\"mov\\t%0, %0, lsr #31\", operands);
4238: }
4239: if (GET_CODE (operands[1]) == NE)
4240: {
4241: if (GET_CODE (operands[3]) == CONST_INT
4242: && !const_ok_for_arm (INTVAL (operands[3])))
4243: arm_output_asm_insn (\"adds\\t%0, %2, #%n3\", operands);
4244: else
4245: arm_output_asm_insn (\"subs\\t%0, %2, %3\", operands);
4246: return arm_output_asm_insn (\"movne\\t%0, #1\", operands);
4247: }
4248: if (GET_CODE (operands[3]) == CONST_INT
4249: && !const_ok_for_arm (INTVAL (operands[3])))
4250: arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4251: else
4252: arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4253: arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
4254: return arm_output_asm_insn (\"mov%d1\\t%0, #1\", operands);
4255: "
4256: [(set_attr "conds" "clob")
4257: (set_attr "length" "3")])
4258:
4259: (define_insn ""
4260: [(set (match_operand:SI 0 "s_register_operand" "=&r")
4261: (ior:SI (match_operator 1 "comparison_operator"
4262: [(match_operand:SI 2 "s_register_operand" "r")
4263: (match_operand:SI 3 "arm_rhs_operand" "rI")])
4264: (match_operator 4 "comparison_operator"
4265: [(match_operand:SI 5 "s_register_operand" "r")
4266: (match_operand:SI 6 "arm_rhs_operand" "rI")])))
4267: (clobber (reg 24))]
4268: ""
4269: "*
4270: {
4271: int dominant = comparison_dominates_p (GET_CODE (operands[4]),
4272: GET_CODE (operands[1]));
4273:
4274: arm_output_asm_insn (dominant ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
4275: operands);
4276: arm_output_asm_insn (\"mov\\t%0, #0\", operands);
4277: if (GET_CODE (operands[1]) == GET_CODE (operands[4])
4278: || comparison_dominates_p (GET_CODE (operands[1]),
4279: GET_CODE (operands[4]))
4280: || dominant)
4281: {
4282: arm_output_asm_insn (dominant ? \"cmp%D4\\t%2, %3\" : \"cmp%D1\\t%5,%6\",
4283: operands);
4284: }
4285: else
4286: {
4287: arm_output_asm_insn (\"mov%d1\\t%0, #1\", operands);
4288: arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
4289: }
4290: return arm_output_asm_insn (dominant ? \"mov%d1\\t%0, #1\"
4291: : \"mov%d4\\t%0, #1\", operands);
4292: }
4293: "
4294: [(set_attr "conds" "clob")
4295: ; worst case length
4296: (set_attr "length" "5")])
4297:
4298: (define_split
4299: [(set (pc)
4300: (if_then_else (match_operator 5 "equality_operator"
4301: [(ior:SI (match_operator 6 "comparison_operator"
4302: [(match_operand:SI 0 "s_register_operand" "r")
4303: (match_operand:SI 1 "arm_add_operand" "rL")])
4304: (match_operator 7 "comparison_operator"
4305: [(match_operand:SI 2 "s_register_operand" "r")
4306: (match_operand:SI 3 "arm_add_operand" "rL")]))
4307: (const_int 0)])
4308: (label_ref (match_operand 4 "" ""))
4309: (pc)))
4310: (clobber (reg 24))]
4311: "(GET_CODE (operands[6]) == GET_CODE (operands[7])
4312: || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[7]))
4313: || comparison_dominates_p (GET_CODE (operands[7]), GET_CODE (operands[6])))"
4314: [(set (reg:CC 24)
4315: (compare:CC (ior:CC (match_op_dup 6
4316: [(match_dup 0) (match_dup 1)])
4317: (match_op_dup 7
4318: [(match_dup 2) (match_dup 3)]))
4319: (const_int 0)))
4320: (set (pc)
4321: (if_then_else (match_op_dup 5 [(reg:CC 24) (const_int 0)])
4322: (label_ref (match_dup 4))
4323: (pc)))]
4324: "
4325: {
4326: enum rtx_code code = comparison_dominates_p (GET_CODE (operands[6]),
4327: GET_CODE (operands[7]))
4328: ? GET_CODE (operands[7]) : GET_CODE (operands[6]);
4329:
4330: if (GET_CODE (operands[5]) == NE)
4331: operands[5] = gen_rtx (code, CCmode,
4332: XEXP (operands[5], 0), XEXP (operands[5], 1));
4333: else
4334: operands[5] = gen_rtx (reverse_condition (code), CCmode,
4335: XEXP (operands[5], 0), XEXP (operands[5], 1));
4336: }
4337: ")
4338:
4339: ;; Don't match these patterns if we can use a conditional compare, since they
4340: ;; tell the final prescan branch elimator code that full branch inlining
4341: ;; can't be done.
4342:
4343: (define_insn ""
4344: [(set (pc)
4345: (if_then_else (ne
4346: (ior:SI (match_operator 5 "comparison_operator"
4347: [(match_operand:SI 0 "s_register_operand" "r")
4348: (match_operand:SI 1 "arm_add_operand" "rL")])
4349: (match_operator 6 "comparison_operator"
4350: [(match_operand:SI 2 "s_register_operand" "r")
4351: (match_operand:SI 3 "arm_rhs_operand" "rL")]))
4352: (const_int 0))
4353: (label_ref (match_operand 4 "" ""))
4354: (pc)))
4355: (clobber (reg 24))]
4356: "!(GET_CODE (operands[5]) == GET_CODE (operands[6])
4357: || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[6]))
4358: || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[5])))"
4359: "*
4360: {
4361: extern int arm_ccfsm_state;
4362:
4363: if (GET_CODE (operands[1]) == CONST_INT
4364: && !const_ok_for_arm (INTVAL (operands[1])))
4365: arm_output_asm_insn (\"cmn\\t%0, #%n1\", operands);
4366: else
4367: arm_output_asm_insn (\"cmp\\t%0, %1\", operands);
4368: arm_output_asm_insn (\"b%d5\\t%l4\", operands);
4369: if (GET_CODE (operands[3]) == CONST_INT
4370: && !const_ok_for_arm (INTVAL (operands[3])))
4371: arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4372: else
4373: arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4374: if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4375: {
4376: arm_ccfsm_state += 2;
4377: return \"\";
4378: }
4379: return arm_output_asm_insn (\"b%d6\\t%l4\", operands);
4380: }"
4381: [(set_attr "conds" "jump_clob")
4382: (set_attr "length" "4")])
4383:
4384: (define_insn ""
4385: [(set (reg:CC 24)
4386: (compare:CC (ior:CC (match_operator 4 "comparison_operator"
4387: [(match_operand:SI 0 "s_register_operand" "r")
4388: (match_operand:SI 1 "arm_add_operand" "rL")])
4389: (match_operator 5 "comparison_operator"
4390: [(match_operand:SI 2 "s_register_operand" "r")
4391: (match_operand:SI 3 "arm_add_operand" "rL")]))
4392: (const_int 0)))]
4393: "(GET_CODE (operands[4]) == GET_CODE (operands[5])
4394: || comparison_dominates_p (GET_CODE (operands[4]), GET_CODE (operands[5]))
4395: || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))"
4396: "*
4397: if (comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))
4398: {
4399: if (GET_CODE (operands[3]) == CONST_INT
4400: && !const_ok_for_arm (INTVAL (operands[3])))
4401: arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4402: else
4403: arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4404: if (GET_CODE (operands[1]) == CONST_INT
4405: && !const_ok_for_arm (INTVAL (operands[1])))
4406: return arm_output_asm_insn (\"cmn%D5\\t%0, #%n1\", operands);
4407: return arm_output_asm_insn (\"cmp%D5\\t%0, %1\", operands);
4408: }
4409: if (GET_CODE (operands[1]) == CONST_INT
4410: && !const_ok_for_arm (INTVAL (operands[1])))
4411: arm_output_asm_insn (\"cmn\\t%0, #%n1\", operands);
4412: else
4413: arm_output_asm_insn (\"cmp\\t%0, %1\", operands);
4414: if (GET_CODE (operands[3]) == CONST_INT
4415: && !const_ok_for_arm (INTVAL (operands[3])))
4416: return arm_output_asm_insn (\"cmn%D4\\t%2, #%n3\", operands);
4417: return arm_output_asm_insn (\"cmp%D4\\t%2, %3\", operands);
4418: "
4419: [(set_attr "conds" "set")
4420: (set_attr "length" "2")])
4421:
4422: (define_insn ""
4423: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4424: (if_then_else (match_operator 3 "equality_operator"
4425: [(match_operator 4 "comparison_operator"
4426: [(reg 24) (const_int 0)])
4427: (const_int 0)])
4428: (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4429: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4430: ""
4431: "*
4432: if (GET_CODE (operands[3]) == NE)
4433: {
4434: if (which_alternative != 0)
4435: arm_output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4436: if (which_alternative != 1)
4437: arm_output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4438: return \"\";
4439: }
4440: if (which_alternative != 0)
4441: arm_output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4442: if (which_alternative != 1)
4443: arm_output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4444: return \"\";
4445: "
4446: [(set_attr "conds" "use")
4447: (set_attr "length" "1,1,2")])
4448:
4449: (define_insn ""
4450: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4451: (match_operator:SI 5 "shiftable_operator"
4452: [(match_operator:SI 4 "comparison_operator"
4453: [(match_operand:SI 2 "s_register_operand" "r,r")
4454: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4455: (match_operand:SI 1 "s_register_operand" "0,?r")]))
4456: (clobber (reg 24))]
4457: ""
4458: "*
4459: {
4460: char *instr = arithmetic_instr (operands[5], TRUE);
4461: char pattern[100];
4462:
4463: if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4464: {
4465: sprintf (pattern, \"%s\\t%%0, %%1, %%2, lsr #31\", instr);
4466: return arm_output_asm_insn (pattern, operands);
4467: }
4468: arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4469: if (GET_CODE (operands[5]) == AND)
4470: arm_output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4471: else if (which_alternative != 0)
4472: arm_output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4473: sprintf (pattern, \"%s%%d4\\t%%0, %%1, #1\", instr);
4474: return arm_output_asm_insn (pattern, operands);
4475: }
4476: "
4477: [(set_attr "conds" "clob")
4478: (set_attr "length" "3")])
4479:
4480: (define_insn ""
4481: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4482: (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4483: (match_operator:SI 4 "comparison_operator"
4484: [(match_operand:SI 2 "s_register_operand" "r,r")
4485: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4486: (clobber (reg 24))]
4487: ""
4488: "*
4489: arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4490: if (which_alternative != 0)
4491: arm_output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4492: return arm_output_asm_insn (\"sub%d4\\t%0, %1, #1\", operands);
4493: "
4494: [(set_attr "conds" "clob")
4495: (set_attr "length" "2,3")])
4496:
4497: (define_insn ""
4498: [(set (match_operand:SI 0 "s_register_operand" "=&r")
4499: (and:SI (match_operator 1 "comparison_operator"
4500: [(match_operand:SI 2 "s_register_operand" "r")
4501: (match_operand:SI 3 "arm_rhs_operand" "rI")])
4502: (match_operator 4 "comparison_operator"
4503: [(match_operand:SI 5 "s_register_operand" "r")
4504: (match_operand:SI 6 "arm_rhs_operand" "rI")])))
4505: (clobber (reg 24))]
4506: ""
4507: "*
4508: {
4509: int dominant =
4510: comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4511: reverse_condition (GET_CODE (operands[4])))
4512: ? 1
4513: : comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4514: reverse_condition (GET_CODE (operands[1])))
4515: ? 2 : 0;
4516: arm_output_asm_insn (dominant == 2 ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
4517: operands);
4518: arm_output_asm_insn (\"mov\\t%0, #1\", operands);
4519: if (GET_CODE (operands[1]) == GET_CODE (operands[4]) || dominant)
4520: {
4521: arm_output_asm_insn (dominant == 2 ? \"cmp%d4\\t%2, %3\"
4522: : \"cmp%d1\\t%5, %6\", operands);
4523: }
4524: else
4525: {
4526: arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
4527: arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
4528: }
4529: return arm_output_asm_insn (dominant == 2 ? \"mov%D1\\t%0, #0\"
4530: : \"mov%D4\\t%0, #0\", operands);
4531: }
4532: "
4533: [(set_attr "conds" "clob")
4534: (set_attr "length" "5")])
4535:
4536: (define_split
4537: [(set (pc)
4538: (if_then_else (match_operator 1 "equality_operator"
4539: [(and:SI (match_operator 2 "comparison_operator"
4540: [(match_operand:SI 3 "s_register_operand" "r")
4541: (match_operand:SI 4 "arm_add_operand" "rL")])
4542: (match_operator 0 "comparison_operator"
4543: [(match_operand:SI 5 "s_register_operand" "r")
4544: (match_operand:SI 6 "arm_add_operand" "rL")]))
4545: (const_int 0)])
4546: (label_ref (match_operand 7 "" ""))
4547: (pc)))
4548: (clobber (reg 24))]
4549: "(GET_CODE (operands[2]) == GET_CODE (operands[0])
4550: || comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4551: reverse_condition (GET_CODE (operands[0])))
4552: || comparison_dominates_p (reverse_condition (GET_CODE (operands[0])),
4553: reverse_condition (GET_CODE (operands[2]))))"
4554: [(set (reg:CC 24)
4555: (compare:CC (ior:CC (match_op_dup 2
4556: [(match_dup 3) (match_dup 4)])
4557: (match_op_dup 0
4558: [(match_dup 5) (match_dup 6)]))
4559: (const_int 0)))
4560: (set (pc)
4561: (if_then_else (match_op_dup 1 [(reg:CC 24) (const_int 0)])
4562: (label_ref (match_dup 7))
4563: (pc)))]
4564: "
4565: {
4566: /* Use DeMorgans law to convert this into an IOR of the inverse conditions
4567: This is safe since we only do it for integer comparisons. */
4568: enum rtx_code code =
4569: comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4570: reverse_condition (GET_CODE (operands[0])))
4571: ? GET_CODE (operands[0]) : GET_CODE (operands[2]);
4572:
4573: operands[2] = gen_rtx (reverse_condition (GET_CODE (operands[2])),
4574: GET_MODE (operands[2]), operands[3], operands[4]);
4575: operands[0] = gen_rtx (reverse_condition (GET_CODE (operands[0])),
4576: GET_MODE (operands[0]), operands[5], operands[6]);
4577: if (GET_CODE (operands[1]) == NE)
4578: operands[1] = gen_rtx (code, CCmode,
4579: XEXP (operands[1], 0), XEXP (operands[1], 1));
4580: else
4581: operands[1] = gen_rtx (reverse_condition (code), CCmode,
4582: XEXP (operands[1], 0), XEXP (operands[1], 1));
4583: }
4584: ")
4585:
4586: ;; Don't match these patterns if we can use a conditional compare, since they
4587: ;; tell the final prescan branch elimator code that full branch inlining
4588: ;; can't be done.
4589:
4590: (define_insn ""
4591: [(set (pc)
4592: (if_then_else (eq
4593: (and:SI (match_operator 1 "comparison_operator"
4594: [(match_operand:SI 2 "s_register_operand" "r")
4595: (match_operand:SI 3 "arm_add_operand" "rL")])
4596: (match_operator 4 "comparison_operator"
4597: [(match_operand:SI 5 "s_register_operand" "r")
4598: (match_operand:SI 6 "arm_rhs_operand" "rL")]))
4599: (const_int 0))
4600: (label_ref (match_operand 0 "" ""))
4601: (pc)))
4602: (clobber (reg 24))]
4603: "!(GET_CODE (operands[1]) == GET_CODE (operands[4])
4604: || comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4605: reverse_condition (GET_CODE (operands[4])))
4606: || comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4607: reverse_condition (GET_CODE (operands[1]))))"
4608: "*
4609: {
4610: extern int arm_ccfsm_state;
4611:
4612: if (GET_CODE (operands[3]) == CONST_INT
4613: && !const_ok_for_arm (INTVAL (operands[3])))
4614: arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4615: else
4616: arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4617: arm_output_asm_insn (\"b%D1\\t%l0\", operands);
4618: if (GET_CODE (operands[6]) == CONST_INT
4619: && !const_ok_for_arm (INTVAL (operands[6])))
4620: arm_output_asm_insn (\"cmn\\t%5, #%n6\", operands);
4621: else
4622: arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
4623: if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4624: {
4625: arm_ccfsm_state += 2;
4626: return \"\";
4627: }
4628: return arm_output_asm_insn (\"b%D4\\t%l0\", operands);
4629: }"
4630: [(set_attr "conds" "jump_clob")
4631: (set_attr "length" "4")])
4632:
4633: (define_insn ""
4634: [(set (match_operand:SI 0 "s_register_operand" "=r")
4635: (neg:SI (match_operator 3 "comparison_operator"
4636: [(match_operand:SI 1 "s_register_operand" "r")
4637: (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4638: (clobber (reg 24))]
4639: ""
4640: "*
4641: if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4642: return arm_output_asm_insn (\"mov\\t%0, %1, asr #31\", operands);
4643: if (GET_CODE (operands[3]) == NE)
4644: {
4645: arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
4646: return arm_output_asm_insn (\"mvnne\\t%0, #0\", operands);
4647: }
4648: if (GET_CODE (operands[3]) == GT)
4649: {
4650: arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
4651: return arm_output_asm_insn (\"mvnne\\t%0, %0, asr #31\", operands);
4652: }
4653: arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
4654: arm_output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4655: return arm_output_asm_insn (\"mvn%d3\\t%0, #0\", operands);
4656: "
4657: [(set_attr "conds" "clob")
4658: (set_attr "length" "3")])
4659:
4660: (define_insn "movcond"
4661: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4662: (if_then_else:SI (match_operator 5 "comparison_operator"
4663: [(match_operand:SI 3 "s_register_operand" "r,r,r")
4664: (match_operand:SI 4 "arm_add_operand" "rL,rL,rL")])
4665: (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4666: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4667: (clobber (reg 24))]
4668: ""
4669: "*
4670: if (GET_CODE (operands[5]) == LT
4671: && (operands[4] == const0_rtx))
4672: {
4673: if (which_alternative != 1 && GET_CODE (operands[4]) == REG)
4674: {
4675: arm_output_asm_insn (\"ands\\t%0, %1, %3, asr #32\", operands);
4676: if (operands[2] == const0_rtx)
4677: return \"\";
4678: return arm_output_asm_insn (\"movcc\\t%0, %2\", operands);
4679: }
4680: else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4681: {
4682: arm_output_asm_insn (\"bics\\t%0, %2, %3, asr #32\", operands);
4683: if (operands[1] == const0_rtx)
4684: return \"\";
4685: return arm_output_asm_insn (\"movcs\\t%0, %1\", operands);
4686: }
4687: /* The only case that falls through to here is when both ops 1 & 2
4688: are constants */
4689: }
4690: if (GET_CODE (operands[5]) == GE
4691: && (operands[4] == const0_rtx))
4692: {
4693: if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4694: {
4695: arm_output_asm_insn (\"bics\\t%0, %1, %3, asr #32\", operands);
4696: if (operands[2] == const0_rtx)
4697: return \"\";
4698: return arm_output_asm_insn (\"movcs\\t%0, %2\", operands);
4699: }
4700: else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4701: {
4702: arm_output_asm_insn (\"ands\\t%0, %2, %3, asr #32\", operands);
4703: if (operands[1] == const0_rtx)
4704: return \"\";
4705: return arm_output_asm_insn (\"movcc\\t%0, %1\", operands);
4706: }
4707: /* The only case that falls through to here is when both ops 1 & 2
4708: are constants */
4709: }
4710: if (GET_CODE (operands[4]) == CONST_INT
4711: && !const_ok_for_arm (INTVAL (operands[4])))
4712: arm_output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4713: else
4714: arm_output_asm_insn (\"cmp\\t%3, %4\", operands);
4715: if (which_alternative != 0)
4716: arm_output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4717: if (which_alternative != 1)
4718: arm_output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4719: return \"\";
4720: "
4721: [(set_attr "conds" "clob")
4722: (set_attr "length" "2,2,3")])
4723:
4724: (define_insn ""
4725: [(set (match_operand:SI 0 "s_register_operand" "=r")
4726: (if_then_else:SI (match_operator 9 "comparison_operator"
4727: [(match_operand:SI 5 "s_register_operand" "r")
4728: (match_operand:SI 6 "arm_add_operand" "rL")])
4729: (match_operator:SI 8 "shiftable_operator"
4730: [(match_operand:SI 1 "s_register_operand" "r")
4731: (match_operand:SI 2 "arm_rhs_operand" "rI")])
4732: (match_operator:SI 7 "shiftable_operator"
4733: [(match_operand:SI 3 "s_register_operand" "r")
4734: (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4735: (clobber (reg 24))]
4736: ""
4737: "*
4738: {
4739: char pattern[100];
4740:
4741: if (GET_CODE (operands[6]) == CONST_INT
4742: && !const_ok_for_arm (INTVAL (operands[6])))
4743: arm_output_asm_insn (\"cmn\\t%5, #%n6\", operands);
4744: else
4745: arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
4746: sprintf (pattern, \"%s%%d9\\t%%0, %%1, %%2\", arithmetic_instr (operands[8],
4747: FALSE));
4748: arm_output_asm_insn (pattern, operands);
4749: sprintf (pattern, \"%s%%D9\\t%%0, %%3, %%4\", arithmetic_instr (operands[7],
4750: FALSE));
4751: return arm_output_asm_insn (pattern, operands);
4752: }
4753: "
4754: [(set_attr "conds" "clob")
4755: (set_attr "length" "3")])
4756:
4757: (define_insn ""
4758: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4759: (if_then_else:SI (match_operator 6 "comparison_operator"
4760: [(match_operand:SI 2 "s_register_operand" "r,r")
4761: (match_operand:SI 3 "arm_add_operand" "rL,rL")])
4762: (match_operator:SI 7 "shiftable_operator"
4763: [(match_operand:SI 4 "s_register_operand" "r,r")
4764: (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4765: (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4766: (clobber (reg 24))]
4767: ""
4768: "*
4769: {
4770: char pattern[100];
4771:
4772: /* If we have an operation where (op x 0) is the identity operation and
4773: the condtional operator is LT or GE and we are comparing against zero and
4774: everything is in registers then we can do this in two instructions */
4775: if (operands[3] == const0_rtx
4776: && GET_CODE (operands[7]) != AND
4777: && GET_CODE (operands[5]) == REG
4778: && GET_CODE (operands[1]) == REG
4779: && REGNO (operands[1]) == REGNO (operands[4])
4780: && REGNO (operands[4]) != REGNO (operands[0]))
4781: {
4782: if (GET_CODE (operands[6]) == LT)
4783: {
4784: arm_output_asm_insn (\"and\\t%0, %5, %2, asr #31\", operands);
4785: sprintf (pattern, \"%s\\t%%0, %%4, %%0\",
4786: arithmetic_instr (operands[7], FALSE));
4787: return arm_output_asm_insn (pattern, operands);
4788: }
4789: else if (GET_CODE (operands[6]) == GE)
4790: {
4791: arm_output_asm_insn (\"bic\\t%0, %5, %2, asr #31\", operands);
4792: sprintf (pattern, \"%s\\t%%0, %%4, %%0\",
4793: arithmetic_instr (operands[7], FALSE));
4794: return arm_output_asm_insn (pattern, operands);
4795: }
4796: }
4797: if (GET_CODE (operands[3]) == CONST_INT
4798: && !const_ok_for_arm (INTVAL (operands[3])))
4799: arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4800: else
4801: arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4802: sprintf (pattern, \"%s%%d6\\t%%0, %%4, %%5\", arithmetic_instr (operands[7],
4803: FALSE));
4804: arm_output_asm_insn (pattern, operands);
4805: if (which_alternative != 0)
4806: {
4807: if (GET_CODE (operands[1]) == MEM)
4808: arm_output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4809: else
4810: arm_output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4811: }
4812: return \"\";
4813: }
4814: "
4815: [(set_attr "conds" "clob")
4816: (set_attr "length" "2,3")])
4817:
4818: (define_insn ""
4819: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4820: (if_then_else:SI (match_operator 6 "comparison_operator"
4821: [(match_operand:SI 4 "s_register_operand" "r,r")
4822: (match_operand:SI 5 "arm_add_operand" "rL,rL")])
4823: (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4824: (match_operator:SI 7 "shiftable_operator"
4825: [(match_operand:SI 2 "s_register_operand" "r,r")
4826: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4827: (clobber (reg 24))]
4828: ""
4829: "*
4830: {
4831: char pattern[100];
4832:
4833: /* If we have an operation where (op x 0) is the identity operation and
4834: the condtional operator is LT or GE and we are comparing against zero and
4835: everything is in registers then we can do this in two instructions */
4836: if (operands[5] == const0_rtx
4837: && GET_CODE (operands[7]) != AND
4838: && GET_CODE (operands[3]) == REG
4839: && GET_CODE (operands[1]) == REG
4840: && REGNO (operands[1]) == REGNO (operands[2])
4841: && REGNO (operands[2]) != REGNO (operands[0]))
4842: {
4843: if (GET_CODE (operands[6]) == GE)
4844: {
4845: arm_output_asm_insn (\"and\\t%0, %3, %4, asr #31\", operands);
4846: sprintf (pattern, \"%s\\t%%0, %%2, %%0\",
4847: arithmetic_instr (operands[7], FALSE));
4848: return arm_output_asm_insn (pattern, operands);
4849: }
4850: else if (GET_CODE (operands[6]) == LT)
4851: {
4852: arm_output_asm_insn (\"bic\\t%0, %3, %4, asr #31\", operands);
4853: sprintf (pattern, \"%s\\t%%0, %%2, %%0\",
4854: arithmetic_instr (operands[7], FALSE));
4855: return arm_output_asm_insn (pattern, operands);
4856: }
4857: }
4858: if (GET_CODE (operands[5]) == CONST_INT
4859: && !const_ok_for_arm (INTVAL (operands[5])))
4860: arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4861: else
4862: arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
4863: if (which_alternative != 0)
4864: {
4865: if (GET_CODE (operands[1]) == MEM)
4866: arm_output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4867: else
4868: arm_output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4869: }
4870: sprintf (pattern, \"%s%%D6\\t%%0, %%2, %%3\", arithmetic_instr (operands[7],
4871: FALSE));
4872: return arm_output_asm_insn (pattern, operands);
4873: }
4874: "
4875: [(set_attr "conds" "clob")
4876: (set_attr "length" "2,3")])
4877:
4878: (define_insn ""
4879: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4880: (if_then_else:SI (match_operator 6 "comparison_operator"
4881: [(match_operand:SI 4 "s_register_operand" "r,r")
4882: (match_operand:SI 5 "arm_add_operand" "rL,rL")])
4883: (plus:SI
4884: (match_operand:SI 2 "s_register_operand" "r,r")
4885: (match_operand:SI 3 "arm_add_operand" "rL,rL"))
4886: (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4887: (clobber (reg 24))]
4888: ""
4889: "*
4890: {
4891: if (GET_CODE (operands[5]) == CONST_INT
4892: && !const_ok_for_arm (INTVAL (operands[5])))
4893: arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4894: else
4895: arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
4896: if (GET_CODE (operands[3]) == CONST_INT
4897: && !const_ok_for_arm (INTVAL (operands[3])))
4898: arm_output_asm_insn (\"sub%d6\\t%0, %2, #%n3\", operands);
4899: else
4900: arm_output_asm_insn (\"add%d6\\t%0, %2, %3\", operands);
4901: if (which_alternative != 0)
4902: {
4903: if (GET_CODE (operands[1]) == MEM)
4904: arm_output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4905: else
4906: arm_output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4907: }
4908: return \"\";
4909: }
4910: "
4911: [(set_attr "conds" "clob")
4912: (set_attr "length" "2,3")])
4913:
4914: (define_insn ""
4915: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4916: (if_then_else:SI (match_operator 6 "comparison_operator"
4917: [(match_operand:SI 4 "s_register_operand" "r,r")
4918: (match_operand:SI 5 "arm_add_operand" "rL,rL")])
4919: (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4920: (plus:SI
4921: (match_operand:SI 2 "s_register_operand" "r,r")
4922: (match_operand:SI 3 "arm_add_operand" "rL,rL"))))
4923: (clobber (reg 24))]
4924: ""
4925: "*
4926: {
4927: if (GET_CODE (operands[5]) == CONST_INT
4928: && !const_ok_for_arm (INTVAL (operands[5])))
4929: arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4930: else
4931: arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
4932: if (GET_CODE (operands[3]) == CONST_INT
4933: && !const_ok_for_arm (INTVAL (operands[3])))
4934: arm_output_asm_insn (\"sub%D6\\t%0, %2, #%n3\", operands);
4935: else
4936: arm_output_asm_insn (\"add%D6\\t%0, %2, %3\", operands);
4937: if (which_alternative != 0)
4938: {
4939: if (GET_CODE (operands[6]) == MEM)
4940: arm_output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4941: else
4942: arm_output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4943: }
4944: return \"\";
4945: }
4946: "
4947: [(set_attr "conds" "clob")
4948: (set_attr "length" "2,3")])
4949:
4950: (define_insn ""
4951: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4952: (if_then_else:SI (match_operator 5 "comparison_operator"
4953: [(match_operand:SI 3 "s_register_operand" "r,r")
4954: (match_operand:SI 4 "arm_add_operand" "rL,rL")])
4955: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4956: (not:SI
4957: (match_operand:SI 2 "s_register_operand" "r,r"))))
4958: (clobber (reg 24))]
4959: ""
4960: "#"
4961: [(set_attr "conds" "clob")
4962: (set_attr "length" "2,3")])
4963:
4964: ;; if (GET_CODE (operands[3]) == CONST_INT
4965: ;; && !const_ok_for_arm (INTVAL (operands[3])))
4966: ;; arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4967: ;; else
4968: ;; arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4969: ;; if (which_alternative != 0)
4970: ;; arm_output_asm_insn (\"mov%d1\\t%0, %4\", operands);
4971: ;; return arm_output_asm_insn (\"mvn%D1\\t%0, %5\", operands);
4972:
4973: (define_insn ""
4974: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4975: (if_then_else:SI (match_operator 5 "comparison_operator"
4976: [(match_operand:SI 3 "s_register_operand" "r,r")
4977: (match_operand:SI 4 "arm_add_operand" "rL,rL")])
4978: (not:SI
4979: (match_operand:SI 2 "s_register_operand" "r,r"))
4980: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4981: (clobber (reg 24))]
4982: ""
4983: "*
4984: {
4985: char pattern[100];
4986:
4987: if (GET_CODE (operands[30]) == CONST_INT
4988: && !const_ok_for_arm (INTVAL (operands[4])))
4989: arm_output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4990: else
4991: arm_output_asm_insn (\"cmp\\t%3, %4\", operands);
4992: if (which_alternative != 0)
4993: arm_output_asm_insn (\"mov%D5\\t%0, %1\", operands);
4994: return arm_output_asm_insn (\"mvn%d5\\t%0, %2\", operands);
4995:
4996: }
4997: "
4998: [(set_attr "conds" "clob")
4999: (set_attr "length" "2,3")])
5000:
5001: (define_insn ""
5002: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5003: (if_then_else:SI (match_operator 6 "comparison_operator"
5004: [(match_operand:SI 4 "s_register_operand" "r,r")
5005: (match_operand:SI 5 "arm_add_operand" "rL,rL")])
5006: (match_operator:SI 7 "shift_operator"
5007: [(match_operand:SI 2 "s_register_operand" "r,r")
5008: (match_operand:SI 3 "arm_rhs_operand" "rn,rn")])
5009: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5010: (clobber (reg 24))]
5011: ""
5012: "*
5013: {
5014: char pattern[100];
5015:
5016: if (GET_CODE (operands[5]) == CONST_INT
5017: && !const_ok_for_arm (INTVAL (operands[5])))
5018: arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5019: else
5020: arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
5021: if (which_alternative != 0)
5022: arm_output_asm_insn (\"mov%D6\\t%0, %1\", operands);
5023: sprintf (pattern, \"mov%%d6\\t%%0, %%2, %s %%3\",
5024: shift_instr (GET_CODE (operands[7]), &operands[3]));
5025: return arm_output_asm_insn (pattern, operands);
5026: }
5027: "
5028: [(set_attr "conds" "clob")
5029: (set_attr "length" "2,3")])
5030:
5031: (define_insn ""
5032: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5033: (if_then_else:SI (match_operator 6 "comparison_operator"
5034: [(match_operand:SI 4 "s_register_operand" "r,r")
5035: (match_operand:SI 5 "arm_add_operand" "rL,rL")])
5036: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5037: (match_operator:SI 7 "shift_operator"
5038: [(match_operand:SI 2 "s_register_operand" "r,r")
5039: (match_operand:SI 3 "arm_rhs_operand" "rn,rn")])))
5040: (clobber (reg 24))]
5041: ""
5042: "*
5043: {
5044: char pattern[100];
5045:
5046: if (GET_CODE (operands[5]) == CONST_INT
5047: && !const_ok_for_arm (INTVAL (operands[5])))
5048: arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5049: else
5050: arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
5051: if (which_alternative != 0)
5052: arm_output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5053: sprintf (pattern, \"mov%%D6\\t%%0, %%2, %s %%3\",
5054: shift_instr (GET_CODE (operands[7]), &operands[3]));
5055: return arm_output_asm_insn (pattern, operands);
5056: }
5057: "
5058: [(set_attr "conds" "clob")
5059: (set_attr "length" "2,3")])
5060:
5061: (define_insn ""
5062: [(set (match_operand:SI 0 "s_register_operand" "=r")
5063: (if_then_else:SI (match_operator 7 "comparison_operator"
5064: [(match_operand:SI 5 "s_register_operand" "r")
5065: (match_operand:SI 6 "arm_add_operand" "rL")])
5066: (match_operator:SI 8 "shift_operator"
5067: [(match_operand:SI 1 "s_register_operand" "r")
5068: (match_operand:SI 2 "arm_rhs_operand" "rn")])
5069: (match_operator:SI 9 "shift_operator"
5070: [(match_operand:SI 3 "s_register_operand" "r")
5071: (match_operand:SI 4 "arm_rhs_operand" "rI")])))
5072: (clobber (reg 24))]
5073: ""
5074: "*
5075: {
5076: char pattern[100];
5077:
5078: if (GET_CODE (operands[6]) == CONST_INT
5079: && !const_ok_for_arm (INTVAL (operands[6])))
5080: arm_output_asm_insn (\"cmn\\t%5, #%n6\", operands);
5081: else
5082: arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
5083: sprintf (pattern, \"mov%%d7\\t%%0, %%1, %s %%2\",
5084: shift_instr (GET_CODE (operands[8]), &operands[2]));
5085: arm_output_asm_insn (pattern, operands);
5086: sprintf (pattern, \"mov%%D7\\t%%0, %%3, %s %%4\",
5087: shift_instr (GET_CODE (operands[9]), &operands[4]));
5088: return arm_output_asm_insn (pattern, operands);
5089: }
5090: "
5091: [(set_attr "conds" "clob")
5092: (set_attr "length" "3")])
5093:
5094: (define_insn ""
5095: [(set (match_operand:SI 0 "s_register_operand" "=r")
5096: (if_then_else:SI (match_operator 6 "comparison_operator"
5097: [(match_operand:SI 4 "s_register_operand" "r")
5098: (match_operand:SI 5 "arm_add_operand" "rL")])
5099: (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5100: (match_operator:SI 7 "shiftable_operator"
5101: [(match_operand:SI 2 "s_register_operand" "r")
5102: (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5103: (clobber (reg 24))]
5104: ""
5105: "*
5106: {
5107: char pattern[100];
5108:
5109: if (GET_CODE (operands[5]) == CONST_INT
5110: && !const_ok_for_arm (INTVAL (operands[5])))
5111: arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5112: else
5113: arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
5114: arm_output_asm_insn (\"mvn%d6\\t%0, %1\", operands);
5115: sprintf (pattern, \"%s%%D6\\t%%0, %%2, %%3\", arithmetic_instr (operands[7],
5116: FALSE));
5117: return arm_output_asm_insn (pattern, operands);
5118: }
5119: "
5120: [(set_attr "conds" "clob")
5121: (set_attr "length" "3")])
5122:
5123: (define_insn ""
5124: [(set (match_operand:SI 0 "s_register_operand" "=r")
5125: (if_then_else:SI (match_operator 6 "comparison_operator"
5126: [(match_operand:SI 4 "s_register_operand" "r")
5127: (match_operand:SI 5 "arm_add_operand" "rL")])
5128: (match_operator:SI 7 "shiftable_operator"
5129: [(match_operand:SI 2 "s_register_operand" "r")
5130: (match_operand:SI 3 "arm_rhs_operand" "rI")])
5131: (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5132: (clobber (reg 24))]
5133: ""
5134: "*
5135: {
5136: char pattern[100];
5137:
5138: if (GET_CODE (operands[5]) == CONST_INT
5139: && !const_ok_for_arm (INTVAL (operands[5])))
5140: arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5141: else
5142: arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
5143: arm_output_asm_insn (\"mvn%D6\\t%0, %1\", operands);
5144: sprintf (pattern, \"%s%%d6\\t%%0, %%2, %%3\", arithmetic_instr (operands[7],
5145: FALSE));
5146: return arm_output_asm_insn (pattern, operands);
5147: }
5148: "
5149: [(set_attr "conds" "clob")
5150: (set_attr "length" "3")])
5151:
5152: (define_insn ""
5153: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5154: (if_then_else:SI (match_operator 5 "comparison_operator"
5155: [(match_operand:SI 3 "s_register_operand" "r,r")
5156: (match_operand:SI 4 "arm_add_operand" "rL,rL")])
5157: (neg:SI
5158: (match_operand:SI 2 "s_register_operand" "r,r"))
5159: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5160: (clobber (reg:CC 24))]
5161: ""
5162: "*
5163: if (GET_CODE (operands[4]) == CONST_INT
5164: && !const_ok_for_arm (INTVAL (operands[4])))
5165: arm_output_asm_insn (\"cmn\\t%3, #%n4\", operands);
5166: else
5167: arm_output_asm_insn (\"cmp\\t%3, %4\", operands);
5168: if (which_alternative != 0)
5169: arm_output_asm_insn (\"mov%D5\\t%0, %1\", operands);
5170: return arm_output_asm_insn (\"rsb%d5\\t%0, %2, #0\", operands);
5171: "
5172: [(set_attr "conds" "clob")
5173: (set_attr "length" "2,3")])
5174:
5175: (define_insn ""
5176: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5177: (if_then_else:SI (match_operator 5 "comparison_operator"
5178: [(match_operand:SI 3 "s_register_operand" "r,r")
5179: (match_operand:SI 4 "arm_add_operand" "rL,rL")])
5180: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5181: (neg:SI
5182: (match_operand:SI 2 "s_register_operand" "r,r"))))
5183: (clobber (reg:CC 24))]
5184: ""
5185: "*
5186: if (GET_CODE (operands[4]) == CONST_INT
5187: && !const_ok_for_arm (INTVAL (operands[4])))
5188: arm_output_asm_insn (\"cmn\\t%3, #%n4\", operands);
5189: else
5190: arm_output_asm_insn (\"cmp\\t%3, %4\", operands);
5191: if (which_alternative != 0)
5192: arm_output_asm_insn (\"mov%d5\\t%0, %1\", operands);
5193: return arm_output_asm_insn (\"rsb%D5\\t%0, %2, #0\", operands);
5194: "
5195: [(set_attr "conds" "clob")
5196: (set_attr "length" "2,3")])
5197:
5198: (define_insn ""
5199: [(set (match_operand:SI 0 "s_register_operand" "=r")
5200: (match_operator:SI 1 "shiftable_operator"
5201: [(match_operand:SI 2 "memory_operand" "m")
5202: (match_operand:SI 3 "memory_operand" "m")]))
5203: (clobber (match_scratch:SI 4 "=r"))]
5204: "adjacent_mem_locations (operands[2], operands[3])"
5205: "*
5206: {
5207: rtx ldm[3];
5208: rtx arith[3];
5209: char pattern[100];
5210: int val1 = 0, val2 = 0;
5211:
5212: sprintf (pattern, \"%s\\t%%0, %%1, %%2\",
5213: arithmetic_instr (operands[1], FALSE));
5214: if (REGNO (operands[0]) > REGNO (operands[4]))
5215: {
5216: ldm[1] = operands[4];
5217: ldm[2] = operands[0];
5218: }
5219: else
5220: {
5221: ldm[1] = operands[0];
5222: ldm[2] = operands[4];
5223: }
5224: if (GET_CODE (XEXP (operands[2], 0)) != REG)
5225: val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5226: if (GET_CODE (XEXP (operands[3], 0)) != REG)
5227: val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5228: arith[0] = operands[0];
5229: if (val1 < val2)
5230: {
5231: arith[1] = ldm[1];
5232: arith[2] = ldm[2];
5233: }
5234: else
5235: {
5236: arith[1] = ldm[2];
5237: arith[2] = ldm[1];
5238: }
5239: if (val1 && val2)
5240: {
5241: rtx ops[3];
5242: ldm[0] = ops[0] = operands[4];
5243: ops[1] = XEXP (XEXP (operands[2], 0), 0);
5244: ops[2] = XEXP (XEXP (operands[2], 0), 1);
5245: output_add_immediate (ops);
5246: if (val1 < val2)
5247: arm_output_asm_insn (\"ldmia\\t%0, {%1, %2}\", ldm);
5248: else
5249: arm_output_asm_insn (\"ldmda\\t%0, {%1, %2}\", ldm);
5250: }
5251: else if (val1)
5252: {
5253: ldm[0] = XEXP (operands[3], 0);
5254: if (val1 < val2)
5255: arm_output_asm_insn (\"ldmda\\t%0, {%1, %2}\", ldm);
5256: else
5257: arm_output_asm_insn (\"ldmia\\t%0, {%1, %2}\", ldm);
5258: }
5259: else
5260: {
5261: ldm[0] = XEXP (operands[2], 0);
5262: if (val1 < val2)
5263: arm_output_asm_insn (\"ldmia\\t%0, {%1, %2}\", ldm);
5264: else
5265: arm_output_asm_insn (\"ldmda\\t%0, {%1, %2}\", ldm);
5266: }
5267: return arm_output_asm_insn (pattern, arith);
5268: }
5269: "
5270: [(set_attr "length" "3")
5271: (set_attr "type" "load")])
5272:
5273: ;; the arm can support extended pre-inc instructions
5274:
5275: ;; In all these cases, we use operands 0 and 1 for the register being
5276: ;; incremented because those are the operands that local-alloc will
5277: ;; tie and these are the pair most likely to be tieable (and the ones
5278: ;; that will benefit the most).
5279:
5280: ;; We reject the frame pointer if it occurs anywhere in these patterns since
5281: ;; elimination will cause too many headaches.
5282:
5283: (define_insn ""
5284: [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5285: (match_operand:SI 2 "index_operand" "rJ")))
5286: (match_operand:QI 3 "s_register_operand" "r"))
5287: (set (match_operand:SI 0 "s_register_operand" "=r")
5288: (plus:SI (match_dup 1) (match_dup 2)))]
5289: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5290: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5291: && (GET_CODE (operands[2]) != REG
5292: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5293: "*
5294: return arm_output_asm_insn (\"strb\\t%3, [%0, %2]!\", operands);
5295: "
5296: [(set_attr "type" "store1")])
5297:
5298: (define_insn ""
5299: [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5300: (match_operand:SI 2 "s_register_operand" "r")))
5301: (match_operand:QI 3 "s_register_operand" "r"))
5302: (set (match_operand:SI 0 "s_register_operand" "=r")
5303: (minus:SI (match_dup 1) (match_dup 2)))]
5304: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5305: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5306: && (GET_CODE (operands[2]) != REG
5307: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5308: "*
5309: return arm_output_asm_insn (\"strb\\t%3, [%0, -%2]!\", operands);
5310: "
5311: [(set_attr "type" "store1")])
5312:
5313: (define_insn ""
5314: [(set (match_operand:QI 3 "s_register_operand" "=r")
5315: (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5316: (match_operand:SI 2 "index_operand" "rJ"))))
5317: (set (match_operand:SI 0 "s_register_operand" "=r")
5318: (plus:SI (match_dup 1) (match_dup 2)))]
5319: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5320: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5321: && (GET_CODE (operands[2]) != REG
5322: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5323: "*
5324: return arm_output_asm_insn (\"ldrb\\t%3, [%0, %2]!\", operands);
5325: "
5326: [(set_attr "type" "load")])
5327:
5328: (define_insn ""
5329: [(set (match_operand:QI 3 "s_register_operand" "=r")
5330: (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5331: (match_operand:SI 2 "s_register_operand" "r"))))
5332: (set (match_operand:SI 0 "s_register_operand" "=r")
5333: (minus:SI (match_dup 1) (match_dup 2)))]
5334: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5335: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5336: && (GET_CODE (operands[2]) != REG
5337: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5338: "*
5339: return arm_output_asm_insn (\"ldrb\\t%3, [%0, -%2]!\", operands);
5340: "
5341: [(set_attr "type" "load")])
5342:
5343: (define_insn ""
5344: [(set (match_operand:SI 3 "s_register_operand" "=r")
5345: (zero_extend:SI
5346: (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5347: (match_operand:SI 2 "index_operand" "rJ")))))
5348: (set (match_operand:SI 0 "s_register_operand" "=r")
5349: (plus:SI (match_dup 1) (match_dup 2)))]
5350: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5351: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5352: && (GET_CODE (operands[2]) != REG
5353: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5354: "*
5355: return arm_output_asm_insn (\"ldrb\\t%3, [%0, %2]!\\t@ z_extendqisi\",
5356: operands);
5357: "
5358: [(set_attr "type" "load")])
5359:
5360: (define_insn ""
5361: [(set (match_operand:SI 3 "s_register_operand" "=r")
5362: (zero_extend:SI
5363: (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5364: (match_operand:SI 2 "s_register_operand" "r")))))
5365: (set (match_operand:SI 0 "s_register_operand" "=r")
5366: (minus:SI (match_dup 1) (match_dup 2)))]
5367: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5368: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5369: && (GET_CODE (operands[2]) != REG
5370: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5371: "*
5372: return arm_output_asm_insn (\"ldrb\\t%3, [%0, -%2]!\\t@ z_extendqisi\",
5373: operands);
5374: "
5375: [(set_attr "type" "load")])
5376:
5377: (define_insn ""
5378: [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5379: (match_operand:SI 2 "index_operand" "rJ")))
5380: (match_operand:SI 3 "s_register_operand" "r"))
5381: (set (match_operand:SI 0 "s_register_operand" "=r")
5382: (plus:SI (match_dup 1) (match_dup 2)))]
5383: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5384: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5385: && (GET_CODE (operands[2]) != REG
5386: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5387: "*
5388: return arm_output_asm_insn (\"str\\t%3, [%0, %2]!\", operands);
5389: "
5390: [(set_attr "type" "store1")])
5391:
5392: (define_insn ""
5393: [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5394: (match_operand:SI 2 "s_register_operand" "r")))
5395: (match_operand:SI 3 "s_register_operand" "r"))
5396: (set (match_operand:SI 0 "s_register_operand" "=r")
5397: (minus:SI (match_dup 1) (match_dup 2)))]
5398: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5399: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5400: && (GET_CODE (operands[2]) != REG
5401: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5402: "*
5403: return arm_output_asm_insn (\"str\\t%3, [%0, -%2]!\", operands);
5404: "
5405: [(set_attr "type" "store1")])
5406:
5407: (define_insn ""
5408: [(set (match_operand:SI 3 "s_register_operand" "=r")
5409: (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5410: (match_operand:SI 2 "index_operand" "rJ"))))
5411: (set (match_operand:SI 0 "s_register_operand" "=r")
5412: (plus:SI (match_dup 1) (match_dup 2)))]
5413: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5414: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5415: && (GET_CODE (operands[2]) != REG
5416: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5417: "*
5418: return arm_output_asm_insn (\"ldr\\t%3, [%0, %2]!\", operands);
5419: "
5420: [(set_attr "type" "load")])
5421:
5422: (define_insn ""
5423: [(set (match_operand:SI 3 "s_register_operand" "=r")
5424: (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5425: (match_operand:SI 2 "s_register_operand" "r"))))
5426: (set (match_operand:SI 0 "s_register_operand" "=r")
5427: (minus:SI (match_dup 1) (match_dup 2)))]
5428: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5429: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5430: && (GET_CODE (operands[2]) != REG
5431: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5432: "*
5433: return arm_output_asm_insn (\"ldr\\t%3, [%0, -%2]!\", operands);
5434: "
5435: [(set_attr "type" "load")])
5436:
5437: (define_insn ""
5438: [(set (match_operand:HI 3 "s_register_operand" "=r")
5439: (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5440: (match_operand:SI 2 "index_operand" "rJ"))))
5441: (set (match_operand:SI 0 "s_register_operand" "=r")
5442: (plus:SI (match_dup 1) (match_dup 2)))]
5443: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5444: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5445: && (GET_CODE (operands[2]) != REG
5446: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5447: "*
5448: return arm_output_asm_insn (\"ldr\\t%3, [%0, %2]!\\t@ loadhi\", operands);
5449: "
5450: [(set_attr "type" "load")])
5451:
5452: (define_insn ""
5453: [(set (match_operand:HI 3 "s_register_operand" "=r")
5454: (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5455: (match_operand:SI 2 "s_register_operand" "r"))))
5456: (set (match_operand:SI 0 "s_register_operand" "=r")
5457: (minus:SI (match_dup 1) (match_dup 2)))]
5458: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5459: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5460: && (GET_CODE (operands[2]) != REG
5461: || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5462: "*
5463: return arm_output_asm_insn (\"ldr\\t%3, [%0, -%2]!\\t@ loadhi\", operands);
5464: "
5465: [(set_attr "type" "load")])
5466:
5467: (define_insn ""
5468: [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5469: [(match_operand:SI 3 "s_register_operand" "r")
5470: (match_operand:SI 4 "const_shift_operand" "n")])
5471: (match_operand:SI 1 "s_register_operand" "0")))
5472: (match_operand:QI 5 "s_register_operand" "r"))
5473: (set (match_operand:SI 0 "s_register_operand" "=r")
5474: (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5475: (match_dup 1)))]
5476: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5477: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5478: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5479: "*
5480: {
5481: char instr[100];
5482:
5483: sprintf (instr, \"strb\\t%%5, [%%0, %%3, %s %%4]!\",
5484: shift_instr (GET_CODE (operands[2]), &operands[4]));
5485: return arm_output_asm_insn (instr, operands);
5486: }
5487: "
5488: [(set_attr "type" "store1")])
5489:
5490: (define_insn ""
5491: [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5492: (match_operator:SI 2 "shift_operator"
5493: [(match_operand:SI 3 "s_register_operand" "r")
5494: (match_operand:SI 4 "const_shift_operand" "n")])))
5495: (match_operand:QI 5 "s_register_operand" "r"))
5496: (set (match_operand:SI 0 "s_register_operand" "=r")
5497: (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5498: (match_dup 4)])))]
5499: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5500: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5501: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5502: "*
5503: {
5504: char instr[100];
5505:
5506: sprintf (instr, \"strb\\t%%5, [%%0, -%%3, %s %%4]!\",
5507: shift_instr (GET_CODE (operands[2]), &operands[4]));
5508: return arm_output_asm_insn (instr, operands);
5509: }
5510: "
5511: [(set_attr "type" "store1")])
5512:
5513: (define_insn ""
5514: [(set (match_operand:QI 5 "s_register_operand" "=r")
5515: (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5516: [(match_operand:SI 3 "s_register_operand" "r")
5517: (match_operand:SI 4 "const_shift_operand" "n")])
5518: (match_operand:SI 1 "s_register_operand" "0"))))
5519: (set (match_operand:SI 0 "s_register_operand" "=r")
5520: (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5521: (match_dup 1)))]
5522: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5523: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5524: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5525: "*
5526: {
5527: char instr[100];
5528:
5529: sprintf (instr, \"ldrb\\t%%5, [%%0, %%3, %s %%4]!\",
5530: shift_instr (GET_CODE (operands[2]), &operands[4]));
5531: return arm_output_asm_insn (instr, operands);
5532: }
5533: "
5534: [(set_attr "type" "load")])
5535:
5536: (define_insn ""
5537: [(set (match_operand:QI 5 "s_register_operand" "=r")
5538: (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5539: (match_operator:SI 2 "shift_operator"
5540: [(match_operand:SI 3 "s_register_operand" "r")
5541: (match_operand:SI 4 "const_shift_operand" "n")]))))
5542: (set (match_operand:SI 0 "s_register_operand" "=r")
5543: (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5544: (match_dup 4)])))]
5545: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5546: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5547: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5548: "*
5549: {
5550: char instr[100];
5551:
5552: sprintf (instr, \"ldrb\\t%%5, [%%0, -%%3, %s %%4]!\",
5553: shift_instr (GET_CODE (operands[2]), &operands[4]));
5554: return arm_output_asm_insn (instr, operands);
5555: }
5556: "
5557: [(set_attr "type" "load")])
5558:
5559: (define_insn ""
5560: [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5561: [(match_operand:SI 3 "s_register_operand" "r")
5562: (match_operand:SI 4 "const_shift_operand" "n")])
5563: (match_operand:SI 1 "s_register_operand" "0")))
5564: (match_operand:SI 5 "s_register_operand" "r"))
5565: (set (match_operand:SI 0 "s_register_operand" "=r")
5566: (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5567: (match_dup 1)))]
5568: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5569: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5570: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5571: "*
5572: {
5573: char instr[100];
5574:
5575: sprintf (instr, \"str\\t%%5, [%%0, %%3, %s %%4]!\",
5576: shift_instr (GET_CODE (operands[2]), &operands[4]));
5577: return arm_output_asm_insn (instr, operands);
5578: }
5579: "
5580: [(set_attr "type" "store1")])
5581:
5582: (define_insn ""
5583: [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5584: (match_operator:SI 2 "shift_operator"
5585: [(match_operand:SI 3 "s_register_operand" "r")
5586: (match_operand:SI 4 "const_shift_operand" "n")])))
5587: (match_operand:SI 5 "s_register_operand" "r"))
5588: (set (match_operand:SI 0 "s_register_operand" "=r")
5589: (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5590: (match_dup 4)])))]
5591: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5592: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5593: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5594: "*
5595: {
5596: char instr[100];
5597:
5598: sprintf (instr, \"str\\t%%5, [%%0, -%%3, %s %%4]!\",
5599: shift_instr (GET_CODE (operands[2]), &operands[4]));
5600: return arm_output_asm_insn (instr, operands);
5601: }
5602: "
5603: [(set_attr "type" "store1")])
5604:
5605: (define_insn ""
5606: [(set (match_operand:SI 5 "s_register_operand" "=r")
5607: (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5608: [(match_operand:SI 3 "s_register_operand" "r")
5609: (match_operand:SI 4 "const_shift_operand" "n")])
5610: (match_operand:SI 1 "s_register_operand" "0"))))
5611: (set (match_operand:SI 0 "s_register_operand" "=r")
5612: (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5613: (match_dup 1)))]
5614: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5615: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5616: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5617: "*
5618: {
5619: char instr[100];
5620:
5621: sprintf (instr, \"ldr\\t%%5, [%%0, %%3, %s %%4]!\",
5622: shift_instr (GET_CODE (operands[2]), &operands[4]));
5623: return arm_output_asm_insn (instr, operands);
5624: }
5625: "
5626: [(set_attr "type" "load")])
5627:
5628: (define_insn ""
5629: [(set (match_operand:SI 5 "s_register_operand" "=r")
5630: (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5631: (match_operator:SI 2 "shift_operator"
5632: [(match_operand:SI 3 "s_register_operand" "r")
5633: (match_operand:SI 4 "const_shift_operand" "n")]))))
5634: (set (match_operand:SI 0 "s_register_operand" "=r")
5635: (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5636: (match_dup 4)])))]
5637: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5638: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5639: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5640: "*
5641: {
5642: char instr[100];
5643:
5644: sprintf (instr, \"ldr\\t%%5, [%%0, -%%3, %s %%4]!\",
5645: shift_instr (GET_CODE (operands[2]), &operands[4]));
5646: return arm_output_asm_insn (instr, operands);
5647: }
5648: "
5649: [(set_attr "type" "load")])
5650:
5651: (define_insn ""
5652: [(set (match_operand:HI 5 "s_register_operand" "=r")
5653: (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5654: [(match_operand:SI 3 "s_register_operand" "r")
5655: (match_operand:SI 4 "const_shift_operand" "n")])
5656: (match_operand:SI 1 "s_register_operand" "0"))))
5657: (set (match_operand:SI 0 "s_register_operand" "=r")
5658: (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5659: (match_dup 1)))]
5660: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5661: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5662: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5663: "*
5664: {
5665: char instr[100];
5666:
5667: sprintf (instr, \"ldr\\t%%5, [%%0, %%3, %s %%4]!\\t@ loadhi\",
5668: shift_instr (GET_CODE (operands[2]), &operands[4]));
5669: return arm_output_asm_insn (instr, operands);
5670: }
5671: "
5672: [(set_attr "type" "load")])
5673:
5674: (define_insn ""
5675: [(set (match_operand:HI 5 "s_register_operand" "=r")
5676: (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5677: (match_operator:SI 2 "shift_operator"
5678: [(match_operand:SI 3 "s_register_operand" "r")
5679: (match_operand:SI 4 "const_shift_operand" "n")]))))
5680: (set (match_operand:SI 0 "s_register_operand" "=r")
5681: (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5682: (match_dup 4)])))]
5683: "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5684: && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5685: && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5686: "*
5687: {
5688: char instr[100];
5689:
5690: sprintf (instr, \"ldr\\t%%5, [%%0, -%%3, %s %%4]!\\t@ loadhi\",
5691: shift_instr (GET_CODE (operands[2]), &operands[4]));
5692: return arm_output_asm_insn (instr, operands);
5693: }
5694: "
5695: [(set_attr "type" "load")])
5696:
5697: ; It can also support extended post-inc expressions, but combine doesn't
5698: ; try these....
5699: ; It doesn't seem worth adding peepholes for anything but the most common
5700: ; cases since, unlike combine, the increment must immediately follow the load
5701: ; for this pattern to match.
5702: ; When loading we must watch to see that the base register isn't trampled by
5703: ; the load. In such cases this isn't a post-inc expression.
5704:
5705: (define_peephole
5706: [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5707: (match_operand:QI 2 "s_register_operand" "r"))
5708: (set (match_dup 0)
5709: (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5710: ""
5711: "*
5712: return arm_output_asm_insn (\"strb\\t%2, [%0], %1\", operands);
5713: ")
5714:
5715: (define_peephole
5716: [(set (match_operand:QI 0 "s_register_operand" "=r")
5717: (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5718: (set (match_dup 1)
5719: (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5720: "REGNO(operands[0]) != REGNO(operands[1])
5721: && (GET_CODE (operands[2]) != REG
5722: || REGNO(operands[0]) != REGNO (operands[2]))"
5723: "*
5724: return arm_output_asm_insn (\"ldrb\\t%0, [%1], %2\", operands);
5725: ")
5726:
5727: (define_peephole
5728: [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5729: (match_operand:SI 2 "s_register_operand" "r"))
5730: (set (match_dup 0)
5731: (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5732: ""
5733: "*
5734: return arm_output_asm_insn (\"str\\t%2, [%0], %1\", operands);
5735: ")
5736:
5737: (define_peephole
5738: [(set (match_operand:HI 0 "s_register_operand" "=r")
5739: (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5740: (set (match_dup 1)
5741: (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5742: "REGNO(operands[0]) != REGNO(operands[1])
5743: && (GET_CODE (operands[2]) != REG
5744: || REGNO(operands[0]) != REGNO (operands[2]))"
5745: "*
5746: return arm_output_asm_insn (\"ldr\\t%0, [%1], %2\\t@ loadhi\", operands);
5747: ")
5748:
5749: (define_peephole
5750: [(set (match_operand:SI 0 "s_register_operand" "=r")
5751: (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5752: (set (match_dup 1)
5753: (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5754: "REGNO(operands[0]) != REGNO(operands[1])
5755: && (GET_CODE (operands[2]) != REG
5756: || REGNO(operands[0]) != REGNO (operands[2]))"
5757: "*
5758: return arm_output_asm_insn (\"ldr\\t%0, [%1], %2\", operands);
5759: ")
5760:
5761: ; This pattern is never tried by combine, so do it as a peephole
5762:
5763: (define_peephole
5764: [(set (match_operand:SI 0 "s_register_operand" "=r")
5765: (match_operand:SI 1 "s_register_operand" "r"))
5766: (set (match_operand 2 "cc_register" "")
5767: (compare (match_dup 1) (const_int 0)))]
5768: ""
5769: "*
5770: return arm_output_asm_insn (\"subs\\t%0, %1, #0\", operands);
5771: "
5772: [(set_attr "conds" "set")])
5773:
5774: ; Peepholes to spot possible load- and store-multiples, if the ordering is
5775: ; reversed, check that the memory references aren't volatile.
5776:
5777: (define_peephole
5778: [(set (match_operand:SI 0 "s_register_operand" "=r")
5779: (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5780: (const_int 12))))
5781: (set (match_operand:SI 2 "s_register_operand" "=r")
5782: (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5783: (set (match_operand:SI 3 "s_register_operand" "=r")
5784: (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5785: (set (match_operand:SI 4 "s_register_operand" "=r")
5786: (mem:SI (match_dup 1)))]
5787: "REGNO (operands[0]) > REGNO (operands[2])
5788: && REGNO (operands[2]) > REGNO (operands[3])
5789: && REGNO (operands[3]) > REGNO (operands[4])
5790: && !(REGNO (operands[1]) == REGNO (operands[0])
5791: || REGNO (operands[1]) == REGNO (operands[2])
5792: || REGNO (operands[1]) == REGNO (operands[3])
5793: || REGNO (operands[1]) == REGNO (operands[4]))
5794: && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5795: && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5796: && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5797: (prev_nonnote_insn (insn)))))
5798: && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5799: (prev_nonnote_insn
5800: (prev_nonnote_insn (insn))))))"
5801: "*
5802: return arm_output_asm_insn (\"ldmia\\t%1, {%4, %3, %2, %0}\\t@ phole ldm\",
5803: operands);
5804: ")
5805:
5806: (define_peephole
5807: [(set (match_operand:SI 0 "s_register_operand" "=r")
5808: (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5809: (const_int 8))))
5810: (set (match_operand:SI 2 "s_register_operand" "=r")
5811: (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5812: (set (match_operand:SI 3 "s_register_operand" "=r")
5813: (mem:SI (match_dup 1)))]
5814: "REGNO (operands[0]) > REGNO (operands[2])
5815: && REGNO (operands[2]) > REGNO (operands[3])
5816: && !(REGNO (operands[1]) == REGNO (operands[0])
5817: || REGNO (operands[1]) == REGNO (operands[2])
5818: || REGNO (operands[1]) == REGNO (operands[3]))
5819: && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5820: && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5821: && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5822: (prev_nonnote_insn (insn)))))"
5823: "*
5824: return arm_output_asm_insn (\"ldmia\\t%1, {%3, %2, %0}\\t@ phole ldm\",
5825: operands);
5826: ")
5827:
5828: (define_peephole
5829: [(set (match_operand:SI 0 "s_register_operand" "=r")
5830: (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5831: (const_int 4))))
5832: (set (match_operand:SI 2 "s_register_operand" "=r")
5833: (mem:SI (match_dup 1)))]
5834: "REGNO (operands[0]) > REGNO (operands[2])
5835: && !(REGNO (operands[1]) == REGNO (operands[0])
5836: || REGNO (operands[1]) == REGNO (operands[2]))
5837: && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5838: && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))"
5839: "*
5840: return arm_output_asm_insn (\"ldmia\\t%1, {%2, %0}\\t@ phole ldm\",
5841: operands);
5842: ")
5843:
5844: (define_peephole
5845: [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5846: (const_int 12)))
5847: (match_operand:SI 0 "s_register_operand" "r"))
5848: (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5849: (match_operand:SI 2 "s_register_operand" "r"))
5850: (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5851: (match_operand:SI 3 "s_register_operand" "r"))
5852: (set (mem:SI (match_dup 1))
5853: (match_operand:SI 4 "s_register_operand" "r"))]
5854: "REGNO (operands[0]) > REGNO (operands[2])
5855: && REGNO (operands[2]) > REGNO (operands[3])
5856: && REGNO (operands[3]) > REGNO (operands[4])
5857: && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5858: && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5859: && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5860: (prev_nonnote_insn (insn)))))
5861: && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5862: (prev_nonnote_insn
5863: (prev_nonnote_insn (insn))))))"
5864: "*
5865: return arm_output_asm_insn (\"stmia\\t%1, {%4, %3, %2, %0}\\t@ phole stm\",
5866: operands);
5867: ")
5868:
5869: (define_peephole
5870: [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5871: (const_int 8)))
5872: (match_operand:SI 0 "s_register_operand" "r"))
5873: (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5874: (match_operand:SI 2 "s_register_operand" "r"))
5875: (set (mem:SI (match_dup 1))
5876: (match_operand:SI 3 "s_register_operand" "r"))]
5877: "REGNO (operands[0]) > REGNO (operands[2])
5878: && REGNO (operands[2]) > REGNO (operands[3])
5879: && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5880: && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5881: && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5882: (prev_nonnote_insn (insn)))))"
5883: "*
5884: return arm_output_asm_insn (\"stmia\\t%1, {%3, %2, %0}\\t@ phole stm\",
5885: operands);
5886: ")
5887:
5888: (define_peephole
5889: [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5890: (const_int 4)))
5891: (match_operand:SI 0 "s_register_operand" "r"))
5892: (set (mem:SI (match_dup 1))
5893: (match_operand:SI 2 "s_register_operand" "r"))]
5894: "REGNO (operands[0]) > REGNO (operands[2])
5895: && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5896: && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))"
5897: "*
5898: return arm_output_asm_insn (\"stmia\\t%1, {%2, %0}\\t@ phole stm\",
5899: operands);
5900: ")
5901:
5902: ;; A call followed by return can be replaced by restoring the regs and
5903: ;; jumping to the subroutine, provided we aren't passing the address of
5904: ;; any of our local variables. If we call alloca then this is unsafe
5905: ;; since restoring the frame frees the memory, which is not what we want.
5906: ;; Sometimes the return might have been targeted by the final prescan:
5907: ;; if so then emit a propper return insn as well.
5908: ;; Unfortunately, if the frame pointer is required, we don't know if the
5909: ;; current function has any implicit stack pointer adjustments that will
5910: ;; be restored by the return: we can't therefore do a tail call.
5911: ;; Another unfortunate that we can't handle is if current_function_args_size
5912: ;; is non-zero: in this case elimination of the argument pointer assumed
5913: ;; that lr was pushed onto the stack, so eliminating upsets the offset
5914: ;; calculations.
5915:
5916: (define_peephole
5917: [(parallel [(call (mem:SI (match_operand:SI 0 "" "i"))
5918: (match_operand:SI 1 "general_operand" "g"))
5919: (clobber (reg:SI 14))])
5920: (return)]
5921: "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5922: && !get_frame_size () && !current_function_calls_alloca
5923: && !frame_pointer_needed && !current_function_args_size)"
5924: "*
5925: {
5926: extern rtx arm_target_insn;
5927: extern int arm_ccfsm_state, arm_current_cc;
5928:
5929: if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5930: {
5931: arm_current_cc ^= 1;
5932: output_return_instruction (NULL, TRUE);
5933: arm_ccfsm_state = 0;
5934: arm_target_insn = NULL;
5935: }
5936:
5937: output_return_instruction (NULL, FALSE);
5938: return (arm_output_asm_insn (\"b\\t%a0\", operands));
5939: }"
5940: [(set (attr "conds")
5941: (if_then_else (eq_attr "cpu" "arm6")
5942: (const_string "clob")
5943: (const_string "nocond")))
5944: (set_attr "length" "2")])
5945:
5946: (define_peephole
5947: [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5948: (call (mem:SI (match_operand:SI 1 "" "i"))
5949: (match_operand:SI 2 "general_operand" "g")))
5950: (clobber (reg:SI 14))])
5951: (return)]
5952: "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5953: && !get_frame_size () && !current_function_calls_alloca
5954: && !frame_pointer_needed && !current_function_args_size)"
5955: "*
5956: {
5957: extern rtx arm_target_insn;
5958: extern int arm_ccfsm_state, arm_current_cc;
5959:
5960: if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5961: {
5962: arm_current_cc ^= 1;
5963: output_return_instruction (NULL, TRUE);
5964: arm_ccfsm_state = 0;
5965: arm_target_insn = NULL;
5966: }
5967:
5968: output_return_instruction (NULL, FALSE);
5969: return (arm_output_asm_insn (\"b\\t%a1\", operands));
5970: }"
5971: [(set (attr "conds")
5972: (if_then_else (eq_attr "cpu" "arm6")
5973: (const_string "clob")
5974: (const_string "nocond")))
5975: (set_attr "length" "2")])
5976:
5977: ;; As above but when this function is not void, we must be returning the
5978: ;; result of the called subroutine.
5979:
5980: (define_peephole
5981: [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5982: (call (mem:SI (match_operand:SI 1 "" "i"))
5983: (match_operand:SI 2 "general_operand" "g")))
5984: (clobber (reg:SI 14))])
5985: (use (match_dup 0))
5986: (return)]
5987: "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5988: && !get_frame_size () && !current_function_calls_alloca
5989: && !frame_pointer_needed && !current_function_args_size)"
5990: "*
5991: {
5992: extern rtx arm_target_insn;
5993: extern int arm_ccfsm_state, arm_current_cc;
5994:
5995: if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5996: {
5997: arm_current_cc ^= 1;
5998: output_return_instruction (NULL, TRUE);
5999: arm_ccfsm_state = 0;
6000: arm_target_insn = NULL;
6001: }
6002:
6003: output_return_instruction (NULL, FALSE);
6004: return (arm_output_asm_insn (\"b\\t%a1\", operands));
6005: }"
6006: [(set (attr "conds")
6007: (if_then_else (eq_attr "cpu" "arm6")
6008: (const_string "clob")
6009: (const_string "nocond")))
6010: (set_attr "length" "2")])
6011:
6012: ;; If calling a subroutine and then jumping back to somewhere else, but not
6013: ;; too far away, then we can set the link register with the branch address
6014: ;; and jump direct to the subroutine. On return from the subroutine
6015: ;; execution continues at the branch; this avoids a prefetch stall.
6016: ;; We use the length attribute (via short_branch ()) to establish whether or
6017: ;; not this is possible, this is the same asthe sparc does.
6018:
6019: (define_peephole
6020: [(parallel[(call (mem:SI (match_operand:SI 0 "" "i"))
6021: (match_operand:SI 1 "general_operand" "g"))
6022: (clobber (reg:SI 14))])
6023: (set (pc)
6024: (label_ref (match_operand 2 "" "")))]
6025: "GET_CODE (operands[0]) == SYMBOL_REF
6026: && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
6027: && arm_insn_not_targeted (insn)"
6028: "*
6029: {
6030: int backward = arm_backwards_branch (INSN_UID (insn),
6031: INSN_UID (operands[2]));
6032:
6033: #if 0
6034: /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
6035: * above, leaving it out means that the code will still run on an arm 2 or 3
6036: */
6037: if (TARGET_6)
6038: {
6039: if (backward)
6040: arm_output_asm_insn (\"sub\\tlr, pc, #(8 + . -%l2)\", operands);
6041: else
6042: arm_output_asm_insn (\"add\\tlr, pc, #(%l2 - . -8)\", operands);
6043: }
6044: else
6045: #endif
6046: {
6047: arm_output_asm_insn (\"mov\\tlr, pc\\t@ protect cc\");
6048: if (backward)
6049: arm_output_asm_insn (\"sub\\tlr, lr, #(4 + . -%l2)\", operands);
6050: else
6051: arm_output_asm_insn (\"add\\tlr, lr, #(%l2 - . -4)\", operands);
6052: }
6053: return arm_output_asm_insn (\"b\\t%a0\", operands);
6054: }"
6055: [(set (attr "conds")
6056: (if_then_else (eq_attr "cpu" "arm6")
6057: (const_string "clob")
6058: (const_string "nocond")))
6059: (set (attr "length")
6060: (if_then_else (eq_attr "cpu" "arm6")
6061: (const_int 2)
6062: (const_int 3)))])
6063:
6064: (define_peephole
6065: [(parallel[(set (match_operand:SI 0 "s_register_operand" "=r")
6066: (call (mem:SI (match_operand:SI 1 "" "i"))
6067: (match_operand:SI 2 "general_operand" "g")))
6068: (clobber (reg:SI 14))])
6069: (set (pc)
6070: (label_ref (match_operand 3 "" "")))]
6071: "GET_CODE (operands[0]) == SYMBOL_REF
6072: && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
6073: && arm_insn_not_targeted (insn)"
6074: "*
6075: {
6076: int backward = arm_backwards_branch (INSN_UID (insn),
6077: INSN_UID (operands[3]));
6078:
6079: #if 0
6080: /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
6081: * above, leaving it out means that the code will still run on an arm 2 or 3
6082: */
6083: if (TARGET_6)
6084: {
6085: if (backward)
6086: arm_output_asm_insn (\"sub\\tlr, pc, #(8 + . -%l3)\", operands);
6087: else
6088: arm_output_asm_insn (\"add\\tlr, pc, #(%l3 - . -8)\", operands);
6089: }
6090: else
6091: #endif
6092: {
6093: arm_output_asm_insn (\"mov\\tlr, pc\\t@ protect cc\");
6094: if (backward)
6095: arm_output_asm_insn (\"sub\\tlr, lr, #(4 + . -%l3)\", operands);
6096: else
6097: arm_output_asm_insn (\"add\\tlr, lr, #(%l3 - . -4)\", operands);
6098: }
6099: return arm_output_asm_insn (\"b\\t%a1\", operands);
6100: }"
6101: [(set (attr "conds")
6102: (if_then_else (eq_attr "cpu" "arm6")
6103: (const_string "clob")
6104: (const_string "nocond")))
6105: (set (attr "length")
6106: (if_then_else (eq_attr "cpu" "arm6")
6107: (const_int 2)
6108: (const_int 3)))])
6109:
6110: (define_split
6111: [(set (pc)
6112: (if_then_else (match_operator 0 "comparison_operator"
6113: [(match_operator:SI 1 "shift_operator"
6114: [(match_operand:SI 2 "s_register_operand" "r")
6115: (match_operand:SI 3 "nonmemory_operand" "rn")])
6116: (match_operand:SI 4 "s_register_operand" "r")])
6117: (label_ref (match_operand 5 "" ""))
6118: (pc)))
6119: (clobber (reg 24))]
6120: ""
6121: [(set (reg:CC 24)
6122: (compare:CC (match_dup 4)
6123: (match_op_dup 1 [(match_dup 2) (match_dup 3)])))
6124: (set (pc)
6125: (if_then_else (match_op_dup 0 [(reg 24) (const_int 0)])
6126: (label_ref (match_dup 5))
6127: (pc)))]
6128: "
6129: operands[0] = gen_rtx (swap_condition (GET_CODE (operands[0])), VOIDmode,
6130: operands[1], operands[2]);
6131: ")
6132:
6133: (define_split
6134: [(set (match_operand:SI 0 "s_register_operand" "")
6135: (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6136: (const_int 0))
6137: (neg:SI (match_operator:SI 2 "comparison_operator"
6138: [(match_operand:SI 3 "s_register_operand" "")
6139: (match_operand:SI 4 "arm_rhs_operand" "")]))))
6140: (clobber (match_operand:SI 5 "s_register_operand" ""))]
6141: ""
6142: [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6143: (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6144: (match_dup 5)))]
6145: "")
6146:
6147: ;; This pattern can be used because cc_noov mode implies that the following
6148: ;; branch will be an equality (EQ or NE), so the sign extension is not
6149: ;; needed. Combine doesn't eliminate these because by the time it sees the
6150: ;; branch it no-longer knows that the data came from memory.
6151:
6152: (define_insn ""
6153: [(set (reg:CC_NOOV 24)
6154: (compare:CC_NOOV
6155: (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "m") 0)
6156: (const_int 24))
6157: (match_operand 1 "immediate_operand" "I")))
6158: (clobber (match_scratch:SI 2 "=r"))]
6159: "((unsigned long) INTVAL (operands[1]))
6160: == (((unsigned long) INTVAL (operands[1])) >> 24) << 24"
6161: "*
6162: operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6163: arm_output_asm_insn (\"ldrb\\t%2, %0\", operands);
6164: return arm_output_asm_insn (\"cmp\\t%2, %1\", operands);
6165: "
6166: [(set_attr "conds" "set")
6167: (set_attr "length" "2")
6168: (set_attr "type" "load")])
6169:
6170: (define_expand "save_stack_nonlocal"
6171: [(match_operand:DI 0 "memory_operand" "")
6172: (match_operand:SI 1 "s_register_operand" "")]
6173: ""
6174: "
6175: {
6176: /* We also need to save the frame pointer for non-local gotos */
6177: emit_move_insn (operand_subword (operands[0], 0, 0, DImode),
6178: hard_frame_pointer_rtx);
6179: emit_move_insn (operand_subword (operands[0], 1, 0, DImode), operands[1]);
6180: DONE;
6181: }")
6182:
6183: (define_expand "restore_stack_nonlocal"
6184: [(match_operand:SI 0 "s_register_operand" "")
6185: (match_operand:DI 1 "memory_operand" "")]
6186: ""
6187: "
6188: {
6189: /* Restore the frame pointer first, the stack pointer second. */
6190: emit_move_insn (operands[0], operand_subword (operands[1], 1, 0, DImode));
6191: emit_move_insn (hard_frame_pointer_rtx, operand_subword (operands[1], 0, 0,
6192: DImode));
6193: DONE;
6194: }")
6195:
6196: ;; This split is only used during output to reduce the number of patterns
6197: ;; that need assembler instructions adding to them. We allowed the setting
6198: ;; of the conditions to be implicit during rtl generation so that
6199: ;; the conditional compare patterns would work. However this conflicts to
6200: ;; some extend with the conditional data operations, so we have to split them
6201: ;; up again here.
6202:
6203: (define_split
6204: [(set (match_operand:SI 0 "s_register_operand" "")
6205: (if_then_else:SI (match_operator 1 "comparison_operator"
6206: [(match_operand 2 "" "") (match_operand 3 "" "")])
6207: (match_operand 4 "" "")
6208: (match_operand 5 "" "")))
6209: (clobber (reg 24))]
6210: "reload_completed"
6211: [(set (match_dup 6) (match_dup 7))
6212: (set (match_dup 0)
6213: (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6214: (match_dup 4)
6215: (match_dup 5)))]
6216: "
6217: {
6218: enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6219: operands[3]);
6220:
6221: operands[6] = gen_rtx (REG, mode, 24);
6222: operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
6223: }
6224: ")
6225:
6226:
6227: (define_insn ""
6228: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6229: (if_then_else:SI (match_operator 4 "comparison_operator"
6230: [(match_operand 3 "cc_register" "") (const_int 0)])
6231: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
6232: (not:SI
6233: (match_operand:SI 2 "s_register_operand" "r,r"))))]
6234: ""
6235: "*
6236: if (which_alternative != 0)
6237: arm_output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6238: return arm_output_asm_insn (\"mvn%D4\\t%0, %2\", operands);
6239: "
6240: [(set_attr "conds" "use")
6241: (set_attr "length" "1,2")])
6242:
6243: ;; The next two patterns occur when an AND operation is followed by a
6244: ;; scc insn sequence
6245:
6246: (define_insn ""
6247: [(set (match_operand:SI 0 "s_register_operand" "=r")
6248: (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6249: (const_int 1)
6250: (match_operand:SI 2 "immediate_operand" "n")))]
6251: ""
6252: "*
6253: operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6254: arm_output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6255: return arm_output_asm_insn (\"mvnne\\t%0, #0\", operands);
6256: "
6257: [(set_attr "conds" "clob")
6258: (set_attr "length" "2")])
6259:
6260: (define_insn ""
6261: [(set (match_operand:SI 0 "s_register_operand" "=r")
6262: (not:SI
6263: (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6264: (const_int 1)
6265: (match_operand:SI 2 "immediate_operand" "n"))))]
6266: ""
6267: "*
6268: operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6269: arm_output_asm_insn (\"tst\\t%1, %2\", operands);
6270: arm_output_asm_insn (\"mvneq\\t%0, #0\", operands);
6271: return arm_output_asm_insn (\"movne\\t%0, #0\", operands);
6272: "
6273: [(set_attr "conds" "clob")
6274: (set_attr "length" "3")])
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.