]>
Commit | Line | Data |
---|---|---|
e2ca1c07 PS |
1 | --- gcc/gcc/builtins.c 2005-07-12 11:19:59.000000000 +0200 |
2 | +++ gcc/gcc/builtins.c 2005-07-18 06:14:15.000000000 +0200 | |
3 | @@ -52,6 +52,14 @@ Software Foundation, 51 Franklin Street, | |
4 | #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN | |
5 | #endif | |
6 | ||
7 | +#ifndef FUNCTION_VALUE_REGNO_P_APPLY_RESULT | |
8 | +#define FUNCTION_VALUE_REGNO_P_APPLY_RESULT FUNCTION_VALUE_REGNO_P | |
9 | +#endif | |
10 | + | |
11 | +#ifndef FUNCTION_ARG_REGNO_P_APPLY_ARGS | |
12 | +#define FUNCTION_ARG_REGNO_P_APPLY_ARGS FUNCTION_ARG_REGNO_P | |
13 | +#endif | |
14 | + | |
15 | /* Define the names of the builtin function types and codes. */ | |
16 | const char *const built_in_class_names[4] | |
17 | = {"NOT_BUILT_IN", "BUILT_IN_FRONTEND", "BUILT_IN_MD", "BUILT_IN_NORMAL"}; | |
18 | @@ -1079,7 +1087,7 @@ apply_args_size (void) | |
19 | size += GET_MODE_SIZE (Pmode); | |
20 | ||
21 | for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
22 | - if (FUNCTION_ARG_REGNO_P (regno)) | |
23 | + if (FUNCTION_ARG_REGNO_P_APPLY_ARGS (regno)) | |
24 | { | |
25 | mode = reg_raw_mode[regno]; | |
26 | ||
27 | @@ -1117,7 +1125,7 @@ apply_result_size (void) | |
28 | size = 0; | |
29 | ||
30 | for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
31 | - if (FUNCTION_VALUE_REGNO_P (regno)) | |
32 | + if (FUNCTION_VALUE_REGNO_P_APPLY_RESULT (regno)) | |
33 | { | |
34 | mode = reg_raw_mode[regno]; | |
35 | ||
36 | --- gcc/gcc/caller-save.c 2005-06-25 03:59:25.000000000 +0200 | |
37 | +++ gcc/gcc/caller-save.c 2005-07-18 06:14:15.000000000 +0200 | |
38 | @@ -377,6 +377,7 @@ save_call_clobbered_regs (void) | |
39 | { | |
40 | rtx insn = chain->insn; | |
41 | enum rtx_code code = GET_CODE (insn); | |
42 | + rtx reg ATTRIBUTE_UNUSED; | |
43 | ||
44 | next = chain->next; | |
45 | ||
46 | @@ -450,6 +451,12 @@ save_call_clobbered_regs (void) | |
47 | CLEAR_HARD_REG_SET (this_insn_sets); | |
48 | note_stores (PATTERN (insn), mark_set_regs, NULL); | |
49 | ||
50 | +#ifdef CALL_INSN_SETS | |
51 | + reg = CALL_INSN_SETS (insn); | |
52 | + | |
53 | + if (reg) | |
54 | + mark_set_regs (reg, NULL_RTX, NULL); | |
55 | +#endif | |
56 | /* Compute which hard regs must be saved before this call. */ | |
57 | AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set); | |
58 | AND_COMPL_HARD_REG_SET (hard_regs_to_save, this_insn_sets); | |
59 | --- gcc/gcc/config/i386/i386.c 2005-07-14 09:46:16.000000000 +0200 | |
60 | +++ gcc/gcc/config/i386/i386.c 2005-07-18 06:14:15.000000000 +0200 | |
61 | @@ -2067,12 +2067,13 @@ ix86_return_pops_args (tree fundecl, tre | |
62 | ||
63 | /* Return true when register may be used to pass function parameters. */ | |
64 | bool | |
65 | -ix86_function_arg_regno_p (int regno) | |
66 | +ix86_function_arg_regno_p (int regno, bool from_builtin) | |
67 | { | |
68 | int i; | |
69 | if (!TARGET_64BIT) | |
70 | return (regno < REGPARM_MAX | |
71 | - || (TARGET_MMX && MMX_REGNO_P (regno) | |
72 | + || (TARGET_MMX && !(TARGET_80387 && from_builtin) | |
73 | + && MMX_REGNO_P (regno) | |
74 | && (regno < FIRST_MMX_REG + MMX_REGPARM_MAX)) | |
75 | || (TARGET_SSE && SSE_REGNO_P (regno) | |
76 | && (regno < FIRST_SSE_REG + SSE_REGPARM_MAX))); | |
77 | @@ -3181,14 +3182,14 @@ ix86_function_arg_boundary (enum machine | |
78 | ||
79 | /* Return true if N is a possible register number of function value. */ | |
80 | bool | |
81 | -ix86_function_value_regno_p (int regno) | |
82 | +ix86_function_value_regno_p (int regno, bool from_builtin) | |
83 | { | |
84 | if (regno == 0 | |
85 | || (regno == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387) | |
86 | || (regno == FIRST_SSE_REG && TARGET_SSE)) | |
87 | return true; | |
88 | ||
89 | - if (!TARGET_64BIT | |
90 | + if (!TARGET_64BIT && !(TARGET_80387 && from_builtin) | |
91 | && (regno == FIRST_MMX_REG && TARGET_MMX)) | |
92 | return true; | |
93 | ||
94 | @@ -7450,12 +7451,152 @@ output_387_binary_op (rtx insn, rtx *ope | |
95 | return buf; | |
96 | } | |
97 | ||
98 | -/* Return needed mode for entity in optimize_mode_switching pass. */ | |
99 | +/* Return needed mode for entity in optimize_mode_switching pass. | |
100 | + Returned mode should match ix86_mode_entry () for function calls. */ | |
101 | ||
102 | int | |
103 | ix86_mode_needed (int entity, rtx insn) | |
104 | { | |
105 | - enum attr_i387_cw mode; | |
106 | + int unit, mode; | |
107 | + | |
108 | + if (entity == I387_FPU_MODE) | |
109 | + { | |
110 | + /* If a function call uses MMX registers, select MMX FPU mode and | |
111 | + if function call uses x87 registers, select x87 FPU mode. */ | |
112 | + if (CALL_P (insn)) | |
113 | + { | |
114 | + rtx link; | |
115 | + rtx reg; | |
116 | + bool mmx = false; | |
117 | + bool x87 = false; | |
118 | + | |
119 | + for (link = CALL_INSN_FUNCTION_USAGE (insn); | |
120 | + link; | |
121 | + link = XEXP (link, 1)) | |
122 | + { | |
123 | + if (GET_CODE (XEXP (link, 0)) == USE) | |
124 | + { | |
125 | + reg = XEXP (XEXP (link, 0), 0); | |
126 | + | |
127 | + if (reg) | |
128 | + { | |
129 | + if (MMX_REG_P (reg)) | |
130 | + mmx = true; | |
131 | + | |
132 | + if (FP_REG_P (reg)) | |
133 | + x87 = true; | |
134 | + } | |
135 | + } | |
136 | + } | |
137 | + | |
138 | + /* Mixing of x87 and MMX registers is not allowed | |
139 | + in function call. */ | |
140 | + gcc_assert (!mmx || !x87); | |
141 | + | |
142 | + if (mmx) | |
143 | + return FPU_MODE_MMX; | |
144 | + | |
145 | + /* Fall back to default mode. */ | |
146 | + return FPU_MODE_X87; | |
147 | + } | |
148 | + | |
149 | + /* Parse ASM operands to check input and output constraints. If | |
150 | + an ASM uses MMX registers, select MMX mode and if it uses x87 | |
151 | + registers, select x87 mode. Mixing of MMX and x87 constraints | |
152 | + is not allowed. If no MMX or x87 input and output registers | |
153 | + are used, switch to default mode. */ | |
154 | + if (NONJUMP_INSN_P (insn)) | |
155 | + { | |
156 | + rtx pat = PATTERN (insn); | |
157 | + int noperands = asm_noperands (pat); | |
158 | + | |
159 | + if (noperands >= 0) | |
160 | + { | |
161 | + const char **constraints; | |
162 | + int i; | |
163 | + bool mmx = false; | |
164 | + bool x87 = false; | |
165 | + | |
166 | + constraints = alloca (noperands * sizeof (char *)); | |
167 | + decode_asm_operands (pat, NULL, NULL, constraints, NULL); | |
168 | + | |
169 | + for (i = 0; i < noperands; i++) | |
170 | + { | |
171 | + const char *c = constraints[i]; | |
172 | + enum reg_class class; | |
173 | + | |
174 | + if (c[0] == '%') | |
175 | + c++; | |
176 | + if (ISDIGIT ((unsigned char) c[0]) && c[1] == '\0') | |
177 | + c = constraints[c[0] - '0']; | |
178 | + | |
179 | + while (*c) | |
180 | + { | |
181 | + char cc = *c; | |
182 | + int len; | |
183 | + switch (cc) | |
184 | + { | |
185 | + case ',': | |
186 | + cc++; | |
187 | + continue; | |
188 | + case '=': | |
189 | + case '+': | |
190 | + case '*': | |
191 | + case '%': | |
192 | + case '!': | |
193 | + case '#': | |
194 | + case '&': | |
195 | + case '?': | |
196 | + break; | |
197 | + | |
198 | + default: | |
199 | + class = REG_CLASS_FROM_LETTER (cc); | |
200 | + | |
201 | + if (MMX_CLASS_P (class)) | |
202 | + mmx = true; | |
203 | + | |
204 | + if (FLOAT_CLASS_P (class)) | |
205 | + x87 = true; | |
206 | + } | |
207 | + | |
208 | + len = CONSTRAINT_LEN (cc, c); | |
209 | + do | |
210 | + c++; | |
211 | + while (--len && *c); | |
212 | + } | |
213 | + } | |
214 | + | |
215 | + /* Mixing x87 and MMX registers in ASM is not allowed. */ | |
216 | + if (mmx && x87) | |
217 | + error_for_asm (insn, "mixing of x87 and MMX registers " | |
218 | + "is not allowed in %<asm%>"); | |
219 | + | |
220 | + if (mmx) | |
221 | + return FPU_MODE_MMX; | |
222 | + | |
223 | + /* Fall back to default mode. */ | |
224 | + return FPU_MODE_X87; | |
225 | + } | |
226 | + } | |
227 | + | |
228 | + if (recog_memoized (insn) < 0) | |
229 | + return FPU_MODE_ANY; | |
230 | + | |
231 | + unit = get_attr_unit (insn); | |
232 | + | |
233 | + switch (unit) | |
234 | + { | |
235 | + case UNIT_MMX: | |
236 | + return FPU_MODE_MMX; | |
237 | + | |
238 | + case UNIT_I387: | |
239 | + return FPU_MODE_X87; | |
240 | + | |
241 | + default: | |
242 | + return FPU_MODE_ANY; | |
243 | + | |
244 | + } | |
245 | + } | |
246 | ||
247 | /* The mode UNINITIALIZED is used to store control word after a | |
248 | function call or ASM pattern. The mode ANY specify that function | |
249 | @@ -7502,21 +7643,132 @@ ix86_mode_needed (int entity, rtx insn) | |
250 | return I387_CW_ANY; | |
251 | } | |
252 | ||
253 | -/* Output code to initialize control word copies used by trunc?f?i and | |
254 | - rounding patterns. CURRENT_MODE is set to current control word, | |
255 | - while NEW_MODE is set to new control word. */ | |
256 | + | |
257 | +/* Switch FPU mode to appropriate mode after function call in | |
258 | + optimize_mode_switchig pass. Returned mode should match | |
259 | + ix86_mode_exit (). */ | |
260 | + | |
261 | +int | |
262 | +ix86_mode_after (int entity, int mode, rtx insn) | |
263 | +{ | |
264 | + if (entity == I387_FPU_MODE) | |
265 | + { | |
266 | + /* Switch FPU to MMX mode after funciton call if function value | |
267 | + is returned in MMX register and similar for x87 reg. | |
268 | + If no value is returned in MMX or x87 reg, fall back to | |
269 | + default mode. */ | |
270 | + if (CALL_P (insn)) | |
271 | + { | |
272 | + rtx reg = SET_DEST (PATTERN (insn)); | |
273 | + | |
274 | + int new_mode; | |
275 | + | |
276 | + if (reg && MMX_REG_P (reg)) | |
277 | + new_mode = FPU_MODE_MMX; | |
278 | + else | |
279 | + new_mode = FPU_MODE_X87; | |
280 | + | |
281 | + /* Call insn should never operate in FPU_MODE_ANY. */ | |
282 | + if ((mode != FPU_MODE_ANY) && (new_mode != mode)) | |
283 | + ix86_fpu_mode_changed = 1; | |
284 | + | |
285 | + return new_mode; | |
286 | + } | |
287 | + } | |
288 | + | |
289 | + return mode; | |
290 | +} | |
291 | + | |
292 | +/* Switch FPU mode of function entry to appropriate mode in | |
293 | + optimize_mode_switchig pass. Returned mode should match | |
294 | + ix86_mode_needed () for function calls. */ | |
295 | + | |
296 | +int | |
297 | +ix86_mode_entry (int entity) | |
298 | +{ | |
299 | + if (entity == I387_FPU_MODE) | |
300 | + { | |
301 | + if (! current_function_args_info.maybe_vaarg) | |
302 | + { | |
303 | + if (current_function_args_info.mmx_nregs != MMX_REGPARM_MAX) | |
304 | + return FPU_MODE_MMX; | |
305 | + | |
306 | + /* ??? Handle x87 registers for fpregparm. */ | |
307 | + } | |
308 | + | |
309 | + /* Fall back to default mode. */ | |
310 | + return FPU_MODE_X87; | |
311 | + } | |
312 | + | |
313 | + return I387_CW_ANY; | |
314 | +} | |
315 | + | |
316 | +/* Switch FPU mode of function exit to appropriate mode in | |
317 | + optimize_mode_switchig pass. Returned mode should match | |
318 | + ix86_mode_after () for function calls. */ | |
319 | + | |
320 | +int | |
321 | +ix86_mode_exit (int entity) | |
322 | +{ | |
323 | + if (entity == I387_FPU_MODE) | |
324 | + { | |
325 | + rtx reg = current_function_return_rtx; | |
326 | + | |
327 | + /* If MMX output register is specified, switch FPU mode | |
328 | + of function exit to MMX mode. */ | |
329 | + if (reg && MMX_REG_P (reg)) | |
330 | + return FPU_MODE_MMX; | |
331 | + | |
332 | + /* Fall back to default mode. */ | |
333 | + return FPU_MODE_X87; | |
334 | + } | |
335 | + | |
336 | + return I387_CW_ANY; | |
337 | +} | |
338 | + | |
339 | +/* Emit mode switching instructions in optimize_mode_switching pass. */ | |
340 | ||
341 | void | |
342 | -emit_i387_cw_initialization (int mode) | |
343 | +ix86_emit_mode_set (int entity, int mode) | |
344 | { | |
345 | - rtx stored_mode = assign_386_stack_local (HImode, SLOT_CW_STORED); | |
346 | - rtx new_mode; | |
347 | + rtx stored_mode, new_mode; | |
348 | + rtx reg; | |
349 | ||
350 | int slot; | |
351 | ||
352 | - rtx reg = gen_reg_rtx (HImode); | |
353 | + if (entity == I387_FPU_MODE) | |
354 | + { | |
355 | + switch (mode) | |
356 | + { | |
357 | + case FPU_MODE_ANY: | |
358 | + return; | |
359 | + | |
360 | + case FPU_MODE_X87: | |
361 | + emit_insn (gen_emms ()); | |
362 | + ix86_fpu_mode_changed = 1; | |
363 | + return; | |
364 | + | |
365 | + case FPU_MODE_MMX: | |
366 | + emit_insn (gen_efpu ()); | |
367 | + ix86_fpu_mode_changed = 1; | |
368 | + return; | |
369 | + | |
370 | + default: | |
371 | + gcc_unreachable (); | |
372 | + } | |
373 | + } | |
374 | + | |
375 | + /* Output code to initialize control word copies used by trunc?f?i | |
376 | + and rounding patterns. STORED_MODE is set to current control | |
377 | + word, while NEW_MODE is set to new control word. */ | |
378 | ||
379 | + if ((mode == I387_CW_UNINITIALIZED) || (mode == I387_CW_ANY)) | |
380 | + return; | |
381 | + | |
382 | + stored_mode = assign_386_stack_local (HImode, SLOT_CW_STORED); | |
383 | emit_insn (gen_x86_fnstcw_1 (stored_mode)); | |
384 | + | |
385 | + reg = gen_reg_rtx (HImode); | |
386 | emit_move_insn (reg, stored_mode); | |
387 | ||
388 | if (TARGET_64BIT || TARGET_PARTIAL_REG_STALL || optimize_size) | |
389 | @@ -12279,6 +12531,7 @@ ix86_init_machine_status (void) | |
390 | ||
391 | f = ggc_alloc_cleared (sizeof (struct machine_function)); | |
392 | f->use_fast_prologue_epilogue_nregs = -1; | |
393 | + f->optimize_mode_switching[I387_FPU_MODE] = TARGET_80387 && TARGET_MMX; | |
394 | ||
395 | return f; | |
396 | } | |
397 | @@ -12877,7 +13130,77 @@ ix86_local_alignment (tree type, int ali | |
398 | } | |
399 | return align; | |
400 | } | |
401 | + | |
402 | \f | |
403 | + | |
404 | +/* Return true to prevent register allocator from allocating registers | |
405 | + from the unit that is not active. */ | |
406 | + | |
407 | +bool | |
408 | +ix86_epilogue_uses (int regno) | |
409 | +{ | |
410 | + int mode; | |
411 | + | |
412 | + if (! ix86_fpu_mode_changed) | |
413 | + return false; | |
414 | + | |
415 | + mode = ix86_mode_exit (I387_FPU_MODE); | |
416 | + | |
417 | + if (mode == FPU_MODE_MMX) | |
418 | + return FP_REGNO_P (regno); | |
419 | + else | |
420 | + return MMX_REGNO_P (regno); | |
421 | +} | |
422 | + | |
423 | +/* Return RTX code of additional register that CALL_INSN uses. | |
424 | + This function is used to maintain correct register life | |
425 | + information before CALL_INSN in case of MMX/x87 switching. */ | |
426 | + | |
427 | +rtx | |
428 | +ix86_call_insn_uses (rtx insn) | |
429 | +{ | |
430 | + int mode; | |
431 | + | |
432 | + if (! ix86_fpu_mode_changed) | |
433 | + return NULL_RTX; | |
434 | + | |
435 | + gcc_assert (CALL_P (insn)); | |
436 | + | |
437 | + mode = ix86_mode_needed (I387_FPU_MODE, insn); | |
438 | + if (mode == FPU_MODE_MMX) | |
439 | + return gen_rtx_REG (ALLREGSmode, FIRST_FLOAT_REG); | |
440 | + else | |
441 | + return gen_rtx_REG (ALLREGSmode, FIRST_MMX_REG); | |
442 | + | |
443 | + return NULL_RTX; | |
444 | +} | |
445 | + | |
446 | +/* Return RTX code of additional register that CALL_INSN sets. | |
447 | + This function is used to maintain correct register life | |
448 | + information after CALL_INSN in case of MMX/x87 switching. */ | |
449 | + | |
450 | +rtx | |
451 | +ix86_call_insn_sets (rtx insn) | |
452 | +{ | |
453 | + int mode; | |
454 | + | |
455 | + if (! ix86_fpu_mode_changed) | |
456 | + return NULL_RTX; | |
457 | + | |
458 | + gcc_assert (CALL_P (insn)); | |
459 | + | |
460 | + /* Current mode in call to ix86_mode_after is set to FPU_MODE_ANY | |
461 | + to prevent setting of ix86_fpu_mode_changed variable. */ | |
462 | + mode = ix86_mode_after (I387_FPU_MODE, FPU_MODE_ANY, insn); | |
463 | + if (mode == FPU_MODE_MMX) | |
464 | + return gen_rtx_REG (ALLREGSmode, FIRST_FLOAT_REG); | |
465 | + else | |
466 | + return gen_rtx_REG (ALLREGSmode, FIRST_MMX_REG); | |
467 | + | |
468 | + return NULL_RTX; | |
469 | +} | |
470 | + | |
471 | + | |
472 | /* Emit RTL insns to initialize the variable parts of a trampoline. | |
473 | FNADDR is an RTX for the address of the function's pure code. | |
474 | CXT is an RTX for the static chain value for the function. */ | |
475 | @@ -13357,9 +13680,11 @@ enum ix86_builtins | |
476 | IX86_BUILTIN_MONITOR, | |
477 | IX86_BUILTIN_MWAIT, | |
478 | ||
479 | + IX86_BUILTIN_VEC_INIT_V2SF, | |
480 | IX86_BUILTIN_VEC_INIT_V2SI, | |
481 | IX86_BUILTIN_VEC_INIT_V4HI, | |
482 | IX86_BUILTIN_VEC_INIT_V8QI, | |
483 | + IX86_BUILTIN_VEC_EXT_V2SF, | |
484 | IX86_BUILTIN_VEC_EXT_V2DF, | |
485 | IX86_BUILTIN_VEC_EXT_V2DI, | |
486 | IX86_BUILTIN_VEC_EXT_V4SF, | |
487 | @@ -13541,24 +13866,24 @@ static const struct builtin_description | |
488 | { MASK_SSE, CODE_FOR_sse_cvtsi2ss, 0, IX86_BUILTIN_CVTSI2SS, 0, 0 }, | |
489 | { MASK_SSE | MASK_64BIT, CODE_FOR_sse_cvtsi2ssq, 0, IX86_BUILTIN_CVTSI642SS, 0, 0 }, | |
490 | ||
491 | - { MASK_MMX, CODE_FOR_mmx_ashlv4hi3, 0, IX86_BUILTIN_PSLLW, 0, 0 }, | |
492 | - { MASK_MMX, CODE_FOR_mmx_ashlv4hi3, 0, IX86_BUILTIN_PSLLWI, 0, 0 }, | |
493 | - { MASK_MMX, CODE_FOR_mmx_ashlv2si3, 0, IX86_BUILTIN_PSLLD, 0, 0 }, | |
494 | - { MASK_MMX, CODE_FOR_mmx_ashlv2si3, 0, IX86_BUILTIN_PSLLDI, 0, 0 }, | |
495 | + { MASK_MMX, CODE_FOR_ashlv4hi3, 0, IX86_BUILTIN_PSLLW, 0, 0 }, | |
496 | + { MASK_MMX, CODE_FOR_ashlv4hi3, 0, IX86_BUILTIN_PSLLWI, 0, 0 }, | |
497 | + { MASK_MMX, CODE_FOR_ashlv2si3, 0, IX86_BUILTIN_PSLLD, 0, 0 }, | |
498 | + { MASK_MMX, CODE_FOR_ashlv2si3, 0, IX86_BUILTIN_PSLLDI, 0, 0 }, | |
499 | { MASK_MMX, CODE_FOR_mmx_ashldi3, 0, IX86_BUILTIN_PSLLQ, 0, 0 }, | |
500 | { MASK_MMX, CODE_FOR_mmx_ashldi3, 0, IX86_BUILTIN_PSLLQI, 0, 0 }, | |
501 | ||
502 | - { MASK_MMX, CODE_FOR_mmx_lshrv4hi3, 0, IX86_BUILTIN_PSRLW, 0, 0 }, | |
503 | - { MASK_MMX, CODE_FOR_mmx_lshrv4hi3, 0, IX86_BUILTIN_PSRLWI, 0, 0 }, | |
504 | - { MASK_MMX, CODE_FOR_mmx_lshrv2si3, 0, IX86_BUILTIN_PSRLD, 0, 0 }, | |
505 | - { MASK_MMX, CODE_FOR_mmx_lshrv2si3, 0, IX86_BUILTIN_PSRLDI, 0, 0 }, | |
506 | + { MASK_MMX, CODE_FOR_lshrv4hi3, 0, IX86_BUILTIN_PSRLW, 0, 0 }, | |
507 | + { MASK_MMX, CODE_FOR_lshrv4hi3, 0, IX86_BUILTIN_PSRLWI, 0, 0 }, | |
508 | + { MASK_MMX, CODE_FOR_lshrv2si3, 0, IX86_BUILTIN_PSRLD, 0, 0 }, | |
509 | + { MASK_MMX, CODE_FOR_lshrv2si3, 0, IX86_BUILTIN_PSRLDI, 0, 0 }, | |
510 | { MASK_MMX, CODE_FOR_mmx_lshrdi3, 0, IX86_BUILTIN_PSRLQ, 0, 0 }, | |
511 | { MASK_MMX, CODE_FOR_mmx_lshrdi3, 0, IX86_BUILTIN_PSRLQI, 0, 0 }, | |
512 | ||
513 | - { MASK_MMX, CODE_FOR_mmx_ashrv4hi3, 0, IX86_BUILTIN_PSRAW, 0, 0 }, | |
514 | - { MASK_MMX, CODE_FOR_mmx_ashrv4hi3, 0, IX86_BUILTIN_PSRAWI, 0, 0 }, | |
515 | - { MASK_MMX, CODE_FOR_mmx_ashrv2si3, 0, IX86_BUILTIN_PSRAD, 0, 0 }, | |
516 | - { MASK_MMX, CODE_FOR_mmx_ashrv2si3, 0, IX86_BUILTIN_PSRADI, 0, 0 }, | |
517 | + { MASK_MMX, CODE_FOR_ashrv4hi3, 0, IX86_BUILTIN_PSRAW, 0, 0 }, | |
518 | + { MASK_MMX, CODE_FOR_ashrv4hi3, 0, IX86_BUILTIN_PSRAWI, 0, 0 }, | |
519 | + { MASK_MMX, CODE_FOR_ashrv2si3, 0, IX86_BUILTIN_PSRAD, 0, 0 }, | |
520 | + { MASK_MMX, CODE_FOR_ashrv2si3, 0, IX86_BUILTIN_PSRADI, 0, 0 }, | |
521 | ||
522 | { MASK_SSE | MASK_3DNOW_A, CODE_FOR_mmx_psadbw, 0, IX86_BUILTIN_PSADBW, 0, 0 }, | |
523 | { MASK_MMX, CODE_FOR_mmx_pmaddwd, 0, IX86_BUILTIN_PMADDWD, 0, 0 }, | |
524 | @@ -14323,6 +14648,11 @@ ix86_init_mmx_sse_builtins (void) | |
525 | v16qi_ftype_pcchar, IX86_BUILTIN_LDDQU); | |
526 | ||
527 | /* Access to the vec_init patterns. */ | |
528 | + ftype = build_function_type_list (V2SF_type_node, float_type_node, | |
529 | + integer_type_node, NULL_TREE); | |
530 | + def_builtin (MASK_3DNOW, "__builtin_ia32_vec_init_v2sf", | |
531 | + ftype, IX86_BUILTIN_VEC_INIT_V2SF); | |
532 | + | |
533 | ftype = build_function_type_list (V2SI_type_node, integer_type_node, | |
534 | integer_type_node, NULL_TREE); | |
535 | def_builtin (MASK_MMX, "__builtin_ia32_vec_init_v2si", | |
536 | @@ -14344,6 +14674,11 @@ ix86_init_mmx_sse_builtins (void) | |
537 | ftype, IX86_BUILTIN_VEC_INIT_V8QI); | |
538 | ||
539 | /* Access to the vec_extract patterns. */ | |
540 | + ftype = build_function_type_list (float_type_node, V2SF_type_node, | |
541 | + integer_type_node, NULL_TREE); | |
542 | + def_builtin (MASK_3DNOW, "__builtin_ia32_vec_ext_v2sf", | |
543 | + ftype, IX86_BUILTIN_VEC_EXT_V2DF); | |
544 | + | |
545 | ftype = build_function_type_list (double_type_node, V2DF_type_node, | |
546 | integer_type_node, NULL_TREE); | |
547 | def_builtin (MASK_SSE, "__builtin_ia32_vec_ext_v2df", | |
548 | @@ -14818,7 +15153,7 @@ ix86_expand_builtin (tree exp, rtx targe | |
549 | switch (fcode) | |
550 | { | |
551 | case IX86_BUILTIN_EMMS: | |
552 | - emit_insn (gen_mmx_emms ()); | |
553 | + /* emms insn is emitted automatically. */ | |
554 | return 0; | |
555 | ||
556 | case IX86_BUILTIN_SFENCE: | |
557 | @@ -15035,7 +15370,7 @@ ix86_expand_builtin (tree exp, rtx targe | |
558 | return target; | |
559 | ||
560 | case IX86_BUILTIN_FEMMS: | |
561 | - emit_insn (gen_mmx_femms ()); | |
562 | + /* femms insn is emitted automatically. */ | |
563 | return NULL_RTX; | |
564 | ||
565 | case IX86_BUILTIN_PAVGUSB: | |
566 | @@ -15181,11 +15516,13 @@ ix86_expand_builtin (tree exp, rtx targe | |
567 | return ix86_expand_unop_builtin (CODE_FOR_sse3_lddqu, arglist, | |
568 | target, 1); | |
569 | ||
570 | + case IX86_BUILTIN_VEC_INIT_V2SF: | |
571 | case IX86_BUILTIN_VEC_INIT_V2SI: | |
572 | case IX86_BUILTIN_VEC_INIT_V4HI: | |
573 | case IX86_BUILTIN_VEC_INIT_V8QI: | |
574 | return ix86_expand_vec_init_builtin (TREE_TYPE (exp), arglist, target); | |
575 | ||
576 | + case IX86_BUILTIN_VEC_EXT_V2SF: | |
577 | case IX86_BUILTIN_VEC_EXT_V2DF: | |
578 | case IX86_BUILTIN_VEC_EXT_V2DI: | |
579 | case IX86_BUILTIN_VEC_EXT_V4SF: | |
580 | --- gcc/gcc/config/i386/i386.h 2005-07-14 09:46:21.000000000 +0200 | |
581 | +++ gcc/gcc/config/i386/i386.h 2005-07-18 06:14:15.000000000 +0200 | |
582 | @@ -819,7 +819,9 @@ do { \ | |
583 | ||
584 | #define HARD_REGNO_NREGS(REGNO, MODE) \ | |
585 | (FP_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) \ | |
586 | - ? (COMPLEX_MODE_P (MODE) ? 2 : 1) \ | |
587 | + ? ((MODE) == ALLREGSmode \ | |
588 | + ? 8 \ | |
589 | + : (COMPLEX_MODE_P (MODE) ? 2 : 1)) \ | |
590 | : ((MODE) == XFmode \ | |
591 | ? (TARGET_64BIT ? 2 : 3) \ | |
592 | : (MODE) == XCmode \ | |
593 | @@ -841,9 +843,8 @@ do { \ | |
594 | ((MODE) == DImode || (MODE) == V8QImode || (MODE) == V4HImode \ | |
595 | || (MODE) == V2SImode || (MODE) == SImode) | |
596 | ||
597 | -/* ??? No autovectorization into MMX or 3DNOW until we can reliably | |
598 | - place emms and femms instructions. */ | |
599 | -#define UNITS_PER_SIMD_WORD (TARGET_SSE ? 16 : UNITS_PER_WORD) | |
600 | +#define UNITS_PER_SIMD_WORD \ | |
601 | + (TARGET_SSE ? 16 : TARGET_MMX ? 8 : UNITS_PER_WORD) | |
602 | ||
603 | #define VALID_FP_MODE_P(MODE) \ | |
604 | ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode \ | |
605 | @@ -1433,8 +1434,16 @@ enum reg_class | |
606 | #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) \ | |
607 | ix86_return_pops_args ((FUNDECL), (FUNTYPE), (SIZE)) | |
608 | ||
609 | +/* 1 if N is the number of a register in which the values of | |
610 | + called function may come back. */ | |
611 | #define FUNCTION_VALUE_REGNO_P(N) \ | |
612 | - ix86_function_value_regno_p (N) | |
613 | + ix86_function_value_regno_p ((N), false) | |
614 | + | |
615 | +/* 1 if N is the number of a register in which the value of | |
616 | + __builtin_return builtin function may come back. */ | |
617 | + | |
618 | +#define FUNCTION_VALUE_REGNO_P_APPLY_RESULT(N) \ | |
619 | + ix86_function_value_regno_p ((N), true) | |
620 | ||
621 | /* Define how to find the value returned by a library function | |
622 | assuming the value has mode MODE. */ | |
623 | @@ -1449,7 +1458,13 @@ enum reg_class | |
624 | #define APPLY_RESULT_SIZE (8+108) | |
625 | ||
626 | /* 1 if N is a possible register number for function argument passing. */ | |
627 | -#define FUNCTION_ARG_REGNO_P(N) ix86_function_arg_regno_p (N) | |
628 | +#define FUNCTION_ARG_REGNO_P(N) ix86_function_arg_regno_p ((N), false) | |
629 | + | |
630 | +/* 1 if N is a possible register number for function argument passing | |
631 | + from __builtin_apply_args and __builtin_apply builtin functions. */ | |
632 | + | |
633 | +#define FUNCTION_ARG_REGNO_P_APPLY_ARGS(N) \ | |
634 | + ix86_function_arg_regno_p ((N), true) | |
635 | ||
636 | /* Define a data type for recording info about an argument list | |
637 | during the scan of that argument list. This data type should | |
638 | @@ -1531,6 +1546,23 @@ typedef struct ix86_args { | |
639 | ||
640 | #define EXIT_IGNORE_STACK 1 | |
641 | ||
642 | +/* Define this macro as a C expression that is nonzero for registers | |
643 | + that are used by the epilogue or the return' pattern. The stack | |
644 | + and frame pointer registers are already be assumed to be used as | |
645 | + needed. */ | |
646 | + | |
647 | +#define EPILOGUE_USES(REGNO) ix86_epilogue_uses (REGNO) | |
648 | + | |
649 | +/* Define this macro as a C expression that returns RTL expression of | |
650 | + additional hard register set by call_insn. */ | |
651 | + | |
652 | +#define CALL_INSN_SETS(INSN) ix86_call_insn_sets (INSN) | |
653 | + | |
654 | +/* Define this macro as a C expression that returns RTL expression of | |
655 | + additional hard register used by call_insn. */ | |
656 | + | |
657 | +#define CALL_INSN_USES(INSN) ix86_call_insn_uses (INSN) | |
658 | + | |
659 | /* Output assembler code for a block containing the constant parts | |
660 | of a trampoline, leaving space for the variable parts. */ | |
661 | ||
662 | @@ -2167,6 +2199,10 @@ extern rtx ix86_compare_op0; /* operand | |
663 | extern rtx ix86_compare_op1; /* operand 1 for comparisons */ | |
664 | extern rtx ix86_compare_emitted; | |
665 | \f | |
666 | + | |
667 | +/* x87 FPU modes for x87/MMX switching. */ | |
668 | +enum ix86_fpu_mode { FPU_MODE_X87, FPU_MODE_MMX, FPU_MODE_ANY }; | |
669 | + | |
670 | /* To properly truncate FP values into integers, we need to set i387 control | |
671 | word. We can't emit proper mode switching code before reload, as spills | |
672 | generated by reload may truncate values incorrectly, but we still can avoid | |
673 | @@ -2188,6 +2224,7 @@ enum ix86_entity | |
674 | I387_FLOOR, | |
675 | I387_CEIL, | |
676 | I387_MASK_PM, | |
677 | + I387_FPU_MODE, | |
678 | MAX_386_ENTITIES | |
679 | }; | |
680 | ||
681 | @@ -2217,7 +2254,12 @@ enum ix86_stack_slot | |
682 | refer to the mode-switched entity in question. */ | |
683 | ||
684 | #define NUM_MODES_FOR_MODE_SWITCHING \ | |
685 | - { I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY } | |
686 | + { I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, FPU_MODE_ANY } | |
687 | + | |
688 | +/* Define this macro if the port needs extra register life analysis | |
689 | + after mode switching. */ | |
690 | + | |
691 | +#define LIFE_ANALYSIS_AFTER_MODE_SWITCHING ix86_fpu_mode_changed | |
692 | ||
693 | /* ENTITY is an integer specifying a mode-switched entity. If | |
694 | `OPTIMIZE_MODE_SWITCHING' is defined, you must define this macro to | |
695 | @@ -2227,6 +2269,22 @@ enum ix86_stack_slot | |
696 | ||
697 | #define MODE_NEEDED(ENTITY, I) ix86_mode_needed ((ENTITY), (I)) | |
698 | ||
699 | +/* This macro determines the mode that an INSN results in (if different | |
700 | + from the incoming mode). */ | |
701 | + | |
702 | +#define MODE_AFTER(ENTITY, MODE, I) \ | |
703 | + ix86_mode_after ((ENTITY), (MODE), (I)) | |
704 | + | |
705 | +/* This macro specifies a mode that ENTITY is assumed to be | |
706 | + switched to at function entry. */ | |
707 | + | |
708 | +#define MODE_ENTRY(ENTITY) ix86_mode_entry (ENTITY) | |
709 | + | |
710 | +/* This macro specifies a mode that ENTITY is assumed to be | |
711 | + switched to at function exit. */ | |
712 | + | |
713 | +#define MODE_EXIT(ENTITY) ix86_mode_exit (ENTITY) | |
714 | + | |
715 | /* This macro specifies the order in which modes for ENTITY are | |
716 | processed. 0 is the highest priority. */ | |
717 | ||
718 | @@ -2236,10 +2294,8 @@ enum ix86_stack_slot | |
719 | is the set of hard registers live at the point where the insn(s) | |
720 | are to be inserted. */ | |
721 | ||
722 | -#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \ | |
723 | - ((MODE) != I387_CW_ANY && (MODE) != I387_CW_UNINITIALIZED \ | |
724 | - ? emit_i387_cw_initialization (MODE), 0 \ | |
725 | - : 0) | |
726 | +#define EMIT_MODE_SET(ENTITY, MODE, HARD_REGS_LIVE) \ | |
727 | + ix86_emit_mode_set ((ENTITY), (MODE)) | |
728 | ||
729 | \f | |
730 | /* Avoid renaming of stack registers, as doing so in combination with | |
731 | @@ -2263,6 +2319,7 @@ struct machine_function GTY(()) | |
732 | int save_varrargs_registers; | |
733 | int accesses_prev_frame; | |
734 | int optimize_mode_switching[MAX_386_ENTITIES]; | |
735 | + int fpu_mode_changed; | |
736 | /* Set by ix86_compute_frame_layout and used by prologue/epilogue expander to | |
737 | determine the style used. */ | |
738 | int use_fast_prologue_epilogue; | |
739 | @@ -2274,6 +2331,7 @@ struct machine_function GTY(()) | |
740 | #define ix86_stack_locals (cfun->machine->stack_locals) | |
741 | #define ix86_save_varrargs_registers (cfun->machine->save_varrargs_registers) | |
742 | #define ix86_optimize_mode_switching (cfun->machine->optimize_mode_switching) | |
743 | +#define ix86_fpu_mode_changed (cfun->machine->fpu_mode_changed) | |
744 | ||
745 | /* Control behavior of x86_file_start. */ | |
746 | #define X86_FILE_START_VERSION_DIRECTIVE false | |
747 | --- gcc/gcc/config/i386/i386.md 2005-07-12 11:20:12.000000000 +0200 | |
748 | +++ gcc/gcc/config/i386/i386.md 2005-07-18 06:14:15.000000000 +0200 | |
749 | @@ -152,7 +152,7 @@ | |
750 | (UNSPECV_EMMS 2) | |
751 | (UNSPECV_LDMXCSR 3) | |
752 | (UNSPECV_STMXCSR 4) | |
753 | - (UNSPECV_FEMMS 5) | |
754 | + (UNSPECV_EFPU 5) | |
755 | (UNSPECV_CLFLUSH 6) | |
756 | (UNSPECV_ALIGN 7) | |
757 | (UNSPECV_MONITOR 8) | |
758 | @@ -167,9 +167,11 @@ | |
759 | (define_constants | |
760 | [(BP_REG 6) | |
761 | (SP_REG 7) | |
762 | + (FIRSTFP_REG 8) | |
763 | (FLAGS_REG 17) | |
764 | (FPSR_REG 18) | |
765 | (DIRFLAG_REG 19) | |
766 | + (FIRSTMMX_REG 29) | |
767 | ]) | |
768 | ||
769 | ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls | |
770 | --- gcc/gcc/config/i386/i386-modes.def 2005-06-25 03:21:07.000000000 +0200 | |
771 | +++ gcc/gcc/config/i386/i386-modes.def 2005-07-18 06:14:15.000000000 +0200 | |
772 | @@ -62,6 +62,9 @@ CC_MODE (CCZ); | |
773 | CC_MODE (CCFP); | |
774 | CC_MODE (CCFPU); | |
775 | ||
776 | +/* This mode is used to cover all MMX and all x87 registers. */ | |
777 | +RANDOM_MODE (ALLREGS); | |
778 | + | |
779 | /* Vector modes. */ | |
780 | VECTOR_MODES (INT, 4); /* V4QI V2HI */ | |
781 | VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */ | |
782 | --- gcc/gcc/config/i386/i386-protos.h 2005-07-14 09:46:16.000000000 +0200 | |
783 | +++ gcc/gcc/config/i386/i386-protos.h 2005-07-18 06:14:15.000000000 +0200 | |
784 | @@ -152,6 +152,9 @@ extern bool ix86_expand_fp_vcond (rtx[]) | |
785 | extern bool ix86_expand_int_vcond (rtx[]); | |
786 | extern int ix86_expand_int_addcc (rtx[]); | |
787 | extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int); | |
788 | +extern bool ix86_epilogue_uses (int); | |
789 | +extern rtx ix86_call_insn_sets (rtx); | |
790 | +extern rtx ix86_call_insn_uses (rtx); | |
791 | extern void x86_initialize_trampoline (rtx, rtx, rtx); | |
792 | extern rtx ix86_zero_extend_to_Pmode (rtx); | |
793 | extern void ix86_split_long_move (rtx[]); | |
794 | @@ -168,8 +171,8 @@ extern int ix86_attr_length_address_defa | |
795 | extern enum machine_mode ix86_fp_compare_mode (enum rtx_code); | |
796 | ||
797 | extern rtx ix86_libcall_value (enum machine_mode); | |
798 | -extern bool ix86_function_value_regno_p (int); | |
799 | -extern bool ix86_function_arg_regno_p (int); | |
800 | +extern bool ix86_function_value_regno_p (int, bool); | |
801 | +extern bool ix86_function_arg_regno_p (int, bool); | |
802 | extern int ix86_function_arg_boundary (enum machine_mode, tree); | |
803 | extern int ix86_return_in_memory (tree); | |
804 | extern void ix86_va_start (tree, rtx); | |
805 | @@ -190,7 +193,10 @@ extern bool ix86_cannot_change_mode_clas | |
806 | extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class); | |
807 | extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int); | |
808 | extern int ix86_mode_needed (int, rtx); | |
809 | -extern void emit_i387_cw_initialization (int); | |
810 | +extern int ix86_mode_after (int, int, rtx); | |
811 | +extern int ix86_mode_entry (int); | |
812 | +extern int ix86_mode_exit (int); | |
813 | +extern void ix86_emit_mode_set (int, int); | |
814 | extern bool ix86_fp_jump_nontrivial_p (enum rtx_code); | |
815 | extern void x86_order_regs_for_local_alloc (void); | |
816 | extern void x86_function_profiler (FILE *, int); | |
817 | --- gcc/gcc/config/i386/mm3dnow.h 2005-06-25 03:21:23.000000000 +0200 | |
818 | +++ gcc/gcc/config/i386/mm3dnow.h 2005-07-18 06:14:15.000000000 +0200 | |
819 | @@ -172,14 +172,13 @@ _m_prefetchw (void *__P) | |
820 | static __inline __m64 | |
821 | _m_from_float (float __A) | |
822 | { | |
823 | - return (__m64)(__v2sf){ __A, 0 }; | |
824 | + return (__m64) __builtin_ia32_vec_init_v2sf (__A, 0); | |
825 | } | |
826 | ||
827 | static __inline float | |
828 | _m_to_float (__m64 __A) | |
829 | { | |
830 | - union { __v2sf v; float a[2]; } __tmp = { (__v2sf)__A }; | |
831 | - return __tmp.a[0]; | |
832 | + return __builtin_ia32_vec_ext_v2sf ((__v2sf)__A, 0); | |
833 | } | |
834 | ||
835 | #ifdef __3dNOW_A__ | |
836 | --- gcc/gcc/config/i386/mmx.md 2005-06-25 03:21:23.000000000 +0200 | |
837 | +++ gcc/gcc/config/i386/mmx.md 2005-07-18 06:14:15.000000000 +0200 | |
838 | @@ -23,14 +23,6 @@ | |
839 | ;; the same register file, and 3dNOW! adds a number of extensions to | |
840 | ;; the base integer MMX isa. | |
841 | ||
842 | -;; Note! Except for the basic move instructions, *all* of these | |
843 | -;; patterns are outside the normal optabs namespace. This is because | |
844 | -;; use of these registers requires the insertion of emms or femms | |
845 | -;; instructions to return to normal fpu mode. The compiler doesn't | |
846 | -;; know how to do that itself, which means it's up to the user. Which | |
847 | -;; means that we should never use any of these patterns except at the | |
848 | -;; direction of the user via a builtin. | |
849 | - | |
850 | ;; 8 byte integral modes handled by MMX (and by extension, SSE) | |
851 | (define_mode_macro MMXMODEI [V8QI V4HI V2SI]) | |
852 | ||
853 | @@ -481,7 +473,7 @@ | |
854 | (match_operand 2 "const_int_operand" "")] | |
855 | "TARGET_MMX" | |
856 | { | |
857 | - ix86_expand_vector_set (false, operands[0], operands[1], | |
858 | + ix86_expand_vector_set (true, operands[0], operands[1], | |
859 | INTVAL (operands[2])); | |
860 | DONE; | |
861 | }) | |
862 | @@ -537,7 +529,7 @@ | |
863 | (match_operand 2 "const_int_operand" "")] | |
864 | "TARGET_MMX" | |
865 | { | |
866 | - ix86_expand_vector_extract (false, operands[0], operands[1], | |
867 | + ix86_expand_vector_extract (true, operands[0], operands[1], | |
868 | INTVAL (operands[2])); | |
869 | DONE; | |
870 | }) | |
871 | @@ -547,7 +539,7 @@ | |
872 | (match_operand 1 "" "")] | |
873 | "TARGET_SSE" | |
874 | { | |
875 | - ix86_expand_vector_init (false, operands[0], operands[1]); | |
876 | + ix86_expand_vector_init (true, operands[0], operands[1]); | |
877 | DONE; | |
878 | }) | |
879 | ||
880 | @@ -557,6 +549,21 @@ | |
881 | ;; | |
882 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
883 | ||
884 | +(define_expand "neg<mode>2" | |
885 | + [(set (match_operand:MMXMODEI 0 "register_operand" "") | |
886 | + (minus:MMXMODEI | |
887 | + (match_dup 2) | |
888 | + (match_operand:MMXMODEI 1 "nonimmediate_operand" "")))] | |
889 | + "TARGET_MMX" | |
890 | + "operands[2] = force_reg (<MODE>mode, CONST0_RTX (<MODE>mode));") | |
891 | + | |
892 | +(define_expand "add<mode>3" | |
893 | + [(set (match_operand:MMXMODEI 0 "register_operand" "") | |
894 | + (plus:MMXMODEI (match_operand:MMXMODEI 1 "nonimmediate_operand" "") | |
895 | + (match_operand:MMXMODEI 2 "nonimmediate_operand" "")))] | |
896 | + "TARGET_MMX" | |
897 | + "ix86_fixup_binary_operands_no_copy (PLUS, <MODE>mode, operands);") | |
898 | + | |
899 | (define_insn "mmx_add<mode>3" | |
900 | [(set (match_operand:MMXMODEI 0 "register_operand" "=y") | |
901 | (plus:MMXMODEI | |
902 | @@ -598,6 +605,13 @@ | |
903 | [(set_attr "type" "mmxadd") | |
904 | (set_attr "mode" "DI")]) | |
905 | ||
906 | +(define_expand "sub<mode>3" | |
907 | + [(set (match_operand:MMXMODEI 0 "register_operand" "") | |
908 | + (minus:MMXMODEI (match_operand:MMXMODEI 1 "register_operand" "") | |
909 | + (match_operand:MMXMODEI 2 "nonimmediate_operand" "")))] | |
910 | + "TARGET_MMX" | |
911 | + "ix86_fixup_binary_operands_no_copy (MINUS, <MODE>mode, operands);") | |
912 | + | |
913 | (define_insn "mmx_sub<mode>3" | |
914 | [(set (match_operand:MMXMODEI 0 "register_operand" "=y") | |
915 | (minus:MMXMODEI | |
916 | @@ -639,6 +653,13 @@ | |
917 | [(set_attr "type" "mmxadd") | |
918 | (set_attr "mode" "DI")]) | |
919 | ||
920 | +(define_expand "mulv4hi3" | |
921 | + [(set (match_operand:V4HI 0 "register_operand" "") | |
922 | + (mult:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "") | |
923 | + (match_operand:V4HI 2 "nonimmediate_operand" "")))] | |
924 | + "TARGET_MMX" | |
925 | + "ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);") | |
926 | + | |
927 | (define_insn "mmx_mulv4hi3" | |
928 | [(set (match_operand:V4HI 0 "register_operand" "=y") | |
929 | (mult:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0") | |
930 | @@ -735,6 +756,13 @@ | |
931 | [(set_attr "type" "mmxmul") | |
932 | (set_attr "mode" "DI")]) | |
933 | ||
934 | +(define_expand "umaxv8qi3" | |
935 | + [(set (match_operand:V8QI 0 "register_operand" "") | |
936 | + (umax:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "") | |
937 | + (match_operand:V8QI 2 "nonimmediate_operand" "")))] | |
938 | + "(TARGET_SSE || TARGET_3DNOW_A)" | |
939 | + "ix86_fixup_binary_operands_no_copy (UMAX, V8QImode, operands);") | |
940 | + | |
941 | (define_insn "mmx_umaxv8qi3" | |
942 | [(set (match_operand:V8QI 0 "register_operand" "=y") | |
943 | (umax:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "%0") | |
944 | @@ -745,6 +773,13 @@ | |
945 | [(set_attr "type" "mmxadd") | |
946 | (set_attr "mode" "DI")]) | |
947 | ||
948 | +(define_expand "smaxv4hi3" | |
949 | + [(set (match_operand:V4HI 0 "register_operand" "") | |
950 | + (smax:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "") | |
951 | + (match_operand:V4HI 2 "nonimmediate_operand" "")))] | |
952 | + "(TARGET_SSE || TARGET_3DNOW_A)" | |
953 | + "ix86_fixup_binary_operands_no_copy (SMAX, V4HImode, operands);") | |
954 | + | |
955 | (define_insn "mmx_smaxv4hi3" | |
956 | [(set (match_operand:V4HI 0 "register_operand" "=y") | |
957 | (smax:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0") | |
958 | @@ -755,6 +790,13 @@ | |
959 | [(set_attr "type" "mmxadd") | |
960 | (set_attr "mode" "DI")]) | |
961 | ||
962 | +(define_expand "uminv8qi3" | |
963 | + [(set (match_operand:V8QI 0 "register_operand" "") | |
964 | + (umin:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "") | |
965 | + (match_operand:V8QI 2 "nonimmediate_operand" "")))] | |
966 | + "(TARGET_SSE || TARGET_3DNOW_A)" | |
967 | + "ix86_fixup_binary_operands_no_copy (UMAX, V8QImode, operands);") | |
968 | + | |
969 | (define_insn "mmx_uminv8qi3" | |
970 | [(set (match_operand:V8QI 0 "register_operand" "=y") | |
971 | (umin:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "%0") | |
972 | @@ -765,6 +807,13 @@ | |
973 | [(set_attr "type" "mmxadd") | |
974 | (set_attr "mode" "DI")]) | |
975 | ||
976 | +(define_expand "sminv4hi3" | |
977 | + [(set (match_operand:V4HI 0 "register_operand" "") | |
978 | + (smin:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "") | |
979 | + (match_operand:V4HI 2 "nonimmediate_operand" "")))] | |
980 | + "(TARGET_SSE || TARGET_3DNOW_A)" | |
981 | + "ix86_fixup_binary_operands_no_copy (SMIN, V4HImode, operands);") | |
982 | + | |
983 | (define_insn "mmx_sminv4hi3" | |
984 | [(set (match_operand:V4HI 0 "register_operand" "=y") | |
985 | (smin:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0") | |
986 | @@ -775,7 +824,7 @@ | |
987 | [(set_attr "type" "mmxadd") | |
988 | (set_attr "mode" "DI")]) | |
989 | ||
990 | -(define_insn "mmx_ashr<mode>3" | |
991 | +(define_insn "ashr<mode>3" | |
992 | [(set (match_operand:MMXMODE24 0 "register_operand" "=y") | |
993 | (ashiftrt:MMXMODE24 | |
994 | (match_operand:MMXMODE24 1 "register_operand" "0") | |
995 | @@ -785,7 +834,7 @@ | |
996 | [(set_attr "type" "mmxshft") | |
997 | (set_attr "mode" "DI")]) | |
998 | ||
999 | -(define_insn "mmx_lshr<mode>3" | |
1000 | +(define_insn "lshr<mode>3" | |
1001 | [(set (match_operand:MMXMODE24 0 "register_operand" "=y") | |
1002 | (lshiftrt:MMXMODE24 | |
1003 | (match_operand:MMXMODE24 1 "register_operand" "0") | |
1004 | @@ -806,7 +855,7 @@ | |
1005 | [(set_attr "type" "mmxshft") | |
1006 | (set_attr "mode" "DI")]) | |
1007 | ||
1008 | -(define_insn "mmx_ashl<mode>3" | |
1009 | +(define_insn "ashl<mode>3" | |
1010 | [(set (match_operand:MMXMODE24 0 "register_operand" "=y") | |
1011 | (ashift:MMXMODE24 | |
1012 | (match_operand:MMXMODE24 1 "register_operand" "0") | |
1013 | @@ -853,12 +902,66 @@ | |
1014 | [(set_attr "type" "mmxcmp") | |
1015 | (set_attr "mode" "DI")]) | |
1016 | ||
1017 | +(define_expand "vcond<mode>" | |
1018 | + [(set (match_operand:MMXMODE12 0 "register_operand" "") | |
1019 | + (if_then_else:MMXMODE12 | |
1020 | + (match_operator 3 "" | |
1021 | + [(match_operand:MMXMODE12 4 "nonimmediate_operand" "") | |
1022 | + (match_operand:MMXMODE12 5 "nonimmediate_operand" "")]) | |
1023 | + (match_operand:MMXMODE12 1 "general_operand" "") | |
1024 | + (match_operand:MMXMODE12 2 "general_operand" "")))] | |
1025 | + "TARGET_MMX" | |
1026 | +{ | |
1027 | + if (ix86_expand_int_vcond (operands)) | |
1028 | + DONE; | |
1029 | + else | |
1030 | + FAIL; | |
1031 | +}) | |
1032 | + | |
1033 | +(define_expand "vconduv8qi" | |
1034 | + [(set (match_operand:V8QI 0 "register_operand" "") | |
1035 | + (if_then_else:V8QI | |
1036 | + (match_operator 3 "" | |
1037 | + [(match_operand:V8QI 4 "nonimmediate_operand" "") | |
1038 | + (match_operand:V8QI 5 "nonimmediate_operand" "")]) | |
1039 | + (match_operand:V8QI 1 "general_operand" "") | |
1040 | + (match_operand:V8QI 2 "general_operand" "")))] | |
1041 | + "TARGET_MMX" | |
1042 | +{ | |
1043 | + if (ix86_expand_int_vcond (operands)) | |
1044 | + DONE; | |
1045 | + else | |
1046 | + FAIL; | |
1047 | +}) | |
1048 | + | |
1049 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1050 | ;; | |
1051 | ;; Parallel integral logical operations | |
1052 | ;; | |
1053 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
1054 | ||
1055 | +(define_expand "one_cmpl<mode>2" | |
1056 | + [(set (match_operand:MMXMODEI 0 "register_operand" "") | |
1057 | + (xor:MMXMODEI (match_operand:MMXMODEI 1 "nonimmediate_operand" "") | |
1058 | + (match_dup 2)))] | |
1059 | + "TARGET_MMX" | |
1060 | +{ | |
1061 | + int i, n = GET_MODE_NUNITS (<MODE>mode); | |
1062 | + rtvec v = rtvec_alloc (n); | |
1063 | + | |
1064 | + for (i = 0; i < n; ++i) | |
1065 | + RTVEC_ELT (v, i) = constm1_rtx; | |
1066 | + | |
1067 | + operands[2] = force_reg (<MODE>mode, gen_rtx_CONST_VECTOR (<MODE>mode, v)); | |
1068 | +}) | |
1069 | + | |
1070 | +(define_expand "and<mode>3" | |
1071 | + [(set (match_operand:MMXMODEI 0 "register_operand" "") | |
1072 | + (and:MMXMODEI (match_operand:MMXMODEI 1 "nonimmediate_operand" "") | |
1073 | + (match_operand:MMXMODEI 2 "nonimmediate_operand" "")))] | |
1074 | + "TARGET_MMX" | |
1075 | + "ix86_fixup_binary_operands_no_copy (AND, <MODE>mode, operands);") | |
1076 | + | |
1077 | (define_insn "mmx_and<mode>3" | |
1078 | [(set (match_operand:MMXMODEI 0 "register_operand" "=y") | |
1079 | (and:MMXMODEI | |
1080 | @@ -879,6 +982,13 @@ | |
1081 | [(set_attr "type" "mmxadd") | |
1082 | (set_attr "mode" "DI")]) | |
1083 | ||
1084 | +(define_expand "ior<mode>3" | |
1085 | + [(set (match_operand:MMXMODEI 0 "register_operand" "") | |
1086 | + (ior:MMXMODEI (match_operand:MMXMODEI 1 "nonimmediate_operand" "") | |
1087 | + (match_operand:MMXMODEI 2 "nonimmediate_operand" "")))] | |
1088 | + "TARGET_MMX" | |
1089 | + "ix86_fixup_binary_operands_no_copy (IOR, <MODE>mode, operands);") | |
1090 | + | |
1091 | (define_insn "mmx_ior<mode>3" | |
1092 | [(set (match_operand:MMXMODEI 0 "register_operand" "=y") | |
1093 | (ior:MMXMODEI | |
1094 | @@ -889,6 +999,13 @@ | |
1095 | [(set_attr "type" "mmxadd") | |
1096 | (set_attr "mode" "DI")]) | |
1097 | ||
1098 | +(define_expand "xor<mode>3" | |
1099 | + [(set (match_operand:MMXMODEI 0 "register_operand" "") | |
1100 | + (xor:MMXMODEI (match_operand:MMXMODEI 1 "nonimmediate_operand" "") | |
1101 | + (match_operand:MMXMODEI 2 "nonimmediate_operand" "")))] | |
1102 | + "TARGET_MMX" | |
1103 | + "ix86_fixup_binary_operands_no_copy (XOR, <MODE>mode, operands);") | |
1104 | + | |
1105 | (define_insn "mmx_xor<mode>3" | |
1106 | [(set (match_operand:MMXMODEI 0 "register_operand" "=y") | |
1107 | (xor:MMXMODEI | |
1108 | @@ -1147,7 +1264,7 @@ | |
1109 | (match_operand 2 "const_int_operand" "")] | |
1110 | "TARGET_MMX" | |
1111 | { | |
1112 | - ix86_expand_vector_set (false, operands[0], operands[1], | |
1113 | + ix86_expand_vector_set (true, operands[0], operands[1], | |
1114 | INTVAL (operands[2])); | |
1115 | DONE; | |
1116 | }) | |
1117 | @@ -1205,7 +1322,7 @@ | |
1118 | (match_operand 2 "const_int_operand" "")] | |
1119 | "TARGET_MMX" | |
1120 | { | |
1121 | - ix86_expand_vector_extract (false, operands[0], operands[1], | |
1122 | + ix86_expand_vector_extract (true, operands[0], operands[1], | |
1123 | INTVAL (operands[2])); | |
1124 | DONE; | |
1125 | }) | |
1126 | @@ -1215,7 +1332,7 @@ | |
1127 | (match_operand 1 "" "")] | |
1128 | "TARGET_SSE" | |
1129 | { | |
1130 | - ix86_expand_vector_init (false, operands[0], operands[1]); | |
1131 | + ix86_expand_vector_init (true, operands[0], operands[1]); | |
1132 | DONE; | |
1133 | }) | |
1134 | ||
1135 | @@ -1225,7 +1342,7 @@ | |
1136 | (match_operand 2 "const_int_operand" "")] | |
1137 | "TARGET_MMX" | |
1138 | { | |
1139 | - ix86_expand_vector_set (false, operands[0], operands[1], | |
1140 | + ix86_expand_vector_set (true, operands[0], operands[1], | |
1141 | INTVAL (operands[2])); | |
1142 | DONE; | |
1143 | }) | |
1144 | @@ -1236,7 +1353,7 @@ | |
1145 | (match_operand 2 "const_int_operand" "")] | |
1146 | "TARGET_MMX" | |
1147 | { | |
1148 | - ix86_expand_vector_extract (false, operands[0], operands[1], | |
1149 | + ix86_expand_vector_extract (true, operands[0], operands[1], | |
1150 | INTVAL (operands[2])); | |
1151 | DONE; | |
1152 | }) | |
1153 | @@ -1246,7 +1363,7 @@ | |
1154 | (match_operand 1 "" "")] | |
1155 | "TARGET_SSE" | |
1156 | { | |
1157 | - ix86_expand_vector_init (false, operands[0], operands[1]); | |
1158 | + ix86_expand_vector_init (true, operands[0], operands[1]); | |
1159 | DONE; | |
1160 | }) | |
1161 | ||
1162 | @@ -1256,7 +1373,7 @@ | |
1163 | (match_operand 2 "const_int_operand" "")] | |
1164 | "TARGET_MMX" | |
1165 | { | |
1166 | - ix86_expand_vector_set (false, operands[0], operands[1], | |
1167 | + ix86_expand_vector_set (true, operands[0], operands[1], | |
1168 | INTVAL (operands[2])); | |
1169 | DONE; | |
1170 | }) | |
1171 | @@ -1267,7 +1384,7 @@ | |
1172 | (match_operand 2 "const_int_operand" "")] | |
1173 | "TARGET_MMX" | |
1174 | { | |
1175 | - ix86_expand_vector_extract (false, operands[0], operands[1], | |
1176 | + ix86_expand_vector_extract (true, operands[0], operands[1], | |
1177 | INTVAL (operands[2])); | |
1178 | DONE; | |
1179 | }) | |
1180 | @@ -1277,7 +1394,7 @@ | |
1181 | (match_operand 1 "" "")] | |
1182 | "TARGET_SSE" | |
1183 | { | |
1184 | - ix86_expand_vector_init (false, operands[0], operands[1]); | |
1185 | + ix86_expand_vector_init (true, operands[0], operands[1]); | |
1186 | DONE; | |
1187 | }) | |
1188 | ||
1189 | @@ -1386,48 +1503,20 @@ | |
1190 | [(set_attr "type" "mmxcvt") | |
1191 | (set_attr "mode" "DI")]) | |
1192 | ||
1193 | -(define_insn "mmx_emms" | |
1194 | - [(unspec_volatile [(const_int 0)] UNSPECV_EMMS) | |
1195 | - (clobber (reg:XF 8)) | |
1196 | - (clobber (reg:XF 9)) | |
1197 | - (clobber (reg:XF 10)) | |
1198 | - (clobber (reg:XF 11)) | |
1199 | - (clobber (reg:XF 12)) | |
1200 | - (clobber (reg:XF 13)) | |
1201 | - (clobber (reg:XF 14)) | |
1202 | - (clobber (reg:XF 15)) | |
1203 | - (clobber (reg:DI 29)) | |
1204 | - (clobber (reg:DI 30)) | |
1205 | - (clobber (reg:DI 31)) | |
1206 | - (clobber (reg:DI 32)) | |
1207 | - (clobber (reg:DI 33)) | |
1208 | - (clobber (reg:DI 34)) | |
1209 | - (clobber (reg:DI 35)) | |
1210 | - (clobber (reg:DI 36))] | |
1211 | - "TARGET_MMX" | |
1212 | - "emms" | |
1213 | - [(set_attr "type" "mmx") | |
1214 | - (set_attr "memory" "unknown")]) | |
1215 | +(define_insn "efpu" | |
1216 | + [(set (reg:ALLREGS FIRSTFP_REG) | |
1217 | + (unspec_volatile:ALLREGS [(reg:ALLREGS FIRSTMMX_REG)] | |
1218 | + UNSPECV_EFPU))] | |
1219 | + "TARGET_80387 && TARGET_MMX" | |
1220 | + "" | |
1221 | + [(set_attr "length" "0")]) | |
1222 | + | |
1223 | +(define_insn "emms" | |
1224 | + [(set (reg:ALLREGS FIRSTMMX_REG) | |
1225 | + (unspec_volatile:ALLREGS [(reg:ALLREGS FIRSTFP_REG)] | |
1226 | + UNSPECV_EMMS))] | |
1227 | + "TARGET_80387 && TARGET_MMX" | |
1228 | +{ | |
1229 | + return TARGET_3DNOW ? "femms" : "emms"; | |
1230 | +}) | |
1231 | ||
1232 | -(define_insn "mmx_femms" | |
1233 | - [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS) | |
1234 | - (clobber (reg:XF 8)) | |
1235 | - (clobber (reg:XF 9)) | |
1236 | - (clobber (reg:XF 10)) | |
1237 | - (clobber (reg:XF 11)) | |
1238 | - (clobber (reg:XF 12)) | |
1239 | - (clobber (reg:XF 13)) | |
1240 | - (clobber (reg:XF 14)) | |
1241 | - (clobber (reg:XF 15)) | |
1242 | - (clobber (reg:DI 29)) | |
1243 | - (clobber (reg:DI 30)) | |
1244 | - (clobber (reg:DI 31)) | |
1245 | - (clobber (reg:DI 32)) | |
1246 | - (clobber (reg:DI 33)) | |
1247 | - (clobber (reg:DI 34)) | |
1248 | - (clobber (reg:DI 35)) | |
1249 | - (clobber (reg:DI 36))] | |
1250 | - "TARGET_3DNOW" | |
1251 | - "femms" | |
1252 | - [(set_attr "type" "mmx") | |
1253 | - (set_attr "memory" "none")]) | |
1254 | --- gcc/gcc/config/i386/sse.md 2005-06-29 19:27:19.000000000 +0200 | |
1255 | +++ gcc/gcc/config/i386/sse.md 2005-07-18 06:14:15.000000000 +0200 | |
1256 | @@ -881,6 +881,7 @@ | |
1257 | "TARGET_SSE" | |
1258 | "cvtpi2ps\t{%2, %0|%0, %2}" | |
1259 | [(set_attr "type" "ssecvt") | |
1260 | + (set_attr "unit" "mmx") | |
1261 | (set_attr "mode" "V4SF")]) | |
1262 | ||
1263 | (define_insn "sse_cvtps2pi" | |
1264 | @@ -3508,6 +3509,7 @@ | |
1265 | movhps\t{%2, %0|%0, %2} | |
1266 | movlps\t{%1, %0|%0, %1}" | |
1267 | [(set_attr "type" "ssemov,ssemov,sselog,ssemov,ssemov,ssemov") | |
1268 | + (set_attr "unit" "*,mmx,*,*,*,*") | |
1269 | (set_attr "mode" "TI,TI,TI,V4SF,V2SF,V2SF")]) | |
1270 | ||
1271 | (define_expand "vec_setv2di" | |
1272 | --- gcc/gcc/config/sh/sh.h 2005-07-03 23:08:07.000000000 +0200 | |
1273 | +++ gcc/gcc/config/sh/sh.h 2005-07-18 06:14:15.000000000 +0200 | |
1274 | @@ -3301,7 +3301,7 @@ extern struct rtx_def *sp_switch; | |
1275 | ? get_attr_fp_mode (INSN) \ | |
1276 | : FP_MODE_NONE) | |
1277 | ||
1278 | -#define MODE_AFTER(MODE, INSN) \ | |
1279 | +#define MODE_AFTER(ENTITY, MODE, INSN) \ | |
1280 | (TARGET_HITACHI \ | |
1281 | && recog_memoized (INSN) >= 0 \ | |
1282 | && get_attr_fp_set (INSN) != FP_SET_NONE \ | |
1283 | --- gcc/gcc/doc/tm.texi 2005-07-13 19:27:39.000000000 +0200 | |
1284 | +++ gcc/gcc/doc/tm.texi 2005-07-18 06:14:15.000000000 +0200 | |
1285 | @@ -4227,6 +4227,16 @@ stack adjustment in a function that has | |
1286 | compiler knows this regardless of @code{EXIT_IGNORE_STACK}. | |
1287 | @end defmac | |
1288 | ||
1289 | +@defmac CALL_INSN_SETS (@var{INSN}) | |
1290 | +Define this macro as a C expression that returns RTL expression of | |
1291 | +additional hard register set by call_insn. | |
1292 | +@end defmac | |
1293 | + | |
1294 | +@defmac CALL_INSN_USES (@var{INSN}) | |
1295 | +Define this macro as a C expression that returns RTL expression of | |
1296 | +additional hard register used by call_insn. | |
1297 | +@end defmac | |
1298 | + | |
1299 | @defmac EPILOGUE_USES (@var{regno}) | |
1300 | Define this macro as a C expression that is nonzero for registers that are | |
1301 | used by the epilogue or the @samp{return} pattern. The stack and frame | |
1302 | @@ -8376,6 +8386,13 @@ represented as numbers 0 @dots{} N @minu | |
1303 | switch is needed / supplied. | |
1304 | @end defmac | |
1305 | ||
1306 | +@defmac LIFE_ANALYSIS_AFTER_MODE_SWITCHING | |
1307 | +Define this macro if the port needs extra register life analysis after | |
1308 | +mode switching. This macro should be defined if mode switching inserts | |
1309 | +instructions that change global registers to maintain consistent global | |
1310 | +register life information. | |
1311 | +@end defmac | |
1312 | + | |
1313 | @defmac MODE_NEEDED (@var{entity}, @var{insn}) | |
1314 | @var{entity} is an integer specifying a mode-switched entity. If | |
1315 | @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro to | |
1316 | @@ -8384,9 +8401,9 @@ return an integer value not larger than | |
1317 | be switched into prior to the execution of @var{insn}. | |
1318 | @end defmac | |
1319 | ||
1320 | -@defmac MODE_AFTER (@var{mode}, @var{insn}) | |
1321 | -If this macro is defined, it is evaluated for every @var{insn} during | |
1322 | -mode switching. It determines the mode that an insn results in (if | |
1323 | +@defmac MODE_AFTER (@var{entity}, @var{mode}, @var{insn}) | |
1324 | +If this macro is defined, it is evaluated for every @var{entity} that needs | |
1325 | +mode switching. It determines the mode that an @var{insn} results in (if | |
1326 | different from the incoming mode). | |
1327 | @end defmac | |
1328 | ||
1329 | --- gcc/gcc/flow.c 2005-07-05 18:19:55.000000000 +0200 | |
1330 | +++ gcc/gcc/flow.c 2005-07-18 06:14:15.000000000 +0200 | |
1331 | @@ -1830,10 +1830,11 @@ propagate_one_insn (struct propagate_blo | |
1332 | { | |
1333 | regset live_at_end; | |
1334 | bool sibcall_p; | |
1335 | - rtx note, cond; | |
1336 | + rtx note; | |
1337 | + rtx cond = NULL_RTX; | |
1338 | + rtx reg ATTRIBUTE_UNUSED; | |
1339 | int i; | |
1340 | ||
1341 | - cond = NULL_RTX; | |
1342 | if (GET_CODE (PATTERN (insn)) == COND_EXEC) | |
1343 | cond = COND_EXEC_TEST (PATTERN (insn)); | |
1344 | ||
1345 | @@ -1856,6 +1857,13 @@ propagate_one_insn (struct propagate_blo | |
1346 | mark_set_1 (pbi, CLOBBER, XEXP (XEXP (note, 0), 0), | |
1347 | cond, insn, pbi->flags); | |
1348 | ||
1349 | +#ifdef CALL_INSN_SETS | |
1350 | + reg = CALL_INSN_SETS (insn); | |
1351 | + | |
1352 | + if (reg) | |
1353 | + mark_set_1 (pbi, SET, reg, cond, insn, pbi->flags); | |
1354 | +#endif | |
1355 | + | |
1356 | /* Calls change all call-used and global registers; sibcalls do not | |
1357 | clobber anything that must be preserved at end-of-function, | |
1358 | except for return values. */ | |
1359 | @@ -1894,10 +1902,11 @@ propagate_one_insn (struct propagate_blo | |
1360 | ||
1361 | if (! insn_is_dead && CALL_P (insn)) | |
1362 | { | |
1363 | + rtx note; | |
1364 | + rtx cond = NULL_RTX; | |
1365 | + rtx reg ATTRIBUTE_UNUSED; | |
1366 | int i; | |
1367 | - rtx note, cond; | |
1368 | ||
1369 | - cond = NULL_RTX; | |
1370 | if (GET_CODE (PATTERN (insn)) == COND_EXEC) | |
1371 | cond = COND_EXEC_TEST (PATTERN (insn)); | |
1372 | ||
1373 | @@ -1910,6 +1919,13 @@ propagate_one_insn (struct propagate_blo | |
1374 | of which mark_used_regs knows how to handle. */ | |
1375 | mark_used_regs (pbi, XEXP (XEXP (note, 0), 0), cond, insn); | |
1376 | ||
1377 | +#ifdef CALL_INSN_USES | |
1378 | + reg = CALL_INSN_USES (insn); | |
1379 | + | |
1380 | + if (reg) | |
1381 | + mark_used_reg (pbi, reg, cond, insn); | |
1382 | +#endif | |
1383 | + | |
1384 | /* The stack ptr is used (honorarily) by a CALL insn. */ | |
1385 | if ((flags & PROP_REG_INFO) | |
1386 | && !REGNO_REG_SET_P (pbi->reg_live, STACK_POINTER_REGNUM)) | |
1387 | --- gcc/gcc/mode-switching.c 2005-07-05 18:20:07.000000000 +0200 | |
1388 | +++ gcc/gcc/mode-switching.c 2005-07-18 06:14:15.000000000 +0200 | |
1389 | @@ -473,7 +473,7 @@ optimize_mode_switching (FILE *file) | |
1390 | RESET_BIT (transp[bb->index], j); | |
1391 | } | |
1392 | #ifdef MODE_AFTER | |
1393 | - last_mode = MODE_AFTER (last_mode, insn); | |
1394 | + last_mode = MODE_AFTER (e, last_mode, insn); | |
1395 | #endif | |
1396 | /* Update LIVE_NOW. */ | |
1397 | for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) | |
1398 | @@ -730,6 +730,14 @@ rest_of_handle_mode_switching (void) | |
1399 | no_new_pseudos = 0; | |
1400 | optimize_mode_switching (NULL); | |
1401 | no_new_pseudos = 1; | |
1402 | + | |
1403 | + /* Mode switching can insert instructions that | |
1404 | + change global registers life data. */ | |
1405 | +#ifdef LIFE_ANALYSIS_AFTER_MODE_SWITCHING | |
1406 | + if (LIFE_ANALYSIS_AFTER_MODE_SWITCHING) | |
1407 | + life_analysis (NULL, PROP_REG_INFO); | |
1408 | +#endif | |
1409 | + | |
1410 | #endif /* OPTIMIZE_MODE_SWITCHING */ | |
1411 | } | |
1412 | ||
1413 | --- gcc/gcc/reg-stack.c 2005-07-14 09:39:54.000000000 +0200 | |
1414 | +++ gcc/gcc/reg-stack.c 2005-07-18 06:14:15.000000000 +0200 | |
1415 | @@ -1579,6 +1579,41 @@ subst_stack_regs_pat (rtx insn, stack re | |
1416 | } | |
1417 | break; | |
1418 | ||
1419 | + case UNSPEC_VOLATILE: | |
1420 | + switch (XINT (pat_src, 1)) | |
1421 | + { | |
1422 | + int i; | |
1423 | + | |
1424 | + case UNSPECV_EFPU: | |
1425 | + /* There should be no stack registers live | |
1426 | + at this point. */ | |
1427 | + gcc_assert (regstack->top == -1); | |
1428 | + | |
1429 | + /* Mark all x87 registers as used. */ | |
1430 | + for (i = LAST_STACK_REG; i >= FIRST_STACK_REG; i--) | |
1431 | + { | |
1432 | + regstack->reg[++regstack->top] = i; | |
1433 | + SET_HARD_REG_BIT (regstack->reg_set, i); | |
1434 | + } | |
1435 | + break; | |
1436 | + | |
1437 | + case UNSPECV_EMMS: | |
1438 | + /* All stack registers should be alive | |
1439 | + at this point. */ | |
1440 | + gcc_assert (regstack->top == REG_STACK_SIZE - 1); | |
1441 | + | |
1442 | + /* Mark all x87 registers as empty. */ | |
1443 | + for (i = LAST_STACK_REG; i >= FIRST_STACK_REG; i--) | |
1444 | + CLEAR_HARD_REG_BIT (regstack->reg_set, i); | |
1445 | + | |
1446 | + regstack->top = -1; | |
1447 | + break; | |
1448 | + | |
1449 | + default: | |
1450 | + gcc_unreachable (); | |
1451 | + } | |
1452 | + break; | |
1453 | + | |
1454 | case UNSPEC: | |
1455 | switch (XINT (pat_src, 1)) | |
1456 | { | |
1457 | @@ -2269,6 +2304,25 @@ subst_stack_regs (rtx insn, stack regsta | |
1458 | if (NOTE_P (insn) || INSN_DELETED_P (insn)) | |
1459 | return control_flow_insn_deleted; | |
1460 | ||
1461 | +#ifdef CALL_INSN_SETS | |
1462 | + if (CALL_P (insn)) | |
1463 | + { | |
1464 | + rtx reg = CALL_INSN_SETS (insn); | |
1465 | + | |
1466 | + if (reg && STACK_REG_P (reg)) | |
1467 | + { | |
1468 | + int count; | |
1469 | + | |
1470 | + for (count = hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]; | |
1471 | + --count >= 0;) | |
1472 | + { | |
1473 | + regstack->reg[++regstack->top] = REGNO (reg) + count; | |
1474 | + SET_HARD_REG_BIT (regstack->reg_set, REGNO (reg) + count); | |
1475 | + } | |
1476 | + } | |
1477 | + } | |
1478 | +#endif | |
1479 | + | |
1480 | /* If there is a REG_UNUSED note on a stack register on this insn, | |
1481 | the indicated reg must be popped. The REG_UNUSED note is removed, | |
1482 | since the form of the newly emitted pop insn references the reg, | |
1483 | @@ -2544,6 +2598,15 @@ convert_regs_entry (void) | |
1484 | basic_block block = e->dest; | |
1485 | block_info bi = BLOCK_INFO (block); | |
1486 | int reg, top = -1; | |
1487 | + int numregs = 0; | |
1488 | + | |
1489 | + /* Check if all stack registers are live at function entry. | |
1490 | + This is the case where stack registers are disabled and no | |
1491 | + register initialization is needed. */ | |
1492 | + | |
1493 | + for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg) | |
1494 | + if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg)) | |
1495 | + numregs++; | |
1496 | ||
1497 | for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg) | |
1498 | if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg)) | |
1499 | @@ -2552,11 +2615,14 @@ convert_regs_entry (void) | |
1500 | ||
1501 | bi->stack_in.reg[++top] = reg; | |
1502 | ||
1503 | - init = gen_rtx_SET (VOIDmode, | |
1504 | - FP_MODE_REG (FIRST_STACK_REG, SFmode), | |
1505 | - not_a_num); | |
1506 | - insert_insn_on_edge (init, e); | |
1507 | - inserted = 1; | |
1508 | + if (numregs != REG_STACK_SIZE) | |
1509 | + { | |
1510 | + init = gen_rtx_SET (VOIDmode, | |
1511 | + FP_MODE_REG (FIRST_STACK_REG, SFmode), | |
1512 | + not_a_num); | |
1513 | + insert_insn_on_edge (init, e); | |
1514 | + inserted = 1; | |
1515 | + } | |
1516 | } | |
1517 | ||
1518 | bi->stack_in.top = top; | |
1519 | @@ -2575,13 +2641,34 @@ convert_regs_exit (void) | |
1520 | stack output_stack; | |
1521 | rtx retvalue; | |
1522 | ||
1523 | - retvalue = stack_result (current_function_decl); | |
1524 | value_reg_low = value_reg_high = -1; | |
1525 | - if (retvalue) | |
1526 | + | |
1527 | +#ifdef EPILOGUE_USES | |
1528 | + { | |
1529 | + int numregs = 0; | |
1530 | + int i; | |
1531 | + | |
1532 | + for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++) | |
1533 | + if (EPILOGUE_USES (i)) | |
1534 | + numregs++; | |
1535 | + | |
1536 | + if (numregs) | |
1537 | + { | |
1538 | + value_reg_low = FIRST_STACK_REG; | |
1539 | + value_reg_high = value_reg_low + numregs - 1; | |
1540 | + } | |
1541 | + } | |
1542 | +#endif | |
1543 | + | |
1544 | + if (value_reg_low < 0) | |
1545 | { | |
1546 | - value_reg_low = REGNO (retvalue); | |
1547 | - value_reg_high = value_reg_low | |
1548 | - + hard_regno_nregs[value_reg_low][GET_MODE (retvalue)] - 1; | |
1549 | + retvalue = stack_result (current_function_decl); | |
1550 | + if (retvalue) | |
1551 | + { | |
1552 | + value_reg_low = REGNO (retvalue); | |
1553 | + value_reg_high = value_reg_low | |
1554 | + + hard_regno_nregs[value_reg_low][GET_MODE (retvalue)] - 1; | |
1555 | + } | |
1556 | } | |
1557 | ||
1558 | output_stack = &BLOCK_INFO (EXIT_BLOCK_PTR)->stack_in; |