1 /*
   2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2016, Intel Corporation. All rights reserved.
   4  * Intel Math Library (LIBM) Source Code
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package org.graalvm.compiler.lir.amd64;
  28 
  29 import static jdk.vm.ci.amd64.AMD64.r11;
  30 import static jdk.vm.ci.amd64.AMD64.rax;
  31 import static jdk.vm.ci.amd64.AMD64.rcx;
  32 import static jdk.vm.ci.amd64.AMD64.rdx;
  33 import static jdk.vm.ci.amd64.AMD64.rsp;
  34 import static jdk.vm.ci.amd64.AMD64.xmm0;
  35 import static jdk.vm.ci.amd64.AMD64.xmm1;
  36 import static jdk.vm.ci.amd64.AMD64.xmm2;
  37 import static jdk.vm.ci.amd64.AMD64.xmm3;
  38 import static jdk.vm.ci.amd64.AMD64.xmm4;
  39 import static jdk.vm.ci.amd64.AMD64.xmm5;
  40 import static jdk.vm.ci.amd64.AMD64.xmm6;
  41 import static jdk.vm.ci.amd64.AMD64.xmm7;
  42 import static org.graalvm.compiler.lir.amd64.AMD64HotSpotHelper.pointerConstant;
  43 import static org.graalvm.compiler.lir.amd64.AMD64HotSpotHelper.recordExternalAddress;
  44 
  45 import org.graalvm.compiler.asm.Label;
  46 import org.graalvm.compiler.asm.amd64.AMD64Address;
  47 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
  48 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
  49 import org.graalvm.compiler.lir.LIRInstructionClass;
  50 import org.graalvm.compiler.lir.asm.ArrayDataPointerConstant;
  51 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
  52 
  53 /**
  54  * <pre>
  55  *                     ALGORITHM DESCRIPTION - EXP()
  56  *                     ---------------------
  57  *
  58  * Description:
  59  *  Let K = 64 (table size).
  60  *        x    x/log(2)     n
  61  *       e  = 2          = 2 * T[j] * (1 + P(y))
  62  *  where
  63  *       x = m*log(2)/K + y,    y in [-log(2)/K..log(2)/K]
  64  *       m = n*K + j,           m,n,j - signed integer, j in [-K/2..K/2]
  65  *                  j/K
  66  *       values of 2   are tabulated as T[j] = T_hi[j] ( 1 + T_lo[j]).
  67  *
  68  *       P(y) is a minimax polynomial approximation of exp(x)-1
  69  *       on small interval [-log(2)/K..log(2)/K] (were calculated by Maple V).
  70  *
  71  *  To avoid problems with arithmetic overflow and underflow,
  72  *            n                        n1  n2
  73  *  value of 2  is safely computed as 2 * 2 where n1 in [-BIAS/2..BIAS/2]
  74  *  where BIAS is a value of exponent bias.
  75  *
  76  * Special cases:
  77  *  exp(NaN) = NaN
  78  *  exp(+INF) = +INF
  79  *  exp(-INF) = 0
  80  *  exp(x) = 1 for subnormals
  81  *  for finite argument, only exp(0)=1 is exact
  82  *  For IEEE double
  83  *    if x >  709.782712893383973096 then exp(x) overflow
  84  *    if x < -745.133219101941108420 then exp(x) underflow
  85  * </pre>
  86  */
  87 public final class AMD64MathExpOp extends AMD64MathIntrinsicUnaryOp {
  88 
  89     public static final LIRInstructionClass<AMD64MathExpOp> TYPE = LIRInstructionClass.create(AMD64MathExpOp.class);
  90 
  91     public AMD64MathExpOp() {
  92         super(TYPE, /* GPR */ rax, rcx, rdx, r11,
  93                         /* XMM */ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
  94     }
  95 
  96     private ArrayDataPointerConstant cv = pointerConstant(16, new int[]{
  97             // @formatter:off
  98             0x652b82fe, 0x40571547, 0x652b82fe, 0x40571547,
  99     });
 100     private ArrayDataPointerConstant cv16 = pointerConstant(16, new int[]{
 101             0xfefa0000, 0x3f862e42, 0xfefa0000, 0x3f862e42,
 102     });
 103     private ArrayDataPointerConstant cv32 = pointerConstant(16, new int[]{
 104             0xbc9e3b3a, 0x3d1cf79a, 0xbc9e3b3a, 0x3d1cf79a,
 105     });
 106     private ArrayDataPointerConstant cv48 = pointerConstant(16, new int[]{
 107             0xfffffffe, 0x3fdfffff, 0xfffffffe, 0x3fdfffff,
 108     });
 109     private ArrayDataPointerConstant cv64 = pointerConstant(16, new int[]{
 110             0xe3289860, 0x3f56c15c, 0x555b9e25, 0x3fa55555,
 111     });
 112     private ArrayDataPointerConstant cv80 = pointerConstant(16, new int[]{
 113             0xc090cf0f, 0x3f811115, 0x55548ba1, 0x3fc55555
 114             // @formatter:on
 115     });
 116 
 117     private ArrayDataPointerConstant shifter = pointerConstant(16, new int[]{
 118             // @formatter:off
 119             0x00000000, 0x43380000, 0x00000000, 0x43380000
 120             // @formatter:on
 121     });
 122 
 123     private ArrayDataPointerConstant mmask = pointerConstant(16, new int[]{
 124             // @formatter:off
 125             0xffffffc0, 0x00000000, 0xffffffc0, 0x00000000
 126             // @formatter:on
 127     });
 128 
 129     private ArrayDataPointerConstant bias = pointerConstant(16, new int[]{
 130             // @formatter:off
 131             0x0000ffc0, 0x00000000, 0x0000ffc0, 0x00000000
 132             // @formatter:on
 133     });
 134 
 135     private ArrayDataPointerConstant tblAddr = pointerConstant(16, new int[]{
 136             // @formatter:off
 137             0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0e03754d,
 138             0x3cad7bbf, 0x3e778060, 0x00002c9a, 0x3567f613, 0x3c8cd252,
 139             0xd3158574, 0x000059b0, 0x61e6c861, 0x3c60f74e, 0x18759bc8,
 140             0x00008745, 0x5d837b6c, 0x3c979aa6, 0x6cf9890f, 0x0000b558,
 141             0x702f9cd1, 0x3c3ebe3d, 0x32d3d1a2, 0x0000e3ec, 0x1e63bcd8,
 142             0x3ca3516e, 0xd0125b50, 0x00011301, 0x26f0387b, 0x3ca4c554,
 143             0xaea92ddf, 0x0001429a, 0x62523fb6, 0x3ca95153, 0x3c7d517a,
 144             0x000172b8, 0x3f1353bf, 0x3c8b898c, 0xeb6fcb75, 0x0001a35b,
 145             0x3e3a2f5f, 0x3c9aecf7, 0x3168b9aa, 0x0001d487, 0x44a6c38d,
 146             0x3c8a6f41, 0x88628cd6, 0x0002063b, 0xe3a8a894, 0x3c968efd,
 147             0x6e756238, 0x0002387a, 0x981fe7f2, 0x3c80472b, 0x65e27cdd,
 148             0x00026b45, 0x6d09ab31, 0x3c82f7e1, 0xf51fdee1, 0x00029e9d,
 149             0x720c0ab3, 0x3c8b3782, 0xa6e4030b, 0x0002d285, 0x4db0abb6,
 150             0x3c834d75, 0x0a31b715, 0x000306fe, 0x5dd3f84a, 0x3c8fdd39,
 151             0xb26416ff, 0x00033c08, 0xcc187d29, 0x3ca12f8c, 0x373aa9ca,
 152             0x000371a7, 0x738b5e8b, 0x3ca7d229, 0x34e59ff6, 0x0003a7db,
 153             0xa72a4c6d, 0x3c859f48, 0x4c123422, 0x0003dea6, 0x259d9205,
 154             0x3ca8b846, 0x21f72e29, 0x0004160a, 0x60c2ac12, 0x3c4363ed,
 155             0x6061892d, 0x00044e08, 0xdaa10379, 0x3c6ecce1, 0xb5c13cd0,
 156             0x000486a2, 0xbb7aafb0, 0x3c7690ce, 0xd5362a27, 0x0004bfda,
 157             0x9b282a09, 0x3ca083cc, 0x769d2ca6, 0x0004f9b2, 0xc1aae707,
 158             0x3ca509b0, 0x569d4f81, 0x0005342b, 0x18fdd78e, 0x3c933505,
 159             0x36b527da, 0x00056f47, 0xe21c5409, 0x3c9063e1, 0xdd485429,
 160             0x0005ab07, 0x2b64c035, 0x3c9432e6, 0x15ad2148, 0x0005e76f,
 161             0x99f08c0a, 0x3ca01284, 0xb03a5584, 0x0006247e, 0x0073dc06,
 162             0x3c99f087, 0x82552224, 0x00066238, 0x0da05571, 0x3c998d4d,
 163             0x667f3bcc, 0x0006a09e, 0x86ce4786, 0x3ca52bb9, 0x3c651a2e,
 164             0x0006dfb2, 0x206f0dab, 0x3ca32092, 0xe8ec5f73, 0x00071f75,
 165             0x8e17a7a6, 0x3ca06122, 0x564267c8, 0x00075feb, 0x461e9f86,
 166             0x3ca244ac, 0x73eb0186, 0x0007a114, 0xabd66c55, 0x3c65ebe1,
 167             0x36cf4e62, 0x0007e2f3, 0xbbff67d0, 0x3c96fe9f, 0x994cce12,
 168             0x00082589, 0x14c801df, 0x3c951f14, 0x9b4492ec, 0x000868d9,
 169             0xc1f0eab4, 0x3c8db72f, 0x422aa0db, 0x0008ace5, 0x59f35f44,
 170             0x3c7bf683, 0x99157736, 0x0008f1ae, 0x9c06283c, 0x3ca360ba,
 171             0xb0cdc5e4, 0x00093737, 0x20f962aa, 0x3c95e8d1, 0x9fde4e4f,
 172             0x00097d82, 0x2b91ce27, 0x3c71affc, 0x82a3f090, 0x0009c491,
 173             0x589a2ebd, 0x3c9b6d34, 0x7b5de564, 0x000a0c66, 0x9ab89880,
 174             0x3c95277c, 0xb23e255c, 0x000a5503, 0x6e735ab3, 0x3c846984,
 175             0x5579fdbf, 0x000a9e6b, 0x92cb3387, 0x3c8c1a77, 0x995ad3ad,
 176             0x000ae89f, 0xdc2d1d96, 0x3ca22466, 0xb84f15fa, 0x000b33a2,
 177             0xb19505ae, 0x3ca1112e, 0xf2fb5e46, 0x000b7f76, 0x0a5fddcd,
 178             0x3c74ffd7, 0x904bc1d2, 0x000bcc1e, 0x30af0cb3, 0x3c736eae,
 179             0xdd85529c, 0x000c199b, 0xd10959ac, 0x3c84e08f, 0x2e57d14b,
 180             0x000c67f1, 0x6c921968, 0x3c676b2c, 0xdcef9069, 0x000cb720,
 181             0x36df99b3, 0x3c937009, 0x4a07897b, 0x000d072d, 0xa63d07a7,
 182             0x3c74a385, 0xdcfba487, 0x000d5818, 0xd5c192ac, 0x3c8e5a50,
 183             0x03db3285, 0x000da9e6, 0x1c4a9792, 0x3c98bb73, 0x337b9b5e,
 184             0x000dfc97, 0x603a88d3, 0x3c74b604, 0xe78b3ff6, 0x000e502e,
 185             0x92094926, 0x3c916f27, 0xa2a490d9, 0x000ea4af, 0x41aa2008,
 186             0x3c8ec3bc, 0xee615a27, 0x000efa1b, 0x31d185ee, 0x3c8a64a9,
 187             0x5b6e4540, 0x000f5076, 0x4d91cd9d, 0x3c77893b, 0x819e90d8,
 188             0x000fa7c1
 189             // @formatter:on
 190     });
 191 
 192     private ArrayDataPointerConstant allones = pointerConstant(16, new int[]{
 193             // @formatter:off
 194             0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
 195             // @formatter:on
 196     });
 197 
 198     private ArrayDataPointerConstant ebias = pointerConstant(16, new int[]{
 199             // @formatter:off
 200             0x00000000, 0x3ff00000, 0x00000000, 0x3ff00000
 201             // @formatter:on
 202     });
 203 
 204     private ArrayDataPointerConstant xmax = pointerConstant(4, new int[]{
 205             // @formatter:off
 206             0xffffffff, 0x7fefffff
 207             // @formatter:on
 208     });
 209 
 210     private ArrayDataPointerConstant xmin = pointerConstant(4, new int[]{
 211             // @formatter:off
 212             0x00000000, 0x00100000
 213             // @formatter:on
 214     });
 215 
 216     private ArrayDataPointerConstant inf = pointerConstant(4, new int[]{
 217             // @formatter:off
 218             0x00000000, 0x7ff00000
 219             // @formatter:on
 220     });
 221 
 222     private ArrayDataPointerConstant zero = pointerConstant(4, new int[]{
 223             // @formatter:off
 224             0x00000000, 0x00000000
 225             // @formatter:on
 226     });
 227 
 228     private ArrayDataPointerConstant oneVal = pointerConstant(4, new int[]{
 229             // @formatter:off
 230             0x00000000, 0x3ff00000
 231             // @formatter:on
 232     });
 233 
 234     @Override
 235     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
 236         // Registers:
 237         // input: xmm0
 238         // scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
 239         // rax, rdx, rcx, tmp - r11
 240 
 241         // Code generated by Intel C compiler for LIBM library
 242         Label block0 = new Label();
 243         Label block1 = new Label();
 244         Label block2 = new Label();
 245         Label block3 = new Label();
 246         Label block4 = new Label();
 247         Label block5 = new Label();
 248         Label block6 = new Label();
 249         Label block7 = new Label();
 250         Label block8 = new Label();
 251         Label block9 = new Label();
 252         Label block10 = new Label();
 253         Label block11 = new Label();
 254         Label block12 = new Label();
 255         Label block13 = new Label();
 256 
 257         masm.subq(rsp, 24);
 258         masm.movsd(new AMD64Address(rsp, 8), xmm0);
 259         masm.unpcklpd(xmm0, xmm0);
 260         masm.movdqu(xmm1, recordExternalAddress(crb, cv));             // 0x652b82fe, 0x40571547,
 261                                                                        // 0x652b82fe, 0x40571547
 262         masm.movdqu(xmm6, recordExternalAddress(crb, shifter));        // 0x00000000, 0x43380000,
 263                                                                        // 0x00000000, 0x43380000
 264         masm.movdqu(xmm2, recordExternalAddress(crb, cv16));           // 0xfefa0000, 0x3f862e42,
 265                                                                        // 0xfefa0000, 0x3f862e42
 266         masm.movdqu(xmm3, recordExternalAddress(crb, cv32));           // 0xbc9e3b3a, 0x3d1cf79a,
 267                                                                        // 0xbc9e3b3a, 0x3d1cf79a
 268         masm.pextrw(rax, xmm0, 3);
 269         masm.andl(rax, 32767);
 270         masm.movl(rdx, 16527);
 271         masm.subl(rdx, rax);
 272         masm.subl(rax, 15504);
 273         masm.orl(rdx, rax);
 274         masm.cmpl(rdx, Integer.MIN_VALUE);
 275         masm.jcc(ConditionFlag.AboveEqual, block0);
 276         masm.mulpd(xmm1, xmm0);
 277         masm.addpd(xmm1, xmm6);
 278         masm.movapd(xmm7, xmm1);
 279         masm.subpd(xmm1, xmm6);
 280         masm.mulpd(xmm2, xmm1);
 281         masm.movdqu(xmm4, recordExternalAddress(crb, cv64));           // 0xe3289860, 0x3f56c15c,
 282                                                                        // 0x555b9e25, 0x3fa55555
 283         masm.mulpd(xmm3, xmm1);
 284         masm.movdqu(xmm5, recordExternalAddress(crb, cv80));           // 0xc090cf0f, 0x3f811115,
 285                                                                        // 0x55548ba1, 0x3fc55555
 286         masm.subpd(xmm0, xmm2);
 287         masm.movdl(rax, xmm7);
 288         masm.movl(rcx, rax);
 289         masm.andl(rcx, 63);
 290         masm.shll(rcx, 4);
 291         masm.sarl(rax, 6);
 292         masm.movl(rdx, rax);
 293         masm.movdqu(xmm6, recordExternalAddress(crb, mmask));          // 0xffffffc0, 0x00000000,
 294                                                                        // 0xffffffc0, 0x00000000
 295         masm.pand(xmm7, xmm6);
 296         masm.movdqu(xmm6, recordExternalAddress(crb, bias));           // 0x0000ffc0, 0x00000000,
 297                                                                        // 0x0000ffc0, 0x00000000
 298         masm.paddq(xmm7, xmm6);
 299         masm.psllq(xmm7, 46);
 300         masm.subpd(xmm0, xmm3);
 301         masm.leaq(r11, recordExternalAddress(crb, tblAddr));
 302         masm.movdqu(xmm2, new AMD64Address(rcx, r11, AMD64Address.Scale.Times1));
 303         masm.mulpd(xmm4, xmm0);
 304         masm.movapd(xmm6, xmm0);
 305         masm.movapd(xmm1, xmm0);
 306         masm.mulpd(xmm6, xmm6);
 307         masm.mulpd(xmm0, xmm6);
 308         masm.addpd(xmm5, xmm4);
 309         masm.mulsd(xmm0, xmm6);
 310         masm.mulpd(xmm6, recordExternalAddress(crb, cv48));            // 0xfffffffe, 0x3fdfffff,
 311                                                                        // 0xfffffffe, 0x3fdfffff
 312         masm.addsd(xmm1, xmm2);
 313         masm.unpckhpd(xmm2, xmm2);
 314         masm.mulpd(xmm0, xmm5);
 315         masm.addsd(xmm1, xmm0);
 316         masm.por(xmm2, xmm7);
 317         masm.unpckhpd(xmm0, xmm0);
 318         masm.addsd(xmm0, xmm1);
 319         masm.addsd(xmm0, xmm6);
 320         masm.addl(rdx, 894);
 321         masm.cmpl(rdx, 1916);
 322         masm.jcc(ConditionFlag.Above, block1);
 323         masm.mulsd(xmm0, xmm2);
 324         masm.addsd(xmm0, xmm2);
 325         masm.jmp(block13);
 326 
 327         masm.bind(block1);
 328         masm.xorpd(xmm3, xmm3);
 329         masm.movdqu(xmm4, recordExternalAddress(crb, allones));        // 0xffffffff, 0xffffffff,
 330                                                                        // 0xffffffff, 0xffffffff
 331         masm.movl(rdx, -1022);
 332         masm.subl(rdx, rax);
 333         masm.movdl(xmm5, rdx);
 334         masm.psllq(xmm4, xmm5);
 335         masm.movl(rcx, rax);
 336         masm.sarl(rax, 1);
 337         masm.pinsrw(xmm3, rax, 3);
 338         masm.movdqu(xmm6, recordExternalAddress(crb, ebias));          // 0x00000000, 0x3ff00000,
 339                                                                        // 0x00000000, 0x3ff00000
 340         masm.psllq(xmm3, 4);
 341         masm.psubd(xmm2, xmm3);
 342         masm.mulsd(xmm0, xmm2);
 343         masm.cmpl(rdx, 52);
 344         masm.jcc(ConditionFlag.Greater, block2);
 345         masm.pand(xmm4, xmm2);
 346         masm.paddd(xmm3, xmm6);
 347         masm.subsd(xmm2, xmm4);
 348         masm.addsd(xmm0, xmm2);
 349         masm.cmpl(rcx, 1023);
 350         masm.jcc(ConditionFlag.GreaterEqual, block3);
 351         masm.pextrw(rcx, xmm0, 3);
 352         masm.andl(rcx, 32768);
 353         masm.orl(rdx, rcx);
 354         masm.cmpl(rdx, 0);
 355         masm.jcc(ConditionFlag.Equal, block4);
 356         masm.movapd(xmm6, xmm0);
 357         masm.addsd(xmm0, xmm4);
 358         masm.mulsd(xmm0, xmm3);
 359         masm.pextrw(rcx, xmm0, 3);
 360         masm.andl(rcx, 32752);
 361         masm.cmpl(rcx, 0);
 362         masm.jcc(ConditionFlag.Equal, block5);
 363         masm.jmp(block13);
 364 
 365         masm.bind(block5);
 366         masm.mulsd(xmm6, xmm3);
 367         masm.mulsd(xmm4, xmm3);
 368         masm.movdqu(xmm0, xmm6);
 369         masm.pxor(xmm6, xmm4);
 370         masm.psrad(xmm6, 31);
 371         masm.pshufd(xmm6, xmm6, 85);
 372         masm.psllq(xmm0, 1);
 373         masm.psrlq(xmm0, 1);
 374         masm.pxor(xmm0, xmm6);
 375         masm.psrlq(xmm6, 63);
 376         masm.paddq(xmm0, xmm6);
 377         masm.paddq(xmm0, xmm4);
 378         masm.movl(new AMD64Address(rsp, 0), 15);
 379         masm.jmp(block6);
 380 
 381         masm.bind(block4);
 382         masm.addsd(xmm0, xmm4);
 383         masm.mulsd(xmm0, xmm3);
 384         masm.jmp(block13);
 385 
 386         masm.bind(block3);
 387         masm.addsd(xmm0, xmm4);
 388         masm.mulsd(xmm0, xmm3);
 389         masm.pextrw(rcx, xmm0, 3);
 390         masm.andl(rcx, 32752);
 391         masm.cmpl(rcx, 32752);
 392         masm.jcc(ConditionFlag.AboveEqual, block7);
 393         masm.jmp(block13);
 394 
 395         masm.bind(block2);
 396         masm.paddd(xmm3, xmm6);
 397         masm.addpd(xmm0, xmm2);
 398         masm.mulsd(xmm0, xmm3);
 399         masm.movl(new AMD64Address(rsp, 0), 15);
 400         masm.jmp(block6);
 401 
 402         masm.bind(block8);
 403         masm.cmpl(rax, 2146435072);
 404         masm.jcc(ConditionFlag.AboveEqual, block9);
 405         masm.movl(rax, new AMD64Address(rsp, 12));
 406         masm.cmpl(rax, Integer.MIN_VALUE);
 407         masm.jcc(ConditionFlag.AboveEqual, block10);
 408         masm.movsd(xmm0, recordExternalAddress(crb, xmax));            // 0xffffffff, 0x7fefffff
 409         masm.mulsd(xmm0, xmm0);
 410 
 411         masm.bind(block7);
 412         masm.movl(new AMD64Address(rsp, 0), 14);
 413         masm.jmp(block6);
 414 
 415         masm.bind(block10);
 416         masm.movsd(xmm0, recordExternalAddress(crb, xmin));            // 0x00000000, 0x00100000
 417         masm.mulsd(xmm0, xmm0);
 418         masm.movl(new AMD64Address(rsp, 0), 15);
 419         masm.jmp(block6);
 420 
 421         masm.bind(block9);
 422         masm.movl(rdx, new AMD64Address(rsp, 8));
 423         masm.cmpl(rax, 2146435072);
 424         masm.jcc(ConditionFlag.Above, block11);
 425         masm.cmpl(rdx, 0);
 426         masm.jcc(ConditionFlag.NotEqual, block11);
 427         masm.movl(rax, new AMD64Address(rsp, 12));
 428         masm.cmpl(rax, 2146435072);
 429         masm.jcc(ConditionFlag.NotEqual, block12);
 430         masm.movsd(xmm0, recordExternalAddress(crb, inf));             // 0x00000000, 0x7ff00000
 431         masm.jmp(block13);
 432 
 433         masm.bind(block12);
 434         masm.movsd(xmm0, recordExternalAddress(crb, zero));            // 0x00000000, 0x00000000
 435         masm.jmp(block13);
 436 
 437         masm.bind(block11);
 438         masm.movsd(xmm0, new AMD64Address(rsp, 8));
 439         masm.addsd(xmm0, xmm0);
 440         masm.jmp(block13);
 441 
 442         masm.bind(block0);
 443         masm.movl(rax, new AMD64Address(rsp, 12));
 444         masm.andl(rax, 2147483647);
 445         masm.cmpl(rax, 1083179008);
 446         masm.jcc(ConditionFlag.AboveEqual, block8);
 447         masm.movsd(new AMD64Address(rsp, 8), xmm0);
 448         masm.addsd(xmm0, recordExternalAddress(crb, oneVal));          // 0x00000000, 0x3ff00000
 449         masm.jmp(block13);
 450 
 451         masm.bind(block6);
 452         masm.movq(new AMD64Address(rsp, 16), xmm0);
 453 
 454         masm.movq(xmm0, new AMD64Address(rsp, 16));
 455 
 456         masm.bind(block13);
 457         masm.addq(rsp, 24);
 458     }
 459 }