tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MacroAssembler-x86.h (45502B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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/. */
      6 
      7 #ifndef jit_x86_MacroAssembler_x86_h
      8 #define jit_x86_MacroAssembler_x86_h
      9 
     10 #include "jit/JitOptions.h"
     11 #include "jit/MoveResolver.h"
     12 #include "jit/x86-shared/MacroAssembler-x86-shared.h"
     13 #include "js/HeapAPI.h"
     14 #include "wasm/WasmBuiltins.h"
     15 #include "wasm/WasmCodegenTypes.h"
     16 
     17 using js::wasm::FaultingCodeOffsetPair;
     18 
     19 namespace js {
     20 namespace jit {
     21 
     22 // See documentation for ScratchTagScope and ScratchTagScopeRelease in
     23 // MacroAssembler-x64.h.
     24 
     25 class ScratchTagScope {
     26  const ValueOperand& v_;
     27 
     28 public:
     29  ScratchTagScope(MacroAssembler&, const ValueOperand& v) : v_(v) {}
     30  operator Register() { return v_.typeReg(); }
     31  void release() {}
     32  void reacquire() {}
     33 };
     34 
     35 class ScratchTagScopeRelease {
     36 public:
     37  explicit ScratchTagScopeRelease(ScratchTagScope*) {}
     38 };
     39 
     40 class MacroAssemblerX86 : public MacroAssemblerX86Shared {
     41 private:
     42  // Perform a downcast. Should be removed by Bug 996602.
     43  MacroAssembler& asMasm();
     44  const MacroAssembler& asMasm() const;
     45 
     46 protected:
     47  MoveResolver moveResolver_;
     48 
     49 private:
     50  Operand payloadOfAfterStackPush(const Address& address) {
     51    // If we are basing off %esp, the address will be invalid after the
     52    // first push.
     53    if (address.base == StackPointer) {
     54      return Operand(address.base, address.offset + 4);
     55    }
     56    return payloadOf(address);
     57  }
     58  Operand payloadOfAfterStackPush(const BaseIndex& address) {
     59    // If we are basing off %esp, the address will be invalid after the
     60    // first push.
     61    if (address.base == StackPointer) {
     62      return Operand(address.base, address.index, address.scale,
     63                     address.offset + 4);
     64    }
     65    return payloadOf(address);
     66  }
     67  Operand payloadOf(const Address& address) {
     68    return Operand(address.base, address.offset);
     69  }
     70  Operand payloadOf(const BaseIndex& address) {
     71    return Operand(address.base, address.index, address.scale, address.offset);
     72  }
     73  Operand tagOf(const Address& address) {
     74    return Operand(address.base, address.offset + 4);
     75  }
     76  Operand tagOf(const BaseIndex& address) {
     77    return Operand(address.base, address.index, address.scale,
     78                   address.offset + 4);
     79  }
     80 
     81  void setupABICall(uint32_t args);
     82 
     83  void vpPatchOpSimd128(const SimdConstant& v, FloatRegister reg,
     84                        void (X86Encoding::BaseAssemblerX86::*op)(
     85                            const void* address,
     86                            X86Encoding::XMMRegisterID srcId,
     87                            X86Encoding::XMMRegisterID destId)) {
     88    vpPatchOpSimd128(v, reg, reg, op);
     89  }
     90 
     91  void vpPatchOpSimd128(const SimdConstant& v, FloatRegister lhs,
     92                        FloatRegister dest,
     93                        void (X86Encoding::BaseAssemblerX86::*op)(
     94                            const void* address,
     95                            X86Encoding::XMMRegisterID srcId,
     96                            X86Encoding::XMMRegisterID destId));
     97 
     98  void vpPatchOpSimd128(const SimdConstant& v, FloatRegister reg,
     99                        size_t (X86Encoding::BaseAssemblerX86::*op)(
    100                            const void* address,
    101                            X86Encoding::XMMRegisterID srcId,
    102                            X86Encoding::XMMRegisterID destId)) {
    103    vpPatchOpSimd128(v, reg, reg, op);
    104  }
    105 
    106  void vpPatchOpSimd128(const SimdConstant& v, FloatRegister lhs,
    107                        FloatRegister dest,
    108                        size_t (X86Encoding::BaseAssemblerX86::*op)(
    109                            const void* address,
    110                            X86Encoding::XMMRegisterID srcId,
    111                            X86Encoding::XMMRegisterID destId));
    112 
    113 public:
    114  using MacroAssemblerX86Shared::call;
    115  using MacroAssemblerX86Shared::load32;
    116  using MacroAssemblerX86Shared::store16;
    117  using MacroAssemblerX86Shared::store32;
    118 
    119  MacroAssemblerX86() {}
    120 
    121  // The buffer is about to be linked, make sure any constant pools or excess
    122  // bookkeeping has been flushed to the instruction stream.
    123  void finish();
    124 
    125  /////////////////////////////////////////////////////////////////
    126  // X86-specific interface.
    127  /////////////////////////////////////////////////////////////////
    128 
    129  Operand ToPayload(Operand base) { return base; }
    130  Address ToPayload(Address base) { return base; }
    131  BaseIndex ToPayload(BaseIndex base) { return base; }
    132  Operand ToType(Operand base) {
    133    switch (base.kind()) {
    134      case Operand::MEM_REG_DISP:
    135        return Operand(Register::FromCode(base.base()),
    136                       base.disp() + sizeof(void*));
    137 
    138      case Operand::MEM_SCALE:
    139        return Operand(Register::FromCode(base.base()),
    140                       Register::FromCode(base.index()), base.scale(),
    141                       base.disp() + sizeof(void*));
    142 
    143      default:
    144        MOZ_CRASH("unexpected operand kind");
    145    }
    146  }
    147  Address ToType(Address base) { return ToType(Operand(base)).toAddress(); }
    148  BaseIndex ToType(BaseIndex base) {
    149    return ToType(Operand(base)).toBaseIndex();
    150  }
    151 
    152  template <typename T>
    153  void add64FromMemory(const T& address, Register64 dest) {
    154    addl(Operand(LowWord(address)), dest.low);
    155    adcl(Operand(HighWord(address)), dest.high);
    156  }
    157  template <typename T>
    158  void sub64FromMemory(const T& address, Register64 dest) {
    159    subl(Operand(LowWord(address)), dest.low);
    160    sbbl(Operand(HighWord(address)), dest.high);
    161  }
    162  template <typename T>
    163  void and64FromMemory(const T& address, Register64 dest) {
    164    andl(Operand(LowWord(address)), dest.low);
    165    andl(Operand(HighWord(address)), dest.high);
    166  }
    167  template <typename T>
    168  void or64FromMemory(const T& address, Register64 dest) {
    169    orl(Operand(LowWord(address)), dest.low);
    170    orl(Operand(HighWord(address)), dest.high);
    171  }
    172  template <typename T>
    173  void xor64FromMemory(const T& address, Register64 dest) {
    174    xorl(Operand(LowWord(address)), dest.low);
    175    xorl(Operand(HighWord(address)), dest.high);
    176  }
    177 
    178  template <typename T1, typename T2>
    179  inline void cmp64SetAliased(Condition cond, T1 lhs, T2 rhs, Register dest);
    180 
    181  template <typename T1, typename T2>
    182  inline void cmp64SetNonAliased(Condition cond, T1 lhs, T2 rhs, Register dest);
    183 
    184  template <typename T1, typename T2>
    185  inline void branch64Impl(Condition cond, T1 lhs, T2 rhs, Label* success,
    186                           Label* fail);
    187 
    188  /////////////////////////////////////////////////////////////////
    189  // X86/X64-common interface.
    190  /////////////////////////////////////////////////////////////////
    191  void storeValue(ValueOperand val, Operand dest) {
    192    movl(val.payloadReg(), ToPayload(dest));
    193    movl(val.typeReg(), ToType(dest));
    194  }
    195  void storeValue(ValueOperand val, const Address& dest) {
    196    storeValue(val, Operand(dest));
    197  }
    198  template <typename T>
    199  void storeValue(JSValueType type, Register reg, const T& dest) {
    200    storeTypeTag(ImmTag(JSVAL_TYPE_TO_TAG(type)), Operand(dest));
    201    storePayload(reg, Operand(dest));
    202  }
    203  template <typename T>
    204  void storeValue(const Value& val, const T& dest) {
    205    storeTypeTag(ImmTag(val.toNunboxTag()), Operand(dest));
    206    storePayload(val, Operand(dest));
    207  }
    208  void storeValue(ValueOperand val, BaseIndex dest) {
    209    storeValue(val, Operand(dest));
    210  }
    211  void storeValue(const Address& src, const Address& dest, Register temp) {
    212    MOZ_ASSERT(src.base != temp);
    213    MOZ_ASSERT(dest.base != temp);
    214 
    215    load32(ToType(src), temp);
    216    store32(temp, ToType(dest));
    217 
    218    load32(ToPayload(src), temp);
    219    store32(temp, ToPayload(dest));
    220  }
    221  void storePrivateValue(Register src, const Address& dest) {
    222    store32(Imm32(0), ToType(dest));
    223    store32(src, ToPayload(dest));
    224  }
    225  void storePrivateValue(ImmGCPtr imm, const Address& dest) {
    226    store32(Imm32(0), ToType(dest));
    227    movl(imm, Operand(ToPayload(dest)));
    228  }
    229  void loadValue(Operand src, ValueOperand val) {
    230    Operand payload = ToPayload(src);
    231    Operand type = ToType(src);
    232 
    233    // Ensure that loading the payload does not erase the pointer to the
    234    // Value in memory or the index.
    235    Register baseReg = Register::FromCode(src.base());
    236    Register indexReg = (src.kind() == Operand::MEM_SCALE)
    237                            ? Register::FromCode(src.index())
    238                            : InvalidReg;
    239 
    240    // If we have a BaseIndex that uses both result registers, first compute
    241    // the address and then load the Value from there.
    242    if ((baseReg == val.payloadReg() && indexReg == val.typeReg()) ||
    243        (baseReg == val.typeReg() && indexReg == val.payloadReg())) {
    244      computeEffectiveAddress(src, val.scratchReg());
    245      loadValue(Address(val.scratchReg(), 0), val);
    246      return;
    247    }
    248 
    249    if (baseReg == val.payloadReg() || indexReg == val.payloadReg()) {
    250      MOZ_ASSERT(baseReg != val.typeReg());
    251      MOZ_ASSERT(indexReg != val.typeReg());
    252 
    253      movl(type, val.typeReg());
    254      movl(payload, val.payloadReg());
    255    } else {
    256      MOZ_ASSERT(baseReg != val.payloadReg());
    257      MOZ_ASSERT(indexReg != val.payloadReg());
    258 
    259      movl(payload, val.payloadReg());
    260      movl(type, val.typeReg());
    261    }
    262  }
    263  void loadValue(Address src, ValueOperand val) {
    264    loadValue(Operand(src), val);
    265  }
    266  void loadValue(const BaseIndex& src, ValueOperand val) {
    267    loadValue(Operand(src), val);
    268  }
    269  void loadUnalignedValue(const Address& src, ValueOperand dest) {
    270    loadValue(src, dest);
    271  }
    272  void tagValue(JSValueType type, Register payload, ValueOperand dest) {
    273    boxNonDouble(type, payload, dest);
    274  }
    275  void pushValue(ValueOperand val) {
    276    push(val.typeReg());
    277    push(val.payloadReg());
    278  }
    279  void popValue(ValueOperand val) {
    280    pop(val.payloadReg());
    281    pop(val.typeReg());
    282  }
    283  void pushValue(const Value& val) {
    284    push(Imm32(val.toNunboxTag()));
    285    if (val.isGCThing()) {
    286      push(ImmGCPtr(val.toGCThing()));
    287    } else {
    288      push(Imm32(val.toNunboxPayload()));
    289    }
    290  }
    291  void pushValue(JSValueType type, Register reg) {
    292    push(ImmTag(JSVAL_TYPE_TO_TAG(type)));
    293    push(reg);
    294  }
    295  void pushValue(const Address& addr) {
    296    push(tagOf(addr));
    297    push(payloadOfAfterStackPush(addr));
    298  }
    299  void pushValue(const BaseIndex& addr, Register scratch) {
    300    push(tagOf(addr));
    301    push(payloadOfAfterStackPush(addr));
    302  }
    303  void push64(Register64 src) {
    304    push(src.high);
    305    push(src.low);
    306  }
    307  void pop64(Register64 dest) {
    308    pop(dest.low);
    309    pop(dest.high);
    310  }
    311  void storePayload(const Value& val, Operand dest) {
    312    if (val.isGCThing()) {
    313      movl(ImmGCPtr(val.toGCThing()), ToPayload(dest));
    314    } else {
    315      movl(Imm32(val.toNunboxPayload()), ToPayload(dest));
    316    }
    317  }
    318  void storePayload(Register src, Operand dest) { movl(src, ToPayload(dest)); }
    319  void storeTypeTag(ImmTag tag, Operand dest) { movl(tag, ToType(dest)); }
    320 
    321  void movePtr(Register src, Register dest) { movl(src, dest); }
    322  void movePtr(Register src, const Operand& dest) { movl(src, dest); }
    323 
    324  void splitTagForTest(const ValueOperand& value, ScratchTagScope& tag) {
    325    MOZ_ASSERT(value.typeReg() == tag);
    326  }
    327 
    328  Condition testUndefined(Condition cond, Register tag) {
    329    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    330    cmp32(tag, ImmTag(JSVAL_TAG_UNDEFINED));
    331    return cond;
    332  }
    333  Condition testBoolean(Condition cond, Register tag) {
    334    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    335    cmp32(tag, ImmTag(JSVAL_TAG_BOOLEAN));
    336    return cond;
    337  }
    338  Condition testInt32(Condition cond, Register tag) {
    339    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    340    cmp32(tag, ImmTag(JSVAL_TAG_INT32));
    341    return cond;
    342  }
    343  Condition testDouble(Condition cond, Register tag) {
    344    MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    345    Condition actual = (cond == Equal) ? Below : AboveOrEqual;
    346    cmp32(tag, ImmTag(JSVAL_TAG_CLEAR));
    347    return actual;
    348  }
    349  Condition testNull(Condition cond, Register tag) {
    350    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    351    cmp32(tag, ImmTag(JSVAL_TAG_NULL));
    352    return cond;
    353  }
    354  Condition testString(Condition cond, Register tag) {
    355    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    356    cmp32(tag, ImmTag(JSVAL_TAG_STRING));
    357    return cond;
    358  }
    359  Condition testSymbol(Condition cond, Register tag) {
    360    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    361    cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL));
    362    return cond;
    363  }
    364  Condition testBigInt(Condition cond, Register tag) {
    365    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    366    cmp32(tag, ImmTag(JSVAL_TAG_BIGINT));
    367    return cond;
    368  }
    369  Condition testObject(Condition cond, Register tag) {
    370    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    371    cmp32(tag, ImmTag(JSVAL_TAG_OBJECT));
    372    return cond;
    373  }
    374  Condition testNumber(Condition cond, Register tag) {
    375    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    376    cmp32(tag, ImmTag(JS::detail::ValueUpperInclNumberTag));
    377    return cond == Equal ? BelowOrEqual : Above;
    378  }
    379  Condition testGCThing(Condition cond, Register tag) {
    380    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    381    cmp32(tag, ImmTag(JS::detail::ValueLowerInclGCThingTag));
    382    return cond == Equal ? AboveOrEqual : Below;
    383  }
    384  Condition testGCThing(Condition cond, const Address& address) {
    385    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    386    cmp32(tagOf(address), ImmTag(JS::detail::ValueLowerInclGCThingTag));
    387    return cond == Equal ? AboveOrEqual : Below;
    388  }
    389  Condition testMagic(Condition cond, const Address& address) {
    390    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    391    cmp32(tagOf(address), ImmTag(JSVAL_TAG_MAGIC));
    392    return cond;
    393  }
    394  Condition testMagic(Condition cond, Register tag) {
    395    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    396    cmp32(tag, ImmTag(JSVAL_TAG_MAGIC));
    397    return cond;
    398  }
    399  Condition testMagic(Condition cond, const Operand& operand) {
    400    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    401    cmp32(ToType(operand), ImmTag(JSVAL_TAG_MAGIC));
    402    return cond;
    403  }
    404  Condition testPrimitive(Condition cond, Register tag) {
    405    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    406    cmp32(tag, ImmTag(JS::detail::ValueUpperExclPrimitiveTag));
    407    return cond == Equal ? Below : AboveOrEqual;
    408  }
    409  Condition testError(Condition cond, Register tag) {
    410    return testMagic(cond, tag);
    411  }
    412  Condition testBoolean(Condition cond, const Address& address) {
    413    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    414    cmp32(Operand(ToType(address)), ImmTag(JSVAL_TAG_BOOLEAN));
    415    return cond;
    416  }
    417  Condition testInt32(Condition cond, const Operand& operand) {
    418    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    419    cmp32(ToType(operand), ImmTag(JSVAL_TAG_INT32));
    420    return cond;
    421  }
    422  Condition testInt32(Condition cond, const Address& address) {
    423    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    424    return testInt32(cond, Operand(address));
    425  }
    426  Condition testObject(Condition cond, const Operand& operand) {
    427    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    428    cmp32(ToType(operand), ImmTag(JSVAL_TAG_OBJECT));
    429    return cond;
    430  }
    431  Condition testObject(Condition cond, const Address& address) {
    432    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    433    return testObject(cond, Operand(address));
    434  }
    435  Condition testDouble(Condition cond, const Operand& operand) {
    436    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    437    Condition actual = (cond == Equal) ? Below : AboveOrEqual;
    438    cmp32(ToType(operand), ImmTag(JSVAL_TAG_CLEAR));
    439    return actual;
    440  }
    441  Condition testDouble(Condition cond, const Address& address) {
    442    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    443    return testDouble(cond, Operand(address));
    444  }
    445 
    446  Condition testUndefined(Condition cond, const Operand& operand) {
    447    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    448    cmp32(ToType(operand), ImmTag(JSVAL_TAG_UNDEFINED));
    449    return cond;
    450  }
    451  Condition testUndefined(Condition cond, const Address& addr) {
    452    return testUndefined(cond, Operand(addr));
    453  }
    454  Condition testNull(Condition cond, const Operand& operand) {
    455    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    456    cmp32(ToType(operand), ImmTag(JSVAL_TAG_NULL));
    457    return cond;
    458  }
    459  Condition testNull(Condition cond, const Address& addr) {
    460    return testNull(cond, Operand(addr));
    461  }
    462 
    463  Condition testUndefined(Condition cond, const ValueOperand& value) {
    464    return testUndefined(cond, value.typeReg());
    465  }
    466  Condition testBoolean(Condition cond, const ValueOperand& value) {
    467    return testBoolean(cond, value.typeReg());
    468  }
    469  Condition testInt32(Condition cond, const ValueOperand& value) {
    470    return testInt32(cond, value.typeReg());
    471  }
    472  Condition testDouble(Condition cond, const ValueOperand& value) {
    473    return testDouble(cond, value.typeReg());
    474  }
    475  Condition testNull(Condition cond, const ValueOperand& value) {
    476    return testNull(cond, value.typeReg());
    477  }
    478  Condition testString(Condition cond, const ValueOperand& value) {
    479    return testString(cond, value.typeReg());
    480  }
    481  Condition testSymbol(Condition cond, const ValueOperand& value) {
    482    return testSymbol(cond, value.typeReg());
    483  }
    484  Condition testBigInt(Condition cond, const ValueOperand& value) {
    485    return testBigInt(cond, value.typeReg());
    486  }
    487  Condition testObject(Condition cond, const ValueOperand& value) {
    488    return testObject(cond, value.typeReg());
    489  }
    490  Condition testMagic(Condition cond, const ValueOperand& value) {
    491    return testMagic(cond, value.typeReg());
    492  }
    493  Condition testError(Condition cond, const ValueOperand& value) {
    494    return testMagic(cond, value);
    495  }
    496  Condition testNumber(Condition cond, const ValueOperand& value) {
    497    return testNumber(cond, value.typeReg());
    498  }
    499  Condition testGCThing(Condition cond, const ValueOperand& value) {
    500    return testGCThing(cond, value.typeReg());
    501  }
    502  Condition testPrimitive(Condition cond, const ValueOperand& value) {
    503    return testPrimitive(cond, value.typeReg());
    504  }
    505 
    506  Condition testUndefined(Condition cond, const BaseIndex& address) {
    507    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    508    cmp32(tagOf(address), ImmTag(JSVAL_TAG_UNDEFINED));
    509    return cond;
    510  }
    511  Condition testNull(Condition cond, const BaseIndex& address) {
    512    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    513    cmp32(tagOf(address), ImmTag(JSVAL_TAG_NULL));
    514    return cond;
    515  }
    516  Condition testBoolean(Condition cond, const BaseIndex& address) {
    517    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    518    cmp32(tagOf(address), ImmTag(JSVAL_TAG_BOOLEAN));
    519    return cond;
    520  }
    521  Condition testString(Condition cond, const Address& address) {
    522    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    523    cmp32(tagOf(address), ImmTag(JSVAL_TAG_STRING));
    524    return cond;
    525  }
    526  Condition testString(Condition cond, const BaseIndex& address) {
    527    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    528    cmp32(tagOf(address), ImmTag(JSVAL_TAG_STRING));
    529    return cond;
    530  }
    531  Condition testSymbol(Condition cond, const Address& address) {
    532    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    533    cmp32(tagOf(address), ImmTag(JSVAL_TAG_SYMBOL));
    534    return cond;
    535  }
    536  Condition testSymbol(Condition cond, const BaseIndex& address) {
    537    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    538    cmp32(tagOf(address), ImmTag(JSVAL_TAG_SYMBOL));
    539    return cond;
    540  }
    541  Condition testBigInt(Condition cond, const Address& address) {
    542    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    543    cmp32(tagOf(address), ImmTag(JSVAL_TAG_BIGINT));
    544    return cond;
    545  }
    546  Condition testBigInt(Condition cond, const BaseIndex& address) {
    547    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    548    cmp32(tagOf(address), ImmTag(JSVAL_TAG_BIGINT));
    549    return cond;
    550  }
    551  Condition testInt32(Condition cond, const BaseIndex& address) {
    552    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    553    cmp32(tagOf(address), ImmTag(JSVAL_TAG_INT32));
    554    return cond;
    555  }
    556  Condition testObject(Condition cond, const BaseIndex& address) {
    557    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    558    cmp32(tagOf(address), ImmTag(JSVAL_TAG_OBJECT));
    559    return cond;
    560  }
    561  Condition testDouble(Condition cond, const BaseIndex& address) {
    562    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    563    Condition actual = (cond == Equal) ? Below : AboveOrEqual;
    564    cmp32(tagOf(address), ImmTag(JSVAL_TAG_CLEAR));
    565    return actual;
    566  }
    567  Condition testMagic(Condition cond, const BaseIndex& address) {
    568    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    569    cmp32(tagOf(address), ImmTag(JSVAL_TAG_MAGIC));
    570    return cond;
    571  }
    572  Condition testGCThing(Condition cond, const BaseIndex& address) {
    573    MOZ_ASSERT(cond == Equal || cond == NotEqual);
    574    cmp32(tagOf(address), ImmTag(JS::detail::ValueLowerInclGCThingTag));
    575    return cond == Equal ? AboveOrEqual : Below;
    576  }
    577 
    578  void testNullSet(Condition cond, const ValueOperand& value, Register dest) {
    579    bool destIsZero = maybeEmitSetZeroByteRegister(value, dest);
    580    cond = testNull(cond, value);
    581    emitSet(cond, dest, destIsZero);
    582  }
    583 
    584  void testObjectSet(Condition cond, const ValueOperand& value, Register dest) {
    585    bool destIsZero = maybeEmitSetZeroByteRegister(value, dest);
    586    cond = testObject(cond, value);
    587    emitSet(cond, dest, destIsZero);
    588  }
    589 
    590  void testUndefinedSet(Condition cond, const ValueOperand& value,
    591                        Register dest) {
    592    bool destIsZero = maybeEmitSetZeroByteRegister(value, dest);
    593    cond = testUndefined(cond, value);
    594    emitSet(cond, dest, destIsZero);
    595  }
    596 
    597  void cmpPtr(Register lhs, const Imm32 rhs) { cmpl(rhs, lhs); }
    598  void cmpPtr(Register lhs, const ImmWord rhs) { cmpl(Imm32(rhs.value), lhs); }
    599  void cmpPtr(Register lhs, const ImmPtr imm) {
    600    cmpPtr(lhs, ImmWord(uintptr_t(imm.value)));
    601  }
    602  void cmpPtr(Register lhs, const ImmGCPtr rhs) { cmpl(rhs, lhs); }
    603  void cmpPtr(const Operand& lhs, Imm32 rhs) { cmp32(lhs, rhs); }
    604  void cmpPtr(const Operand& lhs, const ImmWord rhs) {
    605    cmp32(lhs, Imm32(rhs.value));
    606  }
    607  void cmpPtr(const Operand& lhs, const ImmPtr imm) {
    608    cmpPtr(lhs, ImmWord(uintptr_t(imm.value)));
    609  }
    610  void cmpPtr(const Operand& lhs, const ImmGCPtr rhs) { cmpl(rhs, lhs); }
    611  void cmpPtr(const Address& lhs, Register rhs) { cmpPtr(Operand(lhs), rhs); }
    612  void cmpPtr(const Operand& lhs, Register rhs) { cmp32(lhs, rhs); }
    613  void cmpPtr(const Address& lhs, const ImmWord rhs) {
    614    cmpPtr(Operand(lhs), rhs);
    615  }
    616  void cmpPtr(const Address& lhs, const ImmPtr rhs) {
    617    cmpPtr(lhs, ImmWord(uintptr_t(rhs.value)));
    618  }
    619  void cmpPtr(const Address& lhs, const ImmGCPtr rhs) {
    620    cmpPtr(Operand(lhs), rhs);
    621  }
    622  void cmpPtr(Register lhs, Register rhs) { cmp32(lhs, rhs); }
    623  void testPtr(Register lhs, Register rhs) { test32(lhs, rhs); }
    624  void testPtr(Register lhs, Imm32 rhs) { test32(lhs, rhs); }
    625  void testPtr(Register lhs, ImmWord rhs) { test32(lhs, Imm32(rhs.value)); }
    626  void testPtr(const Operand& lhs, Imm32 rhs) { test32(lhs, rhs); }
    627  void testPtr(const Operand& lhs, ImmWord rhs) {
    628    test32(lhs, Imm32(rhs.value));
    629  }
    630 
    631  /////////////////////////////////////////////////////////////////
    632  // Common interface.
    633  /////////////////////////////////////////////////////////////////
    634 
    635  void movePtr(ImmWord imm, Register dest) { movl(Imm32(imm.value), dest); }
    636  void movePtr(ImmPtr imm, Register dest) { movl(imm, dest); }
    637  void movePtr(wasm::SymbolicAddress imm, Register dest) { mov(imm, dest); }
    638  void movePtr(ImmGCPtr imm, Register dest) { movl(imm, dest); }
    639  FaultingCodeOffset loadPtr(const Address& address, Register dest) {
    640    FaultingCodeOffset fco = FaultingCodeOffset(currentOffset());
    641    movl(Operand(address), dest);
    642    return fco;
    643  }
    644  void loadPtr(const Operand& src, Register dest) { movl(src, dest); }
    645  FaultingCodeOffset loadPtr(const BaseIndex& src, Register dest) {
    646    FaultingCodeOffset fco = FaultingCodeOffset(currentOffset());
    647    movl(Operand(src), dest);
    648    return fco;
    649  }
    650  void loadPtr(AbsoluteAddress address, Register dest) {
    651    movl(Operand(address), dest);
    652  }
    653  void loadPrivate(const Address& src, Register dest) {
    654    movl(payloadOf(src), dest);
    655  }
    656  void load32(AbsoluteAddress address, Register dest) {
    657    movl(Operand(address), dest);
    658  }
    659  FaultingCodeOffsetPair load64(const Address& address, Register64 dest) {
    660    FaultingCodeOffset fco1, fco2;
    661    bool highBeforeLow = address.base == dest.low;
    662    if (highBeforeLow) {
    663      fco1 = FaultingCodeOffset(currentOffset());
    664      movl(Operand(HighWord(address)), dest.high);
    665      fco2 = FaultingCodeOffset(currentOffset());
    666      movl(Operand(LowWord(address)), dest.low);
    667    } else {
    668      fco1 = FaultingCodeOffset(currentOffset());
    669      movl(Operand(LowWord(address)), dest.low);
    670      fco2 = FaultingCodeOffset(currentOffset());
    671      movl(Operand(HighWord(address)), dest.high);
    672    }
    673    return FaultingCodeOffsetPair(fco1, fco2);
    674  }
    675  FaultingCodeOffsetPair load64(const BaseIndex& address, Register64 dest) {
    676    // If you run into this, relax your register allocation constraints.
    677    MOZ_RELEASE_ASSERT(
    678        !((address.base == dest.low || address.base == dest.high) &&
    679          (address.index == dest.low || address.index == dest.high)));
    680    FaultingCodeOffset fco1, fco2;
    681    bool highBeforeLow = address.base == dest.low || address.index == dest.low;
    682    if (highBeforeLow) {
    683      fco1 = FaultingCodeOffset(currentOffset());
    684      movl(Operand(HighWord(address)), dest.high);
    685      fco2 = FaultingCodeOffset(currentOffset());
    686      movl(Operand(LowWord(address)), dest.low);
    687    } else {
    688      fco1 = FaultingCodeOffset(currentOffset());
    689      movl(Operand(LowWord(address)), dest.low);
    690      fco2 = FaultingCodeOffset(currentOffset());
    691      movl(Operand(HighWord(address)), dest.high);
    692    }
    693    return FaultingCodeOffsetPair(fco1, fco2);
    694  }
    695  template <typename T>
    696  void load64Unaligned(const T& address, Register64 dest) {
    697    load64(address, dest);
    698  }
    699  template <typename T>
    700  void storePtr(ImmWord imm, T address) {
    701    movl(Imm32(imm.value), Operand(address));
    702  }
    703  template <typename T>
    704  void storePtr(ImmPtr imm, T address) {
    705    storePtr(ImmWord(uintptr_t(imm.value)), address);
    706  }
    707  template <typename T>
    708  void storePtr(ImmGCPtr imm, T address) {
    709    movl(imm, Operand(address));
    710  }
    711  FaultingCodeOffset storePtr(Register src, const Address& address) {
    712    FaultingCodeOffset fco = FaultingCodeOffset(currentOffset());
    713    movl(src, Operand(address));
    714    return fco;
    715  }
    716  FaultingCodeOffset storePtr(Register src, const BaseIndex& address) {
    717    FaultingCodeOffset fco = FaultingCodeOffset(currentOffset());
    718    movl(src, Operand(address));
    719    return fco;
    720  }
    721  void storePtr(Register src, const Operand& dest) { movl(src, dest); }
    722  void storePtr(Register src, AbsoluteAddress address) {
    723    movl(src, Operand(address));
    724  }
    725  void store32(Register src, AbsoluteAddress address) {
    726    movl(src, Operand(address));
    727  }
    728  void store16(Register src, AbsoluteAddress address) {
    729    movw(src, Operand(address));
    730  }
    731  template <typename T>
    732  FaultingCodeOffsetPair store64(Register64 src, const T& address) {
    733    FaultingCodeOffset fco1 = FaultingCodeOffset(currentOffset());
    734    movl(src.low, Operand(LowWord(address)));
    735    FaultingCodeOffset fco2 = FaultingCodeOffset(currentOffset());
    736    movl(src.high, Operand(HighWord(address)));
    737    return FaultingCodeOffsetPair(fco1, fco2);
    738  }
    739  void store64(Imm64 imm, Address address) {
    740    movl(imm.low(), Operand(LowWord(address)));
    741    movl(imm.hi(), Operand(HighWord(address)));
    742  }
    743  void store64(Imm64 imm, const BaseIndex& address) {
    744    movl(imm.low(), Operand(LowWord(address)));
    745    movl(imm.hi(), Operand(HighWord(address)));
    746  }
    747  template <typename S, typename T>
    748  void store64Unaligned(const S& src, const T& dest) {
    749    store64(src, dest);
    750  }
    751 
    752  void setStackArg(Register reg, uint32_t arg) {
    753    movl(reg, Operand(esp, arg * sizeof(intptr_t)));
    754  }
    755 
    756  void boxDouble(FloatRegister src, const ValueOperand& dest,
    757                 FloatRegister temp) {
    758    if (Assembler::HasSSE41()) {
    759      vmovd(src, dest.payloadReg());
    760      vpextrd(1, src, dest.typeReg());
    761    } else {
    762      vmovd(src, dest.payloadReg());
    763      if (src != temp) {
    764        moveDouble(src, temp);
    765      }
    766      vpsrldq(Imm32(4), temp, temp);
    767      vmovd(temp, dest.typeReg());
    768    }
    769  }
    770  void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest);
    771  void boxNonDouble(Register type, Register src, const ValueOperand& dest);
    772 
    773  void unboxNonDouble(const ValueOperand& src, Register dest, JSValueType type,
    774                      Register scratch = InvalidReg) {
    775    unboxNonDouble(Operand(src.typeReg()), Operand(src.payloadReg()), dest,
    776                   type, scratch);
    777  }
    778  void unboxNonDouble(const Operand& tag, const Operand& payload, Register dest,
    779                      JSValueType type, Register scratch = InvalidReg) {
    780    auto movPayloadToDest = [&]() {
    781      if (payload.kind() != Operand::REG || !payload.containsReg(dest)) {
    782        movl(payload, dest);
    783      }
    784    };
    785    if (!JitOptions.spectreValueMasking) {
    786      movPayloadToDest();
    787      return;
    788    }
    789 
    790    // Spectre mitigation: We zero the payload if the tag does not match the
    791    // expected type and if this is a pointer type.
    792    if (type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN) {
    793      movPayloadToDest();
    794      return;
    795    }
    796 
    797    if (!tag.containsReg(dest) && !payload.containsReg(dest)) {
    798      // We zero the destination register and move the payload into it if
    799      // the tag corresponds to the given type.
    800      xorl(dest, dest);
    801      cmpl(Imm32(JSVAL_TYPE_TO_TAG(type)), tag);
    802      cmovCCl(Condition::Equal, payload, dest);
    803      return;
    804    }
    805 
    806    if (scratch == InvalidReg || scratch == dest || tag.containsReg(scratch) ||
    807        payload.containsReg(scratch)) {
    808      // UnboxedLayout::makeConstructorCode calls extractObject with a
    809      // scratch register which aliases the tag register, thus we cannot
    810      // assert the above condition.
    811      scratch = InvalidReg;
    812    }
    813 
    814    // The destination register aliases one of the operands. We create a
    815    // zero value either in a scratch register or on the stack and use it
    816    // to reset the destination register after reading both the tag and the
    817    // payload.
    818    Operand zero(Address(esp, 0));
    819    if (scratch == InvalidReg) {
    820      push(Imm32(0));
    821    } else {
    822      xorl(scratch, scratch);
    823      zero = Operand(scratch);
    824    }
    825    cmpl(Imm32(JSVAL_TYPE_TO_TAG(type)), tag);
    826    movPayloadToDest();
    827    cmovCCl(Condition::NotEqual, zero, dest);
    828    if (scratch == InvalidReg) {
    829      addl(Imm32(sizeof(void*)), esp);
    830    }
    831  }
    832  void unboxNonDouble(const Address& src, Register dest, JSValueType type) {
    833    unboxNonDouble(tagOf(src), payloadOf(src), dest, type);
    834  }
    835  void unboxNonDouble(const BaseIndex& src, Register dest, JSValueType type) {
    836    unboxNonDouble(tagOf(src), payloadOf(src), dest, type);
    837  }
    838  void unboxInt32(const ValueOperand& src, Register dest) {
    839    unboxNonDouble(src, dest, JSVAL_TYPE_INT32);
    840  }
    841  void unboxInt32(const Address& src, Register dest) {
    842    unboxNonDouble(src, dest, JSVAL_TYPE_INT32);
    843  }
    844  void unboxInt32(const BaseIndex& src, Register dest) {
    845    unboxNonDouble(src, dest, JSVAL_TYPE_INT32);
    846  }
    847  void unboxBoolean(const ValueOperand& src, Register dest) {
    848    unboxNonDouble(src, dest, JSVAL_TYPE_BOOLEAN);
    849  }
    850  void unboxBoolean(const Address& src, Register dest) {
    851    unboxNonDouble(src, dest, JSVAL_TYPE_BOOLEAN);
    852  }
    853  void unboxBoolean(const BaseIndex& src, Register dest) {
    854    unboxNonDouble(src, dest, JSVAL_TYPE_BOOLEAN);
    855  }
    856  void unboxString(const ValueOperand& src, Register dest) {
    857    unboxNonDouble(src, dest, JSVAL_TYPE_STRING);
    858  }
    859  void unboxString(const Address& src, Register dest) {
    860    unboxNonDouble(src, dest, JSVAL_TYPE_STRING);
    861  }
    862  void unboxSymbol(const ValueOperand& src, Register dest) {
    863    unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL);
    864  }
    865  void unboxSymbol(const Address& src, Register dest) {
    866    unboxNonDouble(src, dest, JSVAL_TYPE_SYMBOL);
    867  }
    868  void unboxBigInt(const ValueOperand& src, Register dest) {
    869    unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT);
    870  }
    871  void unboxBigInt(const Address& src, Register dest) {
    872    unboxNonDouble(src, dest, JSVAL_TYPE_BIGINT);
    873  }
    874  void unboxObject(const ValueOperand& src, Register dest) {
    875    unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT);
    876  }
    877  void unboxObject(const Address& src, Register dest) {
    878    unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT);
    879  }
    880  void unboxObject(const BaseIndex& src, Register dest) {
    881    unboxNonDouble(src, dest, JSVAL_TYPE_OBJECT);
    882  }
    883  template <typename T>
    884  void unboxDouble(const T& src, FloatRegister dest) {
    885    loadDouble(Operand(src), dest);
    886  }
    887  void unboxDouble(const ValueOperand& src, FloatRegister dest) {
    888    if (Assembler::HasSSE41()) {
    889      vmovd(src.payloadReg(), dest);
    890      vpinsrd(1, src.typeReg(), dest, dest);
    891    } else {
    892      ScratchDoubleScope fpscratch(asMasm());
    893      vmovd(src.payloadReg(), dest);
    894      vmovd(src.typeReg(), fpscratch);
    895      vunpcklps(fpscratch, dest, dest);
    896    }
    897  }
    898  void unboxDouble(const Operand& payload, const Operand& type,
    899                   Register scratch, FloatRegister dest) {
    900    if (Assembler::HasSSE41()) {
    901      movl(payload, scratch);
    902      vmovd(scratch, dest);
    903      movl(type, scratch);
    904      vpinsrd(1, scratch, dest, dest);
    905    } else {
    906      ScratchDoubleScope fpscratch(asMasm());
    907      movl(payload, scratch);
    908      vmovd(scratch, dest);
    909      movl(type, scratch);
    910      vmovd(scratch, fpscratch);
    911      vunpcklps(fpscratch, dest, dest);
    912    }
    913  }
    914  inline void unboxValue(const ValueOperand& src, AnyRegister dest,
    915                         JSValueType type);
    916 
    917  // See comment in MacroAssembler-x64.h.
    918  void unboxGCThingForGCBarrier(const Address& src, Register dest) {
    919    movl(payloadOf(src), dest);
    920  }
    921  void unboxGCThingForGCBarrier(const ValueOperand& src, Register dest) {
    922    if (src.payloadReg() != dest) {
    923      movl(src.payloadReg(), dest);
    924    }
    925  }
    926 
    927  void unboxWasmAnyRefGCThingForGCBarrier(const Address& src, Register dest) {
    928    movl(ImmWord(wasm::AnyRef::GCThingMask), dest);
    929    andl(Operand(src), dest);
    930  }
    931 
    932  void getWasmAnyRefGCThingChunk(Register src, Register dest) {
    933    MOZ_ASSERT(src != dest);
    934    movl(ImmWord(wasm::AnyRef::GCThingChunkMask), dest);
    935    andl(src, dest);
    936  }
    937 
    938  void notBoolean(const ValueOperand& val) { xorl(Imm32(1), val.payloadReg()); }
    939 
    940  template <typename T>
    941  void fallibleUnboxPtrImpl(const T& src, Register dest, JSValueType type,
    942                            Label* fail);
    943 
    944  // Extended unboxing API. If the payload is already in a register, returns
    945  // that register. Otherwise, provides a move to the given scratch register,
    946  // and returns that.
    947  [[nodiscard]] Register extractObject(const Address& address, Register dest) {
    948    unboxObject(address, dest);
    949    return dest;
    950  }
    951  [[nodiscard]] Register extractObject(const ValueOperand& value,
    952                                       Register scratch) {
    953    unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_OBJECT, scratch);
    954    return value.payloadReg();
    955  }
    956  [[nodiscard]] Register extractSymbol(const ValueOperand& value,
    957                                       Register scratch) {
    958    unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_SYMBOL, scratch);
    959    return value.payloadReg();
    960  }
    961  [[nodiscard]] Register extractInt32(const ValueOperand& value,
    962                                      Register scratch) {
    963    return value.payloadReg();
    964  }
    965  [[nodiscard]] Register extractBoolean(const ValueOperand& value,
    966                                        Register scratch) {
    967    return value.payloadReg();
    968  }
    969  [[nodiscard]] Register extractTag(const Address& address, Register scratch) {
    970    movl(tagOf(address), scratch);
    971    return scratch;
    972  }
    973  [[nodiscard]] Register extractTag(const ValueOperand& value,
    974                                    Register scratch) {
    975    return value.typeReg();
    976  }
    977 
    978  void convertDoubleToPtr(FloatRegister src, Register dest, Label* fail,
    979                          bool negativeZeroCheck = true) {
    980    convertDoubleToInt32(src, dest, fail, negativeZeroCheck);
    981  }
    982 
    983  void loadConstantDouble(double d, FloatRegister dest);
    984  void loadConstantFloat32(float f, FloatRegister dest);
    985 
    986  void loadConstantSimd128Int(const SimdConstant& v, FloatRegister dest);
    987  void loadConstantSimd128Float(const SimdConstant& v, FloatRegister dest);
    988  void vpaddbSimd128(const SimdConstant& v, FloatRegister lhs,
    989                     FloatRegister dest);
    990  void vpaddwSimd128(const SimdConstant& v, FloatRegister lhs,
    991                     FloatRegister dest);
    992  void vpadddSimd128(const SimdConstant& v, FloatRegister lhs,
    993                     FloatRegister dest);
    994  void vpaddqSimd128(const SimdConstant& v, FloatRegister lhs,
    995                     FloatRegister dest);
    996  void vpsubbSimd128(const SimdConstant& v, FloatRegister lhs,
    997                     FloatRegister dest);
    998  void vpsubwSimd128(const SimdConstant& v, FloatRegister lhs,
    999                     FloatRegister dest);
   1000  void vpsubdSimd128(const SimdConstant& v, FloatRegister lhs,
   1001                     FloatRegister dest);
   1002  void vpsubqSimd128(const SimdConstant& v, FloatRegister lhs,
   1003                     FloatRegister dest);
   1004  void vpmullwSimd128(const SimdConstant& v, FloatRegister lhs,
   1005                      FloatRegister dest);
   1006  void vpmulldSimd128(const SimdConstant& v, FloatRegister lhs,
   1007                      FloatRegister dest);
   1008  void vpaddsbSimd128(const SimdConstant& v, FloatRegister lhs,
   1009                      FloatRegister dest);
   1010  void vpaddusbSimd128(const SimdConstant& v, FloatRegister lhs,
   1011                       FloatRegister dest);
   1012  void vpaddswSimd128(const SimdConstant& v, FloatRegister lhs,
   1013                      FloatRegister dest);
   1014  void vpadduswSimd128(const SimdConstant& v, FloatRegister lhs,
   1015                       FloatRegister dest);
   1016  void vpsubsbSimd128(const SimdConstant& v, FloatRegister lhs,
   1017                      FloatRegister dest);
   1018  void vpsubusbSimd128(const SimdConstant& v, FloatRegister lhs,
   1019                       FloatRegister dest);
   1020  void vpsubswSimd128(const SimdConstant& v, FloatRegister lhs,
   1021                      FloatRegister dest);
   1022  void vpsubuswSimd128(const SimdConstant& v, FloatRegister lhs,
   1023                       FloatRegister dest);
   1024  void vpminsbSimd128(const SimdConstant& v, FloatRegister lhs,
   1025                      FloatRegister dest);
   1026  void vpminubSimd128(const SimdConstant& v, FloatRegister lhs,
   1027                      FloatRegister dest);
   1028  void vpminswSimd128(const SimdConstant& v, FloatRegister lhs,
   1029                      FloatRegister dest);
   1030  void vpminuwSimd128(const SimdConstant& v, FloatRegister lhs,
   1031                      FloatRegister dest);
   1032  void vpminsdSimd128(const SimdConstant& v, FloatRegister lhs,
   1033                      FloatRegister dest);
   1034  void vpminudSimd128(const SimdConstant& v, FloatRegister lhs,
   1035                      FloatRegister dest);
   1036  void vpmaxsbSimd128(const SimdConstant& v, FloatRegister lhs,
   1037                      FloatRegister dest);
   1038  void vpmaxubSimd128(const SimdConstant& v, FloatRegister lhs,
   1039                      FloatRegister dest);
   1040  void vpmaxswSimd128(const SimdConstant& v, FloatRegister lhs,
   1041                      FloatRegister dest);
   1042  void vpmaxuwSimd128(const SimdConstant& v, FloatRegister lhs,
   1043                      FloatRegister dest);
   1044  void vpmaxsdSimd128(const SimdConstant& v, FloatRegister lhs,
   1045                      FloatRegister dest);
   1046  void vpmaxudSimd128(const SimdConstant& v, FloatRegister lhs,
   1047                      FloatRegister dest);
   1048  void vpandSimd128(const SimdConstant& v, FloatRegister lhs,
   1049                    FloatRegister dest);
   1050  void vpxorSimd128(const SimdConstant& v, FloatRegister lhs,
   1051                    FloatRegister dest);
   1052  void vporSimd128(const SimdConstant& v, FloatRegister lhs,
   1053                   FloatRegister dest);
   1054  void vaddpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1055                     FloatRegister dest);
   1056  void vaddpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1057                     FloatRegister dest);
   1058  void vsubpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1059                     FloatRegister dest);
   1060  void vsubpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1061                     FloatRegister dest);
   1062  void vdivpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1063                     FloatRegister dest);
   1064  void vdivpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1065                     FloatRegister dest);
   1066  void vmulpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1067                     FloatRegister dest);
   1068  void vmulpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1069                     FloatRegister dest);
   1070  void vandpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1071                     FloatRegister dest);
   1072  void vandpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1073                     FloatRegister dest);
   1074  void vxorpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1075                     FloatRegister dest);
   1076  void vxorpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1077                     FloatRegister dest);
   1078  void vminpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1079                     FloatRegister dest);
   1080  void vpacksswbSimd128(const SimdConstant& v, FloatRegister lhs,
   1081                        FloatRegister dest);
   1082  void vpackuswbSimd128(const SimdConstant& v, FloatRegister lhs,
   1083                        FloatRegister dest);
   1084  void vpackssdwSimd128(const SimdConstant& v, FloatRegister lhs,
   1085                        FloatRegister dest);
   1086  void vpackusdwSimd128(const SimdConstant& v, FloatRegister lhs,
   1087                        FloatRegister dest);
   1088  void vpunpckldqSimd128(const SimdConstant& v, FloatRegister lhs,
   1089                         FloatRegister dest);
   1090  void vunpcklpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1091                        FloatRegister dest);
   1092  void vpshufbSimd128(const SimdConstant& v, FloatRegister lhs,
   1093                      FloatRegister dest);
   1094  void vptestSimd128(const SimdConstant& v, FloatRegister lhs);
   1095  void vpmaddwdSimd128(const SimdConstant& v, FloatRegister lhs,
   1096                       FloatRegister dest);
   1097  void vpcmpeqbSimd128(const SimdConstant& v, FloatRegister lhs,
   1098                       FloatRegister dest);
   1099  void vpcmpgtbSimd128(const SimdConstant& v, FloatRegister lhs,
   1100                       FloatRegister dest);
   1101  void vpcmpeqwSimd128(const SimdConstant& v, FloatRegister lhs,
   1102                       FloatRegister dest);
   1103  void vpcmpgtwSimd128(const SimdConstant& v, FloatRegister lhs,
   1104                       FloatRegister dest);
   1105  void vpcmpeqdSimd128(const SimdConstant& v, FloatRegister lhs,
   1106                       FloatRegister dest);
   1107  void vpcmpgtdSimd128(const SimdConstant& v, FloatRegister lhs,
   1108                       FloatRegister dest);
   1109  void vcmpeqpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1110                       FloatRegister dest);
   1111  void vcmpneqpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1112                        FloatRegister dest);
   1113  void vcmpltpsSimd128(const SimdConstant& v, FloatRegister lhs,
   1114                       FloatRegister dest);
   1115  void vcmplepsSimd128(const SimdConstant& v, FloatRegister lhs,
   1116                       FloatRegister dest);
   1117  void vcmpgepsSimd128(const SimdConstant& v, FloatRegister lhs,
   1118                       FloatRegister dest);
   1119  void vcmpeqpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1120                       FloatRegister dest);
   1121  void vcmpneqpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1122                        FloatRegister dest);
   1123  void vcmpltpdSimd128(const SimdConstant& v, FloatRegister lhs,
   1124                       FloatRegister dest);
   1125  void vcmplepdSimd128(const SimdConstant& v, FloatRegister lhs,
   1126                       FloatRegister dest);
   1127  void vpmaddubswSimd128(const SimdConstant& v, FloatRegister lhs,
   1128                         FloatRegister dest);
   1129  void vpmuludqSimd128(const SimdConstant& v, FloatRegister lhs,
   1130                       FloatRegister dest);
   1131 
   1132  Condition testInt32Truthy(bool truthy, const ValueOperand& operand) {
   1133    test32(operand.payloadReg(), operand.payloadReg());
   1134    return truthy ? NonZero : Zero;
   1135  }
   1136  Condition testStringTruthy(bool truthy, const ValueOperand& value);
   1137  Condition testBigIntTruthy(bool truthy, const ValueOperand& value);
   1138 
   1139  template <typename T>
   1140  inline void loadInt32OrDouble(const T& src, FloatRegister dest);
   1141 
   1142  template <typename T>
   1143  inline void loadUnboxedValue(const T& src, MIRType type, AnyRegister dest);
   1144 
   1145  // Note: this function clobbers the source register.
   1146  inline void convertUInt32ToDouble(Register src, FloatRegister dest);
   1147 
   1148  // Note: this function clobbers the source register.
   1149  inline void convertUInt32ToFloat32(Register src, FloatRegister dest);
   1150 
   1151  void incrementInt32Value(const Address& addr) {
   1152    addl(Imm32(1), payloadOf(addr));
   1153  }
   1154 
   1155  void minMax32(Register lhs, Register rhs, Register dest, bool isMax);
   1156  void minMax32(Register lhs, Imm32 rhs, Register dest, bool isMax);
   1157 
   1158 public:
   1159  // Used from within an Exit frame to handle a pending exception.
   1160  void handleFailureWithHandlerTail(Label* profilerExitTail, Label* bailoutTail,
   1161                                    uint32_t* returnValueCheckOffset);
   1162 
   1163  // Instrumentation for entering and leaving the profiler.
   1164  void profilerEnterFrame(Register framePtr, Register scratch);
   1165  void profilerExitFrame();
   1166 };
   1167 
   1168 using MacroAssemblerSpecific = MacroAssemblerX86;
   1169 
   1170 }  // namespace jit
   1171 }  // namespace js
   1172 
   1173 #endif /* jit_x86_MacroAssembler_x86_h */