/*
 * Copyright (C) 2012-2023  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.
 *
 * Authors:
 *	Paulo Cesar Pereira de Andrade
 */

#if PROTO
#  if __X32
#    define x87_address_p(i0)		1
#  else
#    if __X64_32
#      define x87_address_p(i0)		((jit_word_t)(i0) >= 0)
#    else
#      define x87_address_p(i0)		can_sign_extend_int_p(i0)
#    endif
#  endif
#  define _ST0_REGNO			0
#  define _ST1_REGNO			1
#  define _ST2_REGNO			2
#  define _ST3_REGNO			3
#  define _ST4_REGNO			4
#  define _ST5_REGNO			5
#  define _ST6_REGNO			6
#  define x87rx(code, md, rb, ri, ms)	_x87rx(_jit, code, md, rb, ri, ms)
#  define fldcwm(md, rb, ri, ms)	x87rx(015, md, rb, ri, ms)
#  define fstcwm(md, rb, ri, ms)	_fstcwm(_jit, md, rb, ri, ms)
static void
_fstcwm(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t, jit_int32_t);
#  define fldsm(md, rb, ri, ms)		x87rx(010, md, rb, ri, ms)
#  define fstsm(md, rb, ri, ms)		x87rx(012, md, rb, ri, ms)
#  define fldlm(md, rb, ri, ms)		x87rx(050, md, rb, ri, ms)
#  define fstlm(md, rb, ri, ms)		x87rx(052, md, rb, ri, ms)
#  define fisttplm(md, rb, ri, ms)	x87rx(031, md, rb, ri, ms)
#  define fistlm(md, rb, ri, ms)	x87rx(032, md, rb, ri, ms)
#  define fisttpqm(md, rb, ri, ms)	x87rx(071, md, rb, ri, ms)
#  define fildlm(md, rb, ri, ms)	x87rx(030, md, rb,ri, ms)
#  define fildqm(md, rb, ri, ms)	x87rx(075, md, rb,ri, ms)
static void
_x87rx(jit_state_t*, jit_int32_t, jit_int32_t,
       jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87ri(cc,r0)			_x87ri(_jit,cc,r0)
#  define fchs_()			x87ri(014, 0)
#  define fabs_()			x87ri(014, 1)
#  define fld1()			x87ri(015, 0)
#  define fldl2t()			x87ri(015, 1)
#  define fldl2e()			x87ri(015, 2)
#  define fldpi()			x87ri(015, 3)
#  define fldlg2()			x87ri(015, 4)
#  define fldln2()			x87ri(015, 5)
#  define fldz()			x87ri(015, 6)
#  define fsqrt_()			x87ri(017, 2)
#  define fldr(r0)			x87ri(010, r0)
#  define fxchr(r0)			x87ri(011, r0)
#  define fstr(r0)			x87ri(052, r0)
#  define fstpr(r0)			x87ri(053, r0)
#  define fucomir(r0)			x87ri(035, r0)
#  define fucomipr(r0)			x87ri(075, r0)
static void _x87ri(jit_state_t*, jit_int32_t, jit_int32_t);
#  define faddr(r0, r1)			x87rri(000, r0, r1)
#  define fmulr(r0, r1)			x87rri(001, r0, r1)
#  define fsubr(r0, r1)			x87rri(004, r0, r1)
#  define fsubrr(r0, r1)		x87rri(005, r0, r1)
#  define fdivr(r0, r1)			x87rri(006, r0, r1)
#  define fdivrr(r0, r1)		x87rri(007, r0, r1)
#  define x87rri(cc, r0, r1)		_x87rri(_jit, cc, r0, r1)
static void _x87rri(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_addr_f(r0, r1, r2)	_x87_addr_d(_jit, r0, r1, r2)
#  define x87_addi_f(r0, r1, i0)	_x87_addi_f(_jit, r0, r1, i0)
static void _x87_addi_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_addr_d(r0, r1, r2)	_x87_addr_d(_jit, r0, r1, r2)
static void _x87_addr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_addi_d(r0, r1, i0)	_x87_addi_d(_jit, r0, r1, i0)
static void _x87_addi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_subr_f(r0, r1, r2)	_x87_subr_d(_jit, r0, r1, r2)
#  define x87_subi_f(r0, r1, i0)	_x87_subi_f(_jit, r0, r1, i0)
static void _x87_subi_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_subr_d(r0, r1, r2)	_x87_subr_d(_jit, r0, r1, r2)
static void _x87_subr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_subi_d(r0, r1, i0)	_x87_subi_d(_jit, r0, r1, i0)
static void _x87_subi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_rsbr_f(r0, r1, r2)	x87_subr_f(r0, r2, r1)
#  define x87_rsbi_f(r0, r1, i0)	_x87_rsbi_f(_jit, r0, r1, i0)
static void _x87_rsbi_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_rsbr_d(r0, r1, r2)	x87_subr_d(r0, r2, r1)
#  define x87_rsbi_d(r0, r1, i0)	_x87_rsbi_d(_jit, r0, r1, i0)
static void _x87_rsbi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_mulr_f(r0, r1, r2)	_x87_mulr_d(_jit, r0, r1, r2)
#  define x87_muli_f(r0, r1, i0)	_x87_muli_f(_jit, r0, r1, i0)
static void _x87_muli_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_mulr_d(r0, r1, r2)	_x87_mulr_d(_jit, r0, r1, r2)
static void _x87_mulr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_muli_d(r0, r1, i0)	_x87_muli_d(_jit, r0, r1, i0)
static void _x87_muli_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_divr_f(r0, r1, r2)	_x87_divr_d(_jit, r0, r1, r2)
#  define x87_divi_f(r0, r1, i0)	_x87_divi_f(_jit, r0, r1, i0)
static void _x87_divi_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_divr_d(r0, r1, r2)	_x87_divr_d(_jit, r0, r1, r2)
static void _x87_divr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_divi_d(r0, r1, i0)	_x87_divi_d(_jit, r0, r1, i0)
static void _x87_divi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_absr_f(r0, r1)		_x87_absr_d(_jit, r0, r1)
#  define x87_absr_d(r0, r1)		_x87_absr_d(_jit, r0, r1)
static void _x87_absr_d(jit_state_t*, jit_int32_t, jit_int32_t);
#  define x87_negr_f(r0, r1)		_x87_negr_d(_jit, r0, r1)
#  define x87_negr_d(r0, r1)		_x87_negr_d(_jit, r0, r1)
static void _x87_negr_d(jit_state_t*, jit_int32_t, jit_int32_t);
#  define x87_sqrtr_f(r0, r1)		_x87_sqrtr_d(_jit, r0, r1)
#  define x87_sqrtr_d(r0, r1)		_x87_sqrtr_d(_jit, r0, r1)
static void _x87_sqrtr_d(jit_state_t*, jit_int32_t, jit_int32_t);
#  define x87_truncr_f_i(r0, r1)	_x87_truncr_d_i(_jit, r0, r1)
#  define x87_truncr_d_i(r0, r1)	_x87_truncr_d_i(_jit, r0, r1)
static void _x87_truncr_d_i(jit_state_t*, jit_int32_t, jit_int32_t);
#  if __X64
#    define x87_truncr_f_l(r0, r1)	_x87_truncr_d_l(_jit, r0, r1)
#    define x87_truncr_d_l(r0, r1)	_x87_truncr_d_l(_jit, r0, r1)
static void _x87_truncr_d_l(jit_state_t*, jit_int32_t, jit_int32_t);
#  endif
#  define x87_extr_f(r0, r1)		_x87_extr_d(_jit, r0, r1)
#  define x87_extr_d(r0, r1)		_x87_extr_d(_jit, r0, r1)
#  define x87_extr_f_d(r0, r1)		x87_movr_d(r0, r1)
#  define x87_extr_d_f(r0, r1)		x87_movr_d(r0, r1)
static void _x87_extr_d(jit_state_t*, jit_int32_t, jit_int32_t);
#  define x87cmp(code, r0, r1, r2)	_x87cmp(_jit, code, r0, r1, r2)
static void
_x87cmp(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87cmp2(code, r0, r1, r2)	_x87cmp2(_jit, code, r0, r1, r2)
static void
_x87cmp2(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87jcc(code, i0, r0, r1)	_x87jcc(_jit, code, i0, r0, r1)
static jit_word_t
_x87jcc(jit_state_t*, jit_int32_t, jit_word_t, jit_int32_t, jit_int32_t);
#  define x87jcc2(code, i0, r0, r1)	_x87jcc2(_jit, code, i0, r0, r1)
static jit_word_t
_x87jcc2(jit_state_t*, jit_int32_t, jit_word_t, jit_int32_t, jit_int32_t);
#define x87_movi_f(r0,i0)		_x87_movi_f(_jit,r0,i0)
static void _x87_movi_f(jit_state_t*, jit_int32_t, jit_float32_t*);
#  define x87_ldr_f(r0, r1)		_x87_ldr_f(_jit, r0, r1)
static void _x87_ldr_f(jit_state_t*, jit_int32_t, jit_int32_t);
#  define x87_ldi_f(r0, i0)		_x87_ldi_f(_jit, r0, i0)
static void _x87_ldi_f(jit_state_t*, jit_int32_t, jit_word_t);
#  define x87_ldxr_f(r0, r1, r2)	_x87_ldxr_f(_jit, r0, r1, r2)
static void _x87_ldxr_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_ldxi_f(r0, r1, i0)	_x87_ldxi_f(_jit, r0, r1, i0)
static void _x87_ldxi_f(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define x87_str_f(r0, r1)		_x87_str_f(_jit, r0, r1)
static void _x87_str_f(jit_state_t*,jit_int32_t,jit_int32_t);
#  define x87_sti_f(i0, r0)		_x87_sti_f(_jit, i0, r0)
static void _x87_sti_f(jit_state_t*,jit_word_t, jit_int32_t);
#  define x87_stxr_f(r0, r1, r2)	_x87_stxr_f(_jit, r0, r1, r2)
static void _x87_stxr_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
#  define x87_stxi_f(i0, r0, r1)	_x87_stxi_f(_jit, i0, r0, r1)
static void _x87_stxi_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
#  define x87_ltr_f(r0, r1, r2)		x87cmp(X86_CC_A, r0, r2, r1)
#  define x87_lti_f(r0, r1, i0)		_x87_lti_f(_jit, r0, r1, i0)
static void _x87_lti_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_ler_f(r0, r1, r2)		x87cmp(X86_CC_AE, r0, r2, r1)
#  define x87_lei_f(r0, r1, i0)		_x87_lei_f(_jit, r0, r1, i0)
static void _x87_lei_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_eqr_f(r0, r1, r2)		x87_eqr_d(r0, r2, r1)
#  define x87_eqi_f(r0, r1, i0)		_x87_eqi_f(_jit, r0, r1, i0)
static void _x87_eqi_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_ger_f(r0, r1, r2)		x87cmp(X86_CC_AE, r0, r1, r2)
#  define x87_gei_f(r0, r1, i0)		_x87_gei_f(_jit, r0, r1, i0)
static void _x87_gei_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_gtr_f(r0, r1, r2)		x87cmp(X86_CC_A, r0, r1, r2)
#  define x87_gti_f(r0, r1, i0)		_x87_gti_f(_jit, r0, r1, i0)
static void _x87_gti_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_ner_f(r0, r1, r2)		x87_ner_d(r0, r2, r1)
#  define x87_nei_f(r0, r1, i0)		_x87_nei_f(_jit, r0, r1, i0)
static void _x87_nei_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_unltr_f(r0, r1, r2)	x87cmp(X86_CC_NAE, r0, r1, r2)
#  define x87_unlti_f(r0, r1, i0)	_x87_unlti_f(_jit, r0, r1, i0)
static void _x87_unlti_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_unler_f(r0, r1, r2)	x87cmp(X86_CC_NA, r0, r1, r2)
#  define x87_unlei_f(r0, r1, i0)	_x87_unlei_f(_jit, r0, r1, i0)
static void _x87_unlei_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_uneqr_f(r0, r1, r2)	x87cmp2(X86_CC_E, r0, r1, r2)
#  define x87_uneqi_f(r0, r1, i0)	_x87_uneqi_f(_jit, r0, r1, i0)
static void _x87_uneqi_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_unger_f(r0, r1, r2)	x87cmp(X86_CC_NA, r0, r2, r1)
#  define x87_ungei_f(r0, r1, i0)	_x87_ungei_f(_jit, r0, r1, i0)
static void _x87_ungei_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_ungtr_f(r0, r1, r2)	x87cmp(X86_CC_NAE, r0, r2, r1)
#  define x87_ungti_f(r0, r1, i0)	_x87_ungti_f(_jit, r0, r1, i0)
static void _x87_ungti_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_ltgtr_f(r0, r1, r2)	x87_ltgtr_d(r0, r1, r2)
#  define x87_ltgti_f(r0, r1, i0)	_x87_ltgti_f(_jit, r0, r1, i0)
static void _x87_ltgti_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_ordr_f(r0, r1, r2)	x87cmp2(X86_CC_NP, r0, r2, r1)
#  define x87_ordi_f(r0, r1, i0)	_x87_ordi_f(_jit, r0, r1, i0)
static void _x87_ordi_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_unordr_f(r0, r1, r2)	x87cmp2(X86_CC_P, r0, r2, r1)
#  define x87_unordi_f(r0, r1, i0)	_x87_unordi_f(_jit, r0, r1, i0)
static void _x87_unordi_f(jit_state_t*,jit_int32_t,jit_int32_t,jit_float32_t*);
#  define x87_ltr_d(r0, r1, r2)		x87cmp(X86_CC_A, r0, r2, r1)
#  define x87_lti_d(r0, r1, i0)		_x87_lti_d(_jit, r0, r1, i0)
static void _x87_lti_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_ler_d(r0, r1, r2)		x87cmp(X86_CC_AE, r0, r2, r1)
#  define x87_lei_d(r0, r1, i0)		_x87_lei_d(_jit, r0, r1, i0)
static void _x87_lei_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_eqr_d(r0, r1, r2)		_x87_eqr_d(_jit, r0, r2, r1)
static void _x87_eqr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_eqi_d(r0, r1, i0)		_x87_eqi_d(_jit, r0, r1, i0)
static void _x87_eqi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_ger_d(r0, r1, r2)		x87cmp(X86_CC_AE, r0, r1, r2)
#  define x87_gei_d(r0, r1, i0)		_x87_gei_d(_jit, r0, r1, i0)
static void _x87_gei_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_gtr_d(r0, r1, r2)		x87cmp(X86_CC_A, r0, r1, r2)
#  define x87_gti_d(r0, r1, i0)		_x87_gti_d(_jit, r0, r1, i0)
static void _x87_gti_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_ner_d(r0, r1, r2)		_x87_ner_d(_jit, r0, r2, r1)
static void _x87_ner_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_nei_d(r0, r1, i0)		_x87_nei_d(_jit, r0, r1, i0)
static void _x87_nei_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_unltr_d(r0, r1, r2)	x87cmp(X86_CC_NAE, r0, r1, r2)
#  define x87_unlti_d(r0, r1, i0)	_x87_unlti_d(_jit, r0, r1, i0)
static void _x87_unlti_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_unler_d(r0, r1, r2)	x87cmp(X86_CC_NA, r0, r1, r2)
#  define x87_unlei_d(r0, r1, i0)	_x87_unlei_d(_jit, r0, r1, i0)
static void _x87_unlei_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_uneqr_d(r0, r1, r2)	x87cmp2(X86_CC_E, r0, r1, r2)
#  define x87_uneqi_d(r0, r1, i0)	_x87_uneqi_d(_jit, r0, r1, i0)
static void _x87_uneqi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_unger_d(r0, r1, r2)	x87cmp(X86_CC_NA, r0, r2, r1)
#  define x87_ungei_d(r0, r1, i0)	_x87_ungei_d(_jit, r0, r1, i0)
static void _x87_ungei_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_ungtr_d(r0, r1, r2)	x87cmp(X86_CC_NAE, r0, r2, r1)
#  define x87_ungti_d(r0, r1, i0)	_x87_ungti_d(_jit, r0, r1, i0)
static void _x87_ungti_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_ltgtr_d(r0, r1, r2)	_x87_ltgtr_d(_jit, r0, r1, r2)
static void _x87_ltgtr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_ltgti_d(r0, r1, i0)	_x87_ltgti_d(_jit, r0, r1, i0)
static void _x87_ltgti_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_ordr_d(r0, r1, r2)	x87cmp2(X86_CC_NP, r0, r2, r1)
#  define x87_ordi_d(r0, r1, i0)	_x87_ordi_d(_jit, r0, r1, i0)
static void _x87_ordi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#  define x87_unordr_d(r0, r1, r2)	x87cmp2(X86_CC_P, r0, r2, r1)
#  define x87_unordi_d(r0, r1, i0)	_x87_unordi_d(_jit, r0, r1, i0)
static void _x87_unordi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*);
#define x87_movr_f(r0,r1)		_x87_movr_d(_jit,r0,r1)
#define x87_movr_d(r0,r1)		_x87_movr_d(_jit,r0,r1)
static void _x87_movr_d(jit_state_t*, jit_int32_t, jit_int32_t);
#define x87_movi_d(r0,i0)		_x87_movi_d(_jit,r0,i0)
static void _x87_movi_d(jit_state_t*, jit_int32_t, jit_float64_t*);
#  define x87_ldr_d(r0, r1)		_x87_ldr_d(_jit, r0, r1)
static void _x87_ldr_d(jit_state_t*, jit_int32_t, jit_int32_t);
#  define x87_ldi_d(r0, i0)		_x87_ldi_d(_jit, r0, i0)
static void _x87_ldi_d(jit_state_t*, jit_int32_t, jit_word_t);
#  define x87_ldxr_d(r0, r1, r2)	_x87_ldxr_d(_jit, r0, r1, r2)
static void _x87_ldxr_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_int32_t);
#  define x87_ldxi_d(r0, r1, i0)	_x87_ldxi_d(_jit, r0, r1, i0)
static void _x87_ldxi_d(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
#  define x87_str_d(r0, r1)		_x87_str_d(_jit, r0, r1)
static void _x87_str_d(jit_state_t*,jit_int32_t,jit_int32_t);
#  define x87_sti_d(i0, r0)		_x87_sti_d(_jit, i0, r0)
static void _x87_sti_d(jit_state_t*,jit_word_t,jit_int32_t);
#  define x87_stxr_d(r0, r1, r2)	_x87_stxr_d(_jit, r0, r1, r2)
static void _x87_stxr_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
#  define x87_stxi_d(i0, r0, r1)	_x87_stxi_d(_jit, i0, r0, r1)
static void _x87_stxi_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t);
#  define x87_bltr_f(i0, r0, r1)	x87jcc(X86_CC_A, i0, r1, r0)
#  define x87_blti_f(i0, r0, i1)	_x87_blti_f(_jit, i0, r0, i1)
static jit_word_t
_x87_blti_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bler_f(i0, r0, r1)	x87jcc(X86_CC_AE, i0, r1, r0)
#  define x87_blei_f(i0, r0, i1)	_x87_blei_f(_jit, i0, r0, i1)
static jit_word_t
_x87_blei_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_beqr_f(i0, r0, r1)	_x87_beqr_d(_jit, i0, r0, r1)
#  define x87_beqi_f(i0, r0, i1)	_x87_beqi_f(_jit, i0, r0, i1)
static jit_word_t
_x87_beqi_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bger_f(i0, r0, r1)	x87jcc(X86_CC_AE, i0, r0, r1)
#  define x87_bgei_f(i0, r0, i1)	_x87_bgei_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bgei_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bgtr_f(i0, r0, r1)	x87jcc(X86_CC_A, i0, r0, r1)
#  define x87_bgti_f(i0, r0, i1)	_x87_bgti_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bgti_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bner_f(i0, r0, r1)	_x87_bner_d(_jit, i0, r0, r1)
#  define x87_bnei_f(i0, r0, i1)	_x87_bnei_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bnei_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bunltr_f(i0, r0, r1)	x87jcc(X86_CC_NAE, i0, r0, r1)
#  define x87_bunlti_f(i0, r0, i1)	_x87_bunlti_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bunlti_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bunler_f(i0, r0, r1)	x87jcc(X86_CC_NA, i0, r0, r1)
#  define x87_bunlei_f(i0, r0, i1)	_x87_bunlei_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bunlei_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_buneqr_f(i0, r0, r1)	x87jcc2(X86_CC_E, i0, r0, r1)
#  define x87_buneqi_f(i0, r0, i1)	_x87_buneqi_f(_jit, i0, r0, i1)
static jit_word_t
_x87_buneqi_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bunger_f(i0, r0, r1)	x87jcc(X86_CC_NA, i0, r1, r0)
#  define x87_bungei_f(i0, r0, i1)	_x87_bungei_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bungei_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bungtr_f(i0, r0, r1)	x87jcc(X86_CC_NAE, i0, r1, r0)
#  define x87_bungti_f(i0, r0, i1)	_x87_bungti_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bungti_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bltgtr_f(i0, r0, r1)	x87jcc2(X86_CC_NE, i0, r0, r1)
#  define x87_bltgti_f(i0, r0, i1)	_x87_bltgti_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bltgti_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bordr_f(i0, r0, r1)	x87jcc2(X86_CC_NP, i0, r0, r1)
#  define x87_bordi_f(i0, r0, i1)	_x87_bordi_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bordi_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bunordr_f(i0, r0, r1)	x87jcc2(X86_CC_P, i0, r0, r1)
#  define x87_bunordi_f(i0, r0, i1)	_x87_bunordi_f(_jit, i0, r0, i1)
static jit_word_t
_x87_bunordi_f(jit_state_t*, jit_word_t, jit_int32_t, jit_float32_t*);
#  define x87_bltr_d(i0, r0, r1)	x87jcc(X86_CC_A, i0, r1, r0)
#  define x87_blti_d(i0, r0, i1)	_x87_blti_d(_jit, i0, r0, i1)
static jit_word_t
_x87_blti_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bler_d(i0, r0, r1)	x87jcc(X86_CC_AE, i0, r1, r0)
#  define x87_blei_d(i0, r0, i1)	_x87_blei_d(_jit, i0, r0, i1)
static jit_word_t
_x87_blei_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_beqr_d(i0, r0, r1)	_x87_beqr_d(_jit, i0, r0, r1)
static jit_word_t
_x87_beqr_d(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
#  define x87_beqi_d(i0, r0, i1)	_x87_beqi_d(_jit, i0, r0, i1)
static jit_word_t
_x87_beqi_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bger_d(i0, r0, r1)	x87jcc(X86_CC_AE, i0, r0, r1)
#  define x87_bgei_d(i0, r0, i1)	_x87_bgei_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bgei_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bgtr_d(i0, r0, r1)	x87jcc(X86_CC_A, i0, r0, r1)
#  define x87_bgti_d(i0, r0, i1)	_x87_bgti_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bgti_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bner_d(i0, r0, r1)	_x87_bner_d(_jit, i0, r0, r1)
static jit_word_t
_x87_bner_d(jit_state_t*, jit_word_t, jit_int32_t, jit_int32_t);
#  define x87_bnei_d(i0, r0, i1)	_x87_bnei_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bnei_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bunltr_d(i0, r0, r1)	x87jcc(X86_CC_NAE, i0, r0, r1)
#  define x87_bunlti_d(i0, r0, i1)	_x87_bunlti_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bunlti_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bunler_d(i0, r0, r1)	x87jcc(X86_CC_NA, i0, r0, r1)
#  define x87_bunlei_d(i0, r0, i1)	_x87_bunlei_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bunlei_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_buneqr_d(i0, r0, r1)	x87jcc2(X86_CC_E, i0, r0, r1)
#  define x87_buneqi_d(i0, r0, i1)	_x87_buneqi_d(_jit, i0, r0, i1)
static jit_word_t
_x87_buneqi_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bunger_d(i0, r0, r1)	x87jcc(X86_CC_NA, i0, r1, r0)
#  define x87_bungei_d(i0, r0, i1)	_x87_bungei_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bungei_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bungtr_d(i0, r0, r1)	x87jcc(X86_CC_NAE, i0, r1, r0)
#  define x87_bungti_d(i0, r0, i1)	_x87_bungti_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bungti_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bltgtr_d(i0, r0, r1)	x87jcc2(X86_CC_NE, i0, r0, r1)
#  define x87_bltgti_d(i0, r0, i1)	_x87_bltgti_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bltgti_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bordr_d(i0, r0, r1)	x87jcc2(X86_CC_NP, i0, r0, r1)
#  define x87_bordi_d(i0, r0, i1)	_x87_bordi_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bordi_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#  define x87_bunordr_d(i0, r0, r1)	x87jcc2(X86_CC_P, i0, r0, r1)
#  define x87_bunordi_d(i0, r0, i1)	_x87_bunordi_d(_jit, i0, r0, i1)
static jit_word_t
_x87_bunordi_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*);
#endif

#if CODE
#  define fpr_opi(name, type, size)					\
static void								\
_x87_##name##i_##type(jit_state_t *_jit,				\
		      jit_int32_t r0, jit_int32_t r1,			\
		      jit_float##size##_t *i0)				\
{									\
    jit_int32_t		reg = jit_get_reg(jit_class_fpr);		\
    assert(jit_x87_reg_p(reg));						\
    x87_movi_##type(rn(reg), i0);					\
    x87_##name##r_##type(r0, r1, rn(reg));				\
    jit_unget_reg(reg);							\
}
#  define fpr_bopi(name, type, size)					\
static jit_word_t							\
_x87_b##name##i_##type(jit_state_t *_jit,				\
		       jit_word_t i0, jit_int32_t r0,			\
		       jit_float##size##_t *i1)				\
{									\
    jit_word_t		w;						\
    jit_int32_t		reg = jit_get_reg(jit_class_fpr|		\
					  jit_class_nospill);		\
    assert(jit_x87_reg_p(reg));						\
    x87_movi_##type(rn(reg), i1);					\
    w = x87_b##name##r_##type(i0, r0, rn(reg));				\
    jit_unget_reg(reg);							\
    return (w);								\
}
#  define fopi(name)			fpr_opi(name, f, 32)
#  define fbopi(name)			fpr_bopi(name, f, 32)
#  define dopi(name)			fpr_opi(name, d, 64)
#  define dbopi(name)			fpr_bopi(name, d, 64)

static void
_fstcwm(jit_state_t *_jit, jit_int32_t md,
	jit_int32_t rb,	jit_int32_t ri, jit_int32_t ms)
{
    ic(0x9b);
    rex(0, 1, rb, ri, _NOREG);
    x87rx(017, md, rb, ri, ms);
}

static void
_x87rx(jit_state_t *_jit, jit_int32_t code, jit_int32_t md,
       jit_int32_t rb, jit_int32_t ri, jit_int32_t ms)
{
    rex(0, 1, rb, ri, _NOREG);
    ic(0xd8 | (code >> 3));
    rx((code & 7), md, rb, ri, ms);
}

static void
_x87ri(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0)
{
    ic(0xd8 | (code >> 3));
    mrm(0x03, (code & 7), r0);
}

static void
_x87rri(jit_state_t *_jit, jit_int32_t code, jit_int32_t r0, jit_int32_t r1)
{
    if (r1 == _ST0_REGNO)
	x87ri(code | 040, r0);
    else {
	assert(r0 == _ST0_REGNO);
	x87ri(code, r1);
    }
}

fopi(add)
fopi(sub)
fopi(rsb)
fopi(mul)
fopi(div)

static void
_x87_addr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    if (r0 == r1) {
	if (r2 == _ST0_REGNO)
	    faddr(r0, _ST0_REGNO);
	else if (r0 == _ST0_REGNO)
	    faddr(_ST0_REGNO, r2);
	else {
	    fxchr(r0);
	    faddr(_ST0_REGNO, r0 == r2 ? _ST0_REGNO : r2);
	    fxchr(r0);
	}
    }
    else if (r0 == r2) {
	if (r1 == _ST0_REGNO)
	    faddr(r0, _ST0_REGNO);
	else if (r0 == _ST0_REGNO)
	    faddr(_ST0_REGNO, r1);
	else {
	    fxchr(r0);
	    faddr(_ST0_REGNO, r1);
	    fxchr(r0);
	}
    }
    else {
	fldr(r1);
	faddr(_ST0_REGNO, r2 + 1);
	fstpr(r0 + 1);
    }
}

dopi(add)

static void
_x87_subr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    if (r0 == r1) {
	if (r2 == _ST0_REGNO)
	    fsubrr(r0, _ST0_REGNO);
	else if (r0 == _ST0_REGNO)
	    fsubr(_ST0_REGNO, r2);
	else {
	    fxchr(r0);
	    fsubr(_ST0_REGNO, r0 == r2 ? _ST0_REGNO : r2);
	    fxchr(r0);
	}
    }
    else if (r0 == r2) {
	if (r1 == _ST0_REGNO)
	    fsubr(r0, _ST0_REGNO);
	else if (r0 == _ST0_REGNO)
	    fsubrr(_ST0_REGNO, r1);
	else {
	    fxchr(r0);
	    fsubrr(_ST0_REGNO, r1);
	    fxchr(r0);
	}
    }
    else {
	fldr(r1);
	fsubr(_ST0_REGNO, r2 + 1);
	fstpr(r0 + 1);
    }
}

dopi(sub)

dopi(rsb)

static void
_x87_mulr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    if (r0 == r1) {
	if (r2 == _ST0_REGNO)
	    fmulr(r0, _ST0_REGNO);
	else if (r0 == _ST0_REGNO)
	    fmulr(_ST0_REGNO, r2);
	else {
	    fxchr(r0);
	    fmulr(_ST0_REGNO, r0 == r2 ? _ST0_REGNO : r2);
	    fxchr(r0);
	}
    }
    else if (r0 == r2) {
	if (r1 == _ST0_REGNO)
	    fmulr(r0, _ST0_REGNO);
	else if (r0 == _ST0_REGNO)
	    fmulr(_ST0_REGNO, r1);
	else {
	    fxchr(r0);
	    fmulr(_ST0_REGNO, r1);
	    fxchr(r0);
	}
    }
    else {
	fldr(r1);
	fmulr(_ST0_REGNO, r2 + 1);
	fstpr(r0 + 1);
    }
}

dopi(mul)

static void
_x87_divr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    if (r0 == r1) {
	if (r2 == _ST0_REGNO)
	    fdivrr(r0, _ST0_REGNO);
	else if (r0 == _ST0_REGNO)
	    fdivr(_ST0_REGNO, r2);
	else {
	    fxchr(r0);
	    fdivr(_ST0_REGNO, r0 == r2 ? _ST0_REGNO : r2);
	    fxchr(r0);
	}
    }
    else if (r0 == r2) {
	if (r1 == _ST0_REGNO)
	    fdivr(r0, _ST0_REGNO);
	else if (r0 == _ST0_REGNO)
	    fsubrr(_ST0_REGNO, r1);
	else {
	    fxchr(r0);
	    fdivrr(_ST0_REGNO, r1);
	    fxchr(r0);
	}
    }
    else {
	fldr(r1);
	fdivr(_ST0_REGNO, r2 + 1);
	fstpr(r0 + 1);
    }
}

dopi(div)

static void
_x87_absr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (r0 == r1) {
	if (r1 == _ST0_REGNO)
	    fabs_();
	else {
	    fxchr(r0);
	    fabs_();
	    fxchr(r0);
	}
    }
    else {
	fldr(r1);
	fabs_();
	fstpr(r0 + 1);
    }
}

static void
_x87_negr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (r0 == r1) {
	if (r1 == _ST0_REGNO)
	    fchs_();
	else {
	    fxchr(r0);
	    fchs_();
	    fxchr(r0);
	}
    }
    else {
	fldr(r1);
	fchs_();
	fstpr(r0 + 1);
    }
}

static void
_x87_sqrtr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (r0 == r1) {
	if (r1 == _ST0_REGNO)
	    fsqrt_();
	else {
	    fxchr(r0);
	    fsqrt_();
	    fxchr(r0);
	}
    }
    else {
	fldr(r1);
	fsqrt_();
	fstpr(r0 + 1);
    }
}

static void
_x87_truncr_d_i(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    CHECK_CVT_OFFSET();
#if defined(sun)
    /* for the sake of passing test cases in x87 mode, otherwise only sse
     * is supported */
    fstcwm(-4, _RBP_REGNO, _NOREG, _SCL1);
    ldxi_s(r0, _RBP_REGNO, -4);
    extr_uc(r0, r0);
#  define FPCW_CHOP	0xc00
    ori(r0, r0, FPCW_CHOP);
    stxi_s(-8, _RBP_REGNO, r0);
    fldcwm(-8, _RBP_REGNO, _NOREG, _SCL1);
    if (r1 == _ST0_REGNO)
	fistlm(CVT_OFFSET, _RBP_REGNO, _NOREG, _SCL1);
    else {
	fxchr(r1);
	fistlm(CVT_OFFSET, _RBP_REGNO, _NOREG, _SCL1);
	fxchr(r1);
    }
    fldcwm(-4, _RBP_REGNO, _NOREG, _SCL1);
    ldxi(r0, _RBP_REGNO, CVT_OFFSET);
#else
    fldr(r1);
    fisttplm(CVT_OFFSET, _RBP_REGNO, _NOREG, _SCL1);
    ldxi_i(r0, _RBP_REGNO, CVT_OFFSET);
#endif
}

#  if __X64
static void
_x87_truncr_d_l(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    CHECK_CVT_OFFSET();
    fldr(r1);
    fisttpqm(CVT_OFFSET, _RBP_REGNO, _NOREG, _SCL1);
    ldxi(r0, _RBP_REGNO, CVT_OFFSET);
}
#  endif

static void
_x87_extr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    CHECK_CVT_OFFSET();
    stxi(CVT_OFFSET, _RBP_REGNO, r1);
#  if __X32
    fildlm(CVT_OFFSET, _RBP_REGNO, _NOREG, _SCL1);
#  else
    fildqm(CVT_OFFSET, _RBP_REGNO, _NOREG, _SCL1);
#  endif
    fstpr(r0 + 1);
}

static void
_x87cmp(jit_state_t *_jit, jit_int32_t code,
	jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_bool_t		rc;
    jit_int32_t		reg;
    if ((rc = reg8_p(r0)))
	reg = r0;
    else {
	reg = _RAX_REGNO;
	movr(r0, reg);
    }
    ixorr(reg, reg);
    if (r1 == _ST0_REGNO)
	fucomir(r2);
    else {
	fldr(r1);
	fucomipr(r2 + 1);
    }
    cc(code, reg);
    if (!rc)
	xchgr(r0, reg);
}

static void
_x87cmp2(jit_state_t *_jit, jit_int32_t code,
	 jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_bool_t			rc;
    jit_int32_t			reg;
    jit_int32_t			f1, f2;
    if (r2 == _ST0_REGNO)	f1 = r2, f2 = r1;
    else			f1 = r1, f2 = r2;
    if ((rc = reg8_p(r0)))
	reg = r0;
    else {
	reg = _RAX_REGNO;
	movr(r0, reg);
    }
    ixorr(reg, reg);
    if (f1 == _ST0_REGNO)
	fucomir(f2);
    else {
	fldr(f1);
	fucomipr(f2 + 1);
    }
    cc(code, reg);
    if (!rc)
	xchgr(r0, reg);
}

static jit_word_t
_x87jcc(jit_state_t *_jit, jit_int32_t code,
	jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    if (r0 == _ST0_REGNO)
	fucomir(r1);
    else {
	fldr(r0);
	fucomipr(r1 + 1);
    }
    return (jcc(code, i0));
}

static jit_word_t
_x87jcc2(jit_state_t *_jit, jit_int32_t code,
	 jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_int32_t			f0, f1;
    if (r1 == _ST0_REGNO)	f0 = r1, f1 = r0;
    else			f0 = r0, f1 = r1;
    if (f0 == _ST0_REGNO)
	fucomir(f1);
    else {
	fldr(f0);
	fucomipr(f1 + 1);
    }
    return (jcc(code, i0));
}

fopi(lt)
fopi(le)
fopi(eq)
fopi(ge)
fopi(gt)
fopi(ne)
fopi(unlt)
fopi(unle)
fopi(uneq)
fopi(unge)
fopi(ungt)
fopi(ltgt)
fopi(ord)
fopi(unord)
fbopi(lt)
fbopi(le)
fbopi(eq)
fbopi(ge)
fbopi(gt)
fbopi(ne)
fbopi(unlt)
fbopi(unle)
fbopi(uneq)
fbopi(unge)
fbopi(ungt)
fbopi(ltgt)
fbopi(ord)
fbopi(unord)

static void
_x87_movi_f(jit_state_t *_jit, jit_int32_t r0, jit_float32_t *i0)
{
    union {
	jit_int32_t	 i;
	jit_float32_t	 f;
    } data;
    jit_int32_t		 reg;

    data.f = *i0;
    if (data.f == 0.0 && !(data.i & 0x80000000))
	fldz();
    else if (data.f == 1.0)
	fld1();
    else if (data.f == 3.3219280948873623478703195458468f)
	fldl2t();
    else if (data.f == 1.4426950408889634073599246886656f)
	fldl2e();
    else if (data.f == 3.1415926535897932384626421096161f)
	fldpi();
    else if (data.f == 0.3010299956639811952137387498515f)
	fldlg2();
    else if (data.f == 0.6931471805599453094172323683399f)
	fldln2();
    else {
	if (_jitc->no_data) {
	    CHECK_CVT_OFFSET();
	    reg = jit_get_reg(jit_class_gpr);
	    movi(rn(reg), data.i);
	    stxi_i(CVT_OFFSET, _RBP_REGNO, rn(reg));
	    jit_unget_reg(reg);
	    x87_ldxi_f(r0, _RBP_REGNO, CVT_OFFSET);
	}
	else
	    x87_ldi_f(r0, (jit_word_t)i0);
	return;
    }
    fstpr(r0 + 1);
}

static void
_x87_ldr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    fldsm(0, r1, _NOREG, _SCL1);
    fstpr(r0 + 1);
}

static void
_x87_ldi_f(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (x87_address_p(i0)) {
	fldsm(i0, _NOREG, _NOREG, _SCL1);
	fstpr(r0 + 1);
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	x87_ldr_f(r0, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_x87_ldxr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
#if __X64_32
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr);
    addr(rn(reg), r1, r2);
    x87_ldr_f(r0, rn(reg));
    jit_unget_reg(reg);
#else
    fldsm(0, r1, r2, _SCL1);
    fstpr(r0 + 1);
#endif
}

static void
_x87_ldxi_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (can_sign_extend_int_p(i0)) {
	fldsm(i0, r1, _NOREG, _SCL1);
	fstpr(r0 + 1);
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
#if __X64_32
	addi(rn(reg), r1, i0);
	x87_ldr_f(r0, rn(reg));
#else
	movi(rn(reg), i0);
	x87_ldxr_f(r0, r1, rn(reg));
#endif
	jit_unget_reg(reg);
    }
}

static void
_x87_str_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (r1 == _ST0_REGNO)
	fstsm(0, r0, _NOREG, _SCL1);
    else {
	fxchr(r1);
	fstsm(0, r0, _NOREG, _SCL1);
	fxchr(r1);
    }
}

static void
_x87_sti_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
{
    jit_int32_t		reg;
    if (!x87_address_p(i0)) {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	x87_str_f(rn(reg), r0);
	jit_unget_reg(reg);
    }
    else if (r0 == _ST0_REGNO)
	fstsm(i0, _NOREG, _NOREG, _SCL1);
    else {
	fxchr(r0);
	fstsm(i0, _NOREG, _NOREG, _SCL1);
	fxchr(r0);
    }
}

static void
_x87_stxr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
#if __X64_32
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr);
    addr(rn(reg), r0, r1);
    x87_str_f(rn(reg), r2);
    jit_unget_reg(reg);
#else
    if (r2 == _ST0_REGNO)
	fstsm(0, r0, r1, _SCL1);
    else {
	fxchr(r2);
	fstsm(0, r0, r1, _SCL1);
	fxchr(r2);
    }
#endif
}

static void
_x87_stxi_f(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_int32_t		reg;
    if (!can_sign_extend_int_p(i0)) {
	reg = jit_get_reg(jit_class_gpr);
#if __X64_32
	addi(rn(reg), r0, i0);
	x87_str_f(rn(reg), r1);
#else
	movi(rn(reg), i0);
	x87_stxr_f(rn(reg), r0, r1);
#endif
	jit_unget_reg(reg);
    }
    else if (r1 == _ST0_REGNO)
	fstsm(i0, r0, _NOREG, _SCL1);
    else {
	fxchr(r1);
	fstsm(i0, r0, _NOREG, _SCL1);
	fxchr(r1);
    }
}

static void
_x87_movr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (r0 != r1) {
	if (r1 == _ST0)
	    fstr(r0);
	else if (r0 == _ST0) {
	    fxchr(r1);
	    fstr(r1);
	}
	else {
	    fldr(r1);
	    fstpr(r0 + 1);
	}
    }
}

static void
_x87_movi_d(jit_state_t *_jit, jit_int32_t r0, jit_float64_t *i0)
{
    union {
	jit_int32_t	 ii[2];
	jit_word_t	 w;
	jit_float64_t	 d;
    } data;
    jit_int32_t		 reg;

    data.d = *i0;
    if (data.d == 0.0 && !(data.ii[1] & 0x80000000))
	fldz();
    else if (data.d == 1.0)
	fld1();
    else if (data.d == 3.3219280948873623478703195458468)
	fldl2t();
    else if (data.d == 1.4426950408889634073599246886656)
	fldl2e();
    else if (data.d == 3.1415926535897932384626421096161)
	fldpi();
    else if (data.d == 0.3010299956639811952137387498515)
	fldlg2();
    else if (data.d == 0.6931471805599453094172323683399)
	fldln2();
    else {
	if (_jitc->no_data) {
	    CHECK_CVT_OFFSET();
	    reg = jit_get_reg(jit_class_gpr);
#if __X32 || __X64_32
	    movi(rn(reg), data.ii[0]);
	    stxi_i(CVT_OFFSET, _RBP_REGNO, rn(reg));
	    movi(rn(reg), data.ii[1]);
	    stxi_i(CVT_OFFSET + 4, _RBP_REGNO, rn(reg));
#else
	    movi(rn(reg), data.w);
	    stxi_l(CVT_OFFSET, _RBP_REGNO, rn(reg));
#endif
	    jit_unget_reg(reg);
	    x87_ldxi_d(r0, _RBP_REGNO, CVT_OFFSET);
	}
	else
	    x87_ldi_d(r0, (jit_word_t)i0);
	return;
    }
    fstpr(r0 + 1);
}

dopi(lt)
dopi(le)

static void
_x87_eqr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_bool_t			rc;
    jit_word_t			jp_code;
    jit_int32_t			reg, f1, f2;
    if (r2 == _ST0_REGNO)	f1 = r2, f2 = r1;
    else			f1 = r1, f2 = r2;
    if ((rc = reg8_p(r0)))
	reg = r0;
    else {
	reg = _RAX_REGNO;
	movr(r0, reg);
    }
    ixorr(reg, reg);
    if (f1 == _ST0_REGNO)
	fucomir(f2);
    else {
	fldr(f1);
	fucomipr(f2 + 1);
    }
    jp_code = jpes(0);
    cc(X86_CC_E, reg);
    patch_at(jp_code, _jit->pc.w);
    if (!rc)
	xchgr(r0, reg);
}

dopi(eq)
dopi(ge)
dopi(gt)

static void
_x87_ner_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    jit_bool_t			rc;
    jit_word_t			jp_code;
    jit_int32_t			reg, f1, f2;
    if (r2 == _ST0_REGNO)	f1 = r2, f2 = r1;
    else			f1 = r1, f2 = r2;
    if ((rc = reg8_p(r0)))
	reg = r0;
    else {
	reg = _RAX_REGNO;
	movr(r0, reg);
    }
    imovi(reg, 1);
    if (f1 == _ST0_REGNO)
	fucomir(f2);
    else {
	fldr(f1);
	fucomipr(f2 + 1);
    }
    jp_code = jpes(0);
    cc(X86_CC_NE, reg);
    patch_at(jp_code, _jit->pc.w);
    if (!rc)
	xchgr(r0, reg);
}

dopi(ne)
dopi(unlt)
dopi(unle)
dopi(uneq)
dopi(unge)
dopi(ungt)

static void
_x87_ltgtr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
    if (r1 == r2)
	movi(r0, 1);
    else
	x87cmp2(X86_CC_NE, r0, r1, r2);
}

dopi(ltgt)
dopi(ord)
dopi(unord)

static void
_x87_ldr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    fldlm(0, r1, _NOREG, _SCL1);
    fstpr(r0 + 1);
}

static void
_x87_ldi_d(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0)
{
    jit_int32_t		reg;
    if (x87_address_p(i0)) {
	fldlm(i0, _NOREG, _NOREG, _SCL1);
	fstpr(r0 + 1);
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	x87_ldr_d(r0, rn(reg));
	jit_unget_reg(reg);
    }
}

static void
_x87_ldxr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
#if __X64_32
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr);
    addr(rn(reg), r1, r2);
    x87_ldr_d(r0, rn(reg));
    jit_unget_reg(reg);
#else
    fldlm(0, r1, r2, _SCL1);
    fstpr(r0 + 1);
#endif
}

static void
_x87_ldxi_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
{
    jit_int32_t		reg;
    if (can_sign_extend_int_p(i0)) {
	fldlm(i0, r1, _NOREG, _SCL1);
	fstpr(r0 + 1);
    }
    else {
	reg = jit_get_reg(jit_class_gpr);
#if __X64_32
	addi(rn(reg), r1, i0);
	x87_ldr_d(r0, rn(reg));
#else
	movi(rn(reg), i0);
	x87_ldxr_d(r0, r1, rn(reg));
#endif
	jit_unget_reg(reg);
    }
}

static void
_x87_str_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
    if (r1 == _ST0_REGNO)
	fstlm(0, r0, _NOREG, _SCL1);
    else {
	fxchr(r1);
	fstlm(0, r0, _NOREG, _SCL1);
	fxchr(r1);
    }
}

static void
_x87_sti_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0)
{
    jit_int32_t		reg;
    if (!x87_address_p(i0)) {
	reg = jit_get_reg(jit_class_gpr);
	movi(rn(reg), i0);
	x87_str_d(rn(reg), r0);
	jit_unget_reg(reg);
    }
    else if (r0 == _ST0_REGNO)
	fstlm(i0, _NOREG, _NOREG, _SCL1);
    else {
	fxchr(r0);
	fstlm(i0, _NOREG, _NOREG, _SCL1);
	fxchr(r0);
    }
}

static void
_x87_stxr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
{
#if __X64_32
    jit_int32_t		reg;
    reg = jit_get_reg(jit_class_gpr);
    addr(rn(reg), r0, r1);
    x87_str_d(rn(reg), r2);
    jit_unget_reg(reg);
#else
    if (r2 == _ST0_REGNO)
	fstlm(0, r0, r1, _SCL1);
    else {
	fxchr(r2);
	fstlm(0, r0, r1, _SCL1);
	fxchr(r2);
    }
#endif
}

static void
_x87_stxi_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_int32_t		reg;
    if (!can_sign_extend_int_p(i0)) {
	reg = jit_get_reg(jit_class_gpr);
#if __X64_32
	addi(rn(reg), r0, i0);
	x87_str_d(rn(reg), r1);
#else
	movi(rn(reg), i0);
	x87_stxr_d(rn(reg), r0, r1);
#endif
	jit_unget_reg(reg);
    }
    else if (r1 == _ST0_REGNO)
	fstlm(i0, r0, _NOREG, _SCL1);
    else {
	fxchr(r1);
	fstlm(i0, r0, _NOREG, _SCL1);
	fxchr(r1);
    }
}

dbopi(lt)
dbopi(le)

static jit_word_t
_x87_beqr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_word_t			w;
    jit_int32_t			f0, f1;
    jit_word_t			jp_code;
    if (r1 == _ST0_REGNO)	f0 = r1, f1 = r0;
    else			f0 = r0, f1 = r1;
    if (f0 == _ST0_REGNO)
	fucomir(f1);
    else {
	fldr(f0);
	fucomipr(f1 + 1);
    }
    jp_code = jpes(0);
    w = jcc(X86_CC_E, i0);
    patch_at(jp_code, _jit->pc.w);
    return (w);
}
dbopi(eq)
dbopi(ge)
dbopi(gt)

static jit_word_t
_x87_bner_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
{
    jit_word_t			w;
    jit_int32_t			f0, f1;
    jit_word_t			jp_code;
    jit_word_t			jz_code;
    if (r1 == _ST0_REGNO)	f0 = r1, f1 = r0;
    else			f0 = r0, f1 = r1;
    if (f0 == _ST0_REGNO)
	fucomir(f1);
    else {
	fldr(f0);
	fucomipr(f1 + 1);
    }
    jp_code = jpes(0);
    jz_code = jzs(0);
    patch_at(jp_code, _jit->pc.w);
    w = jmpi(i0);
    patch_at(jz_code, _jit->pc.w);
    return (w);
}
dbopi(ne)
dbopi(unlt)
dbopi(unle)
dbopi(uneq)
dbopi(unge)
dbopi(ungt)
dbopi(ltgt)
dbopi(ord)
dbopi(unord)
#  undef fopi
#  undef fbopi
#  undef dopi
#  undef dbopi
#  undef fpr_bopi
#  undef fpr_opi
#endif
