On Fri, 13 May 2011 17:31:18 +0100 Julian Brown wrote: > On Fri, 13 May 2011 14:54:47 +0000 (UTC) > "Joseph S. Myers" wrote: > > > On Fri, 13 May 2011, Julian Brown wrote: > > > > > although Joseph's comments have (hopefully) all been addressed. > > > One must now configure with "--enable-fixed-point" to enable the > > > fixed-point support. > > > > No, that's not how this configure logic works; it enables fixed > > point by default for the given targets. The bit that enables it by > > default for MIPS (and that you're changing to cover ARM as well) is > > the code that is called if the user *doesn't* pass > > --enable-fixed-point or --disable-fixed-point. > > Yes, you're quite right: I had forgotten to run autoconf after > changing configure.ac whilst testing. Sorry for the misinformation! This is a new version of the patch, which fixes a couple of issues discovered on our internal branch since the last version was posted. This version handles "long long" fixed point types in the same way as 32-bit MIPS: basically the sizes of those types are clamped to 64 bits. This means the testsuite changes in: http://gcc.gnu.org/ml/gcc-patches/2011-05/msg00969.html are no longer required. Another couple of problems have also been fixed, relating to big-endian mode. One was the use of simplify_gen_subreg with a hard-wired offset in a several of the insn expanders, where I should have just used gen_highpart -- which works in either endianness, and makes the intent clearer anyway. The other issue is ABI-related. My previous assertion that fixed-point types (smaller than word size) should be passed to and returned from functions "like integers" doesn't really work out very well after all in big-endian mode, so needs re-thinking. The problem is basically that such fixed-point types are incorrectly padded in big-endian mode, so the data ends up in a different part of the passed word than expected. The way chars and shorts is handled is as follows: when those types are passed to a function, they are promoted to word-size ints, which is a nop-op: the values can simply be reinterpreted as ints, and that works fine in either endianness. We might hope to be able to do the same thing for smaller-than-word-size fixed-point types, but unfortunately we can't: e.g. a "short fract" or "fract" can't just be reinterpreted as a "long fract" (the 32-bit fractional type), because the fixed-point is in a different place for the wider type (and performing conversions would itself require libcalls at present). It also doesn't work to promote small fixed-point types to SImode: as well as being conceptually messy, we hit ICEs very quickly attempting that. So instead, I think that small fixed-point types should be handled the same way as small aggregates or small complex-valued types. This means effectively no change in little-endian mode, but in big-endian mode: * for register arguments, fixed-point types are passed in the most-significant end of the register. * for stack arguments, fixed-point types are passed in lower memory addresses. * for return values, fixed-point types are again in the most-significant end of the return register (r0). This is quite easy to set up in the backend code, but unfortunately I hit a snag in libcall expansion in calls.c: padding of arguments and return values is not properly supported, as it is for regular function calls. I've implemented that, and will post it as a separate patch. OK to apply? Tested alongside the rest of the patch series, in both big & little-endian mode. Julian ChangeLog gcc/ * configure.ac (fixed-point): Add ARM support. * configure: Regenerate. * config/arm/arm.c (arm_fixed_mode_set): New struct. (arm_set_fixed_optab_libfunc): New. (arm_set_fixed_conv_libfunc): New. (arm_init_libfuncs): Initialise fixed-point helper libfuncs with ARM-specific names. (aapcs_libcall_value): Return sub-word-size fixed-point libcall return values in SImode. (arm_return_in_msb): Return fixed-point types in the msb. (arm_pad_reg_upwards, arm_pad_arg_upwards): Pad fixed-point types upwards. (arm_scalar_mode_supported_p): Support fixed-point modes. (arm_vector_mode_supported_p): Support vector fixed-point modes. * config/arm/arm.h (SHORT_FRACT_TYPE_SIZE, FRACT_TYPE_SIZE) (LONG_FRACT_TYPE_SIZE, LONG_LONG_FRACT_TYPE_SIZE) (SHORT_ACCUM_TYPE_SIZE, ACCUM_TYPE_SIZE, LONG_ACCUM_TYPE_SIZE) (LONG_LONG_ACCUM_TYPE_SIZE, MAX_FIXED_MODE_SIZE): Define. * config/arm/arm-modes.def (FRACT, UFRACT, ACCUM, UACCUM): Declare vector modes. * config/arm/predicates.md (sat_shift_operator): New predicate. * config/arm/arm-fixed.md: New. * config/arm/arm.md: Include arm-fixed.md. * config/arm/t-arm (MD_INCLUDES): Add arm-fixed.md. * config/arm/fixed-bit-machine.h: New. libgcc/ * config.host (arm*-*-linux*, arm*-*-uclinux*, arm*-*-eabi*) (arm*-*-symbianelf*): Add arm/t-fixed-point makefile fragment. target-specific or generic fixed_bit_machine_header to decorate the names of fixed-point helper functions. * config/arm/t-fixed-point: New. gcc/testsuite/ * gcc.target/arm/fixed-point-exec.c: New test.