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.

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

mercurial