Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/spu/spu.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | 3bfb6c00c1e0 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
46 #include "reload.h" | 46 #include "reload.h" |
47 #include "cfglayout.h" | 47 #include "cfglayout.h" |
48 #include "sched-int.h" | 48 #include "sched-int.h" |
49 #include "params.h" | 49 #include "params.h" |
50 #include "assert.h" | 50 #include "assert.h" |
51 #include "c-common.h" | |
52 #include "machmode.h" | 51 #include "machmode.h" |
53 #include "gimple.h" | 52 #include "gimple.h" |
54 #include "tm-constrs.h" | 53 #include "tm-constrs.h" |
55 #include "ddg.h" | 54 #include "ddg.h" |
56 #include "sbitmap.h" | 55 #include "sbitmap.h" |
149 /* Target specific attribute specifications. */ | 148 /* Target specific attribute specifications. */ |
150 char regs_ever_allocated[FIRST_PSEUDO_REGISTER]; | 149 char regs_ever_allocated[FIRST_PSEUDO_REGISTER]; |
151 | 150 |
152 /* Prototypes and external defs. */ | 151 /* Prototypes and external defs. */ |
153 static void spu_init_builtins (void); | 152 static void spu_init_builtins (void); |
153 static tree spu_builtin_decl (unsigned, bool); | |
154 static unsigned char spu_scalar_mode_supported_p (enum machine_mode mode); | 154 static unsigned char spu_scalar_mode_supported_p (enum machine_mode mode); |
155 static unsigned char spu_vector_mode_supported_p (enum machine_mode mode); | 155 static unsigned char spu_vector_mode_supported_p (enum machine_mode mode); |
156 static bool spu_legitimate_address_p (enum machine_mode, rtx, bool); | |
157 static bool spu_addr_space_legitimate_address_p (enum machine_mode, rtx, | |
158 bool, addr_space_t); | |
156 static rtx adjust_operand (rtx op, HOST_WIDE_INT * start); | 159 static rtx adjust_operand (rtx op, HOST_WIDE_INT * start); |
157 static rtx get_pic_reg (void); | 160 static rtx get_pic_reg (void); |
158 static int need_to_save_reg (int regno, int saving); | 161 static int need_to_save_reg (int regno, int saving); |
159 static rtx frame_emit_store (int regno, rtx addr, HOST_WIDE_INT offset); | 162 static rtx frame_emit_store (int regno, rtx addr, HOST_WIDE_INT offset); |
160 static rtx frame_emit_load (int regno, rtx addr, HOST_WIDE_INT offset); | 163 static rtx frame_emit_load (int regno, rtx addr, HOST_WIDE_INT offset); |
199 static unsigned char spu_function_ok_for_sibcall (tree decl, tree exp); | 202 static unsigned char spu_function_ok_for_sibcall (tree decl, tree exp); |
200 static void spu_init_libfuncs (void); | 203 static void spu_init_libfuncs (void); |
201 static bool spu_return_in_memory (const_tree type, const_tree fntype); | 204 static bool spu_return_in_memory (const_tree type, const_tree fntype); |
202 static void fix_range (const char *); | 205 static void fix_range (const char *); |
203 static void spu_encode_section_info (tree, rtx, int); | 206 static void spu_encode_section_info (tree, rtx, int); |
207 static rtx spu_legitimize_address (rtx, rtx, enum machine_mode); | |
208 static rtx spu_addr_space_legitimize_address (rtx, rtx, enum machine_mode, | |
209 addr_space_t); | |
204 static tree spu_builtin_mul_widen_even (tree); | 210 static tree spu_builtin_mul_widen_even (tree); |
205 static tree spu_builtin_mul_widen_odd (tree); | 211 static tree spu_builtin_mul_widen_odd (tree); |
206 static tree spu_builtin_mask_for_load (void); | 212 static tree spu_builtin_mask_for_load (void); |
207 static int spu_builtin_vectorization_cost (bool); | 213 static int spu_builtin_vectorization_cost (bool); |
208 static bool spu_vector_alignment_reachable (const_tree, bool); | 214 static bool spu_vector_alignment_reachable (const_tree, bool); |
209 static tree spu_builtin_vec_perm (tree, tree *); | 215 static tree spu_builtin_vec_perm (tree, tree *); |
216 static enum machine_mode spu_addr_space_pointer_mode (addr_space_t); | |
217 static enum machine_mode spu_addr_space_address_mode (addr_space_t); | |
218 static bool spu_addr_space_subset_p (addr_space_t, addr_space_t); | |
219 static rtx spu_addr_space_convert (rtx, tree, tree); | |
210 static int spu_sms_res_mii (struct ddg *g); | 220 static int spu_sms_res_mii (struct ddg *g); |
211 static void asm_file_start (void); | 221 static void asm_file_start (void); |
212 static unsigned int spu_section_type_flags (tree, const char *, int); | 222 static unsigned int spu_section_type_flags (tree, const char *, int); |
223 static section *spu_select_section (tree, int, unsigned HOST_WIDE_INT); | |
224 static void spu_unique_section (tree, int); | |
213 static rtx spu_expand_load (rtx, rtx, rtx, int); | 225 static rtx spu_expand_load (rtx, rtx, rtx, int); |
226 static void spu_trampoline_init (rtx, tree, rtx); | |
214 | 227 |
215 extern const char *reg_names[]; | 228 extern const char *reg_names[]; |
216 rtx spu_compare_op0, spu_compare_op1; | |
217 | 229 |
218 /* Which instruction set architecture to use. */ | 230 /* Which instruction set architecture to use. */ |
219 int spu_arch; | 231 int spu_arch; |
220 /* Which cpu are we tuning for. */ | 232 /* Which cpu are we tuning for. */ |
221 int spu_tune; | 233 int spu_tune; |
267 spu_libgcc_cmp_return_mode (void); | 279 spu_libgcc_cmp_return_mode (void); |
268 | 280 |
269 static enum machine_mode | 281 static enum machine_mode |
270 spu_libgcc_shift_count_mode (void); | 282 spu_libgcc_shift_count_mode (void); |
271 | 283 |
284 /* Pointer mode for __ea references. */ | |
285 #define EAmode (spu_ea_model != 32 ? DImode : SImode) | |
286 | |
287 | |
288 /* Table of machine attributes. */ | |
289 static const struct attribute_spec spu_attribute_table[] = | |
290 { | |
291 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ | |
292 { "naked", 0, 0, true, false, false, spu_handle_fndecl_attribute }, | |
293 { "spu_vector", 0, 0, false, true, false, spu_handle_vector_attribute }, | |
294 { NULL, 0, 0, false, false, false, NULL } | |
295 }; | |
272 | 296 |
273 /* TARGET overrides. */ | 297 /* TARGET overrides. */ |
274 | 298 |
299 #undef TARGET_ADDR_SPACE_POINTER_MODE | |
300 #define TARGET_ADDR_SPACE_POINTER_MODE spu_addr_space_pointer_mode | |
301 | |
302 #undef TARGET_ADDR_SPACE_ADDRESS_MODE | |
303 #define TARGET_ADDR_SPACE_ADDRESS_MODE spu_addr_space_address_mode | |
304 | |
305 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P | |
306 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \ | |
307 spu_addr_space_legitimate_address_p | |
308 | |
309 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS | |
310 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS spu_addr_space_legitimize_address | |
311 | |
312 #undef TARGET_ADDR_SPACE_SUBSET_P | |
313 #define TARGET_ADDR_SPACE_SUBSET_P spu_addr_space_subset_p | |
314 | |
315 #undef TARGET_ADDR_SPACE_CONVERT | |
316 #define TARGET_ADDR_SPACE_CONVERT spu_addr_space_convert | |
317 | |
275 #undef TARGET_INIT_BUILTINS | 318 #undef TARGET_INIT_BUILTINS |
276 #define TARGET_INIT_BUILTINS spu_init_builtins | 319 #define TARGET_INIT_BUILTINS spu_init_builtins |
320 #undef TARGET_BUILTIN_DECL | |
321 #define TARGET_BUILTIN_DECL spu_builtin_decl | |
277 | 322 |
278 #undef TARGET_EXPAND_BUILTIN | 323 #undef TARGET_EXPAND_BUILTIN |
279 #define TARGET_EXPAND_BUILTIN spu_expand_builtin | 324 #define TARGET_EXPAND_BUILTIN spu_expand_builtin |
280 | 325 |
281 #undef TARGET_UNWIND_WORD_MODE | 326 #undef TARGET_UNWIND_WORD_MODE |
282 #define TARGET_UNWIND_WORD_MODE spu_unwind_word_mode | 327 #define TARGET_UNWIND_WORD_MODE spu_unwind_word_mode |
328 | |
329 #undef TARGET_LEGITIMIZE_ADDRESS | |
330 #define TARGET_LEGITIMIZE_ADDRESS spu_legitimize_address | |
331 | |
332 /* The current assembler doesn't like .4byte foo@ppu, so use the normal .long | |
333 and .quad for the debugger. When it is known that the assembler is fixed, | |
334 these can be removed. */ | |
335 #undef TARGET_ASM_UNALIGNED_SI_OP | |
336 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t" | |
337 | |
338 #undef TARGET_ASM_ALIGNED_DI_OP | |
339 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t" | |
283 | 340 |
284 /* The .8byte directive doesn't seem to work well for a 32 bit | 341 /* The .8byte directive doesn't seem to work well for a 32 bit |
285 architecture. */ | 342 architecture. */ |
286 #undef TARGET_ASM_UNALIGNED_DI_OP | 343 #undef TARGET_ASM_UNALIGNED_DI_OP |
287 #define TARGET_ASM_UNALIGNED_DI_OP NULL | 344 #define TARGET_ASM_UNALIGNED_DI_OP NULL |
311 #define TARGET_SCHED_REORDER2 spu_sched_reorder | 368 #define TARGET_SCHED_REORDER2 spu_sched_reorder |
312 | 369 |
313 #undef TARGET_SCHED_ADJUST_COST | 370 #undef TARGET_SCHED_ADJUST_COST |
314 #define TARGET_SCHED_ADJUST_COST spu_sched_adjust_cost | 371 #define TARGET_SCHED_ADJUST_COST spu_sched_adjust_cost |
315 | 372 |
316 const struct attribute_spec spu_attribute_table[]; | |
317 #undef TARGET_ATTRIBUTE_TABLE | 373 #undef TARGET_ATTRIBUTE_TABLE |
318 #define TARGET_ATTRIBUTE_TABLE spu_attribute_table | 374 #define TARGET_ATTRIBUTE_TABLE spu_attribute_table |
319 | 375 |
320 #undef TARGET_ASM_INTEGER | 376 #undef TARGET_ASM_INTEGER |
321 #define TARGET_ASM_INTEGER spu_assemble_integer | 377 #define TARGET_ASM_INTEGER spu_assemble_integer |
395 #undef TARGET_ASM_FILE_START | 451 #undef TARGET_ASM_FILE_START |
396 #define TARGET_ASM_FILE_START asm_file_start | 452 #define TARGET_ASM_FILE_START asm_file_start |
397 | 453 |
398 #undef TARGET_SECTION_TYPE_FLAGS | 454 #undef TARGET_SECTION_TYPE_FLAGS |
399 #define TARGET_SECTION_TYPE_FLAGS spu_section_type_flags | 455 #define TARGET_SECTION_TYPE_FLAGS spu_section_type_flags |
456 | |
457 #undef TARGET_ASM_SELECT_SECTION | |
458 #define TARGET_ASM_SELECT_SECTION spu_select_section | |
459 | |
460 #undef TARGET_ASM_UNIQUE_SECTION | |
461 #define TARGET_ASM_UNIQUE_SECTION spu_unique_section | |
462 | |
463 #undef TARGET_LEGITIMATE_ADDRESS_P | |
464 #define TARGET_LEGITIMATE_ADDRESS_P spu_legitimate_address_p | |
465 | |
466 #undef TARGET_TRAMPOLINE_INIT | |
467 #define TARGET_TRAMPOLINE_INIT spu_trampoline_init | |
400 | 468 |
401 struct gcc_target targetm = TARGET_INITIALIZER; | 469 struct gcc_target targetm = TARGET_INITIALIZER; |
402 | 470 |
403 void | 471 void |
404 spu_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED) | 472 spu_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED) |
472 REAL_MODE_FORMAT (SFmode) = &spu_single_format; | 540 REAL_MODE_FORMAT (SFmode) = &spu_single_format; |
473 } | 541 } |
474 | 542 |
475 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in | 543 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in |
476 struct attribute_spec.handler. */ | 544 struct attribute_spec.handler. */ |
477 | |
478 /* Table of machine attributes. */ | |
479 const struct attribute_spec spu_attribute_table[] = | |
480 { | |
481 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ | |
482 { "naked", 0, 0, true, false, false, spu_handle_fndecl_attribute }, | |
483 { "spu_vector", 0, 0, false, true, false, spu_handle_vector_attribute }, | |
484 { NULL, 0, 0, false, false, false, NULL } | |
485 }; | |
486 | 545 |
487 /* True if MODE is valid for the target. By "valid", we mean able to | 546 /* True if MODE is valid for the target. By "valid", we mean able to |
488 be manipulated in non-trivial ways. In particular, this means all | 547 be manipulated in non-trivial ways. In particular, this means all |
489 the arithmetic is supported. */ | 548 the arithmetic is supported. */ |
490 static bool | 549 static bool |
635 if (GET_MODE_SIZE (GET_MODE (r)) < GET_MODE_SIZE (TImode)) | 694 if (GET_MODE_SIZE (GET_MODE (r)) < GET_MODE_SIZE (TImode)) |
636 emit_insn (gen_rtx_SET (VOIDmode, s0, gen_rtx_ZERO_EXTEND (TImode, r))); | 695 emit_insn (gen_rtx_SET (VOIDmode, s0, gen_rtx_ZERO_EXTEND (TImode, r))); |
637 else | 696 else |
638 emit_move_insn (s0, src); | 697 emit_move_insn (s0, src); |
639 } | 698 } |
640 else | 699 else |
641 { | 700 { |
642 gcc_assert (REG_P (src) && GET_MODE (src) == TImode); | 701 gcc_assert (REG_P (src) && GET_MODE (src) == TImode); |
643 s0 = gen_reg_rtx (TImode); | 702 s0 = gen_reg_rtx (TImode); |
644 emit_move_insn (s0, src); | 703 emit_move_insn (s0, src); |
645 } | 704 } |
862 the result of the compare. GCC can figure this out too if we don't | 921 the result of the compare. GCC can figure this out too if we don't |
863 provide all variations of compares, but GCC always wants to use | 922 provide all variations of compares, but GCC always wants to use |
864 WORD_MODE, we can generate better code in most cases if we do it | 923 WORD_MODE, we can generate better code in most cases if we do it |
865 ourselves. */ | 924 ourselves. */ |
866 void | 925 void |
867 spu_emit_branch_or_set (int is_set, enum rtx_code code, rtx operands[]) | 926 spu_emit_branch_or_set (int is_set, rtx cmp, rtx operands[]) |
868 { | 927 { |
869 int reverse_compare = 0; | 928 int reverse_compare = 0; |
870 int reverse_test = 0; | 929 int reverse_test = 0; |
871 rtx compare_result, eq_result; | 930 rtx compare_result, eq_result; |
872 rtx comp_rtx, eq_rtx; | 931 rtx comp_rtx, eq_rtx; |
873 rtx target = operands[0]; | |
874 enum machine_mode comp_mode; | 932 enum machine_mode comp_mode; |
875 enum machine_mode op_mode; | 933 enum machine_mode op_mode; |
876 enum spu_comp_code scode, eq_code, ior_code; | 934 enum spu_comp_code scode, eq_code; |
935 enum insn_code ior_code; | |
936 enum rtx_code code = GET_CODE (cmp); | |
937 rtx op0 = XEXP (cmp, 0); | |
938 rtx op1 = XEXP (cmp, 1); | |
877 int index; | 939 int index; |
878 int eq_test = 0; | 940 int eq_test = 0; |
879 | 941 |
880 /* When spu_compare_op1 is a CONST_INT change (X >= C) to (X > C-1), | 942 /* When op1 is a CONST_INT change (X >= C) to (X > C-1), |
881 and so on, to keep the constant in operand 1. */ | 943 and so on, to keep the constant in operand 1. */ |
882 if (GET_CODE (spu_compare_op1) == CONST_INT) | 944 if (GET_CODE (op1) == CONST_INT) |
883 { | 945 { |
884 HOST_WIDE_INT val = INTVAL (spu_compare_op1) - 1; | 946 HOST_WIDE_INT val = INTVAL (op1) - 1; |
885 if (trunc_int_for_mode (val, GET_MODE (spu_compare_op0)) == val) | 947 if (trunc_int_for_mode (val, GET_MODE (op0)) == val) |
886 switch (code) | 948 switch (code) |
887 { | 949 { |
888 case GE: | 950 case GE: |
889 spu_compare_op1 = GEN_INT (val); | 951 op1 = GEN_INT (val); |
890 code = GT; | 952 code = GT; |
891 break; | 953 break; |
892 case LT: | 954 case LT: |
893 spu_compare_op1 = GEN_INT (val); | 955 op1 = GEN_INT (val); |
894 code = LE; | 956 code = LE; |
895 break; | 957 break; |
896 case GEU: | 958 case GEU: |
897 spu_compare_op1 = GEN_INT (val); | 959 op1 = GEN_INT (val); |
898 code = GTU; | 960 code = GTU; |
899 break; | 961 break; |
900 case LTU: | 962 case LTU: |
901 spu_compare_op1 = GEN_INT (val); | 963 op1 = GEN_INT (val); |
902 code = LEU; | 964 code = LEU; |
903 break; | 965 break; |
904 default: | 966 default: |
905 break; | 967 break; |
906 } | 968 } |
907 } | 969 } |
908 | 970 |
909 comp_mode = SImode; | 971 comp_mode = SImode; |
910 op_mode = GET_MODE (spu_compare_op0); | 972 op_mode = GET_MODE (op0); |
911 | 973 |
912 switch (code) | 974 switch (code) |
913 { | 975 { |
914 case GE: | 976 case GE: |
915 scode = SPU_GT; | 977 scode = SPU_GT; |
1029 case V2DImode: | 1091 case V2DImode: |
1030 default: | 1092 default: |
1031 abort (); | 1093 abort (); |
1032 } | 1094 } |
1033 | 1095 |
1034 if (GET_MODE (spu_compare_op1) == DFmode | 1096 if (GET_MODE (op1) == DFmode |
1035 && (scode != SPU_GT && scode != SPU_EQ)) | 1097 && (scode != SPU_GT && scode != SPU_EQ)) |
1036 abort (); | 1098 abort (); |
1037 | 1099 |
1038 if (is_set == 0 && spu_compare_op1 == const0_rtx | 1100 if (is_set == 0 && op1 == const0_rtx |
1039 && (GET_MODE (spu_compare_op0) == SImode | 1101 && (GET_MODE (op0) == SImode |
1040 || GET_MODE (spu_compare_op0) == HImode) && scode == SPU_EQ) | 1102 || GET_MODE (op0) == HImode) && scode == SPU_EQ) |
1041 { | 1103 { |
1042 /* Don't need to set a register with the result when we are | 1104 /* Don't need to set a register with the result when we are |
1043 comparing against zero and branching. */ | 1105 comparing against zero and branching. */ |
1044 reverse_test = !reverse_test; | 1106 reverse_test = !reverse_test; |
1045 compare_result = spu_compare_op0; | 1107 compare_result = op0; |
1046 } | 1108 } |
1047 else | 1109 else |
1048 { | 1110 { |
1049 compare_result = gen_reg_rtx (comp_mode); | 1111 compare_result = gen_reg_rtx (comp_mode); |
1050 | 1112 |
1051 if (reverse_compare) | 1113 if (reverse_compare) |
1052 { | 1114 { |
1053 rtx t = spu_compare_op1; | 1115 rtx t = op1; |
1054 spu_compare_op1 = spu_compare_op0; | 1116 op1 = op0; |
1055 spu_compare_op0 = t; | 1117 op0 = t; |
1056 } | 1118 } |
1057 | 1119 |
1058 if (spu_comp_icode[index][scode] == 0) | 1120 if (spu_comp_icode[index][scode] == 0) |
1059 abort (); | 1121 abort (); |
1060 | 1122 |
1061 if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate) | 1123 if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate) |
1062 (spu_compare_op0, op_mode)) | 1124 (op0, op_mode)) |
1063 spu_compare_op0 = force_reg (op_mode, spu_compare_op0); | 1125 op0 = force_reg (op_mode, op0); |
1064 if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate) | 1126 if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate) |
1065 (spu_compare_op1, op_mode)) | 1127 (op1, op_mode)) |
1066 spu_compare_op1 = force_reg (op_mode, spu_compare_op1); | 1128 op1 = force_reg (op_mode, op1); |
1067 comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result, | 1129 comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result, |
1068 spu_compare_op0, | 1130 op0, op1); |
1069 spu_compare_op1); | |
1070 if (comp_rtx == 0) | 1131 if (comp_rtx == 0) |
1071 abort (); | 1132 abort (); |
1072 emit_insn (comp_rtx); | 1133 emit_insn (comp_rtx); |
1073 | 1134 |
1074 if (eq_test) | 1135 if (eq_test) |
1075 { | 1136 { |
1076 eq_result = gen_reg_rtx (comp_mode); | 1137 eq_result = gen_reg_rtx (comp_mode); |
1077 eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result, | 1138 eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result, |
1078 spu_compare_op0, | 1139 op0, op1); |
1079 spu_compare_op1); | |
1080 if (eq_rtx == 0) | 1140 if (eq_rtx == 0) |
1081 abort (); | 1141 abort (); |
1082 emit_insn (eq_rtx); | 1142 emit_insn (eq_rtx); |
1083 ior_code = ior_optab->handlers[(int)comp_mode].insn_code; | 1143 ior_code = ior_optab->handlers[(int)comp_mode].insn_code; |
1084 gcc_assert (ior_code != CODE_FOR_nothing); | 1144 gcc_assert (ior_code != CODE_FOR_nothing); |
1105 if (reverse_test) | 1165 if (reverse_test) |
1106 bcomp = gen_rtx_EQ (comp_mode, compare_result, const0_rtx); | 1166 bcomp = gen_rtx_EQ (comp_mode, compare_result, const0_rtx); |
1107 else | 1167 else |
1108 bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx); | 1168 bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx); |
1109 | 1169 |
1110 loc_ref = gen_rtx_LABEL_REF (VOIDmode, target); | 1170 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]); |
1111 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, | 1171 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, |
1112 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, | 1172 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, |
1113 loc_ref, pc_rtx))); | 1173 loc_ref, pc_rtx))); |
1114 } | 1174 } |
1115 else if (is_set == 2) | 1175 else if (is_set == 2) |
1116 { | 1176 { |
1177 rtx target = operands[0]; | |
1117 int compare_size = GET_MODE_BITSIZE (comp_mode); | 1178 int compare_size = GET_MODE_BITSIZE (comp_mode); |
1118 int target_size = GET_MODE_BITSIZE (GET_MODE (target)); | 1179 int target_size = GET_MODE_BITSIZE (GET_MODE (target)); |
1119 enum machine_mode mode = mode_for_size (target_size, MODE_INT, 0); | 1180 enum machine_mode mode = mode_for_size (target_size, MODE_INT, 0); |
1120 rtx select_mask; | 1181 rtx select_mask; |
1121 rtx op_t = operands[2]; | 1182 rtx op_t = operands[2]; |
1146 else | 1207 else |
1147 emit_insn (gen_selb (target, op_f, op_t, select_mask)); | 1208 emit_insn (gen_selb (target, op_f, op_t, select_mask)); |
1148 } | 1209 } |
1149 else | 1210 else |
1150 { | 1211 { |
1212 rtx target = operands[0]; | |
1151 if (reverse_test) | 1213 if (reverse_test) |
1152 emit_insn (gen_rtx_SET (VOIDmode, compare_result, | 1214 emit_insn (gen_rtx_SET (VOIDmode, compare_result, |
1153 gen_rtx_NOT (comp_mode, compare_result))); | 1215 gen_rtx_NOT (comp_mode, compare_result))); |
1154 if (GET_MODE (target) == SImode && GET_MODE (compare_result) == HImode) | 1216 if (GET_MODE (target) == SImode && GET_MODE (compare_result) == HImode) |
1155 emit_insn (gen_extendhisi2 (target, compare_result)); | 1217 emit_insn (gen_extendhisi2 (target, compare_result)); |
1972 /* In this case we save the back chain first. */ | 2034 /* In this case we save the back chain first. */ |
1973 insn = frame_emit_store (STACK_POINTER_REGNUM, sp_reg, -total_size); | 2035 insn = frame_emit_store (STACK_POINTER_REGNUM, sp_reg, -total_size); |
1974 insn = | 2036 insn = |
1975 frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_0); | 2037 frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_0); |
1976 } | 2038 } |
1977 else if (satisfies_constraint_K (GEN_INT (-total_size))) | |
1978 { | |
1979 insn = emit_move_insn (scratch_reg_0, sp_reg); | |
1980 insn = | |
1981 emit_insn (gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size))); | |
1982 } | |
1983 else | 2039 else |
1984 { | 2040 { |
1985 insn = emit_move_insn (scratch_reg_0, sp_reg); | 2041 insn = emit_move_insn (scratch_reg_0, sp_reg); |
1986 insn = | 2042 insn = |
1987 frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_1); | 2043 frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_1); |
1988 } | 2044 } |
1989 RTX_FRAME_RELATED_P (insn) = 1; | 2045 RTX_FRAME_RELATED_P (insn) = 1; |
1990 real = gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size)); | 2046 real = gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size)); |
1991 REG_NOTES (insn) = | 2047 add_reg_note (insn, REG_FRAME_RELATED_EXPR, real); |
1992 gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, real, REG_NOTES (insn)); | |
1993 | 2048 |
1994 if (total_size > 2000) | 2049 if (total_size > 2000) |
1995 { | 2050 { |
1996 /* Save the back chain ptr */ | 2051 /* Save the back chain ptr */ |
1997 insn = frame_emit_store (REGNO (scratch_reg_0), sp_reg, 0); | 2052 insn = frame_emit_store (REGNO (scratch_reg_0), sp_reg, 0); |
2004 + crtl->outgoing_args_size; | 2059 + crtl->outgoing_args_size; |
2005 /* Set the new frame_pointer */ | 2060 /* Set the new frame_pointer */ |
2006 insn = frame_emit_add_imm (fp_reg, sp_reg, fp_offset, scratch_reg_0); | 2061 insn = frame_emit_add_imm (fp_reg, sp_reg, fp_offset, scratch_reg_0); |
2007 RTX_FRAME_RELATED_P (insn) = 1; | 2062 RTX_FRAME_RELATED_P (insn) = 1; |
2008 real = gen_addsi3 (fp_reg, sp_reg, GEN_INT (fp_offset)); | 2063 real = gen_addsi3 (fp_reg, sp_reg, GEN_INT (fp_offset)); |
2009 REG_NOTES (insn) = | 2064 add_reg_note (insn, REG_FRAME_RELATED_EXPR, real); |
2010 gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, | |
2011 real, REG_NOTES (insn)); | |
2012 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY; | 2065 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY; |
2013 } | 2066 } |
2014 } | 2067 } |
2015 | 2068 |
2016 emit_note (NOTE_INSN_DELETED); | 2069 emit_note (NOTE_INSN_DELETED); |
2361 | 2414 |
2362 /* jump table */ | 2415 /* jump table */ |
2363 if (GET_CODE (PATTERN (branch)) == ADDR_VEC | 2416 if (GET_CODE (PATTERN (branch)) == ADDR_VEC |
2364 || GET_CODE (PATTERN (branch)) == ADDR_DIFF_VEC) | 2417 || GET_CODE (PATTERN (branch)) == ADDR_DIFF_VEC) |
2365 return 0; | 2418 return 0; |
2419 | |
2420 /* ASM GOTOs. */ | |
2421 if (extract_asm_operands (PATTERN (branch)) != NULL) | |
2422 return NULL; | |
2366 | 2423 |
2367 set = single_set (branch); | 2424 set = single_set (branch); |
2368 src = SET_SRC (set); | 2425 src = SET_SRC (set); |
2369 if (GET_CODE (SET_DEST (set)) != PC) | 2426 if (GET_CODE (SET_DEST (set)) != PC) |
2370 abort (); | 2427 abort (); |
3604 && exp >= low && exp <= high; | 3661 && exp >= low && exp <= high; |
3605 } | 3662 } |
3606 return FALSE; | 3663 return FALSE; |
3607 } | 3664 } |
3608 | 3665 |
3666 /* Return true if X is a SYMBOL_REF to an __ea qualified variable. */ | |
3667 | |
3668 static int | |
3669 ea_symbol_ref (rtx *px, void *data ATTRIBUTE_UNUSED) | |
3670 { | |
3671 rtx x = *px; | |
3672 tree decl; | |
3673 | |
3674 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS) | |
3675 { | |
3676 rtx plus = XEXP (x, 0); | |
3677 rtx op0 = XEXP (plus, 0); | |
3678 rtx op1 = XEXP (plus, 1); | |
3679 if (GET_CODE (op1) == CONST_INT) | |
3680 x = op0; | |
3681 } | |
3682 | |
3683 return (GET_CODE (x) == SYMBOL_REF | |
3684 && (decl = SYMBOL_REF_DECL (x)) != 0 | |
3685 && TREE_CODE (decl) == VAR_DECL | |
3686 && TYPE_ADDR_SPACE (TREE_TYPE (decl))); | |
3687 } | |
3688 | |
3609 /* We accept: | 3689 /* We accept: |
3610 - any 32-bit constant (SImode, SFmode) | 3690 - any 32-bit constant (SImode, SFmode) |
3611 - any constant that can be generated with fsmbi (any mode) | 3691 - any constant that can be generated with fsmbi (any mode) |
3612 - a 64-bit constant where the high and low bits are identical | 3692 - a 64-bit constant where the high and low bits are identical |
3613 (DImode, DFmode) | 3693 (DImode, DFmode) |
3615 int | 3695 int |
3616 spu_legitimate_constant_p (rtx x) | 3696 spu_legitimate_constant_p (rtx x) |
3617 { | 3697 { |
3618 if (GET_CODE (x) == HIGH) | 3698 if (GET_CODE (x) == HIGH) |
3619 x = XEXP (x, 0); | 3699 x = XEXP (x, 0); |
3700 | |
3701 /* Reject any __ea qualified reference. These can't appear in | |
3702 instructions but must be forced to the constant pool. */ | |
3703 if (for_each_rtx (&x, ea_symbol_ref, 0)) | |
3704 return 0; | |
3705 | |
3620 /* V4SI with all identical symbols is valid. */ | 3706 /* V4SI with all identical symbols is valid. */ |
3621 if (!flag_pic | 3707 if (!flag_pic |
3622 && GET_MODE (x) == V4SImode | 3708 && GET_MODE (x) == V4SImode |
3623 && (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF | 3709 && (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF |
3624 || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF | 3710 || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF |
3640 - reg + reg, alignment doesn't matter | 3726 - reg + reg, alignment doesn't matter |
3641 The alignment matters in the reg+const case because lqd and stqd | 3727 The alignment matters in the reg+const case because lqd and stqd |
3642 ignore the 4 least significant bits of the const. We only care about | 3728 ignore the 4 least significant bits of the const. We only care about |
3643 16 byte modes because the expand phase will change all smaller MEM | 3729 16 byte modes because the expand phase will change all smaller MEM |
3644 references to TImode. */ | 3730 references to TImode. */ |
3645 int | 3731 static bool |
3646 spu_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, | 3732 spu_legitimate_address_p (enum machine_mode mode, |
3647 rtx x, int reg_ok_strict) | 3733 rtx x, bool reg_ok_strict) |
3648 { | 3734 { |
3649 int aligned = GET_MODE_SIZE (mode) >= 16; | 3735 int aligned = GET_MODE_SIZE (mode) >= 16; |
3650 if (aligned | 3736 if (aligned |
3651 && GET_CODE (x) == AND | 3737 && GET_CODE (x) == AND |
3652 && GET_CODE (XEXP (x, 1)) == CONST_INT | 3738 && GET_CODE (XEXP (x, 1)) == CONST_INT |
3653 && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) - 16) | 3739 && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) - 16) |
3654 x = XEXP (x, 0); | 3740 x = XEXP (x, 0); |
3655 switch (GET_CODE (x)) | 3741 switch (GET_CODE (x)) |
3656 { | 3742 { |
3657 case LABEL_REF: | 3743 case LABEL_REF: |
3744 return !TARGET_LARGE_MEM; | |
3745 | |
3658 case SYMBOL_REF: | 3746 case SYMBOL_REF: |
3659 case CONST: | 3747 case CONST: |
3748 /* Keep __ea references until reload so that spu_expand_mov can see them | |
3749 in MEMs. */ | |
3750 if (ea_symbol_ref (&x, 0)) | |
3751 return !reload_in_progress && !reload_completed; | |
3660 return !TARGET_LARGE_MEM; | 3752 return !TARGET_LARGE_MEM; |
3661 | 3753 |
3662 case CONST_INT: | 3754 case CONST_INT: |
3663 return INTVAL (x) >= 0 && INTVAL (x) <= 0x3ffff; | 3755 return INTVAL (x) >= 0 && INTVAL (x) <= 0x3ffff; |
3664 | 3756 |
3698 break; | 3790 break; |
3699 } | 3791 } |
3700 return FALSE; | 3792 return FALSE; |
3701 } | 3793 } |
3702 | 3794 |
3795 /* Like spu_legitimate_address_p, except with named addresses. */ | |
3796 static bool | |
3797 spu_addr_space_legitimate_address_p (enum machine_mode mode, rtx x, | |
3798 bool reg_ok_strict, addr_space_t as) | |
3799 { | |
3800 if (as == ADDR_SPACE_EA) | |
3801 return (REG_P (x) && (GET_MODE (x) == EAmode)); | |
3802 | |
3803 else if (as != ADDR_SPACE_GENERIC) | |
3804 gcc_unreachable (); | |
3805 | |
3806 return spu_legitimate_address_p (mode, x, reg_ok_strict); | |
3807 } | |
3808 | |
3703 /* When the address is reg + const_int, force the const_int into a | 3809 /* When the address is reg + const_int, force the const_int into a |
3704 register. */ | 3810 register. */ |
3705 rtx | 3811 rtx |
3706 spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, | 3812 spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, |
3707 enum machine_mode mode) | 3813 enum machine_mode mode ATTRIBUTE_UNUSED) |
3708 { | 3814 { |
3709 rtx op0, op1; | 3815 rtx op0, op1; |
3710 /* Make sure both operands are registers. */ | 3816 /* Make sure both operands are registers. */ |
3711 if (GET_CODE (x) == PLUS) | 3817 if (GET_CODE (x) == PLUS) |
3712 { | 3818 { |
3725 mark_reg_pointer (op1, 128); | 3831 mark_reg_pointer (op1, 128); |
3726 } | 3832 } |
3727 else if (GET_CODE (op1) != REG) | 3833 else if (GET_CODE (op1) != REG) |
3728 op1 = force_reg (Pmode, op1); | 3834 op1 = force_reg (Pmode, op1); |
3729 x = gen_rtx_PLUS (Pmode, op0, op1); | 3835 x = gen_rtx_PLUS (Pmode, op0, op1); |
3730 if (spu_legitimate_address (mode, x, 0)) | 3836 } |
3731 return x; | 3837 return x; |
3732 } | 3838 } |
3733 return NULL_RTX; | 3839 |
3840 /* Like spu_legitimate_address, except with named address support. */ | |
3841 static rtx | |
3842 spu_addr_space_legitimize_address (rtx x, rtx oldx, enum machine_mode mode, | |
3843 addr_space_t as) | |
3844 { | |
3845 if (as != ADDR_SPACE_GENERIC) | |
3846 return x; | |
3847 | |
3848 return spu_legitimize_address (x, oldx, mode); | |
3734 } | 3849 } |
3735 | 3850 |
3736 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in | 3851 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in |
3737 struct attribute_spec.handler. */ | 3852 struct attribute_spec.handler. */ |
3738 static tree | 3853 static tree |
3741 tree args ATTRIBUTE_UNUSED, | 3856 tree args ATTRIBUTE_UNUSED, |
3742 int flags ATTRIBUTE_UNUSED, bool * no_add_attrs) | 3857 int flags ATTRIBUTE_UNUSED, bool * no_add_attrs) |
3743 { | 3858 { |
3744 if (TREE_CODE (*node) != FUNCTION_DECL) | 3859 if (TREE_CODE (*node) != FUNCTION_DECL) |
3745 { | 3860 { |
3746 warning (0, "`%s' attribute only applies to functions", | 3861 warning (0, "%qE attribute only applies to functions", |
3747 IDENTIFIER_POINTER (name)); | 3862 name); |
3748 *no_add_attrs = true; | 3863 *no_add_attrs = true; |
3749 } | 3864 } |
3750 | 3865 |
3751 return NULL_TREE; | 3866 return NULL_TREE; |
3752 } | 3867 } |
3799 result = build_qualified_type (result, TYPE_QUALS (type)); | 3914 result = build_qualified_type (result, TYPE_QUALS (type)); |
3800 | 3915 |
3801 *no_add_attrs = true; /* No need to hang on to the attribute. */ | 3916 *no_add_attrs = true; /* No need to hang on to the attribute. */ |
3802 | 3917 |
3803 if (!result) | 3918 if (!result) |
3804 warning (0, "`%s' attribute ignored", IDENTIFIER_POINTER (name)); | 3919 warning (0, "%qE attribute ignored", name); |
3805 else | 3920 else |
3806 *node = lang_hooks.types.reconstruct_complex_type (*node, result); | 3921 *node = lang_hooks.types.reconstruct_complex_type (*node, result); |
3807 | 3922 |
3808 return NULL_TREE; | 3923 return NULL_TREE; |
3809 } | 3924 } |
3954 bool owp; | 4069 bool owp; |
3955 | 4070 |
3956 record = (*lang_hooks.types.make_type) (RECORD_TYPE); | 4071 record = (*lang_hooks.types.make_type) (RECORD_TYPE); |
3957 | 4072 |
3958 type_decl = | 4073 type_decl = |
3959 build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record); | 4074 build_decl (BUILTINS_LOCATION, |
3960 | 4075 TYPE_DECL, get_identifier ("__va_list_tag"), record); |
3961 f_args = build_decl (FIELD_DECL, get_identifier ("__args"), ptr_type_node); | 4076 |
3962 f_skip = build_decl (FIELD_DECL, get_identifier ("__skip"), ptr_type_node); | 4077 f_args = build_decl (BUILTINS_LOCATION, |
4078 FIELD_DECL, get_identifier ("__args"), ptr_type_node); | |
4079 f_skip = build_decl (BUILTINS_LOCATION, | |
4080 FIELD_DECL, get_identifier ("__skip"), ptr_type_node); | |
3963 | 4081 |
3964 DECL_FIELD_CONTEXT (f_args) = record; | 4082 DECL_FIELD_CONTEXT (f_args) = record; |
3965 DECL_ALIGN (f_args) = 128; | 4083 DECL_ALIGN (f_args) = 128; |
3966 DECL_USER_ALIGN (f_args) = 1; | 4084 DECL_USER_ALIGN (f_args) = 1; |
3967 | 4085 |
4069 build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); | 4187 build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); |
4070 skip = | 4188 skip = |
4071 build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE); | 4189 build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE); |
4072 | 4190 |
4073 addr = create_tmp_var (ptr_type_node, "va_arg"); | 4191 addr = create_tmp_var (ptr_type_node, "va_arg"); |
4074 DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set (); | |
4075 | 4192 |
4076 /* if an object is dynamically sized, a pointer to it is passed | 4193 /* if an object is dynamically sized, a pointer to it is passed |
4077 instead of the object itself. */ | 4194 instead of the object itself. */ |
4078 pass_by_reference_p = spu_pass_by_reference (NULL, TYPE_MODE (type), type, | 4195 pass_by_reference_p = spu_pass_by_reference (NULL, TYPE_MODE (type), type, |
4079 false); | 4196 false); |
4099 | 4216 |
4100 /* update VALIST.__args */ | 4217 /* update VALIST.__args */ |
4101 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, paddedsize); | 4218 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, paddedsize); |
4102 gimplify_assign (unshare_expr (args), tmp, pre_p); | 4219 gimplify_assign (unshare_expr (args), tmp, pre_p); |
4103 | 4220 |
4104 addr = fold_convert (build_pointer_type (type), addr); | 4221 addr = fold_convert (build_pointer_type_for_mode (type, ptr_mode, true), |
4222 addr); | |
4105 | 4223 |
4106 if (pass_by_reference_p) | 4224 if (pass_by_reference_p) |
4107 addr = build_va_arg_indirect_ref (addr); | 4225 addr = build_va_arg_indirect_ref (addr); |
4108 | 4226 |
4109 return build_va_arg_indirect_ref (addr); | 4227 return build_va_arg_indirect_ref (addr); |
4231 return 1; | 4349 return 1; |
4232 | 4350 |
4233 return 0; | 4351 return 0; |
4234 } | 4352 } |
4235 | 4353 |
4354 static GTY(()) rtx cache_fetch; /* __cache_fetch function */ | |
4355 static GTY(()) rtx cache_fetch_dirty; /* __cache_fetch_dirty function */ | |
4356 static alias_set_type ea_alias_set = -1; /* alias set for __ea memory */ | |
4357 | |
4358 /* MEM is known to be an __ea qualified memory access. Emit a call to | |
4359 fetch the ppu memory to local store, and return its address in local | |
4360 store. */ | |
4361 | |
4362 static void | |
4363 ea_load_store (rtx mem, bool is_store, rtx ea_addr, rtx data_addr) | |
4364 { | |
4365 if (is_store) | |
4366 { | |
4367 rtx ndirty = GEN_INT (GET_MODE_SIZE (GET_MODE (mem))); | |
4368 if (!cache_fetch_dirty) | |
4369 cache_fetch_dirty = init_one_libfunc ("__cache_fetch_dirty"); | |
4370 emit_library_call_value (cache_fetch_dirty, data_addr, LCT_NORMAL, Pmode, | |
4371 2, ea_addr, EAmode, ndirty, SImode); | |
4372 } | |
4373 else | |
4374 { | |
4375 if (!cache_fetch) | |
4376 cache_fetch = init_one_libfunc ("__cache_fetch"); | |
4377 emit_library_call_value (cache_fetch, data_addr, LCT_NORMAL, Pmode, | |
4378 1, ea_addr, EAmode); | |
4379 } | |
4380 } | |
4381 | |
4382 /* Like ea_load_store, but do the cache tag comparison and, for stores, | |
4383 dirty bit marking, inline. | |
4384 | |
4385 The cache control data structure is an array of | |
4386 | |
4387 struct __cache_tag_array | |
4388 { | |
4389 unsigned int tag_lo[4]; | |
4390 unsigned int tag_hi[4]; | |
4391 void *data_pointer[4]; | |
4392 int reserved[4]; | |
4393 vector unsigned short dirty_bits[4]; | |
4394 } */ | |
4395 | |
4396 static void | |
4397 ea_load_store_inline (rtx mem, bool is_store, rtx ea_addr, rtx data_addr) | |
4398 { | |
4399 rtx ea_addr_si; | |
4400 HOST_WIDE_INT v; | |
4401 rtx tag_size_sym = gen_rtx_SYMBOL_REF (Pmode, "__cache_tag_array_size"); | |
4402 rtx tag_arr_sym = gen_rtx_SYMBOL_REF (Pmode, "__cache_tag_array"); | |
4403 rtx index_mask = gen_reg_rtx (SImode); | |
4404 rtx tag_arr = gen_reg_rtx (Pmode); | |
4405 rtx splat_mask = gen_reg_rtx (TImode); | |
4406 rtx splat = gen_reg_rtx (V4SImode); | |
4407 rtx splat_hi = NULL_RTX; | |
4408 rtx tag_index = gen_reg_rtx (Pmode); | |
4409 rtx block_off = gen_reg_rtx (SImode); | |
4410 rtx tag_addr = gen_reg_rtx (Pmode); | |
4411 rtx tag = gen_reg_rtx (V4SImode); | |
4412 rtx cache_tag = gen_reg_rtx (V4SImode); | |
4413 rtx cache_tag_hi = NULL_RTX; | |
4414 rtx cache_ptrs = gen_reg_rtx (TImode); | |
4415 rtx cache_ptrs_si = gen_reg_rtx (SImode); | |
4416 rtx tag_equal = gen_reg_rtx (V4SImode); | |
4417 rtx tag_equal_hi = NULL_RTX; | |
4418 rtx tag_eq_pack = gen_reg_rtx (V4SImode); | |
4419 rtx tag_eq_pack_si = gen_reg_rtx (SImode); | |
4420 rtx eq_index = gen_reg_rtx (SImode); | |
4421 rtx bcomp, hit_label, hit_ref, cont_label, insn; | |
4422 | |
4423 if (spu_ea_model != 32) | |
4424 { | |
4425 splat_hi = gen_reg_rtx (V4SImode); | |
4426 cache_tag_hi = gen_reg_rtx (V4SImode); | |
4427 tag_equal_hi = gen_reg_rtx (V4SImode); | |
4428 } | |
4429 | |
4430 emit_move_insn (index_mask, plus_constant (tag_size_sym, -128)); | |
4431 emit_move_insn (tag_arr, tag_arr_sym); | |
4432 v = 0x0001020300010203LL; | |
4433 emit_move_insn (splat_mask, immed_double_const (v, v, TImode)); | |
4434 ea_addr_si = ea_addr; | |
4435 if (spu_ea_model != 32) | |
4436 ea_addr_si = convert_to_mode (SImode, ea_addr, 1); | |
4437 | |
4438 /* tag_index = ea_addr & (tag_array_size - 128) */ | |
4439 emit_insn (gen_andsi3 (tag_index, ea_addr_si, index_mask)); | |
4440 | |
4441 /* splat ea_addr to all 4 slots. */ | |
4442 emit_insn (gen_shufb (splat, ea_addr_si, ea_addr_si, splat_mask)); | |
4443 /* Similarly for high 32 bits of ea_addr. */ | |
4444 if (spu_ea_model != 32) | |
4445 emit_insn (gen_shufb (splat_hi, ea_addr, ea_addr, splat_mask)); | |
4446 | |
4447 /* block_off = ea_addr & 127 */ | |
4448 emit_insn (gen_andsi3 (block_off, ea_addr_si, spu_const (SImode, 127))); | |
4449 | |
4450 /* tag_addr = tag_arr + tag_index */ | |
4451 emit_insn (gen_addsi3 (tag_addr, tag_arr, tag_index)); | |
4452 | |
4453 /* Read cache tags. */ | |
4454 emit_move_insn (cache_tag, gen_rtx_MEM (V4SImode, tag_addr)); | |
4455 if (spu_ea_model != 32) | |
4456 emit_move_insn (cache_tag_hi, gen_rtx_MEM (V4SImode, | |
4457 plus_constant (tag_addr, 16))); | |
4458 | |
4459 /* tag = ea_addr & -128 */ | |
4460 emit_insn (gen_andv4si3 (tag, splat, spu_const (V4SImode, -128))); | |
4461 | |
4462 /* Read all four cache data pointers. */ | |
4463 emit_move_insn (cache_ptrs, gen_rtx_MEM (TImode, | |
4464 plus_constant (tag_addr, 32))); | |
4465 | |
4466 /* Compare tags. */ | |
4467 emit_insn (gen_ceq_v4si (tag_equal, tag, cache_tag)); | |
4468 if (spu_ea_model != 32) | |
4469 { | |
4470 emit_insn (gen_ceq_v4si (tag_equal_hi, splat_hi, cache_tag_hi)); | |
4471 emit_insn (gen_andv4si3 (tag_equal, tag_equal, tag_equal_hi)); | |
4472 } | |
4473 | |
4474 /* At most one of the tags compare equal, so tag_equal has one | |
4475 32-bit slot set to all 1's, with the other slots all zero. | |
4476 gbb picks off low bit from each byte in the 128-bit registers, | |
4477 so tag_eq_pack is one of 0xf000, 0x0f00, 0x00f0, 0x000f, assuming | |
4478 we have a hit. */ | |
4479 emit_insn (gen_spu_gbb (tag_eq_pack, spu_gen_subreg (V16QImode, tag_equal))); | |
4480 emit_insn (gen_spu_convert (tag_eq_pack_si, tag_eq_pack)); | |
4481 | |
4482 /* So counting leading zeros will set eq_index to 16, 20, 24 or 28. */ | |
4483 emit_insn (gen_clzsi2 (eq_index, tag_eq_pack_si)); | |
4484 | |
4485 /* Allowing us to rotate the corresponding cache data pointer to slot0. | |
4486 (rotating eq_index mod 16 bytes). */ | |
4487 emit_insn (gen_rotqby_ti (cache_ptrs, cache_ptrs, eq_index)); | |
4488 emit_insn (gen_spu_convert (cache_ptrs_si, cache_ptrs)); | |
4489 | |
4490 /* Add block offset to form final data address. */ | |
4491 emit_insn (gen_addsi3 (data_addr, cache_ptrs_si, block_off)); | |
4492 | |
4493 /* Check that we did hit. */ | |
4494 hit_label = gen_label_rtx (); | |
4495 hit_ref = gen_rtx_LABEL_REF (VOIDmode, hit_label); | |
4496 bcomp = gen_rtx_NE (SImode, tag_eq_pack_si, const0_rtx); | |
4497 insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, | |
4498 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, | |
4499 hit_ref, pc_rtx))); | |
4500 /* Say that this branch is very likely to happen. */ | |
4501 v = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100 - 1; | |
4502 REG_NOTES (insn) | |
4503 = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (v), REG_NOTES (insn)); | |
4504 | |
4505 ea_load_store (mem, is_store, ea_addr, data_addr); | |
4506 cont_label = gen_label_rtx (); | |
4507 emit_jump_insn (gen_jump (cont_label)); | |
4508 emit_barrier (); | |
4509 | |
4510 emit_label (hit_label); | |
4511 | |
4512 if (is_store) | |
4513 { | |
4514 HOST_WIDE_INT v_hi; | |
4515 rtx dirty_bits = gen_reg_rtx (TImode); | |
4516 rtx dirty_off = gen_reg_rtx (SImode); | |
4517 rtx dirty_128 = gen_reg_rtx (TImode); | |
4518 rtx neg_block_off = gen_reg_rtx (SImode); | |
4519 | |
4520 /* Set up mask with one dirty bit per byte of the mem we are | |
4521 writing, starting from top bit. */ | |
4522 v_hi = v = -1; | |
4523 v <<= (128 - GET_MODE_SIZE (GET_MODE (mem))) & 63; | |
4524 if ((128 - GET_MODE_SIZE (GET_MODE (mem))) >= 64) | |
4525 { | |
4526 v_hi = v; | |
4527 v = 0; | |
4528 } | |
4529 emit_move_insn (dirty_bits, immed_double_const (v, v_hi, TImode)); | |
4530 | |
4531 /* Form index into cache dirty_bits. eq_index is one of | |
4532 0x10, 0x14, 0x18 or 0x1c. Multiplying by 4 gives us | |
4533 0x40, 0x50, 0x60 or 0x70 which just happens to be the | |
4534 offset to each of the four dirty_bits elements. */ | |
4535 emit_insn (gen_ashlsi3 (dirty_off, eq_index, spu_const (SImode, 2))); | |
4536 | |
4537 emit_insn (gen_spu_lqx (dirty_128, tag_addr, dirty_off)); | |
4538 | |
4539 /* Rotate bit mask to proper bit. */ | |
4540 emit_insn (gen_negsi2 (neg_block_off, block_off)); | |
4541 emit_insn (gen_rotqbybi_ti (dirty_bits, dirty_bits, neg_block_off)); | |
4542 emit_insn (gen_rotqbi_ti (dirty_bits, dirty_bits, neg_block_off)); | |
4543 | |
4544 /* Or in the new dirty bits. */ | |
4545 emit_insn (gen_iorti3 (dirty_128, dirty_bits, dirty_128)); | |
4546 | |
4547 /* Store. */ | |
4548 emit_insn (gen_spu_stqx (dirty_128, tag_addr, dirty_off)); | |
4549 } | |
4550 | |
4551 emit_label (cont_label); | |
4552 } | |
4553 | |
4554 static rtx | |
4555 expand_ea_mem (rtx mem, bool is_store) | |
4556 { | |
4557 rtx ea_addr; | |
4558 rtx data_addr = gen_reg_rtx (Pmode); | |
4559 rtx new_mem; | |
4560 | |
4561 ea_addr = force_reg (EAmode, XEXP (mem, 0)); | |
4562 if (optimize_size || optimize == 0) | |
4563 ea_load_store (mem, is_store, ea_addr, data_addr); | |
4564 else | |
4565 ea_load_store_inline (mem, is_store, ea_addr, data_addr); | |
4566 | |
4567 if (ea_alias_set == -1) | |
4568 ea_alias_set = new_alias_set (); | |
4569 | |
4570 /* We generate a new MEM RTX to refer to the copy of the data | |
4571 in the cache. We do not copy memory attributes (except the | |
4572 alignment) from the original MEM, as they may no longer apply | |
4573 to the cache copy. */ | |
4574 new_mem = gen_rtx_MEM (GET_MODE (mem), data_addr); | |
4575 set_mem_alias_set (new_mem, ea_alias_set); | |
4576 set_mem_align (new_mem, MIN (MEM_ALIGN (mem), 128 * 8)); | |
4577 | |
4578 return new_mem; | |
4579 } | |
4580 | |
4236 int | 4581 int |
4237 spu_expand_mov (rtx * ops, enum machine_mode mode) | 4582 spu_expand_mov (rtx * ops, enum machine_mode mode) |
4238 { | 4583 { |
4239 if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0])) | 4584 if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0])) |
4240 abort (); | 4585 abort (); |
4288 emit_move_insn (ops[0], GEN_INT (val)); | 4633 emit_move_insn (ops[0], GEN_INT (val)); |
4289 return 1; | 4634 return 1; |
4290 } | 4635 } |
4291 } | 4636 } |
4292 if (MEM_P (ops[0])) | 4637 if (MEM_P (ops[0])) |
4293 return spu_split_store (ops); | 4638 { |
4639 if (MEM_ADDR_SPACE (ops[0])) | |
4640 ops[0] = expand_ea_mem (ops[0], true); | |
4641 return spu_split_store (ops); | |
4642 } | |
4294 if (MEM_P (ops[1])) | 4643 if (MEM_P (ops[1])) |
4295 return spu_split_load (ops); | 4644 { |
4645 if (MEM_ADDR_SPACE (ops[1])) | |
4646 ops[1] = expand_ea_mem (ops[1], false); | |
4647 return spu_split_load (ops); | |
4648 } | |
4296 | 4649 |
4297 return 0; | 4650 return 0; |
4298 } | 4651 } |
4299 | 4652 |
4300 static void | 4653 static void |
4315 emit_move_insn (dst, reg); | 4668 emit_move_insn (dst, reg); |
4316 } | 4669 } |
4317 } | 4670 } |
4318 | 4671 |
4319 /* Load TImode values into DST0 and DST1 (when it is non-NULL) using | 4672 /* Load TImode values into DST0 and DST1 (when it is non-NULL) using |
4320 the address from SRC and SRC+16. Return a REG or CONST_INT that | 4673 the address from SRC and SRC+16. Return a REG or CONST_INT that |
4321 specifies how many bytes to rotate the loaded registers, plus any | 4674 specifies how many bytes to rotate the loaded registers, plus any |
4322 extra from EXTRA_ROTQBY. The address and rotate amounts are | 4675 extra from EXTRA_ROTQBY. The address and rotate amounts are |
4323 normalized to improve merging of loads and rotate computations. */ | 4676 normalized to improve merging of loads and rotate computations. */ |
4324 static rtx | 4677 static rtx |
4325 spu_expand_load (rtx dst0, rtx dst1, rtx src, int extra_rotby) | 4678 spu_expand_load (rtx dst0, rtx dst1, rtx src, int extra_rotby) |
4877 | 5230 |
4878 /* Convert a 16 byte array to a constant of mode MODE. When MODE is | 5231 /* Convert a 16 byte array to a constant of mode MODE. When MODE is |
4879 smaller than 16 bytes, use the bytes that would represent that value | 5232 smaller than 16 bytes, use the bytes that would represent that value |
4880 in a register, e.g., for QImode return the value of arr[3]. */ | 5233 in a register, e.g., for QImode return the value of arr[3]. */ |
4881 rtx | 5234 rtx |
4882 array_to_constant (enum machine_mode mode, unsigned char arr[16]) | 5235 array_to_constant (enum machine_mode mode, const unsigned char arr[16]) |
4883 { | 5236 { |
4884 enum machine_mode inner_mode; | 5237 enum machine_mode inner_mode; |
4885 rtvec v; | 5238 rtvec v; |
4886 int units, size, i, j, k; | 5239 int units, size, i, j, k; |
4887 HOST_WIDE_INT val; | 5240 HOST_WIDE_INT val; |
4945 } | 5298 } |
4946 | 5299 |
4947 static void | 5300 static void |
4948 reloc_diagnostic (rtx x) | 5301 reloc_diagnostic (rtx x) |
4949 { | 5302 { |
4950 tree loc_decl, decl = 0; | 5303 tree decl = 0; |
4951 const char *msg; | |
4952 if (!flag_pic || !(TARGET_WARN_RELOC || TARGET_ERROR_RELOC)) | 5304 if (!flag_pic || !(TARGET_WARN_RELOC || TARGET_ERROR_RELOC)) |
4953 return; | 5305 return; |
4954 | 5306 |
4955 if (GET_CODE (x) == SYMBOL_REF) | 5307 if (GET_CODE (x) == SYMBOL_REF) |
4956 decl = SYMBOL_REF_DECL (x); | 5308 decl = SYMBOL_REF_DECL (x); |
4960 | 5312 |
4961 /* SYMBOL_REF_DECL is not necessarily a DECL. */ | 5313 /* SYMBOL_REF_DECL is not necessarily a DECL. */ |
4962 if (decl && !DECL_P (decl)) | 5314 if (decl && !DECL_P (decl)) |
4963 decl = 0; | 5315 decl = 0; |
4964 | 5316 |
4965 /* We use last_assemble_variable_decl to get line information. It's | |
4966 not always going to be right and might not even be close, but will | |
4967 be right for the more common cases. */ | |
4968 if (!last_assemble_variable_decl || in_section == ctors_section) | |
4969 loc_decl = decl; | |
4970 else | |
4971 loc_decl = last_assemble_variable_decl; | |
4972 | |
4973 /* The decl could be a string constant. */ | 5317 /* The decl could be a string constant. */ |
4974 if (decl && DECL_P (decl)) | 5318 if (decl && DECL_P (decl)) |
4975 msg = "%Jcreating run-time relocation for %qD"; | 5319 { |
4976 else | 5320 location_t loc; |
4977 msg = "creating run-time relocation"; | 5321 /* We use last_assemble_variable_decl to get line information. It's |
4978 | 5322 not always going to be right and might not even be close, but will |
4979 if (TARGET_WARN_RELOC) | 5323 be right for the more common cases. */ |
4980 warning (0, msg, loc_decl, decl); | 5324 if (!last_assemble_variable_decl || in_section == ctors_section) |
4981 else | 5325 loc = DECL_SOURCE_LOCATION (decl); |
4982 error (msg, loc_decl, decl); | 5326 else |
5327 loc = DECL_SOURCE_LOCATION (last_assemble_variable_decl); | |
5328 | |
5329 if (TARGET_WARN_RELOC) | |
5330 warning_at (loc, 0, | |
5331 "creating run-time relocation for %qD", decl); | |
5332 else | |
5333 error_at (loc, | |
5334 "creating run-time relocation for %qD", decl); | |
5335 } | |
5336 else | |
5337 { | |
5338 if (TARGET_WARN_RELOC) | |
5339 warning_at (input_location, 0, "creating run-time relocation"); | |
5340 else | |
5341 error_at (input_location, "creating run-time relocation"); | |
5342 } | |
4983 } | 5343 } |
4984 | 5344 |
4985 /* Hook into assemble_integer so we can generate an error for run-time | 5345 /* Hook into assemble_integer so we can generate an error for run-time |
4986 relocations. The SPU ABI disallows them. */ | 5346 relocations. The SPU ABI disallows them. */ |
4987 static bool | 5347 static bool |
5270 #define DEF_BUILTIN(fcode, icode, name, type, params) \ | 5630 #define DEF_BUILTIN(fcode, icode, name, type, params) \ |
5271 {fcode, icode, name, type, params, NULL_TREE}, | 5631 {fcode, icode, name, type, params, NULL_TREE}, |
5272 #include "spu-builtins.def" | 5632 #include "spu-builtins.def" |
5273 #undef DEF_BUILTIN | 5633 #undef DEF_BUILTIN |
5274 }; | 5634 }; |
5635 | |
5636 /* Returns the rs6000 builtin decl for CODE. */ | |
5637 | |
5638 static tree | |
5639 spu_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) | |
5640 { | |
5641 if (code >= NUM_SPU_BUILTINS) | |
5642 return error_mark_node; | |
5643 | |
5644 return spu_builtins[code].fndecl; | |
5645 } | |
5646 | |
5275 | 5647 |
5276 static void | 5648 static void |
5277 spu_init_builtins (void) | 5649 spu_init_builtins (void) |
5278 { | 5650 { |
5279 struct spu_builtin_description *d; | 5651 struct spu_builtin_description *d; |
5574 } | 5946 } |
5575 } | 5947 } |
5576 emit_insn (gen_rotqby_ti (rot, from, offset)); | 5948 emit_insn (gen_rotqby_ti (rot, from, offset)); |
5577 } | 5949 } |
5578 | 5950 |
5579 void | 5951 static void |
5580 spu_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt) | 5952 spu_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt) |
5581 { | 5953 { |
5954 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); | |
5582 rtx shuf = gen_reg_rtx (V4SImode); | 5955 rtx shuf = gen_reg_rtx (V4SImode); |
5583 rtx insn = gen_reg_rtx (V4SImode); | 5956 rtx insn = gen_reg_rtx (V4SImode); |
5584 rtx shufc; | 5957 rtx shufc; |
5585 rtx insnc; | 5958 rtx insnc; |
5586 rtx mem; | 5959 rtx mem; |
5591 if (TARGET_LARGE_MEM) | 5964 if (TARGET_LARGE_MEM) |
5592 { | 5965 { |
5593 rtx rotl = gen_reg_rtx (V4SImode); | 5966 rtx rotl = gen_reg_rtx (V4SImode); |
5594 rtx mask = gen_reg_rtx (V4SImode); | 5967 rtx mask = gen_reg_rtx (V4SImode); |
5595 rtx bi = gen_reg_rtx (SImode); | 5968 rtx bi = gen_reg_rtx (SImode); |
5596 unsigned char shufa[16] = { | 5969 static unsigned char const shufa[16] = { |
5597 2, 3, 0, 1, 18, 19, 16, 17, | 5970 2, 3, 0, 1, 18, 19, 16, 17, |
5598 0, 1, 2, 3, 16, 17, 18, 19 | 5971 0, 1, 2, 3, 16, 17, 18, 19 |
5599 }; | 5972 }; |
5600 unsigned char insna[16] = { | 5973 static unsigned char const insna[16] = { |
5601 0x41, 0, 0, 79, | 5974 0x41, 0, 0, 79, |
5602 0x41, 0, 0, STATIC_CHAIN_REGNUM, | 5975 0x41, 0, 0, STATIC_CHAIN_REGNUM, |
5603 0x60, 0x80, 0, 79, | 5976 0x60, 0x80, 0, 79, |
5604 0x60, 0x80, 0, STATIC_CHAIN_REGNUM | 5977 0x60, 0x80, 0, STATIC_CHAIN_REGNUM |
5605 }; | 5978 }; |
5610 emit_insn (gen_shufb (shuf, fnaddr, cxt, shufc)); | 5983 emit_insn (gen_shufb (shuf, fnaddr, cxt, shufc)); |
5611 emit_insn (gen_vrotlv4si3 (rotl, shuf, spu_const (V4SImode, 7))); | 5984 emit_insn (gen_vrotlv4si3 (rotl, shuf, spu_const (V4SImode, 7))); |
5612 emit_insn (gen_movv4si (mask, spu_const (V4SImode, 0xffff << 7))); | 5985 emit_insn (gen_movv4si (mask, spu_const (V4SImode, 0xffff << 7))); |
5613 emit_insn (gen_selb (insn, insnc, rotl, mask)); | 5986 emit_insn (gen_selb (insn, insnc, rotl, mask)); |
5614 | 5987 |
5615 mem = memory_address (Pmode, tramp); | 5988 mem = adjust_address (m_tramp, V4SImode, 0); |
5616 emit_move_insn (gen_rtx_MEM (V4SImode, mem), insn); | 5989 emit_move_insn (mem, insn); |
5617 | 5990 |
5618 emit_move_insn (bi, GEN_INT (0x35000000 + (79 << 7))); | 5991 emit_move_insn (bi, GEN_INT (0x35000000 + (79 << 7))); |
5619 mem = memory_address (Pmode, plus_constant (tramp, 16)); | 5992 mem = adjust_address (m_tramp, Pmode, 16); |
5620 emit_move_insn (gen_rtx_MEM (Pmode, mem), bi); | 5993 emit_move_insn (mem, bi); |
5621 } | 5994 } |
5622 else | 5995 else |
5623 { | 5996 { |
5624 rtx scxt = gen_reg_rtx (SImode); | 5997 rtx scxt = gen_reg_rtx (SImode); |
5625 rtx sfnaddr = gen_reg_rtx (SImode); | 5998 rtx sfnaddr = gen_reg_rtx (SImode); |
5626 unsigned char insna[16] = { | 5999 static unsigned char const insna[16] = { |
5627 0x42, 0, 0, STATIC_CHAIN_REGNUM, | 6000 0x42, 0, 0, STATIC_CHAIN_REGNUM, |
5628 0x30, 0, 0, 0, | 6001 0x30, 0, 0, 0, |
5629 0, 0, 0, 0, | 6002 0, 0, 0, 0, |
5630 0, 0, 0, 0 | 6003 0, 0, 0, 0 |
5631 }; | 6004 }; |
5643 emit_insn (gen_cpat | 6016 emit_insn (gen_cpat |
5644 (shufc, stack_pointer_rtx, GEN_INT (4), GEN_INT (4))); | 6017 (shufc, stack_pointer_rtx, GEN_INT (4), GEN_INT (4))); |
5645 emit_insn (gen_shufb (shuf, sfnaddr, scxt, shufc)); | 6018 emit_insn (gen_shufb (shuf, sfnaddr, scxt, shufc)); |
5646 emit_insn (gen_iorv4si3 (insn, insnc, shuf)); | 6019 emit_insn (gen_iorv4si3 (insn, insnc, shuf)); |
5647 | 6020 |
5648 mem = memory_address (Pmode, tramp); | 6021 mem = adjust_address (m_tramp, V4SImode, 0); |
5649 emit_move_insn (gen_rtx_MEM (V4SImode, mem), insn); | 6022 emit_move_insn (mem, insn); |
5650 | |
5651 } | 6023 } |
5652 emit_insn (gen_sync ()); | 6024 emit_insn (gen_sync ()); |
5653 } | 6025 } |
5654 | 6026 |
5655 void | 6027 void |
6082 | 6454 |
6083 static int | 6455 static int |
6084 expand_builtin_args (struct spu_builtin_description *d, tree exp, | 6456 expand_builtin_args (struct spu_builtin_description *d, tree exp, |
6085 rtx target, rtx ops[]) | 6457 rtx target, rtx ops[]) |
6086 { | 6458 { |
6087 enum insn_code icode = d->icode; | 6459 enum insn_code icode = (enum insn_code) d->icode; |
6088 int i = 0, a; | 6460 int i = 0, a; |
6089 | 6461 |
6090 /* Expand the arguments into rtl. */ | 6462 /* Expand the arguments into rtl. */ |
6091 | 6463 |
6092 if (d->parm[0] != SPU_BTI_VOID) | 6464 if (d->parm[0] != SPU_BTI_VOID) |
6095 for (a = 0; d->parm[a+1] != SPU_BTI_END_OF_PARAMS; i++, a++) | 6467 for (a = 0; d->parm[a+1] != SPU_BTI_END_OF_PARAMS; i++, a++) |
6096 { | 6468 { |
6097 tree arg = CALL_EXPR_ARG (exp, a); | 6469 tree arg = CALL_EXPR_ARG (exp, a); |
6098 if (arg == 0) | 6470 if (arg == 0) |
6099 abort (); | 6471 abort (); |
6100 ops[i] = expand_expr (arg, NULL_RTX, VOIDmode, 0); | 6472 ops[i] = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL); |
6101 } | 6473 } |
6102 | 6474 |
6103 /* The insn pattern may have additional operands (SCRATCH). | 6475 /* The insn pattern may have additional operands (SCRATCH). |
6104 Return the number of actual non-SCRATCH operands. */ | 6476 Return the number of actual non-SCRATCH operands. */ |
6105 gcc_assert (i <= insn_data[icode].n_operands); | 6477 gcc_assert (i <= insn_data[icode].n_operands); |
6110 spu_expand_builtin_1 (struct spu_builtin_description *d, | 6482 spu_expand_builtin_1 (struct spu_builtin_description *d, |
6111 tree exp, rtx target) | 6483 tree exp, rtx target) |
6112 { | 6484 { |
6113 rtx pat; | 6485 rtx pat; |
6114 rtx ops[8]; | 6486 rtx ops[8]; |
6115 enum insn_code icode = d->icode; | 6487 enum insn_code icode = (enum insn_code) d->icode; |
6116 enum machine_mode mode, tmode; | 6488 enum machine_mode mode, tmode; |
6117 int i, p; | 6489 int i, p; |
6118 int n_operands; | 6490 int n_operands; |
6119 tree return_type; | 6491 tree return_type; |
6120 | 6492 |
6413 | 6785 |
6414 gcc_assert (d); | 6786 gcc_assert (d); |
6415 return d->fndecl; | 6787 return d->fndecl; |
6416 } | 6788 } |
6417 | 6789 |
6790 /* Return the appropriate mode for a named address pointer. */ | |
6791 static enum machine_mode | |
6792 spu_addr_space_pointer_mode (addr_space_t addrspace) | |
6793 { | |
6794 switch (addrspace) | |
6795 { | |
6796 case ADDR_SPACE_GENERIC: | |
6797 return ptr_mode; | |
6798 case ADDR_SPACE_EA: | |
6799 return EAmode; | |
6800 default: | |
6801 gcc_unreachable (); | |
6802 } | |
6803 } | |
6804 | |
6805 /* Return the appropriate mode for a named address address. */ | |
6806 static enum machine_mode | |
6807 spu_addr_space_address_mode (addr_space_t addrspace) | |
6808 { | |
6809 switch (addrspace) | |
6810 { | |
6811 case ADDR_SPACE_GENERIC: | |
6812 return Pmode; | |
6813 case ADDR_SPACE_EA: | |
6814 return EAmode; | |
6815 default: | |
6816 gcc_unreachable (); | |
6817 } | |
6818 } | |
6819 | |
6820 /* Determine if one named address space is a subset of another. */ | |
6821 | |
6822 static bool | |
6823 spu_addr_space_subset_p (addr_space_t subset, addr_space_t superset) | |
6824 { | |
6825 gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_EA); | |
6826 gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_EA); | |
6827 | |
6828 if (subset == superset) | |
6829 return true; | |
6830 | |
6831 /* If we have -mno-address-space-conversion, treat __ea and generic as not | |
6832 being subsets but instead as disjoint address spaces. */ | |
6833 else if (!TARGET_ADDRESS_SPACE_CONVERSION) | |
6834 return false; | |
6835 | |
6836 else | |
6837 return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_EA); | |
6838 } | |
6839 | |
6840 /* Convert from one address space to another. */ | |
6841 static rtx | |
6842 spu_addr_space_convert (rtx op, tree from_type, tree to_type) | |
6843 { | |
6844 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type)); | |
6845 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type)); | |
6846 | |
6847 gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_EA); | |
6848 gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_EA); | |
6849 | |
6850 if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_EA) | |
6851 { | |
6852 rtx result, ls; | |
6853 | |
6854 ls = gen_const_mem (DImode, | |
6855 gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store")); | |
6856 set_mem_align (ls, 128); | |
6857 | |
6858 result = gen_reg_rtx (Pmode); | |
6859 ls = force_reg (Pmode, convert_modes (Pmode, DImode, ls, 1)); | |
6860 op = force_reg (Pmode, convert_modes (Pmode, EAmode, op, 1)); | |
6861 ls = emit_conditional_move (ls, NE, op, const0_rtx, Pmode, | |
6862 ls, const0_rtx, Pmode, 1); | |
6863 | |
6864 emit_insn (gen_subsi3 (result, op, ls)); | |
6865 | |
6866 return result; | |
6867 } | |
6868 | |
6869 else if (to_as == ADDR_SPACE_EA && from_as == ADDR_SPACE_GENERIC) | |
6870 { | |
6871 rtx result, ls; | |
6872 | |
6873 ls = gen_const_mem (DImode, | |
6874 gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store")); | |
6875 set_mem_align (ls, 128); | |
6876 | |
6877 result = gen_reg_rtx (EAmode); | |
6878 ls = force_reg (EAmode, convert_modes (EAmode, DImode, ls, 1)); | |
6879 op = force_reg (Pmode, op); | |
6880 ls = emit_conditional_move (ls, NE, op, const0_rtx, Pmode, | |
6881 ls, const0_rtx, EAmode, 1); | |
6882 op = force_reg (EAmode, convert_modes (EAmode, Pmode, op, 1)); | |
6883 | |
6884 if (EAmode == SImode) | |
6885 emit_insn (gen_addsi3 (result, op, ls)); | |
6886 else | |
6887 emit_insn (gen_adddi3 (result, op, ls)); | |
6888 | |
6889 return result; | |
6890 } | |
6891 | |
6892 else | |
6893 gcc_unreachable (); | |
6894 } | |
6895 | |
6896 | |
6418 /* Count the total number of instructions in each pipe and return the | 6897 /* Count the total number of instructions in each pipe and return the |
6419 maximum, which is used as the Minimum Iteration Interval (MII) | 6898 maximum, which is used as the Minimum Iteration Interval (MII) |
6420 in the modulo scheduler. get_pipe() will return -2, -1, 0, or 1. | 6899 in the modulo scheduler. get_pipe() will return -2, -1, 0, or 1. |
6421 -2 are instructions that can go in pipe0 or pipe1. */ | 6900 -2 are instructions that can go in pipe0 or pipe1. */ |
6422 static int | 6901 static int |
6505 spu_section_type_flags (tree decl, const char *name, int reloc) | 6984 spu_section_type_flags (tree decl, const char *name, int reloc) |
6506 { | 6985 { |
6507 /* .toe needs to have type @nobits. */ | 6986 /* .toe needs to have type @nobits. */ |
6508 if (strcmp (name, ".toe") == 0) | 6987 if (strcmp (name, ".toe") == 0) |
6509 return SECTION_BSS; | 6988 return SECTION_BSS; |
6989 /* Don't load _ea into the current address space. */ | |
6990 if (strcmp (name, "._ea") == 0) | |
6991 return SECTION_WRITE | SECTION_DEBUG; | |
6510 return default_section_type_flags (decl, name, reloc); | 6992 return default_section_type_flags (decl, name, reloc); |
6993 } | |
6994 | |
6995 /* Implement targetm.select_section. */ | |
6996 static section * | |
6997 spu_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align) | |
6998 { | |
6999 /* Variables and constants defined in the __ea address space | |
7000 go into a special section named "._ea". */ | |
7001 if (TREE_TYPE (decl) != error_mark_node | |
7002 && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_EA) | |
7003 { | |
7004 /* We might get called with string constants, but get_named_section | |
7005 doesn't like them as they are not DECLs. Also, we need to set | |
7006 flags in that case. */ | |
7007 if (!DECL_P (decl)) | |
7008 return get_section ("._ea", SECTION_WRITE | SECTION_DEBUG, NULL); | |
7009 | |
7010 return get_named_section (decl, "._ea", reloc); | |
7011 } | |
7012 | |
7013 return default_elf_select_section (decl, reloc, align); | |
7014 } | |
7015 | |
7016 /* Implement targetm.unique_section. */ | |
7017 static void | |
7018 spu_unique_section (tree decl, int reloc) | |
7019 { | |
7020 /* We don't support unique section names in the __ea address | |
7021 space for now. */ | |
7022 if (TREE_TYPE (decl) != error_mark_node | |
7023 && TYPE_ADDR_SPACE (TREE_TYPE (decl)) != 0) | |
7024 return; | |
7025 | |
7026 default_unique_section (decl, reloc); | |
6511 } | 7027 } |
6512 | 7028 |
6513 /* Generate a constant or register which contains 2^SCALE. We assume | 7029 /* Generate a constant or register which contains 2^SCALE. We assume |
6514 the result is valid for MODE. Currently, MODE must be V4SFmode and | 7030 the result is valid for MODE. Currently, MODE must be V4SFmode and |
6515 SCALE must be SImode. */ | 7031 SCALE must be SImode. */ |
6528 emit_insn (gen_addsi3 (exp, reg, GEN_INT (127))); | 7044 emit_insn (gen_addsi3 (exp, reg, GEN_INT (127))); |
6529 emit_insn (gen_ashlsi3 (exp, exp, GEN_INT (23))); | 7045 emit_insn (gen_ashlsi3 (exp, exp, GEN_INT (23))); |
6530 emit_insn (gen_spu_splats (mul, gen_rtx_SUBREG (GET_MODE_INNER (mode), exp, 0))); | 7046 emit_insn (gen_spu_splats (mul, gen_rtx_SUBREG (GET_MODE_INNER (mode), exp, 0))); |
6531 return mul; | 7047 return mul; |
6532 } | 7048 } |
6533 else | 7049 else |
6534 { | 7050 { |
6535 HOST_WIDE_INT exp = 127 + INTVAL (scale); | 7051 HOST_WIDE_INT exp = 127 + INTVAL (scale); |
6536 unsigned char arr[16]; | 7052 unsigned char arr[16]; |
6537 arr[0] = arr[4] = arr[8] = arr[12] = exp >> 1; | 7053 arr[0] = arr[4] = arr[8] = arr[12] = exp >> 1; |
6538 arr[1] = arr[5] = arr[9] = arr[13] = exp << 7; | 7054 arr[1] = arr[5] = arr[9] = arr[13] = exp << 7; |
6556 rtx op1 = gen_rtx_REG (TImode, REGNO (ops[1])); | 7072 rtx op1 = gen_rtx_REG (TImode, REGNO (ops[1])); |
6557 emit_insn (gen_move_insn (op0, op1)); | 7073 emit_insn (gen_move_insn (op0, op1)); |
6558 } | 7074 } |
6559 } | 7075 } |
6560 | 7076 |
7077 void | |
7078 spu_function_profiler (FILE * file, int labelno) | |
7079 { | |
7080 fprintf (file, "# profile\n"); | |
7081 fprintf (file, "brsl $75, _mcount\n"); | |
7082 } | |
7083 | |
6561 #include "gt-spu.h" | 7084 #include "gt-spu.h" |
6562 |