@@ -5100,6 +5100,272 @@ static bool maybe_call_native(Context *ctx, AtomString module_name, AtomString f
51005100 break ;
51015101 }
51025102
5103+ #ifndef AVM_NO_FP
5104+ case OP_FCLEARERROR : {
5105+ // This can be a noop as we raise from bifs
5106+ TRACE ("fclearerror/0\n" );
5107+ NEXT_INSTRUCTION (1 );
5108+ break ;
5109+ }
5110+
5111+ case OP_FCHECKERROR : {
5112+ int next_off = 1 ;
5113+ // This can be a noop as we raise from bifs
5114+ int fail_label ;
5115+ DECODE_LABEL (fail_label , code , i , next_off );
5116+ NEXT_INSTRUCTION (next_off );
5117+ break ;
5118+ }
5119+
5120+ case OP_FMOVE : {
5121+ int next_off = 1 ;
5122+ if (IS_EXTENDED_FP_REGISTER (code , i , next_off )) {
5123+ int freg ;
5124+ DECODE_FP_REGISTER (freg , code , i , next_off );
5125+ dreg_t dreg ;
5126+ dreg_type_t dreg_type ;
5127+ DECODE_DEST_REGISTER (dreg , dreg_type , code , i , next_off );
5128+ #ifdef IMPL_EXECUTE_LOOP
5129+ TRACE ("fmove/2 fp%i, %c%i\n" , freg , T_DEST_REG (dreg_type , dreg ));
5130+ // Space should be available on heap as compiler added an allocate opcode
5131+ context_ensure_fpregs (ctx );
5132+ term float_value = term_from_float (ctx -> fr [freg ], ctx );
5133+ WRITE_REGISTER (dreg_type , dreg , float_value );
5134+ #endif
5135+ #ifdef IMPL_CODE_LOADER
5136+ TRACE ("fmove/2\n" );
5137+ UNUSED (freg )
5138+ UNUSED (dreg )
5139+ UNUSED (dreg_type )
5140+ #endif
5141+ } else {
5142+ term src_value ;
5143+ DECODE_COMPACT_TERM (src_value , code , i , next_off );
5144+ int freg ;
5145+ DECODE_FP_REGISTER (freg , code , i , next_off );
5146+ #ifdef IMPL_EXECUTE_LOOP
5147+ TRACE ("fmove/2 %lx, fp%i\n" , src_value , freg );
5148+ context_ensure_fpregs (ctx );
5149+ ctx -> fr [freg ] = term_to_float (src_value );
5150+ #endif
5151+ #ifdef IMPL_CODE_LOADER
5152+ TRACE ("fmove/2\n" );
5153+ UNUSED (src_value )
5154+ UNUSED (freg )
5155+ #endif
5156+ }
5157+
5158+ NEXT_INSTRUCTION (next_off );
5159+ break ;
5160+ }
5161+
5162+ case OP_FCONV : {
5163+ int next_off = 1 ;
5164+ term src_value ;
5165+ DECODE_COMPACT_TERM (src_value , code , i , next_off );
5166+ int freg ;
5167+ DECODE_FP_REGISTER (freg , code , i , next_off );
5168+
5169+ #ifdef IMPL_EXECUTE_LOOP
5170+ TRACE ("fconv/2 %lx, fp%i\n" , src_value , freg );
5171+ context_ensure_fpregs (ctx );
5172+ ctx -> fr [freg ] = term_conv_to_float (src_value );
5173+ #endif
5174+
5175+ #ifdef IMPL_CODE_LOADER
5176+ TRACE ("fconv/2\n" );
5177+ UNUSED (freg )
5178+ UNUSED (src_value )
5179+ #endif
5180+
5181+ NEXT_INSTRUCTION (next_off );
5182+ break ;
5183+ }
5184+
5185+ case OP_FADD : {
5186+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5187+ #pragma STDC FENV_ACCESS ON
5188+ #endif
5189+ int next_off = 1 ;
5190+ int fail_label ;
5191+ DECODE_LABEL (fail_label , code , i , next_off );
5192+ int freg1 , freg2 , freg3 ;
5193+ DECODE_FP_REGISTER (freg1 , code , i , next_off );
5194+ DECODE_FP_REGISTER (freg2 , code , i , next_off );
5195+ DECODE_FP_REGISTER (freg3 , code , i , next_off );
5196+ #ifdef IMPL_EXECUTE_LOOP
5197+ TRACE ("fadd/3 fp%i, fp%i, fp%i\n" , freg1 , freg2 , freg3 );
5198+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5199+ feclearexcept (FE_OVERFLOW );
5200+ #endif
5201+ context_ensure_fpregs (ctx );
5202+ ctx -> fr [freg3 ] = ctx -> fr [freg1 ] + ctx -> fr [freg2 ];
5203+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5204+ if (fetestexcept (FE_OVERFLOW )) {
5205+ RAISE_ERROR (BADARITH_ATOM );
5206+ }
5207+ #else
5208+ if (!isfinite (ctx -> fr [freg3 ])) {
5209+ RAISE_ERROR (BADARITH_ATOM );
5210+ }
5211+ #endif
5212+ #endif
5213+
5214+ #ifdef IMPL_CODE_LOADER
5215+ TRACE ("fadd/3\n" );
5216+ UNUSED (freg1 )
5217+ UNUSED (freg2 )
5218+ UNUSED (freg3 )
5219+ #endif
5220+
5221+ NEXT_INSTRUCTION (next_off );
5222+ break ;
5223+ }
5224+
5225+ case OP_FSUB : {
5226+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5227+ #pragma STDC FENV_ACCESS ON
5228+ #endif
5229+ int next_off = 1 ;
5230+ int fail_label ;
5231+ DECODE_LABEL (fail_label , code , i , next_off );
5232+ int freg1 , freg2 , freg3 ;
5233+ DECODE_FP_REGISTER (freg1 , code , i , next_off );
5234+ DECODE_FP_REGISTER (freg2 , code , i , next_off );
5235+ DECODE_FP_REGISTER (freg3 , code , i , next_off );
5236+ #ifdef IMPL_EXECUTE_LOOP
5237+ TRACE ("fsub/3 fp%i, fp%i, fp%i\n" , freg1 , freg2 , freg3 );
5238+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5239+ feclearexcept (FE_OVERFLOW );
5240+ #endif
5241+ context_ensure_fpregs (ctx );
5242+ ctx -> fr [freg3 ] = ctx -> fr [freg1 ] - ctx -> fr [freg2 ];
5243+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5244+ if (fetestexcept (FE_OVERFLOW )) {
5245+ RAISE_ERROR (BADARITH_ATOM );
5246+ }
5247+ #else
5248+ if (!isfinite (ctx -> fr [freg3 ])) {
5249+ RAISE_ERROR (BADARITH_ATOM );
5250+ }
5251+ #endif
5252+ #endif
5253+
5254+ #ifdef IMPL_CODE_LOADER
5255+ TRACE ("fsub/3\n" );
5256+ UNUSED (freg1 )
5257+ UNUSED (freg2 )
5258+ UNUSED (freg3 )
5259+ #endif
5260+
5261+ NEXT_INSTRUCTION (next_off );
5262+ break ;
5263+ }
5264+
5265+ case OP_FMUL : {
5266+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5267+ #pragma STDC FENV_ACCESS ON
5268+ #endif
5269+ int next_off = 1 ;
5270+ int fail_label ;
5271+ DECODE_LABEL (fail_label , code , i , next_off );
5272+ int freg1 , freg2 , freg3 ;
5273+ DECODE_FP_REGISTER (freg1 , code , i , next_off );
5274+ DECODE_FP_REGISTER (freg2 , code , i , next_off );
5275+ DECODE_FP_REGISTER (freg3 , code , i , next_off );
5276+ #ifdef IMPL_EXECUTE_LOOP
5277+ TRACE ("fmul/3 fp%i, fp%i, fp%i\n" , freg1 , freg2 , freg3 );
5278+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5279+ feclearexcept (FE_OVERFLOW );
5280+ #endif
5281+ context_ensure_fpregs (ctx );
5282+ ctx -> fr [freg3 ] = ctx -> fr [freg1 ] * ctx -> fr [freg2 ];
5283+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5284+ if (fetestexcept (FE_OVERFLOW )) {
5285+ RAISE_ERROR (BADARITH_ATOM );
5286+ }
5287+ #else
5288+ if (!isfinite (ctx -> fr [freg3 ])) {
5289+ RAISE_ERROR (BADARITH_ATOM );
5290+ }
5291+ #endif
5292+ #endif
5293+
5294+ #ifdef IMPL_CODE_LOADER
5295+ TRACE ("fmul/3\n" );
5296+ UNUSED (freg1 )
5297+ UNUSED (freg2 )
5298+ UNUSED (freg3 )
5299+ #endif
5300+
5301+ NEXT_INSTRUCTION (next_off );
5302+ break ;
5303+ }
5304+
5305+ case OP_FDIV : {
5306+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5307+ #pragma STDC FENV_ACCESS ON
5308+ #endif
5309+ int next_off = 1 ;
5310+ int fail_label ;
5311+ DECODE_LABEL (fail_label , code , i , next_off );
5312+ int freg1 , freg2 , freg3 ;
5313+ DECODE_FP_REGISTER (freg1 , code , i , next_off );
5314+ DECODE_FP_REGISTER (freg2 , code , i , next_off );
5315+ DECODE_FP_REGISTER (freg3 , code , i , next_off );
5316+ #ifdef IMPL_EXECUTE_LOOP
5317+ TRACE ("fdiv/3 fp%i, fp%i, fp%i\n" , freg1 , freg2 , freg3 );
5318+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5319+ feclearexcept (FE_OVERFLOW | FE_DIVBYZERO );
5320+ #endif
5321+ context_ensure_fpregs (ctx );
5322+ ctx -> fr [freg3 ] = ctx -> fr [freg1 ] / ctx -> fr [freg2 ];
5323+ #ifdef HAVE_PRAGMA_STDC_FENV_ACCESS
5324+ if (fetestexcept (FE_OVERFLOW | FE_DIVBYZERO )) {
5325+ RAISE_ERROR (BADARITH_ATOM );
5326+ }
5327+ #else
5328+ if (!isfinite (ctx -> fr [freg3 ])) {
5329+ RAISE_ERROR (BADARITH_ATOM );
5330+ }
5331+ #endif
5332+ #endif
5333+
5334+ #ifdef IMPL_CODE_LOADER
5335+ TRACE ("fdiv/3\n" );
5336+ UNUSED (freg1 )
5337+ UNUSED (freg2 )
5338+ UNUSED (freg3 )
5339+ #endif
5340+
5341+ NEXT_INSTRUCTION (next_off );
5342+ break ;
5343+ }
5344+
5345+ case OP_FNEGATE : {
5346+ int next_off = 1 ;
5347+ int fail_label ;
5348+ DECODE_LABEL (fail_label , code , i , next_off ) ;
5349+ int freg1 , freg2 ;
5350+ DECODE_FP_REGISTER (freg1 , code , i , next_off );
5351+ DECODE_FP_REGISTER (freg2 , code , i , next_off );
5352+ #ifdef IMPL_EXECUTE_LOOP
5353+ TRACE ("fnegate/2 fp%i, fp%i\n" , freg1 , freg2 );
5354+ context_ensure_fpregs (ctx );
5355+ ctx -> fr [freg2 ] = - ctx -> fr [freg1 ];
5356+ #endif
5357+
5358+ #ifdef IMPL_CODE_LOADER
5359+ TRACE ("fnegate/2\n" );
5360+ UNUSED (freg1 )
5361+ UNUSED (freg2 )
5362+ #endif
5363+
5364+ NEXT_INSTRUCTION (next_off );
5365+ break ;
5366+ }
5367+ #endif
5368+
51035369#ifdef ENABLE_OTP21
51045370 case OP_GET_HD : {
51055371 int next_off = 1 ;
0 commit comments