blob: 6faa2081fb27e8153eab6ca6255d12b802493d6a [file]
/*
* Copyright (c) 2025, Intel Corporation. All rights reserved.
* Intel Math Library (LIBM) Source Code
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "macroAssembler_x86.hpp"
#include "stubGenerator_x86_64.hpp"
/******************************************************************************/
// ALGORITHM DESCRIPTION
// ---------------------
//
// x=2^{3*k+j} * 1.b1 b2 ... b5 b6 ... b52
// Let r=(x*2^{-3k-j} - 1.b1 b2 ... b5 1)* rcp[b1 b2 ..b5],
// where rcp[b1 b2 .. b5]=1/(1.b1 b2 b3 b4 b5 1) in double precision
// cbrt(2^j * 1. b1 b2 .. b5 1) is approximated as T[j][b1..b5]+D[j][b1..b5]
// (T stores the high 53 bits, D stores the low order bits)
// Result=2^k*T+(2^k*T*r)*P+2^k*D
// where P=p1+p2*r+..+p8*r^7
//
// Special cases:
// cbrt(NaN) = quiet NaN
// cbrt(+/-INF) = +/-INF
// cbrt(+/-0) = +/-0
//
/******************************************************************************/
/* Represents 0x7FFFFFFFFFFFFFFF double precision in lower 64 bits*/
ATTRIBUTE_ALIGNED(16) static const juint _ABS_MASK[] =
{
4294967295, 2147483647, 0, 0
};
ATTRIBUTE_ALIGNED(4) static const juint _SIG_MASK[] =
{
0, 1032192
};
ATTRIBUTE_ALIGNED(4) static const juint _EXP_MASK[] =
{
0, 3220176896
};
ATTRIBUTE_ALIGNED(4) static const juint _EXP_MSK2[] =
{
0, 3220193280
};
ATTRIBUTE_ALIGNED(4) static const juint _EXP_MSK3[] =
{
4294967295, 1048575
};
ATTRIBUTE_ALIGNED(4) static const juint _SCALE63[] =
{
0, 1138753536
};
ATTRIBUTE_ALIGNED(4) static const juint _ZERON[] =
{
0, 2147483648
};
ATTRIBUTE_ALIGNED(4) static const juint _INF[] =
{
0, 2146435072
};
ATTRIBUTE_ALIGNED(4) static const juint _NEG_INF[] =
{
0, 4293918720
};
ATTRIBUTE_ALIGNED(16) static const juint _coeff_table[] =
{
1553778919, 3213899486, 3534952507, 3215266280, 1646371399,
3214412045, 477218588, 3216798151, 3582521621, 1066628362,
1007461464, 1068473053, 889629714, 1067378449, 1431655765,
1070945621
};
ATTRIBUTE_ALIGNED(4) static const juint _rcp_table[] =
{
528611360, 3220144632, 2884679527, 3220082993, 1991868891, 3220024928,
2298714891, 3219970134, 58835168, 3219918343, 3035110223, 3219869313,
1617585086, 3219822831, 2500867033, 3219778702, 4241943008, 3219736752,
258732970, 3219696825, 404232216, 3219658776, 2172167368, 3219622476,
1544257904, 3219587808, 377579543, 3219554664, 1616385542, 3219522945,
813783277, 3219492562, 3940743189, 3219463431, 2689777499, 3219435478,
1700977147, 3219408632, 3169102082, 3219382828, 327235604, 3219358008,
1244336319, 3219334115, 1300311200, 3219311099, 3095471925, 3219288912,
2166487928, 3219267511, 2913108253, 3219246854, 293672978, 3219226904,
288737297, 3219207624, 1810275472, 3219188981, 174592167, 3219170945,
3539053052, 3219153485, 2164392968, 3219136576
};
ATTRIBUTE_ALIGNED(4) static const juint _cbrt_table[] =
{
572345495, 1072698681, 1998204467, 1072709382, 3861501553, 1072719872,
2268192434, 1072730162, 2981979308, 1072740260, 270859143, 1072750176,
2958651392, 1072759916, 313113243, 1072769490, 919449400, 1072778903,
2809328903, 1072788162, 2222981587, 1072797274, 2352530781, 1072806244,
594152517, 1072815078, 1555767199, 1072823780, 4282421314, 1072832355,
2355578597, 1072840809, 1162590619, 1072849145, 797864051, 1072857367,
431273680, 1072865479, 2669831148, 1072873484, 733477752, 1072881387,
4280220604, 1072889189, 801961634, 1072896896, 2915370760, 1072904508,
1159613482, 1072912030, 2689944798, 1072919463, 1248687822, 1072926811,
2967951030, 1072934075, 630170432, 1072941259, 3760898254, 1072948363,
0, 1072955392, 2370273294, 1072962345, 1261754802, 1072972640,
546334065, 1072986123, 1054893830, 1072999340, 1571187597, 1073012304,
1107975175, 1073025027, 3606909377, 1073037519, 1113616747, 1073049792,
4154744632, 1073061853, 3358931423, 1073073713, 4060702372, 1073085379,
747576176, 1073096860, 3023138255, 1073108161, 1419988548, 1073119291,
1914185305, 1073130255, 294389948, 1073141060, 3761802570, 1073151710,
978281566, 1073162213, 823148820, 1073172572, 2420954441, 1073182792,
3815449908, 1073192878, 2046058587, 1073202835, 1807524753, 1073212666,
2628681401, 1073222375, 3225667357, 1073231966, 1555307421, 1073241443,
3454043099, 1073250808, 1208137896, 1073260066, 3659916772, 1073269218,
1886261264, 1073278269, 3593647839, 1073287220, 3086012205, 1073296075,
2769796922, 1073304836, 888716057, 1073317807, 2201465623, 1073334794,
164369365, 1073351447, 3462666733, 1073367780, 2773905457, 1073383810,
1342879088, 1073399550, 2543933975, 1073415012, 1684477781, 1073430209,
3532178543, 1073445151, 1147747300, 1073459850, 1928031793, 1073474314,
2079717015, 1073488553, 4016765315, 1073502575, 3670431139, 1073516389,
3549227225, 1073530002, 11637607, 1073543422, 588220169, 1073556654,
2635407503, 1073569705, 2042029317, 1073582582, 1925128962, 1073595290,
4136375664, 1073607834, 759964600, 1073620221, 4257606771, 1073632453,
297278907, 1073644538, 3655053093, 1073656477, 2442253172, 1073668277,
1111876799, 1073679941, 3330973139, 1073691472, 3438879452, 1073702875,
3671565478, 1073714153, 1317849547, 1073725310, 1642364115, 1073736348
};
ATTRIBUTE_ALIGNED(4) static const juint _D_table[] =
{
4050900474, 1014427190, 1157977860, 1016444461, 1374568199, 1017271387,
2809163288, 1016882676, 3742377377, 1013168191, 3101606597, 1017541672,
65224358, 1017217597, 2691591250, 1017266643, 4020758549, 1017689313,
1316310992, 1018030788, 1031537856, 1014090882, 3261395239, 1016413641,
886424999, 1016313335, 3114776834, 1014195875, 1681120620, 1017825416,
1329600273, 1016625740, 465474623, 1017097119, 4251633980, 1017169077,
1986990133, 1017710645, 752958613, 1017159641, 2216216792, 1018020163,
4282860129, 1015924861, 1557627859, 1016039538, 3889219754, 1018086237,
3684996408, 1017353275, 723532103, 1017717141, 2951149676, 1012528470,
831890937, 1017830553, 1031212645, 1017387331, 2741737450, 1017604974,
2863311531, 1003776682, 4276736099, 1013153088, 4111778382, 1015673686,
1728065769, 1016413986, 2708718031, 1018078833, 1069335005, 1015291224,
700037144, 1016482032, 2904566452, 1017226861, 4074156649, 1017622651,
25019565, 1015245366, 3601952608, 1015771755, 3267129373, 1017904664,
503203103, 1014921629, 2122011730, 1018027866, 3927295461, 1014189456,
2790625147, 1016024251, 1330460186, 1016940346, 4033568463, 1015538390,
3695818227, 1017509621, 257573361, 1017208868, 3227697852, 1017337964,
234118548, 1017169577, 4009025803, 1017278524, 1948343394, 1017749310,
678398162, 1018144239, 3083864863, 1016669086, 2415453452, 1017890370,
175467344, 1017330033, 3197359580, 1010339928, 2071276951, 1015941358,
268372543, 1016737773, 938132959, 1017389108, 1816750559, 1017337448,
4119203749, 1017152174, 2578653878, 1013108497, 2470331096, 1014678606,
123855735, 1016553320, 1265650889, 1014782687, 3414398172, 1017182638,
1040773369, 1016158401, 3483628886, 1016886550, 4140499405, 1016191425,
3893477850, 1016964495, 3935319771, 1009634717, 2978982660, 1015027112,
2452709923, 1017990229, 3190365712, 1015835149, 4237588139, 1015832925,
2610678389, 1017962711, 2127316774, 1017405770, 824267502, 1017959463,
2165924042, 1017912225, 2774007076, 1013257418, 4123916326, 1017582284,
1976417958, 1016959909, 4092806412, 1017711279, 119251817, 1015363631,
3475418768, 1017675415, 1972580503, 1015470684, 815541017, 1017517969,
2429917451, 1017397776, 4062888482, 1016749897, 68284153, 1017925678,
2207779246, 1016320298, 1183466520, 1017408657, 143326427, 1017060403
};
#define __ _masm->
address StubGenerator::generate_libmCbrt() {
StubGenStubId stub_id = StubGenStubId::dcbrt_id;
StubCodeMark mark(this, stub_id);
address start = __ pc();
Label L_2TAG_PACKET_0_0_1, L_2TAG_PACKET_1_0_1, L_2TAG_PACKET_2_0_1;
Label B1_1, B1_2, B1_4;
address ABS_MASK = (address)_ABS_MASK;
address SIG_MASK = (address)_SIG_MASK;
address EXP_MASK = (address)_EXP_MASK;
address EXP_MSK2 = (address)_EXP_MSK2;
address EXP_MSK3 = (address)_EXP_MSK3;
address SCALE63 = (address)_SCALE63;
address ZERON = (address)_ZERON;
address INF = (address)_INF;
address NEG_INF = (address)_NEG_INF;
address coeff_table = (address)_coeff_table;
address rcp_table = (address)_rcp_table;
address cbrt_table = (address)_cbrt_table;
address D_table = (address)_D_table;
__ enter(); // required for proper stackwalking of RuntimeStub frame
__ bind(B1_1);
__ ucomisd(xmm0, ExternalAddress(ZERON), r11 /*rscratch*/);
__ jcc(Assembler::equal, L_2TAG_PACKET_1_0_1); // Branch only if x is +/- zero or NaN
__ movq(xmm1, xmm0);
__ andpd(xmm1, ExternalAddress(ABS_MASK), r11 /*rscratch*/);
__ ucomisd(xmm1, ExternalAddress(INF), r11 /*rscratch*/);
__ jcc(Assembler::equal, B1_4); // Branch only if x is +/- INF
__ bind(B1_2);
__ movq(xmm7, xmm0);
__ movl(rdx, 524032);
__ movsd(xmm5, ExternalAddress(EXP_MSK3), r11 /*rscratch*/);
__ movsd(xmm3, ExternalAddress(EXP_MSK2), r11 /*rscratch*/);
__ psrlq(xmm7, 44);
__ pextrw(rcx, xmm7, 0);
__ movdl(rax, xmm7);
__ movsd(xmm1, ExternalAddress(EXP_MASK), r11 /*rscratch*/);
__ movsd(xmm2, ExternalAddress(SIG_MASK), r11 /*rscratch*/);
__ andl(rcx, 248);
__ lea(r8, ExternalAddress(rcp_table));
__ movsd(xmm4, Address(rcx, r8, Address::times_1));
__ movq(r9, rax);
__ andl(rdx, rax);
__ cmpl(rdx, 0);
__ jcc(Assembler::equal, L_2TAG_PACKET_0_0_1); // Branch only if |x| is denormalized
__ shrl(rdx, 8);
__ shrq(r9, 8);
__ andpd(xmm2, xmm0);
__ andpd(xmm0, xmm5);
__ orpd(xmm3, xmm2);
__ orpd(xmm1, xmm0);
__ movapd(xmm5, ExternalAddress(coeff_table), r11 /*rscratch*/);
__ movl(rax, 5462);
__ movapd(xmm6, ExternalAddress(coeff_table + 16), r11 /*rscratch*/);
__ mull(rdx);
__ movq(rdx, r9);
__ andq(r9, 2047);
__ shrl(rax, 14);
__ andl(rdx, 2048);
__ subq(r9, rax);
__ subq(r9, rax);
__ subq(r9, rax);
__ shlq(r9, 8);
__ addl(rax, 682);
__ orl(rax, rdx);
__ movdl(xmm7, rax);
__ addq(rcx, r9);
__ psllq(xmm7, 52);
__ bind(L_2TAG_PACKET_2_0_1);
__ movapd(xmm2, ExternalAddress(coeff_table + 32), r11 /*rscratch*/);
__ movapd(xmm0, ExternalAddress(coeff_table + 48), r11 /*rscratch*/);
__ subsd(xmm1, xmm3);
__ movq(xmm3, xmm7);
__ lea(r8, ExternalAddress(cbrt_table));
__ mulsd(xmm7, Address(rcx, r8, Address::times_1));
__ mulsd(xmm1, xmm4);
__ lea(r8, ExternalAddress(D_table));
__ mulsd(xmm3, Address(rcx, r8, Address::times_1));
__ movapd(xmm4, xmm1);
__ unpcklpd(xmm1, xmm1);
__ mulpd(xmm5, xmm1);
__ mulpd(xmm6, xmm1);
__ mulpd(xmm1, xmm1);
__ addpd(xmm2, xmm5);
__ addpd(xmm0, xmm6);
__ mulpd(xmm2, xmm1);
__ mulpd(xmm1, xmm1);
__ mulsd(xmm4, xmm7);
__ addpd(xmm0, xmm2);
__ mulsd(xmm1, xmm0);
__ unpckhpd(xmm0, xmm0);
__ addsd(xmm0, xmm1);
__ mulsd(xmm0, xmm4);
__ addsd(xmm0, xmm3);
__ addsd(xmm0, xmm7);
__ jmp(B1_4);
__ bind(L_2TAG_PACKET_0_0_1);
__ mulsd(xmm0, ExternalAddress(SCALE63), r11 /*rscratch*/);
__ movq(xmm7, xmm0);
__ movl(rdx, 524032);
__ psrlq(xmm7, 44);
__ pextrw(rcx, xmm7, 0);
__ movdl(rax, xmm7);
__ andl(rcx, 248);
__ lea(r8, ExternalAddress(rcp_table));
__ movsd(xmm4, Address(rcx, r8, Address::times_1));
__ movq(r9, rax);
__ andl(rdx, rax);
__ shrl(rdx, 8);
__ shrq(r9, 8);
__ andpd(xmm2, xmm0);
__ andpd(xmm0, xmm5);
__ orpd(xmm3, xmm2);
__ orpd(xmm1, xmm0);
__ movapd(xmm5, ExternalAddress(coeff_table), r11 /*rscratch*/);
__ movl(rax, 5462);
__ movapd(xmm6, ExternalAddress(coeff_table + 16), r11 /*rscratch*/);
__ mull(rdx);
__ movq(rdx, r9);
__ andq(r9, 2047);
__ shrl(rax, 14);
__ andl(rdx, 2048);
__ subq(r9, rax);
__ subq(r9, rax);
__ subq(r9, rax);
__ shlq(r9, 8);
__ addl(rax, 661);
__ orl(rax, rdx);
__ movdl(xmm7, rax);
__ addq(rcx, r9);
__ psllq(xmm7, 52);
__ jmp(L_2TAG_PACKET_2_0_1);
__ bind(L_2TAG_PACKET_1_0_1);
__ addsd(xmm0, xmm0);
__ bind(B1_4);
__ leave(); // required for proper stackwalking of RuntimeStub frame
__ ret(0);
return start;
}
#undef __