# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @depends(target.os, '--help') def arm_option_defaults(os, _): if os == 'Android': arch = 'armv7-a' thumb = 'yes' fpu = 'neon' float_abi = 'softfp' else: arch = thumb = fpu = float_abi = 'toolchain-default' return namespace( arch=arch, thumb=thumb, fpu=fpu, float_abi=float_abi, ) # Note: '{...|}' in the help of all options with a non-constant default to # make the lint happy. The first arm is always going to be used, because a # default is always returned. The lint is fooled by this file being # conditional. If it weren't conditional, the lint wouldn't ask for '{|}' to # be there. js_option('--with-arch', nargs=1, default=arm_option_defaults.arch, help='{Use specific CPU features (-march=type). Resets thumb, fpu, ' 'float-abi, etc. defaults when set|}') @depends('--with-arch') def arch_option(value): if value: if value[0] != 'toolchain-default': return ['-march={}'.format(value[0])] return [] js_option('--with-thumb', choices=('yes', 'no', 'toolchain-default'), default=arm_option_defaults.thumb, nargs='?', help='{Use Thumb instruction set (-mthumb)|}') def normalize_arm_option(value): if value: if len(value): if value[0] == 'yes': return True elif value[0] == 'no': return False else: return value[0] return True return False @depends('--with-thumb') def thumb_option(value): value = normalize_arm_option(value) if value is True: return ['-mthumb'] if value is False: return ['-marm'] return [] js_option('--with-thumb-interwork', choices=('yes', 'no', 'toolchain-default'), default='toolchain-default', nargs='?', help='Use Thumb/ARM instuctions interwork (-mthumb-interwork)') @depends('--with-thumb-interwork') def thumb_interwork_option(value): value = normalize_arm_option(value) if value is True: return ['-mthumb-interwork'] if value is False: return ['-mno-thumb-interwork'] return [] js_option('--with-fpu', nargs=1, default=arm_option_defaults.fpu, help='{Use specific FPU type (-mfpu=type)|}') @depends('--with-fpu') def fpu_option(value): if value: if value[0] != 'toolchain-default': return ['-mfpu={}'.format(value[0])] return [] js_option('--with-float-abi', nargs=1, default=arm_option_defaults.float_abi, help='{Use specific arm float ABI (-mfloat-abi=type)|}') @depends('--with-float-abi') def float_abi_option(value): if value: if value[0] != 'toolchain-default': return ['-mfloat-abi={}'.format(value[0])] return [] js_option('--with-soft-float', choices=('yes', 'no', 'toolchain-default'), default='toolchain-default', nargs='?', help='Use soft float library (-msoft-float)') @depends('--with-soft-float') def soft_float_option(value): value = normalize_arm_option(value) if value is True: return ['-msoft-float'] if value is False: return ['-mno-soft-float'] return [] check_and_add_gcc_flag('-mno-unaligned-access', when=depends(target.os)(lambda os: os == 'Android')) @depends(arch_option, thumb_option, thumb_interwork_option, fpu_option, float_abi_option, soft_float_option) def all_flags(arch, thumb, interwork, fpu, float_abi, soft_float): return arch + thumb + interwork + fpu + float_abi + soft_float add_old_configure_assignment('_ARM_FLAGS', all_flags) add_old_configure_assignment('_THUMB_FLAGS', thumb_option) @depends(c_compiler, all_flags) @checking('ARM version support in compiler', lambda x: x.arm_arch) @imports(_from='textwrap', _import='dedent') def arm_target(compiler, all_flags): # We're going to preprocess the following source to figure out some details # about the arm target options we have enabled. source = dedent('''\ %ARM_ARCH __ARM_ARCH #if __thumb2__ %THUMB2 yes #else %THUMB2 no #endif // Confusingly, the __SOFTFP__ preprocessor variable indicates the // "softfloat" ABI, not the "softfp" ABI. #if __SOFTFP__ %FLOAT_ABI soft #elif __ARM_PCS_VFP %FLOAT_ABI hard #else %FLOAT_ABI softfp #endif // There is more subtlety to it than this preprocessor test, but MOZ_FPU doesn't // need to be too fine-grained. #if __ARM_NEON %FPU neon #elif __ARM_VFPV2__ || __ARM_FP == 12 %FPU vfpv2 #elif __ARM_VFPV3__ %FPU vfpv3 #elif __ARM_VFPV4__ || __ARM_FP == 14 %FPU vfpv4 #elif __ARM_FPV5__ %FPU fp-armv8 #endif ''') result = try_invoke_compiler( compiler.wrapper + [compiler.compiler] + compiler.flags, compiler.language, source, ['-E'] + all_flags, ) # Metadata emitted by preprocessors such as GCC with LANG=ja_JP.utf-8 may # have non-ASCII characters. Treat the output as bytearray. data = {'fpu': None} # fpu may not get a value from the preprocessor. for line in result.splitlines(): if line.startswith(b'%'): k, _, v = line.partition(' ') k = k.lstrip('%').lower() if k == 'arm_arch': data[k] = int(v) else: data[k] = { 'yes': True, 'no': False, }.get(v, v) log.debug('%s = %s', k, data[k]) return namespace(**data) @depends(arm_target.arm_arch, when=depends(target.os)(lambda os: os == 'Android')) def armv7(arch): if arch < 7: die('Android/armv6 and earlier are not supported') set_config('MOZ_THUMB2', True, when=arm_target.thumb2) set_define('MOZ_THUMB2', True, when=arm_target.thumb2) add_old_configure_assignment('MOZ_THUMB2', True, when=arm_target.thumb2) have_arm_simd = c_compiler.try_compile(body='asm("uqadd8 r1, r1, r2");', check_msg='for ARM SIMD support in compiler') set_config('HAVE_ARM_SIMD', have_arm_simd) set_define('HAVE_ARM_SIMD', have_arm_simd) have_arm_neon = c_compiler.try_compile(body='asm(".fpu neon\\n vadd.i8 d0, d0, d0");', check_msg='for ARM NEON support in compiler') set_config('HAVE_ARM_NEON', have_arm_neon) set_define('HAVE_ARM_NEON', have_arm_neon) # We don't need to build NEON support if we're targetting a non-NEON device. # This matches media/webrtc/trunk/webrtc/build/common.gypi. @depends(arm_target.arm_arch, when=have_arm_neon) def build_arm_neon(arm_arch): return arm_arch >= 7 set_config('BUILD_ARM_NEON', build_arm_neon) set_define('BUILD_ARM_NEON', build_arm_neon) set_config('ARM_ARCH', depends(arm_target.arm_arch)(lambda x: str(x))) add_old_configure_assignment('ARM_ARCH', depends(arm_target.arm_arch)(lambda x: str(x))) set_config('MOZ_FPU', arm_target.fpu) @depends(arm_target.float_abi) def neon_flags(float_abi): # Building with -mfpu=neon requires either the "softfp" or the # "hardfp" ABI. Depending on the compiler's default target, and the # CFLAGS, the default ABI might be neither, in which case it is the # "softfloat" ABI. # The "softfloat" ABI is binary-compatible with the "softfp" ABI, so # we can safely mix code built with both ABIs. So, if we detect # that compiling uses the "softfloat" ABI, force the use of the # "softfp" ABI instead. flags = ['-mfpu=neon'] if float_abi == 'soft': flags.append('-mfloat-abi=softfp') return tuple(flags) set_config('NEON_FLAGS', neon_flags)