diff --git a/ChangeLog b/ChangeLog index d63be17..402abb9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ +2004-05-03 Rhys Weatherley + + * tools/gen-apply.c: improve the maintainability of the apply macros. + 2004-05-01 Rhys Weatherley * jit/jit-apply-x86.c, jit/jit-rules-x86.c, tools/gen-apply.c: diff --git a/tools/gen-apply.c b/tools/gen-apply.c index 232565b..0bb1690 100644 --- a/tools/gen-apply.c +++ b/tools/gen-apply.c @@ -76,6 +76,7 @@ int struct_reg_overlaps_word_reg = 0; int struct_return_in_reg[64]; int align_long_regs = 0; int align_long_stack = 0; +int can_split_long = 0; int max_apply_size = 0; int x86_fastcall = 0; int parent_frame_offset = 0; @@ -848,6 +849,10 @@ void detect_struct_conventions(void) if(struct_return_special_reg || num_word_regs > 0) { args[1] = (jit_nint)buffer; + if(struct_reg_overlaps_word_reg) + { + args[2] = (jit_nint)buffer; + } } /* Apply the structure return tests for all sizes from 1 to 64 */ @@ -917,6 +922,280 @@ void detect_struct_conventions(void) call_struct_test(64); } +/* + * Detect alignment of "long" values in registers and on the stack. + */ +#ifdef JIT_NATIVE_INT32 +void detect_reg_alignment_one_word(jit_long y, jit_long z) +{ + jit_nint *args, *stack_args; + jit_builtin_apply_args(jit_nint *, args); + stack_args = (jit_nint *)(args[0]); + if(!mem_cmp(stack_args, &y, sizeof(y))) + { + /* The value of y was pushed out onto the stack, so we + cannot split long values between registers and the stack */ + can_split_long = 0; + } +} +void detect_reg_alignment_two_words(jit_int x, jit_long y, jit_long z) +{ + jit_nint *args, *stack_args; + jit_builtin_apply_args(jit_nint *, args); + stack_args = (jit_nint *)(args[0]); + if(!mem_cmp(stack_args, &y, sizeof(y))) + { + /* The value of y was pushed out, so alignment has occurred */ + can_split_long = 0; + align_long_regs = 1; + } + else if(!mem_cmp(stack_args, ((jit_nint *)&y) + 1, sizeof(jit_nint))) + { + /* The long value was split between registers and the stack */ + can_split_long = 1; + } +} +void detect_reg_alignment_three_words(jit_int x, jit_long y, jit_long z) +{ + jit_nint *args, *stack_args; + jit_builtin_apply_args(jit_nint *, args); + stack_args = (jit_nint *)(args[0]); + if(!mem_cmp(stack_args, &y, sizeof(y))) + { + /* The value of y was pushed out, so alignment has occurred */ + can_split_long = 0; + align_long_regs = 1; + } + else if(!mem_cmp(stack_args, ((jit_nint *)&y) + 1, sizeof(jit_nint))) + { + /* The long value was split between registers and the stack, + so alignment has occurred, together with a split */ + can_split_long = 1; + align_long_regs = 1; + } +} +void detect_reg_alignment_more_words(jit_int x, jit_long y, jit_long z) +{ + jit_nint *args, *word_regs; + jit_builtin_apply_args(jit_nint *, args); + word_regs = args + struct_return_special_reg + 1; + if(!mem_cmp(word_regs + 2, &y, sizeof(y))) + { + /* The value of "y" was aligned within the word registers */ + align_long_regs = 1; + } +} +void detect_reg_split_even_words(jit_int x, jit_long y1, jit_long y2, + jit_long y3, jit_long y4, jit_long y5, + jit_long y6, jit_long y7, jit_long y8, + jit_long y9, jit_long y10, jit_long y11, + jit_long y12, jit_long y13, jit_long y14, + jit_long y15, jit_long y16, jit_long y17, + jit_long y18, jit_long y19, jit_long y20) +{ + jit_nint *args, *stack_args; + int posn; + jit_long value; + jit_builtin_apply_args(jit_nint *, args); + stack_args = (jit_nint *)(args[0]); + for(posn = 1; posn <= 20; ++posn) + { + switch(posn) + { + case 1: value = y1; break; + case 2: value = y2; break; + case 3: value = y3; break; + case 4: value = y4; break; + case 5: value = y5; break; + case 6: value = y6; break; + case 7: value = y7; break; + case 8: value = y8; break; + case 9: value = y9; break; + case 10: value = y10; break; + case 11: value = y11; break; + case 12: value = y12; break; + case 13: value = y13; break; + case 14: value = y14; break; + case 15: value = y15; break; + case 16: value = y16; break; + case 17: value = y17; break; + case 18: value = y18; break; + case 19: value = y19; break; + default: value = y20; break; + } + if(!mem_cmp(stack_args, ((jit_nint *)&value) + 1, sizeof(jit_nint))) + { + /* We've detected a register/stack split in this argument */ + can_split_long = 1; + break; + } + } +} +void detect_reg_split_odd_words(jit_long y1, jit_long y2, + jit_long y3, jit_long y4, jit_long y5, + jit_long y6, jit_long y7, jit_long y8, + jit_long y9, jit_long y10, jit_long y11, + jit_long y12, jit_long y13, jit_long y14, + jit_long y15, jit_long y16, jit_long y17, + jit_long y18, jit_long y19, jit_long y20) +{ + jit_nint *args, *stack_args; + int posn; + jit_long value; + jit_builtin_apply_args(jit_nint *, args); + stack_args = (jit_nint *)(args[0]); + for(posn = 1; posn <= 20; ++posn) + { + switch(posn) + { + case 1: value = y1; break; + case 2: value = y2; break; + case 3: value = y3; break; + case 4: value = y4; break; + case 5: value = y5; break; + case 6: value = y6; break; + case 7: value = y7; break; + case 8: value = y8; break; + case 9: value = y9; break; + case 10: value = y10; break; + case 11: value = y11; break; + case 12: value = y12; break; + case 13: value = y13; break; + case 14: value = y14; break; + case 15: value = y15; break; + case 16: value = y16; break; + case 17: value = y17; break; + case 18: value = y18; break; + case 19: value = y19; break; + default: value = y20; break; + } + if(!mem_cmp(stack_args, ((jit_nint *)&value) + 1, sizeof(jit_nint))) + { + /* We've detected a register/stack split in this argument */ + can_split_long = 1; + break; + } + } +} +void detect_stack_align_even_words + (jit_nint arg1, jit_nint arg2, jit_nint arg3, + jit_nint arg4, jit_nint arg5, jit_nint arg6, + jit_nint arg7, jit_nint arg8, jit_nint arg9, + jit_nint arg10, jit_nint arg11, jit_nint arg12, + jit_nint arg13, jit_nint arg14, jit_nint arg15, + jit_nint arg16, jit_nint arg17, jit_nint arg18, + jit_nint arg19, jit_nint arg20, jit_nint arg21, + jit_nint arg22, jit_nint arg23, jit_nint arg24, + jit_nint arg25, jit_nint arg26, jit_nint arg27, + jit_nint arg28, jit_nint arg29, jit_nint arg30, + jit_nint arg31, jit_nint arg32, jit_nint arg33, + jit_long y, jit_long z) +{ + jit_nint *args, *stack_args; + int index; + jit_builtin_apply_args(jit_nint *, args); + stack_args = (jit_nint *)(args[0]); + index = 33 - num_word_regs; + if(!mem_cmp(stack_args + index + 1, &y, sizeof(y))) + { + align_long_stack = 1; + } +} +void detect_stack_align_odd_words + (jit_nint arg1, jit_nint arg2, jit_nint arg3, + jit_nint arg4, jit_nint arg5, jit_nint arg6, + jit_nint arg7, jit_nint arg8, jit_nint arg9, + jit_nint arg10, jit_nint arg11, jit_nint arg12, + jit_nint arg13, jit_nint arg14, jit_nint arg15, + jit_nint arg16, jit_nint arg17, jit_nint arg18, + jit_nint arg19, jit_nint arg20, jit_nint arg21, + jit_nint arg22, jit_nint arg23, jit_nint arg24, + jit_nint arg25, jit_nint arg26, jit_nint arg27, + jit_nint arg28, jit_nint arg29, jit_nint arg30, + jit_nint arg31, jit_nint arg32, + jit_long y, jit_long z) +{ + jit_nint *args, *stack_args; + int index; + jit_builtin_apply_args(jit_nint *, args); + stack_args = (jit_nint *)(args[0]); + index = 32 - num_word_regs; + if(!mem_cmp(stack_args + index + 1, &y, sizeof(y))) + { + align_long_stack = 1; + } +} +void detect_long_alignment() +{ + jit_long value1, value2; + jit_long align_values[20]; + int posn; + value1 = (((jit_long)0x01020304) << 32) | ((jit_long)0x05060708); + value2 = (((jit_long)0x090A0B0C) << 32) | ((jit_long)0x0D0E0F00); + if(num_word_regs == 1) + { + detect_reg_alignment_one_word(value1, value2); + } + else if(num_word_regs == 2) + { + detect_reg_alignment_two_words((jit_int)(-1), value1, value2); + } + else if(num_word_regs == 3) + { + detect_reg_alignment_three_words((jit_int)(-1), value1, value2); + } + else if(num_word_regs > 0) + { + detect_reg_alignment_more_words((jit_int)(-1), value1, value2); + } + else if(x86_fastcall) + { + /* We can split long values using FASTCALL under Win32 */ + can_split_long = 1; + } + for(posn = 0; posn < 20; ++posn) + { + align_values[posn] = ((jit_long)(posn + 4567)) + + (((jit_long)((posn + 1) * 127)) << 32); + } + if((num_word_regs % 2) == 0) + { + detect_reg_split_even_words + ((jit_int)(-1), align_values[0], align_values[1], + align_values[2], align_values[3], align_values[4], + align_values[5], align_values[6], align_values[7], + align_values[8], align_values[9], align_values[10], + align_values[11], align_values[12], align_values[13], + align_values[14], align_values[15], align_values[16], + align_values[17], align_values[18], align_values[19]); + detect_stack_align_even_words + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + value1, value2); + } + else + { + detect_reg_split_odd_words + (align_values[0], align_values[1], + align_values[2], align_values[3], align_values[4], + align_values[5], align_values[6], align_values[7], + align_values[8], align_values[9], align_values[10], + align_values[11], align_values[12], align_values[13], + align_values[14], align_values[15], align_values[16], + align_values[17], align_values[18], align_values[19]); + detect_stack_align_odd_words + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + value1, value2); + } +} +#else /* JIT_NATIVE_INT64 */ +void detect_long_alignment() +{ + /* Long values are always aligned on 64-bit architectures */ +} +#endif /* JIT_NATIVE_INT64 */ + /* * Determine the maximum size for the apply structure. */ @@ -1325,31 +1604,95 @@ void dump_apply_macros(void) } printf("\t} while (0)\n\n"); + /* Macro to align the word registers for a "long" value */ + printf("#define jit_apply_builder_align_regs(builder,num_words,align) \\\n"); + if((align_long_regs || !can_split_long) && + (num_word_regs > 0 || x86_fastcall)) + { + printf("\tdo { \\\n"); + printf("\t\tif((align) > sizeof(jit_nint) && (num_words) > 1) \\\n"); + printf("\t\t{ \\\n"); + if(align_long_regs) + { + printf("\t\t\tif(((builder)->word_used %% 2) == 1) \\\n"); + printf("\t\t\t{ \\n"); + printf("\t\t\t\t++((builder)->word_used); \\n"); + printf("\t\t\t} \\n"); + } + if(!can_split_long) + { + printf("\t\t\tif((%s - (builder)->word_used) < (num_words)) \\\n", word_reg_limit); + printf("\t\t\t{ \\n"); + printf("\t\t\t\t(builder)->word_used = %s; \\n", word_reg_limit); + printf("\t\t\t} \\n"); + } + printf("\t\t} \\\n"); + printf("\t} while (0)\n\n"); + } + else + { + printf("\tdo { ; } while (0)\n\n"); + } + + /* Macro to align the stack for a "long" value */ + printf("#define jit_apply_builder_align_stack(builder,num_words,align) \\\n"); + if(align_long_stack) + { + printf("\tdo { \\\n"); + printf("\t\tif((align) > sizeof(jit_nint) && (num_words) > 1) \\\n"); + printf("\t\t{ \\\n"); + printf("\t\t\tif(((builder)->stack_used %% 2) == 1) \\\n"); + printf("\t\t\t{ \\n"); + printf("\t\t\t\t++((builder)->stack_used); \\n"); + printf("\t\t\t} \\n"); + printf("\t\t} \\\n"); + printf("\t} while (0)\n\n"); + } + else + { + printf("\tdo { ; } while (0)\n\n"); + } + /* Macro to add a large (e.g. dword) argument to the apply parameters */ - printf("#define jit_apply_builder_add_large(builder,type,value) \\\n"); + printf("#define jit_apply_builder_add_large_inner(builder,ptr,size,align) \\\n"); printf("\tdo { \\\n"); - printf("\t\ttype __temp = (type)(value); \\\n"); - printf("\t\tunsigned int __num_words = (sizeof(__temp) + sizeof(jit_nint) - 1) / sizeof(jit_nint); \\\n"); + printf("\t\tunsigned int __num_words = ((size) + sizeof(jit_nint) - 1) / sizeof(jit_nint); \\\n"); if(num_word_regs > 0 || x86_fastcall) { + printf("\t\tjit_apply_builder_align_regs((builder), __num_words, (align)); \\\n"); printf("\t\tif((%s - (builder)->word_used) >= __num_words) \\\n", word_reg_limit); printf("\t\t{ \\\n"); - printf("\t\t\tjit_memcpy((builder)->apply_args->word_regs + (builder)->word_used, &__temp, sizeof(__temp)); \\\n"); + printf("\t\t\tjit_memcpy((builder)->apply_args->word_regs + (builder)->word_used, (ptr), (size)); \\\n"); printf("\t\t\t(builder)->word_used += __num_words; \\\n"); printf("\t\t} \\\n"); + printf("\t\telse if((builder)->word_used) < %s) \\\n", word_reg_limit); + printf("\t\t{ \\\n"); + printf("\t\t\tunsigned int __split = (%s - (builder)->word_used); \\\n", word_reg_limit); + printf("\t\t\tjit_memcpy((builder)->apply_args->word_regs + (builder)->word_used, (ptr), __split * sizeof(jit_nint)); \\\n"); + printf("\t\t\tjit_memcpy((builder)->apply_args->stack_args, ((jit_nint *)(ptr)) + __split, (size) - __split * sizeof(jit_nint)); \\\n"); + printf("\t\t\t(builder)->word_used = %s; \\\n", word_reg_limit); + printf("\t\t\t(builder)->stack_used = __num_words - __split; \\\n"); + printf("\t\t} \\\n"); printf("\t\telse \\\n"); printf("\t\t{ \\\n"); - printf("\t\t\tjit_memcpy((builder)->apply_args->stack_args + (builder)->stack_used, &__temp, sizeof(__temp)); \\\n"); + printf("\t\t\tjit_apply_builder_align_stack((builder), __num_words, (align)); \\\n"); + printf("\t\t\tjit_memcpy((builder)->apply_args->stack_args + (builder)->stack_used, (ptr), (size)); \\\n"); printf("\t\t\t(builder)->stack_used += __num_words * sizeof(jit_nint); \\\n"); printf("\t\t\t(builder)->word_used = %s; \\\n", word_reg_limit); printf("\t\t} \\\n"); } else { - printf("\t\tjit_memcpy((builder)->apply_args->stack_args + (builder)->stack_used, &__temp, sizeof(__temp)); \\\n"); + printf("\t\tjit_apply_builder_align_stack((builder), __num_words, (align)); \\\n"); + printf("\t\tjit_memcpy((builder)->apply_args->stack_args + (builder)->stack_used, (ptr), (size)); \\\n"); printf("\t\t(builder)->stack_used += __num_words * sizeof(jit_nint); \\\n"); } printf("\t} while (0)\n\n"); + printf("#define jit_apply_builder_add_large(builder,type,value) \\\n"); + printf("\tdo { \\\n"); + printf("\t\ttype __temp = (type)(value); \\\n"); + printf("\t\tjit_apply_builder_add_large_inner((builder), &__temp, sizeof(__temp), sizeof(jit_nint)); \\\n"); + printf("\t} while (0)\n\n"); /* Macro to get a large (e.g. dword) argument from the apply parameters */ printf("#define jit_apply_parser_get_large(builder,type,finaltype,value) \\\n"); @@ -1358,13 +1701,23 @@ void dump_apply_macros(void) printf("\t\tunsigned int __num_words = (sizeof(__temp) + sizeof(jit_nint) - 1) / sizeof(jit_nint); \\\n"); if(num_word_regs > 0 || x86_fastcall) { + printf("\t\tjit_apply_builder_align_regs((builder), __num_words, sizeof(type)); \\\n"); printf("\t\tif((%s - (builder)->word_used) >= __num_words) \\\n", word_reg_limit); printf("\t\t{ \\\n"); printf("\t\t\tjit_memcpy(&__temp, (builder)->apply_args->word_regs + (builder)->word_used, sizeof(__temp)); \\\n"); printf("\t\t\t(builder)->word_used += __num_words; \\\n"); printf("\t\t} \\\n"); + printf("\t\telse if((builder)->word_used) < %s) \\\n", word_reg_limit); + printf("\t\t{ \\\n"); + printf("\t\t\tunsigned int __split = (%s - (builder)->word_used); \\\n", word_reg_limit); + printf("\t\t\tjit_memcpy(&__temp, (builder)->apply_args->word_regs + (builder)->word_used, __split * sizeof(jit_nint)); \\\n"); + printf("\t\t\tjit_memcpy(((jit_nint *)&__temp) + __split, (builder)->apply_args->stack_args, (__num_words - __split) * sizeof(jit_nint)); \\\n"); + printf("\t\t\t(builder)->word_used = %s; \\\n", word_reg_limit); + printf("\t\t\t(builder)->stack_used = __num_words - __split; \\\n"); + printf("\t\t} \\\n"); printf("\t\telse \\\n"); printf("\t\t{ \\\n"); + printf("\t\t\tjit_apply_builder_align_stack((builder), __num_words, sizeof(type)); \\\n"); printf("\t\t\tjit_memcpy(&__temp, (builder)->apply_args->stack_args + (builder)->stack_used, sizeof(__temp)); \\\n"); printf("\t\t\t(builder)->stack_used += __num_words * sizeof(jit_nint); \\\n"); printf("\t\t\t(builder)->word_used = %s; \\\n", word_reg_limit); @@ -1372,6 +1725,7 @@ void dump_apply_macros(void) } else { + printf("\t\tjit_apply_builder_align_stack((builder), __num_words, sizeof(type)); \\\n"); printf("\t\tjit_memcpy(&__temp, (builder)->apply_args->stack_args + (builder)->stack_used, sizeof(__temp)); \\\n"); printf("\t\t(builder)->stack_used += __num_words * sizeof(jit_nint); \\\n"); } @@ -1384,6 +1738,7 @@ void dump_apply_macros(void) printf("\tdo { \\\n"); printf("\t\ttype __temp = (type)(value); \\\n"); printf("\t\tunsigned int __num_words = (sizeof(__temp) + sizeof(jit_nint) - 1) / sizeof(jit_nint); \\\n"); + printf("\t\tjit_apply_builder_align_stack((builder), __num_words, sizeof(type)); \\\n"); printf("\t\tjit_memcpy((builder)->apply_args->stack_args + (builder)->stack_used, &__temp, sizeof(__temp)); \\\n"); printf("\t\t(builder)->stack_used += __num_words * sizeof(jit_nint); \\\n"); printf("\t} while (0)\n\n"); @@ -1394,6 +1749,7 @@ void dump_apply_macros(void) printf("\tdo { \\\n"); printf("\t\ttype __temp; \\\n"); printf("\t\tunsigned int __num_words = (sizeof(__temp) + sizeof(jit_nint) - 1) / sizeof(jit_nint); \\\n"); + printf("\t\tjit_apply_builder_align_stack((builder), __num_words, sizeof(type)); \\\n"); printf("\t\tjit_memcpy(&__temp, (builder)->apply_args->stack_args + (builder)->stack_used, sizeof(__temp)); \\\n"); printf("\t\t(builder)->stack_used += __num_words * sizeof(jit_nint); \\\n"); printf("\t\t(value) = (finaltype)(__temp); \\\n"); @@ -1616,30 +1972,8 @@ void dump_apply_macros(void) printf("#define jit_apply_builder_add_struct(builder,value,size,align) \\\n"); printf("\tdo { \\\n"); printf("\t\tunsigned int __size = (size); \\\n"); - if(align_long_regs || align_long_stack) - { - printf("\t\tunsigned int __align = (align); \\\n"); - } - printf("\t\tunsigned int __num_words = (__size + sizeof(jit_nint) - 1) / sizeof(jit_nint); \\\n"); - if(num_word_regs > 0 || x86_fastcall) - { - printf("\t\tif((builder)->word_used < %s) \\\n", word_reg_limit); - printf("\t\t{ \\\n"); - printf("\t\t\tjit_memcpy((builder)->apply_args->word_regs + (builder)->word_used, (value), __size); \\\n"); - printf("\t\t\t(builder)->word_used += __num_words; \\\n"); - printf("\t\t} \\\n"); - printf("\t\telse \\\n"); - printf("\t\t{ \\\n"); - printf("\t\t\tjit_memcpy((builder)->apply_args->stack_args + (builder)->stack_used, (value), __size); \\\n"); - printf("\t\t\t(builder)->stack_used += __num_words * sizeof(jit_nint); \\\n"); - printf("\t\t\t(builder)->word_used = %s; \\\n", word_reg_limit); - printf("\t\t} \\\n"); - } - else - { - printf("\t\tjit_memcpy((builder)->apply_args->stack_args + (builder)->stack_used, (value), __size); \\\n"); - printf("\t\t(builder)->stack_used += __num_words * sizeof(jit_nint); \\\n"); - } + printf("\t\tunsigned int __align; __align = (align); \\\n"); + printf("\t\tjit_apply_builder_add_large_inner((builder), (value), __size, __align); \\\n"); printf("\t} while (0)\n\n"); printf("\n"); @@ -1899,18 +2233,6 @@ int main(int argc, char *argv[]) 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0); - /* Detect the alignment of "long" values in registers and on the stack */ -#ifdef JIT_NATIVE_INT32 - if(num_word_regs > 1) - { - /* TODO */ - } - else - { - /* TODO */ - } -#endif - /* Determine if variable arguments are always passed on the stack */ detect_varargs_on_stack(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, @@ -1933,6 +2255,9 @@ int main(int argc, char *argv[]) /* TODO */ #endif + /* Detect the alignment of "long" values */ + detect_long_alignment(); + /* Determine the maximum sizes */ detect_max_sizes(); @@ -1974,6 +2299,7 @@ int main(int argc, char *argv[]) struct_reg_overlaps_word_reg); printf("#define JIT_APPLY_ALIGN_LONG_REGS %d\n", align_long_regs); printf("#define JIT_APPLY_ALIGN_LONG_STACK %d\n", align_long_stack); + printf("#define JIT_APPLY_CAN_SPLIT_LONG %d\n", can_split_long); printf("#define JIT_APPLY_STRUCT_RETURN_IN_REG_INIT \\\n\t{"); max_struct_in_reg = 0; for(size = 0; size < 64; size += 8)