js/src/jit/shared/MacroAssembler-x86-shared.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "jit/shared/MacroAssembler-x86-shared.h"
     9 #include "jit/IonFrames.h"
    10 #include "jit/IonMacroAssembler.h"
    12 using namespace js;
    13 using namespace js::jit;
    15 void
    16 MacroAssembler::PushRegsInMask(RegisterSet set)
    17 {
    18     int32_t diffF = set.fpus().size() * sizeof(double);
    19     int32_t diffG = set.gprs().size() * sizeof(intptr_t);
    21     // On x86, always use push to push the integer registers, as it's fast
    22     // on modern hardware and it's a small instruction.
    23     for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
    24         diffG -= sizeof(intptr_t);
    25         Push(*iter);
    26     }
    27     JS_ASSERT(diffG == 0);
    29     reserveStack(diffF);
    30     for (FloatRegisterBackwardIterator iter(set.fpus()); iter.more(); iter++) {
    31         diffF -= sizeof(double);
    32         storeDouble(*iter, Address(StackPointer, diffF));
    33     }
    34     JS_ASSERT(diffF == 0);
    35 }
    37 void
    38 MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
    39 {
    40     int32_t diffG = set.gprs().size() * sizeof(intptr_t);
    41     int32_t diffF = set.fpus().size() * sizeof(double);
    42     const int32_t reservedG = diffG;
    43     const int32_t reservedF = diffF;
    45     for (FloatRegisterBackwardIterator iter(set.fpus()); iter.more(); iter++) {
    46         diffF -= sizeof(double);
    47         if (!ignore.has(*iter))
    48             loadDouble(Address(StackPointer, diffF), *iter);
    49     }
    50     freeStack(reservedF);
    51     JS_ASSERT(diffF == 0);
    53     // On x86, use pop to pop the integer registers, if we're not going to
    54     // ignore any slots, as it's fast on modern hardware and it's a small
    55     // instruction.
    56     if (ignore.empty(false)) {
    57         for (GeneralRegisterForwardIterator iter(set.gprs()); iter.more(); iter++) {
    58             diffG -= sizeof(intptr_t);
    59             Pop(*iter);
    60         }
    61     } else {
    62         for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
    63             diffG -= sizeof(intptr_t);
    64             if (!ignore.has(*iter))
    65                 loadPtr(Address(StackPointer, diffG), *iter);
    66         }
    67         freeStack(reservedG);
    68     }
    69     JS_ASSERT(diffG == 0);
    70 }
    72 // Note: this function clobbers the input register.
    73 void
    74 MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
    75 {
    76     JS_ASSERT(input != ScratchFloatReg);
    77     Label positive, done;
    79     // <= 0 or NaN --> 0
    80     zeroDouble(ScratchFloatReg);
    81     branchDouble(DoubleGreaterThan, input, ScratchFloatReg, &positive);
    82     {
    83         move32(Imm32(0), output);
    84         jump(&done);
    85     }
    87     bind(&positive);
    89     // Add 0.5 and truncate.
    90     loadConstantDouble(0.5, ScratchFloatReg);
    91     addDouble(ScratchFloatReg, input);
    93     Label outOfRange;
    95     // Truncate to int32 and ensure the result <= 255. This relies on the
    96     // processor setting output to a value > 255 for doubles outside the int32
    97     // range (for instance 0x80000000).
    98     cvttsd2si(input, output);
    99     branch32(Assembler::Above, output, Imm32(255), &outOfRange);
   100     {
   101         // Check if we had a tie.
   102         convertInt32ToDouble(output, ScratchFloatReg);
   103         branchDouble(DoubleNotEqual, input, ScratchFloatReg, &done);
   105         // It was a tie. Mask out the ones bit to get an even value.
   106         // See also js_TypedArray_uint8_clamp_double.
   107         and32(Imm32(~1), output);
   108         jump(&done);
   109     }
   111     // > 255 --> 255
   112     bind(&outOfRange);
   113     {
   114         move32(Imm32(255), output);
   115     }
   117     bind(&done);
   118 }
   120 // Builds an exit frame on the stack, with a return address to an internal
   121 // non-function. Returns offset to be passed to markSafepointAt().
   122 bool
   123 MacroAssemblerX86Shared::buildFakeExitFrame(const Register &scratch, uint32_t *offset)
   124 {
   125     mozilla::DebugOnly<uint32_t> initialDepth = framePushed();
   127     CodeLabel cl;
   128     mov(cl.dest(), scratch);
   130     uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS);
   131     Push(Imm32(descriptor));
   132     Push(scratch);
   134     bind(cl.src());
   135     *offset = currentOffset();
   137     JS_ASSERT(framePushed() == initialDepth + IonExitFrameLayout::Size());
   138     return addCodeLabel(cl);
   139 }
   141 void
   142 MacroAssemblerX86Shared::callWithExitFrame(JitCode *target)
   143 {
   144     uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS);
   145     Push(Imm32(descriptor));
   146     call(target);
   147 }
   149 bool
   150 MacroAssemblerX86Shared::buildOOLFakeExitFrame(void *fakeReturnAddr)
   151 {
   152     uint32_t descriptor = MakeFrameDescriptor(framePushed(), JitFrame_IonJS);
   153     Push(Imm32(descriptor));
   154     Push(ImmPtr(fakeReturnAddr));
   155     return true;
   156 }
   158 void
   159 MacroAssemblerX86Shared::branchNegativeZero(const FloatRegister &reg,
   160                                             const Register &scratch,
   161                                             Label *label)
   162 {
   163     // Determines whether the low double contained in the XMM register reg
   164     // is equal to -0.0.
   166 #if defined(JS_CODEGEN_X86)
   167     Label nonZero;
   169     // Compare to zero. Lets through {0, -0}.
   170     xorpd(ScratchFloatReg, ScratchFloatReg);
   172     // If reg is non-zero, jump to nonZero.
   173     branchDouble(DoubleNotEqual, reg, ScratchFloatReg, &nonZero);
   175     // Input register is either zero or negative zero. Retrieve sign of input.
   176     movmskpd(reg, scratch);
   178     // If reg is 1 or 3, input is negative zero.
   179     // If reg is 0 or 2, input is a normal zero.
   180     branchTest32(NonZero, scratch, Imm32(1), label);
   182     bind(&nonZero);
   183 #elif defined(JS_CODEGEN_X64)
   184     movq(reg, scratch);
   185     cmpq(scratch, Imm32(1));
   186     j(Overflow, label);
   187 #endif
   188 }
   190 void
   191 MacroAssemblerX86Shared::branchNegativeZeroFloat32(const FloatRegister &reg,
   192                                                    const Register &scratch,
   193                                                    Label *label)
   194 {
   195     movd(reg, scratch);
   196     cmpl(scratch, Imm32(1));
   197     j(Overflow, label);
   198 }

mercurial