gf-3.6: src/runtime/c/pgf/lightning/arm/fp-vfp.h
/******************************** -*- C -*- ****************************
*
* Support macros for arm VFP floating-point math
*
***********************************************************************/
/***********************************************************************
*
* Copyright 2011 Free Software Foundation, Inc.
*
* This file is part of GNU lightning.
*
* GNU lightning is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU lightning is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GNU lightning; see the file COPYING.LESSER; if not, write to the
* Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* Authors:
* Paulo Cesar Pereira de Andrade
***********************************************************************/
#ifndef __lightning_fp_vfp_h
#define __lightning_fp_vfp_h
#if 0
__jit_inline void
vfp_movr_f(jit_state_t _jit, jit_fpr_t r0, jit_fpr_t r1)
{
if (r0 != r1) {
if (r0 == JIT_FPRET) {
/* jit_ret() must follow! */
if (!jit_hardfp_p())
_VMOV_A_S(_R0, r1);
else
_VMOV_F32(_D0, r1);
}
else
_VMOV_F32(r0, r1);
}
}
__jit_inline void
vfp_movr_d(jit_state_t _jit, jit_fpr_t r0, jit_fpr_t r1)
{
if (r0 != r1) {
if (r0 == JIT_FPRET) {
/* jit_ret() must follow! */
if (!jit_hardfp_p())
_VMOV_AA_D(_R0, _R1, r1);
else
_VMOV_F64(_D0, r1);
}
else
_VMOV_F64(r0, r1);
}
}
__jit_inline void
vfp_movi_f(jit_state_t _jit, jit_fpr_t r0, float i0)
{
union {
int i;
float f;
} u;
int code;
u.f = i0;
if (!jit_hardfp_p() && r0 == JIT_FPRET)
/* jit_ret() must follow! */
jit_movi_i(_R0, u.i);
else {
if (r0 == JIT_FPRET)
r0 = _D0;
if ((code = encode_vfp_double(1, 0, u.i, u.i)) != -1 ||
(code = encode_vfp_double(1, 1, ~u.i, ~u.i)) != -1)
_VIMM(code, r0);
else {
jit_movi_i(JIT_FTMP, u.i);
_VMOV_S_A(r0, JIT_FTMP);
}
}
}
__jit_inline void
vfp_movi_d(jit_state_t _jit, jit_fpr_t r0, double i0)
{
union {
int i[2];
double d;
} u;
int code;
u.d = i0;
if (!jit_hardfp_p() && r0 == JIT_FPRET) {
/* jit_ret() must follow! */
jit_movi_i(_R0, u.i[0]);
jit_movi_i(_R1, u.i[1]);
}
else {
if (r0 == JIT_FPRET)
r0 = _D0;
if ((code = encode_vfp_double(1, 0, u.i[0], u.i[1])) != -1 ||
(code = encode_vfp_double(1, 1, ~u.i[0], ~u.i[1])) != -1)
_VIMM(code, r0);
else {
jit_movi_i(JIT_TMP, u.i[0]);
jit_movi_i(JIT_FTMP, u.i[1]);
_VMOV_D_AA(r0, JIT_TMP, JIT_FTMP);
}
}
}
__jit_inline void
vfp_extr_i_f(jit_state_t _jit, jit_fpr_t r0, jit_gpr_t r1)
{
_VMOV_V_I32(r0, r1);
_VCVT_F32_S32(r0, r0);
}
__jit_inline void
vfp_extr_i_d(jit_state_t _jit, jit_fpr_t r0, jit_gpr_t r1)
{
_VMOV_V_I32(r0, r1);
_VCVT_F64_S32(r0, r0);
}
#define vfp_extr_d_f(_jit, r0, r1) _VCVT_F64_F32(r0, r1)
#define vfp_extr_f_d(_jit, r0, r1) _VCVT_F32_F64(r0, r1)
/* FIXME keeping for now, in case there exists, and/or to support
* only 4 double precision registers */
#define vfp_get_tmp(r, n) \
jit_fpr_t tmp; \
if (0) { \
tmp = r == _D0 ? _D1 : _D0; \
_VPUSH_F##n(tmp, 2); \
} \
else \
tmp = _D15
#define vfp_unget_tmp(n) \
if (0) \
_VPOP_F##n(tmp, 2)
__jit_inline void
vfp_rintr_f_i(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1)
{
vfp_get_tmp(r1, 32);
_VCVT_S32_F32(tmp, r1);
_VMOV_A_S32(r0, tmp);
vfp_unget_tmp(32);
}
__jit_inline void
vfp_rintr_d_i(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1)
{
vfp_get_tmp(r1, 64);
_VCVT_S32_F64(tmp, r1);
_VMOV_A_S32(r0, tmp);
vfp_unget_tmp(64);
}
__jit_inline void
vfp_roundr_f_i(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1)
{
vfp_get_tmp(r1, 32);
_VMOV_A_S(JIT_FTMP, r1);
if (jit_thumb_p()) {
T2_TSTI(JIT_FTMP, encode_thumb_immediate(0x80000000));
_ITE(ARM_CC_NE);
/* add -0.5 if negative */
T2_MOVI(JIT_FTMP, encode_thumb_immediate(0xbf000000));
/* add 0.5 if positive */
T2_MOVI(JIT_FTMP, encode_thumb_immediate(0x3f000000));
}
else {
if (jit_armv6_p())
_TSTI(JIT_FTMP, encode_arm_immediate(0x80000000));
else
_ANDSI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(0x80000000));
/* add -0.5 if negative */
_CC_MOVI(ARM_CC_NE, JIT_FTMP, encode_arm_immediate(0xbf000000));
/* add 0.5 if positive */
_CC_MOVI(ARM_CC_EQ, JIT_FTMP, encode_arm_immediate(0x3f000000));
}
_VMOV_S_A(tmp, JIT_FTMP);
_VADD_F32(tmp, r1, tmp);
/* truncate to zero */
_VCVT_S32_F32(tmp, tmp);
_VMOV_A_S32(r0, tmp);
vfp_unget_tmp(32);
}
__jit_inline void
vfp_roundr_d_i(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1)
{
vfp_get_tmp(r1, 64);
_VMOV_AA_D(JIT_TMP, JIT_FTMP, r1);
if (jit_thumb_p()) {
T2_TSTI(JIT_FTMP, encode_thumb_immediate(0x80000000));
T2_MOVI(JIT_FTMP, encode_thumb_immediate(0x0fe00000));
_ITE(ARM_CC_NE);
/* add -0.5 if negative */
T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(0xb0000000));
/* add 0.5 if positive */
T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(0x30000000));
}
else {
if (jit_armv6_p())
_TSTI(JIT_FTMP, encode_arm_immediate(0x80000000));
else
_ANDSI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(0x80000000));
_MOVI(JIT_FTMP, encode_arm_immediate(0x0fe00000));
/* add -0.5 if negative */
_CC_ORRI(ARM_CC_NE, JIT_FTMP, JIT_FTMP,
encode_arm_immediate(0xb0000000));
/* add 0.5 if positive */
_CC_ORRI(ARM_CC_EQ, JIT_FTMP, JIT_FTMP,
encode_arm_immediate(0x30000000));
}
jit_movi_i(JIT_TMP, 0);
_VMOV_D_AA(tmp, JIT_TMP, JIT_FTMP);
_VADD_F64(tmp, r1, tmp);
/* truncate to zero */
_VCVT_S32_F64(tmp, tmp);
_VMOV_A_S32(r0, tmp);
vfp_unget_tmp(64);
}
#define vfp_truncr_f_i(_jit, r0, r1) vfp_rintr_f_i(_jit, r0, r1)
#define vfp_truncr_d_i(_jit, r0, r1) vfp_rintr_d_i(_jit, r0, r1)
__jit_inline void
vfp_ceilr_f_i(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1)
{
vfp_get_tmp(r1, 32);
_VMRS(JIT_TMP);
if (jit_thumb_p()) {
T2_BICI(JIT_FTMP, JIT_TMP, encode_thumb_immediate(FPSCR_RMASK));
T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(FPSCR_RP));
}
else {
_BICI(JIT_FTMP, JIT_TMP, encode_arm_immediate(FPSCR_RMASK));
_ORRI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(FPSCR_RP));
}
_VMSR(JIT_FTMP);
_VCVTR_S32_F32(tmp, r1);
_VMOV_A_S32(r0, tmp);
_VMSR(JIT_TMP);
vfp_unget_tmp(32);
}
__jit_inline void
vfp_ceilr_d_i(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1)
{
vfp_get_tmp(r1, 64);
_VMRS(JIT_TMP);
if (jit_thumb_p()) {
T2_BICI(JIT_FTMP, JIT_TMP, encode_thumb_immediate(FPSCR_RMASK));
T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(FPSCR_RP));
}
else {
_BICI(JIT_FTMP, JIT_TMP, encode_arm_immediate(FPSCR_RMASK));
_ORRI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(FPSCR_RP));
}
_VMSR(JIT_FTMP);
_VCVTR_S32_F64(tmp, r1);
_VMOV_A_S32(r0, tmp);
_VMSR(JIT_TMP);
vfp_unget_tmp(64);
}
__jit_inline void
vfp_floorr_f_i(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1)
{
vfp_get_tmp(r1, 32);
_VMRS(JIT_TMP);
if (jit_thumb_p()) {
T2_BICI(JIT_FTMP, JIT_TMP, encode_thumb_immediate(FPSCR_RMASK));
T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(FPSCR_RM));
}
else {
_BICI(JIT_FTMP, JIT_TMP, encode_arm_immediate(FPSCR_RMASK));
_ORRI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(FPSCR_RM));
}
_VMSR(JIT_FTMP);
_VCVTR_S32_F32(tmp, r1);
_VMOV_A_S32(r0, tmp);
_VMSR(JIT_TMP);
vfp_unget_tmp(32);
}
__jit_inline void
vfp_floorr_d_i(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1)
{
vfp_get_tmp(r1, 64);
_VMRS(JIT_TMP);
if (jit_thumb_p()) {
T2_BICI(JIT_FTMP, JIT_TMP, encode_thumb_immediate(FPSCR_RMASK));
T2_ORRI(JIT_FTMP, JIT_FTMP, encode_thumb_immediate(FPSCR_RM));
}
else {
_BICI(JIT_FTMP, JIT_TMP, encode_arm_immediate(FPSCR_RMASK));
_ORRI(JIT_FTMP, JIT_FTMP, encode_arm_immediate(FPSCR_RM));
}
_VMSR(JIT_FTMP);
_VCVTR_S32_F64(tmp, r1);
_VMOV_A_S32(r0, tmp);
_VMSR(JIT_TMP);
vfp_unget_tmp(64);
}
#define vfp_absr_f(_jit, r0, r1) _VABS_F32(r0, r1)
#define vfp_absr_d(_jit, r0, r1) _VABS_F64(r0, r1)
#define vfp_negr_f(_jit, r0, r1) _VNEG_F32(r0, r1)
#define vfp_negr_d(_jit, r0, r1) _VNEG_F64(r0, r1)
#define vfp_sqrtr_f(_jit, r0, r1) _VSQRT_F32(r0, r1)
#define vfp_sqrtr_d(_jit, r0, r1) _VSQRT_F64(r0, r1)
#define vfp_addr_f(_jit, r0, r1, r2) _VADD_F32(r0, r1, r2)
#define vfp_addr_d(_jit, r0, r1, r2) _VADD_F64(r0, r1, r2)
#define vfp_subr_f(_jit, r0, r1, r2) _VSUB_F32(r0, r1, r2)
#define vfp_subr_d(_jit, r0, r1, r2) _VSUB_F64(r0, r1, r2)
#define vfp_mulr_f(_jit, r0, r1, r2) _VMUL_F32(r0, r1, r2)
#define vfp_mulr_d(_jit, r0, r1, r2) _VMUL_F64(r0, r1, r2)
#define vfp_divr_f(_jit, r0, r1, r2) _VDIV_F32(r0, r1, r2)
#define vfp_divr_d(_jit, r0, r1, r2) _VDIV_F64(r0, r1, r2)
static void
_vcmp01_x(jit_state_t _jit, int c0, int c1, jit_gpr_t r0)
{
_VMRS(_R15);
if (jit_thumb_p()) {
if ((c0 ^ c1) >> 28 == 1) {
_ITE(c0);
if (r0 < 8) {
T1_MOVI(r0, 0);
T1_MOVI(r0, 1);
}
else {
T2_MOVI(r0, 0);
T2_MOVI(r0, 1);
}
}
else {
if (r0 < 8) {
_IT(c0);
T1_MOVI(r0, 0);
_IT(c1);
T1_MOVI(r0, 1);
}
else {
_IT(c0);
T2_MOVI(r0, 0);
_IT(c1);
T2_MOVI(r0, 1);
}
}
}
else {
_CC_MOVI(c0, r0, 0);
_CC_MOVI(c1, r0, 1);
}
}
static void
_vcmp01_f(jit_state_t _jit, int c0, int c1,
jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F32(r1, r2);
_vcmp01_x(_jit, c0, c1, r0);
}
static void
_vcmp01_d(jit_state_t _jit, int c0, int c1,
jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F64(r1, r2);
_vcmp01_x(_jit, c0, c1, r0);
}
#define vfp_ltr_f(_jit,r0,r1,r2) _vcmp01_f(_jit,ARM_CC_PL,ARM_CC_MI,r0,r1,r2)
#define vfp_ltr_d(_jit,r0,r1,r2) _vcmp01_d(_jit,ARM_CC_PL,ARM_CC_MI,r0,r1,r2)
#define vfp_ler_f(_jit,r0,r1,r2) _vcmp01_f(_jit,ARM_CC_HS,ARM_CC_LS,r0,r1,r2)
#define vfp_ler_d(_jit,r0,r1,r2) _vcmp01_d(_jit,ARM_CC_HS,ARM_CC_LS,r0,r1,r2)
#define vfp_eqr_f(_jit,r0,r1,r2) _vcmp01_f(_jit,ARM_CC_NE,ARM_CC_EQ,r0,r1,r2)
#define vfp_eqr_d(_jit,r0,r1,r2) _vcmp01_d(_jit,ARM_CC_NE,ARM_CC_EQ,r0,r1,r2)
#define vfp_ger_f(_jit,r0,r1,r2) _vcmp01_f(_jit,ARM_CC_LT,ARM_CC_GE,r0,r1,r2)
#define vfp_ger_d(_jit,r0,r1,r2) _vcmp01_d(_jit,ARM_CC_LT,ARM_CC_GE,r0,r1,r2)
#define vfp_gtr_f(_jit,r0,r1,r2) _vcmp01_f(_jit,ARM_CC_LE,ARM_CC_GT,r0,r1,r2)
#define vfp_gtr_d(_jit,r0,r1,r2) _vcmp01_d(_jit,ARM_CC_LE,ARM_CC_GT,r0,r1,r2)
#define vfp_ner_f(_jit,r0,r1,r2) _vcmp01_f(_jit,ARM_CC_EQ,ARM_CC_NE,r0,r1,r2)
#define vfp_ner_d(_jit,r0,r1,r2) _vcmp01_d(_jit,ARM_CC_EQ,ARM_CC_NE,r0,r1,r2)
static void
_vcmp10_x(jit_state_t _jit, int cc, jit_gpr_t r0)
{
if (jit_thumb_p()) {
if (r0 < 8) {
T1_MOVI(r0, 1);
_VMRS(_R15);
_IT(cc);
T1_MOVI(r0, 0);
}
else {
T2_MOVI(r0, 1);
_VMRS(_R15);
_IT(cc);
T2_MOVI(r0, 0);
}
}
else {
_VMRS(_R15);
_MOVI(r0, 1);
_CC_MOVI(cc, r0, 0);
}
}
static void
_vcmp_10_f(jit_state_t _jit, int cc, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F32(r1, r2);
_vcmp10_x(_jit, cc, r0);
}
static void
_vcmp_10_d(jit_state_t _jit, int cc, jit_gpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
{
_VCMP_F64(r1, r2);
_vcmp10_x(_jit, cc, r0);
}
#define vfp_unltr_f(_jit,r0,r1,r2) _vcmp_10_f(_jit,ARM_CC_GE,r0,r1,r2)
#define vfp_unltr_d(_jit,r0,r1,r2) _vcmp_10_d(_jit,ARM_CC_GE,r0,r1,r2)
#define vfp_unler_f(_jit,r0,r1,r2) _vcmp_10_f(_jit,ARM_CC_GT,r0,r1,r2)
#define vfp_unler_d(_jit,r0,r1,r2) _vcmp_10_d(_jit,ARM_CC_GT,r0,r1,r2)
static void
vfp_uneqr_x(jit_state_t _jit, jit_gpr_t r0)
{
_VMRS(_R15);
if (jit_thumb_p()) {
_ITE(ARM_CC_NE);
if (r0 < 8) {
T1_MOVI(r0, 0);
T1_MOVI(r0, 1);
_IT(ARM_CC_VS);
T1_MOVI(r0, 1);
}
else {
T2_MOVI(r0, 0);
T2_MOVI(r0, 1);
_IT(ARM_CC_VS);
T2_MOVI(r0, 1);
}
}
else {
_CC_MOVI(ARM_CC_NE, r0, 0);
_CC_MOVI(ARM_CC_EQ, r0, 1);
_CC_MOVI(ARM_CC_VS, r0, 1);
}
}
__jit_inline void
vfp_uneqr_f(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F32(r1, r2);
vfp_uneqr_x(_jit, r0);
}
__jit_inline void
vfp_uneqr_d(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F64(r1, r2);
vfp_uneqr_x(_jit, r0);
}
static void
_vcmp_01_x(jit_state_t _jit, int cc, jit_gpr_t r0)
{
if (jit_thumb_p()) {
if (r0 < 8) {
T1_MOVI(r0, 0);
_VMRS(_R15);
_IT(cc);
T1_MOVI(r0, 1);
}
else {
T2_MOVI(r0, 0);
_VMRS(_R15);
_IT(cc);
T2_MOVI(r0, 1);
}
}
else {
_VMRS(_R15);
_MOVI(r0, 0);
_CC_MOVI(cc, r0, 1);
}
}
static void
_vcmp_01_f(jit_state_t _jit, int cc, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F32(r1, r2);
_vcmp_01_x(_jit, cc, r0);
}
static void
_vcmp_01_d(jit_state_t _jit, int cc, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F64(r1, r2);
_vcmp_01_x(_jit, cc, r0);
}
#define vfp_unger_f(_jit,r0,r1,r2) _vcmp_01_f(_jit,ARM_CC_CS,r0,r1,r2)
#define vfp_unger_d(_jit,r0,r1,r2) _vcmp_01_d(_jit,ARM_CC_CS,r0,r1,r2)
#define vfp_ungtr_f(_jit,r0,r1,r2) _vcmp_01_f(_jit,ARM_CC_HI,r0,r1,r2)
#define vfp_ungtr_d(_jit,r0,r1,r2) _vcmp_01_d(_jit,ARM_CC_HI,r0,r1,r2)
static void
_vfp_ltgtr_x(jit_state_t _jit, jit_gpr_t r0)
{
_VMRS(_R15);
if (jit_thumb_p()) {
_ITE(ARM_CC_NE);
if (r0 < 8) {
T1_MOVI(r0, 1);
T1_MOVI(r0, 0);
_IT(ARM_CC_VS);
T1_MOVI(r0, 0);
}
else {
T2_MOVI(r0, 1);
T2_MOVI(r0, 0);
_IT(ARM_CC_VS);
T2_MOVI(r0, 0);
}
}
else {
_CC_MOVI(ARM_CC_NE, r0, 1);
_CC_MOVI(ARM_CC_EQ, r0, 0);
_CC_MOVI(ARM_CC_VS, r0, 0);
}
}
__jit_inline void
vfp_ltgtr_f(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F32(r1, r2);
_vfp_ltgtr_x(_jit, r0);
}
__jit_inline void
vfp_ltgtr_d(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F64(r1, r2);
_vfp_ltgtr_x(_jit, r0);
}
__jit_inline void
vfp_ordr_f(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F32(r1, r2);
_vcmp10_x(_jit, ARM_CC_VS, r0);
}
__jit_inline void
vfp_ordr_d(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F64(r1, r2);
_vcmp10_x(_jit, ARM_CC_VS, r0);
}
__jit_inline void
vfp_unordr_f(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F32(r1, r2);
_vcmp_01_x(_jit, ARM_CC_VS, r0);
}
__jit_inline void
vfp_unordr_d(jit_state_t _jit, jit_gpr_t r0, jit_fpr_t r1, jit_fpr_t r2)
{
_VCMP_F64(r1, r2);
_vcmp_01_x(_jit, ARM_CC_VS, r0);
}
static jit_insn *
_vbcmp_x(jit_state_t _jit, int cc, jit_insn *i0)
{
jit_insn *l;
long d;
_VMRS(_R15);
l = _jit->x.pc;
if (jit_thumb_p()) {
d = (((long)i0 - (long)l) >> 1) - 2;
assert(_s20P(d));
T2_CC_B(cc, encode_thumb_cc_jump(d));
}
else {
d = (((long)i0 - (long)l) >> 2) - 2;
assert(_s24P(d));
_CC_B(cc, d & 0x00ffffff);
}
return (l);
}
__jit_inline jit_insn *
_vbcmp_f(jit_state_t _jit, int cc, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F32(r0, r1);
return (_vbcmp_x(_jit, cc, i0));
}
__jit_inline jit_insn *
_vbcmp_d(jit_state_t _jit, int cc, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F64(r0, r1);
return (_vbcmp_x(_jit, cc, i0));
}
#define vfp_bltr_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_MI,i0,r0,r1)
#define vfp_bltr_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_MI,i0,r0,r1)
#define vfp_bler_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_LS,i0,r0,r1)
#define vfp_bler_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_LS,i0,r0,r1)
#define vfp_beqr_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_EQ,i0,r0,r1)
#define vfp_beqr_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_EQ,i0,r0,r1)
#define vfp_bger_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_GE,i0,r0,r1)
#define vfp_bger_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_GE,i0,r0,r1)
#define vfp_bgtr_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_GT,i0,r0,r1)
#define vfp_bgtr_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_GT,i0,r0,r1)
#define vfp_bner_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_NE,i0,r0,r1)
#define vfp_bner_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_NE,i0,r0,r1)
static jit_insn *
_vbncmp_x(jit_state_t _jit, int cc, jit_insn *i0)
{
jit_insn *i;
jit_insn *l;
long d;
_VMRS(_R15);
i = _jit->x.pc;
if (jit_thumb_p()) {
T2_CC_B(cc, 0);
l = _jit->x.pc;
d = (((long)i0 - (long)l) >> 1) - 2;
assert(_s24P(d));
T2_B(encode_thumb_jump(d));
}
else {
_CC_B(cc, 0);
l = _jit->x.pc;
d = (((long)i0 - (long)l) >> 2) - 2;
assert(_s24P(d));
_B(d & 0x00ffffff);
}
jit_patch(i);
return (l);
}
__jit_inline jit_insn *
_vbncmp_f(jit_state_t _jit, int cc, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F32(r0, r1);
return (_vbncmp_x(_jit, cc, i0));
}
__jit_inline jit_insn *
_vbncmp_d(jit_state_t _jit, int cc, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F64(r0, r1);
return (_vbncmp_x(_jit, cc, i0));
}
#define vfp_bunltr_f(_jit,i0,r0,r1) _vbncmp_f(_jit,ARM_CC_GE,i0,r0,r1)
#define vfp_bunltr_d(_jit,i0,r0,r1) _vbncmp_d(_jit,ARM_CC_GE,i0,r0,r1)
#define vfp_bunler_f(_jit,i0,r0,r1) _vbncmp_f(_jit,ARM_CC_GT,i0,r0,r1)
#define vfp_bunler_d(_jit,i0,r0,r1) _vbncmp_d(_jit,ARM_CC_GT,i0,r0,r1)
static jit_insn *
vfp_buneqr_x(jit_state_t _jit, jit_insn *i0)
{
jit_insn *i;
jit_insn *j;
jit_insn *l;
long d;
_VMRS(_R15);
i = _jit->x.pc;
if (jit_thumb_p()) {
T2_CC_B(ARM_CC_VS, 0);
j = _jit->x.pc;
T2_CC_B(ARM_CC_NE, 0);
jit_patch(i);
l = _jit->x.pc;
d = (((long)i0 - (long)l) >> 1) - 2;
assert(_s20P(d));
T2_B(encode_thumb_jump(d));
}
else {
_CC_B(ARM_CC_VS, 0);
j = _jit->x.pc;
_CC_B(ARM_CC_NE, 0);
jit_patch(i);
l = _jit->x.pc;
d = (((long)i0 - (long)l) >> 2) - 2;
assert(_s24P(d));
_B(d & 0x00ffffff);
}
jit_patch(j);
return (l);
}
__jit_inline jit_insn *
vfp_buneqr_f(jit_state_t _jit, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F32(r0, r1);
return (vfp_buneqr_x(_jit, i0));
}
__jit_inline jit_insn *
vfp_buneqr_d(jit_state_t _jit, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F64(r0, r1);
return (vfp_buneqr_x(_jit, i0));
}
static jit_insn *
vfp_bunger_x(jit_state_t _jit, jit_insn *i0)
{
jit_insn *i;
jit_insn *l;
long d;
_VMRS(_R15);
i = _jit->x.pc;
if (jit_thumb_p()) {
T2_CC_B(ARM_CC_MI, 0);
l = _jit->x.pc;
d = (((long)i0 - (long)l) >> 1) - 2;
assert(_s20P(d));
T2_CC_B(ARM_CC_HS, encode_thumb_cc_jump(d));
}
else {
_CC_B(ARM_CC_MI, 0);
l = _jit->x.pc;
d = (((long)i0 - (long)l) >> 2) - 2;
assert(_s24P(d));
_CC_B(ARM_CC_HS, d & 0x00ffffff);
}
jit_patch(i);
return (l);
}
__jit_inline jit_insn *
vfp_bunger_f(jit_state_t _jit, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F32(r0, r1);
return (vfp_bunger_x(_jit, i0));
}
__jit_inline jit_insn *
vfp_bunger_d(jit_state_t _jit, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F64(r0, r1);
return (vfp_bunger_x(_jit, i0));
}
#define vfp_bungtr_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_HI,i0,r0,r1)
#define vfp_bungtr_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_HI,i0,r0,r1)
static jit_insn *
vfp_bltgtr_x(jit_state_t _jit, jit_insn *i0)
{
jit_insn *i;
jit_insn *j;
jit_insn *l;
long d;
_VMRS(_R15);
i = _jit->x.pc;
if (jit_thumb_p()) {
T2_CC_B(ARM_CC_VS, 0);
j = _jit->x.pc;
T2_CC_B(ARM_CC_EQ, 0);
l = _jit->x.pc;
d = (((long)i0 - (long)l) >> 1) - 2;
assert(_s24P(d));
T2_B(encode_thumb_jump(d));
}
else {
_CC_B(ARM_CC_VS, 0);
j = _jit->x.pc;
_CC_B(ARM_CC_EQ, 0);
l = _jit->x.pc;
d = (((long)i0 - (long)l) >> 2) - 2;
assert(_s24P(d));
_B(d & 0x00ffffff);
}
jit_patch(i);
jit_patch(j);
return (l);
}
__jit_inline jit_insn *
vfp_bltgtr_f(jit_state_t _jit, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F32(r0, r1);
return (vfp_bltgtr_x(_jit, i0));
}
__jit_inline jit_insn *
vfp_bltgtr_d(jit_state_t _jit, jit_insn *i0, jit_fpr_t r0, jit_fpr_t r1)
{
_VCMP_F64(r0, r1);
return (vfp_bltgtr_x(_jit, i0));
}
#define vfp_bordr_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_VC,i0,r0,r1)
#define vfp_bordr_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_VC,i0,r0,r1)
#define vfp_bunordr_f(_jit,i0,r0,r1) _vbcmp_f(_jit,ARM_CC_VS,i0,r0,r1)
#define vfp_bunordr_d(_jit,i0,r0,r1) _vbcmp_d(_jit,ARM_CC_VS,i0,r0,r1)
#define vfp_ldr_f(_jit, r0, r1) _VLDR_F32(r0, r1, 0)
#define vfp_ldr_d(_jit, r0, r1) _VLDR_F64(r0, r1, 0)
__jit_inline void
vfp_ldi_f(jit_state_t _jit, jit_fpr_t r0, void *i0)
{
jit_movi_i(JIT_FTMP, (int)i0);
_VLDR_F32(r0, JIT_FTMP, 0);
}
__jit_inline void
vfp_ldi_d(jit_state_t _jit, jit_fpr_t r0, void *i0)
{
jit_movi_i(JIT_FTMP, (int)i0);
_VLDR_F64(r0, JIT_FTMP, 0);
}
__jit_inline void
vfp_ldxr_f(jit_state_t _jit, jit_fpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
{
jit_addr_i(JIT_FTMP, r1, r2);
_VLDR_F32(r0, JIT_FTMP, 0);
}
__jit_inline void
vfp_ldxr_d(jit_state_t _jit, jit_fpr_t r0, jit_gpr_t r1, jit_gpr_t r2)
{
jit_addr_i(JIT_FTMP, r1, r2);
_VLDR_F64(r0, JIT_FTMP, 0);
}
__jit_inline void
vfp_ldxi_f(jit_state_t _jit, jit_fpr_t r0, jit_gpr_t r1, int i0)
{
if (i0 >= 0) {
assert(!(i0 & 3));
i0 >>= 2;
if (i0 < 256)
_VLDR_F32(r0, r1, i0);
else {
jit_addi_i(JIT_FTMP, r1, i0);
_VLDR_F32(r0, JIT_FTMP, 0);
}
}
else {
i0 = -i0;
assert(!(i0 & 3));
i0 >>= 2;
if (i0 < 256)
_VLDRN_F32(r0, r1, i0);
else {
jit_subi_i(JIT_FTMP, r1, i0);
_VLDR_F32(r0, JIT_FTMP, 0);
}
}
}
__jit_inline void
vfp_ldxi_d(jit_state_t _jit, jit_fpr_t r0, jit_gpr_t r1, int i0)
{
if (i0 >= 0) {
assert(!(i0 & 3));
i0 >>= 2;
if (i0 < 256)
_VLDR_F64(r0, r1, i0);
else {
jit_addi_i(JIT_FTMP, r1, i0);
_VLDR_F64(r0, JIT_FTMP, 0);
}
}
else {
i0 = -i0;
assert(!(i0 & 3));
i0 >>= 2;
if (i0 < 256)
_VLDRN_F64(r0, r1, i0);
else {
jit_subi_i(JIT_FTMP, r1, i0);
_VLDR_F64(r0, JIT_FTMP, 0);
}
}
}
#define vfp_str_f(_jit, r0, r1) _VSTR_F32(r1, r0, 0)
#define vfp_str_d(_jit, r0, r1) _VSTR_F64(r1, r0, 0)
__jit_inline void
vfp_sti_f(jit_state_t _jit, void *i0, jit_fpr_t r0)
{
jit_movi_i(JIT_FTMP, (int)i0);
_VSTR_F32(r0, JIT_FTMP, 0);
}
__jit_inline void
vfp_sti_d(jit_state_t _jit, void *i0, jit_fpr_t r0)
{
jit_movi_i(JIT_FTMP, (int)i0);
_VSTR_F64(r0, JIT_FTMP, 0);
}
__jit_inline void
vfp_stxr_f(jit_state_t _jit, jit_gpr_t r0, jit_gpr_t r1, jit_fpr_t r2)
{
jit_addr_i(JIT_FTMP, r0, r1);
_VSTR_F32(r2, JIT_FTMP, 0);
}
__jit_inline void
vfp_stxr_d(jit_state_t _jit, jit_gpr_t r0, jit_gpr_t r1, jit_fpr_t r2)
{
jit_addr_i(JIT_FTMP, r0, r1);
_VSTR_F64(r2, JIT_FTMP, 0);
}
__jit_inline void
vfp_stxi_f(jit_state_t _jit, int i0, jit_gpr_t r0, jit_fpr_t r1)
{
if (i0 >= 0) {
assert(!(i0 & 3));
i0 >>= 2;
if (i0 < 256)
_VSTR_F32(r1, r0, i0);
else {
jit_addi_i(JIT_FTMP, r0, i0);
_VSTR_F32(r1, JIT_FTMP, 0);
}
}
else {
i0 = -i0;
assert(!(i0 & 3));
i0 >>= 2;
if (i0 < 256)
_VSTRN_F32(r1, r0, i0);
else {
jit_subi_i(JIT_FTMP, r0, i0);
_VSTR_F32(r1, JIT_FTMP, 0);
}
}
}
__jit_inline void
vfp_stxi_d(jit_state_t _jit, int i0, jit_gpr_t r0, jit_fpr_t r1)
{
if (i0 >= 0) {
assert(!(i0 & 3));
i0 >>= 2;
if (i0 < 256)
_VSTR_F64(r1, r0, i0);
else {
jit_addi_i(JIT_FTMP, r0, i0);
_VSTR_F64(r1, JIT_FTMP, 0);
}
}
else {
i0 = -i0;
assert(!(i0 & 3));
i0 >>= 2;
if (i0 < 256)
_VSTRN_F64(r1, r0, i0);
else {
jit_subi_i(JIT_FTMP, r0, i0);
_VSTR_F64(r1, JIT_FTMP, 0);
}
}
}
__jit_inline void
vfp_getarg_f(jit_state_t _jit, jit_fpr_t r0, int i0)
{
if (jit_hardfp_p()) {
if (i0 < 16) {
if (r0 != (jit_fpr_t)i0)
_VMOV_F32(r0, (jit_fpr_t)i0);
return;
}
}
else if (i0 < 4) {
/* registers are already saved on stack and argument registers
* may have been clobbered */
#if 0
_VMOV_S_A(r0, i0);
#else
vfp_ldxi_f(_jit, r0, JIT_FP, i0 << 2);
#endif
return;
}
vfp_ldxi_f(_jit, r0, JIT_FP, i0);
}
__jit_inline void
vfp_getarg_d(jit_state_t _jit, jit_fpr_t r0, int i0)
{
if (jit_hardfp_p()) {
if (i0 < 16) {
if (r0 != (jit_fpr_t)i0)
_VMOV_F64(r0, (jit_fpr_t)i0);
return;
}
}
else if (i0 < 4) {
/* registers are already saved on stack and argument registers
* may have been clobbered */
#if 0
_VMOV_D_AA(r0, i0, i0 + 1);
#else
vfp_ldxi_d(_jit, r0, JIT_FP, i0 << 2);
#endif
return;
}
vfp_ldxi_d(_jit, r0, JIT_FP, i0);
}
__jit_inline void
vfp_pusharg_f(jit_state_t _jit, jit_fpr_t r0)
{
int ofs = _jitl.nextarg_put++;
assert(ofs < 256);
_jitl.stack_offset -= sizeof(float);
_jitl.arguments[ofs] = (int *)_jit->x.pc;
_jitl.types[ofs >> 5] &= ~(1 << (ofs & 31));
_VSTR_F32(r0, JIT_SP, 0);
}
__jit_inline void
vfp_pusharg_d(jit_state_t _jit, jit_fpr_t r0)
{
int ofs = _jitl.nextarg_put++;
assert(ofs < 256);
_jitl.stack_offset -= sizeof(double);
_jitl.arguments[ofs] = (int *)_jit->x.pc;
_jitl.types[ofs >> 5] |= 1 << (ofs & 31);
_VSTR_F64(r0, JIT_SP, 0);
}
__jit_inline void
vfp_retval_f(jit_state_t _jit, jit_fpr_t r0)
{
if (jit_hardfp_p()) {
if (r0 != _D0)
_VMOV_F32(r0, _D0);
}
else
_VMOV_S_A(r0, _R0);
}
__jit_inline void
vfp_retval_d(jit_state_t _jit, jit_fpr_t r0)
{
if (jit_hardfp_p()) {
if (r0 != _D0)
_VMOV_F64(r0, _D0);
}
else
_VMOV_D_AA(r0, _R0, _R1);
}
#undef vfp_unget_tmp
#undef vfp_get_tmp
#endif
#endif /* __lightning_fp_vfp_h */