1/*
2 * Copyright (C) 2013 Andrew Turner
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 *
28 */
29
30#ifndef AEABI_VFP_H
31#define	AEABI_VFP_H
32
33#include <machine/acle-compat.h>
34
35/*
36 * ASM helper macros. These allow the functions to be changed depending on
37 * the endian-ness we are building for.
38 */
39
40/* Allow the name of the function to be changed depending on the ABI */
41#ifndef __ARM_PCS_VFP
42#define	AEABI_ENTRY(x)	ENTRY(__aeabi_ ## x ## _vfp)
43#define	AEABI_END(x)	END(__aeabi_ ## x ## _vfp)
44#else
45#define	AEABI_ENTRY(x)	ENTRY(__aeabi_ ## x)
46#define	AEABI_END(x)	END(__aeabi_ ## x)
47#endif
48
49/*
50 * These should be used when a function either takes, or returns a floating
51 * point falue. They will load the data from an ARM to a VFP register(s),
52 * or from a VFP to an ARM register
53 */
54#ifdef __ARM_BIG_ENDIAN
55#define	LOAD_DREG(vreg, reg0, reg1)   vmov vreg, reg1, reg0
56#define	UNLOAD_DREG(reg0, reg1, vreg) vmov reg1, reg0, vreg
57#else
58#define	LOAD_DREG(vreg, reg0, reg1)   vmov vreg, reg0, reg1
59#define	UNLOAD_DREG(reg0, reg1, vreg) vmov reg0, reg1, vreg
60#endif
61
62#define	LOAD_SREGS(vreg0, vreg1, reg0, reg1) vmov vreg0, vreg1, reg0, reg1
63#define	LOAD_SREG(vreg, reg)                 vmov vreg, reg
64#define	UNLOAD_SREG(reg, vreg)               vmov reg, vreg
65
66/*
67 * C Helper macros
68 */
69
70#if __ARM_ARCH >= 6
71/*
72 * Generate a function that will either call into the VFP implementation,
73 * or the soft float version for a given __aeabi_* helper. The function
74 * will take a single argument of the type given by in_type.
75 */
76#define	AEABI_FUNC(name, in_type, soft_func)			\
77__aeabi_ ## name(in_type a)					\
78{								\
79	if (_libc_arm_fpu_present)				\
80		return __aeabi_ ## name ## _vfp(a);		\
81	else							\
82		return soft_func (a);				\
83}
84
85/* As above, but takes two arguments of the same type */
86#define	AEABI_FUNC2(name, in_type, soft_func)			\
87__aeabi_ ## name(in_type a, in_type b)				\
88{								\
89	if (_libc_arm_fpu_present)				\
90		return __aeabi_ ## name ## _vfp(a, b);	\
91	else							\
92		return soft_func (a, b);			\
93}
94
95/* As above, but with the soft float arguments reversed */
96#define	AEABI_FUNC2_REV(name, in_type, soft_func)		\
97__aeabi_ ## name(in_type a, in_type b)				\
98{								\
99	if (_libc_arm_fpu_present)				\
100		return __aeabi_ ## name ## _vfp(a, b);	\
101	else							\
102		return soft_func (b, a);			\
103}
104#else
105/*
106 * Helper macros for when we are only able to use the softfloat
107 * version of these functions, i.e. on arm before armv6.
108 */
109#define	AEABI_FUNC(name, in_type, soft_func)			\
110__aeabi_ ## name(in_type a)					\
111{								\
112	return soft_func (a);					\
113}
114
115/* As above, but takes two arguments of the same type */
116#define	AEABI_FUNC2(name, in_type, soft_func)			\
117__aeabi_ ## name(in_type a, in_type b)				\
118{								\
119	return soft_func (a, b);				\
120}
121
122/* As above, but with the soft float arguments reversed */
123#define	AEABI_FUNC2_REV(name, in_type, soft_func)		\
124__aeabi_ ## name(in_type a, in_type b)				\
125{								\
126	return soft_func (b, a);				\
127}
128#endif
129
130#endif
131
132