Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  testJitMacroAssembler.cpp   Sprache: C

 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "mozilla/Sprintf.h"

#include "jit/IonAnalysis.h"
#include "jit/Linker.h"
#include "jit/MacroAssembler.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
#include "jit/ValueNumbering.h"
#include "js/Value.h"

#include "jsapi-tests/tests.h"
#include "jsapi-tests/testsJit.h"

#include "jit/MacroAssembler-inl.h"

using namespace js;
using namespace js::jit;

using mozilla::NegativeInfinity;
using mozilla::PositiveInfinity;

#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)

BEGIN_TEST(testJitMacroAssembler_flexibleDivMod) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  // Test case divides 9/2;
  const uintptr_t dividend = 9;
  const uintptr_t divisor = 2;
  const uintptr_t quotient_result = 4;
  const uintptr_t remainder_result = 1;

  AllocatableGeneralRegisterSet leftHandSides(GeneralRegisterSet::All());
  while (!leftHandSides.empty()) {
    Register lhs = leftHandSides.takeAny();

    AllocatableGeneralRegisterSet rightHandSides(GeneralRegisterSet::All());
    while (!rightHandSides.empty()) {
      Register rhs = rightHandSides.takeAny();

      AllocatableGeneralRegisterSet quotients(GeneralRegisterSet::All());
      while (!quotients.empty()) {
        Register quotientOutput = quotients.takeAny();

        AllocatableGeneralRegisterSet remainders(GeneralRegisterSet::All());
        while (!remainders.empty()) {
          Register remainderOutput = remainders.takeAny();

          // lhs and rhs are preserved by |flexibleDivMod32|, so neither can be
          // an output register.
          if (lhs == quotientOutput || lhs == remainderOutput) {
            continue;
          }
          if (rhs == quotientOutput || rhs == remainderOutput) {
            continue;
          }

          // Output registers must be distinct.
          if (quotientOutput == remainderOutput) {
            continue;
          }

          AllocatableRegisterSet regs(RegisterSet::Volatile());
          LiveRegisterSet save(regs.asLiveSet());

          Label next, fail;
          masm.mov(ImmWord(dividend), lhs);
          masm.mov(ImmWord(divisor), rhs);
          masm.flexibleDivMod32(lhs, rhs, quotientOutput, remainderOutput,
                                false, save);
          masm.branchPtr(Assembler::NotEqual, quotientOutput,
                         ImmWord(lhs != rhs ? quotient_result : 1), &fail);
          masm.branchPtr(Assembler::NotEqual, remainderOutput,
                         ImmWord(lhs != rhs ? remainder_result : 0), &fail);
          // Ensure LHS was not clobbered
          masm.branchPtr(Assembler::NotEqual, lhs,
                         ImmWord(lhs != rhs ? dividend : divisor), &fail);
          // Ensure RHS was not clobbered
          masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(divisor), &fail);
          masm.jump(&next);
          masm.bind(&fail);
          masm.printf("Failed\n");

          char buffer[128];
          SprintfLiteral(
              buffer,
              "\tlhs = %s, rhs = %s, quotientOutput = %s, remainderOutput "
              "= %s\n",
              lhs.name(), rhs.name(), quotientOutput.name(),
              remainderOutput.name());

          masm.printf(buffer);
          masm.printf("\tlhs = %d\n", lhs);
          masm.printf("\trhs = %d\n", rhs);
          masm.printf("\tquotientOutput = %d\n", quotientOutput);
          masm.printf("\tremainderOutput = %d\n", remainderOutput);

          masm.breakpoint();

          masm.bind(&next);
        }
      }
    }
  }

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_flexibleDivMod)

BEGIN_TEST(testJitMacroAssembler_flexibleRemainder) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  // Test case divides 9/2;
  const uintptr_t dividend = 9;
  const uintptr_t divisor = 2;
  const uintptr_t remainder_result = 1;

  AllocatableGeneralRegisterSet leftHandSides(GeneralRegisterSet::All());
  while (!leftHandSides.empty()) {
    Register lhs = leftHandSides.takeAny();

    AllocatableGeneralRegisterSet rightHandSides(GeneralRegisterSet::All());
    while (!rightHandSides.empty()) {
      Register rhs = rightHandSides.takeAny();

      AllocatableGeneralRegisterSet outputs(GeneralRegisterSet::All());
      while (!outputs.empty()) {
        Register output = outputs.takeAny();

        AllocatableRegisterSet regs(RegisterSet::Volatile());
        LiveRegisterSet save(regs.asLiveSet());

        Label next, fail;
        masm.mov(ImmWord(dividend), lhs);
        masm.mov(ImmWord(divisor), rhs);
        masm.flexibleRemainder32(lhs, rhs, output, false, save);
        masm.branchPtr(Assembler::NotEqual, output,
                       ImmWord(lhs != rhs ? remainder_result : 0), &fail);
        // Ensure LHS was not clobbered
        if (lhs != output) {
          masm.branchPtr(Assembler::NotEqual, lhs,
                         ImmWord(lhs != rhs ? dividend : divisor), &fail);
        }
        // Ensure RHS was not clobbered
        if (rhs != output) {
          masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(divisor), &fail);
        }
        masm.jump(&next);
        masm.bind(&fail);
        masm.printf("Failed\n");

        char buffer[128];
        SprintfLiteral(buffer, "\tlhs = %s, rhs = %s, output = %s\n",
                       lhs.name(), rhs.name(), output.name());

        masm.printf(buffer);
        masm.printf("\tlhs = %d\n", lhs);
        masm.printf("\trhs = %d\n", rhs);
        masm.printf("\toutput = %d\n", output);

        masm.breakpoint();

        masm.bind(&next);
      }
    }
  }

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_flexibleRemainder)

BEGIN_TEST(testJitMacroAssembler_flexibleQuotient) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  // Test case divides 9/2;
  const uintptr_t dividend = 9;
  const uintptr_t divisor = 2;
  const uintptr_t quotient_result = 4;

  AllocatableGeneralRegisterSet leftHandSides(GeneralRegisterSet::All());
  while (!leftHandSides.empty()) {
    Register lhs = leftHandSides.takeAny();

    AllocatableGeneralRegisterSet rightHandSides(GeneralRegisterSet::All());
    while (!rightHandSides.empty()) {
      Register rhs = rightHandSides.takeAny();

      AllocatableGeneralRegisterSet outputs(GeneralRegisterSet::All());
      while (!outputs.empty()) {
        Register output = outputs.takeAny();

        AllocatableRegisterSet regs(RegisterSet::Volatile());
        LiveRegisterSet save(regs.asLiveSet());

        Label next, fail;
        masm.mov(ImmWord(dividend), lhs);
        masm.mov(ImmWord(divisor), rhs);
        masm.flexibleQuotient32(lhs, rhs, output, false, save);
        masm.branchPtr(Assembler::NotEqual, output,
                       ImmWord(lhs != rhs ? quotient_result : 1), &fail);
        // Ensure LHS was not clobbered
        if (lhs != output) {
          masm.branchPtr(Assembler::NotEqual, lhs,
                         ImmWord(lhs != rhs ? dividend : divisor), &fail);
        }
        // Ensure RHS was not clobbered
        if (rhs != output) {
          masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(divisor), &fail);
        }
        masm.jump(&next);
        masm.bind(&fail);
        masm.printf("Failed\n");

        char buffer[128];
        SprintfLiteral(buffer, "\tlhs = %s, rhs = %s, output = %s\n",
                       lhs.name(), rhs.name(), output.name());

        masm.printf(buffer);
        masm.printf("\tlhs = %d\n", lhs);
        masm.printf("\trhs = %d\n", rhs);
        masm.printf("\toutput = %d\n", output);

        masm.breakpoint();

        masm.bind(&next);
      }
    }
  }

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_flexibleQuotient)

bool shiftTest(JSContext* cx, const char* name,
               void (*operation)(StackMacroAssembler& masm, Register, Register),
               uintptr_t lhsInput, uintptr_t rhsInput, uintptr_t result) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  const uintptr_t guardEcx = 0xfeedbad;

  JS::AutoSuppressGCAnalysis suppress;
  AllocatableGeneralRegisterSet leftOutputHandSides(GeneralRegisterSet::All());

  while (!leftOutputHandSides.empty()) {
    Register lhsOutput = leftOutputHandSides.takeAny();

    AllocatableGeneralRegisterSet rightHandSides(GeneralRegisterSet::All());
    while (!rightHandSides.empty()) {
      Register rhs = rightHandSides.takeAny();

      // You can only use shift as the same reg if the values are the same
      if (lhsOutput == rhs && lhsInput != rhsInput) {
        continue;
      }

      Label next, outputFail, clobberRhs, clobberEcx, dump;
      masm.mov(ImmWord(guardEcx), ecx);
      masm.mov(ImmWord(lhsInput), lhsOutput);
      masm.mov(ImmWord(rhsInput), rhs);

      operation(masm, rhs, lhsOutput);

      // Ensure Result is correct
      masm.branchPtr(Assembler::NotEqual, lhsOutput, ImmWord(result),
                     &outputFail);

      // Ensure RHS was not clobbered, unless it's also the output register.
      if (lhsOutput != rhs) {
        masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(rhsInput),
                       &clobberRhs);
      }

      if (lhsOutput != ecx && rhs != ecx) {
        // If neither lhsOutput nor rhs is ecx, make sure ecx has been
        // preserved, otherwise it's expected to be covered by the RHS clobber
        // check above, or intentionally clobbered as the output.
        masm.branchPtr(Assembler::NotEqual, ecx, ImmWord(guardEcx),
                       &clobberEcx);
      }

      masm.jump(&next);

      masm.bind(&outputFail);
      masm.printf("Incorrect output (got %d) ", lhsOutput);
      masm.jump(&dump);

      masm.bind(&clobberRhs);
      masm.printf("rhs clobbered %d", rhs);
      masm.jump(&dump);

      masm.bind(&clobberEcx);
      masm.printf("ecx clobbered");
      masm.jump(&dump);

      masm.bind(&dump);
      masm.mov(ImmPtr(lhsOutput.name()), lhsOutput);
      masm.printf("(lhsOutput/srcDest) %s ", lhsOutput);
      masm.mov(ImmPtr(name), lhsOutput);
      masm.printf("%s ", lhsOutput);
      masm.mov(ImmPtr(rhs.name()), lhsOutput);
      masm.printf("(shift/rhs) %s \n", lhsOutput);
      // Breakpoint to force test failure.
      masm.breakpoint();
      masm.bind(&next);
    }
  }

  return ExecuteJit(cx, masm);
}

BEGIN_TEST(testJitMacroAssembler_flexibleRshift) {
  {
    // Test case  16 >> 2 == 4;
    const uintptr_t lhsInput = 16;
    const uintptr_t rhsInput = 2;
    const uintptr_t result = 4;

    bool res = shiftTest(
        cx, "flexibleRshift32",
        [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) {
          masm.flexibleRshift32(rhs, lhsOutput);
        },
        lhsInput, rhsInput, result);
    if (!res) {
      return false;
    }
  }

  {
    // Test case  16 >> 16 == 0 -- this helps cover the case where the same
    // register can be passed for source and dest.
    const uintptr_t lhsInput = 16;
    const uintptr_t rhsInput = 16;
    const uintptr_t result = 0;

    bool res = shiftTest(
        cx, "flexibleRshift32",
        [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) {
          masm.flexibleRshift32(rhs, lhsOutput);
        },
        lhsInput, rhsInput, result);
    if (!res) {
      return false;
    }
  }

  return true;
}
END_TEST(testJitMacroAssembler_flexibleRshift)

BEGIN_TEST(testJitMacroAssembler_flexibleRshiftArithmetic) {
  {
    // Test case  4294967295 >> 2 == 4294967295;
    const uintptr_t lhsInput = 4294967295;
    const uintptr_t rhsInput = 2;
    const uintptr_t result = 4294967295;
    bool res = shiftTest(
        cx, "flexibleRshift32Arithmetic",
        [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) {
          masm.flexibleRshift32Arithmetic(rhs, lhsOutput);
        },
        lhsInput, rhsInput, result);
    if (!res) {
      return false;
    }
  }

  {
    // Test case  16 >> 16 == 0 -- this helps cover the case where the same
    // register can be passed for source and dest.
    const uintptr_t lhsInput = 16;
    const uintptr_t rhsInput = 16;
    const uintptr_t result = 0;

    bool res = shiftTest(
        cx, "flexibleRshift32Arithmetic",
        [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) {
          masm.flexibleRshift32Arithmetic(rhs, lhsOutput);
        },
        lhsInput, rhsInput, result);
    if (!res) {
      return false;
    }
  }

  return true;
}
END_TEST(testJitMacroAssembler_flexibleRshiftArithmetic)

BEGIN_TEST(testJitMacroAssembler_flexibleLshift) {
  {
    // Test case  16 << 2 == 64;
    const uintptr_t lhsInput = 16;
    const uintptr_t rhsInput = 2;
    const uintptr_t result = 64;

    bool res = shiftTest(
        cx, "flexibleLshift32",
        [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) {
          masm.flexibleLshift32(rhs, lhsOutput);
        },
        lhsInput, rhsInput, result);
    if (!res) {
      return false;
    }
  }

  {
    // Test case  4 << 4 == 64; duplicated input case
    const uintptr_t lhsInput = 4;
    const uintptr_t rhsInput = 4;
    const uintptr_t result = 64;

    bool res = shiftTest(
        cx, "flexibleLshift32",
        [](StackMacroAssembler& masm, Register rhs, Register lhsOutput) {
          masm.flexibleLshift32(rhs, lhsOutput);
        },
        lhsInput, rhsInput, result);
    if (!res) {
      return false;
    }
  }

  return true;
}
END_TEST(testJitMacroAssembler_flexibleLshift)

BEGIN_TEST(testJitMacroAssembler_truncateDoubleToInt64) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
  AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
  FloatRegister input = allFloatRegs.takeAny();
#  ifdef JS_NUNBOX32
  Register64 output(allRegs.takeAny(), allRegs.takeAny());
#  else
  Register64 output(allRegs.takeAny());
#  endif
  Register temp = allRegs.takeAny();

  masm.reserveStack(sizeof(int32_t));

#  define TEST(INPUT, OUTPUT)                                                 \
    {                                                                         \
      Label next;                                                             \
      masm.loadConstantDouble(double(INPUT), input);                          \
      masm.storeDouble(input, Operand(esp, 0));                               \
      masm.truncateDoubleToInt64(Address(esp, 0), Address(esp, 0), temp);     \
      masm.branch64(Assembler::Equal, Address(esp, 0), Imm64(OUTPUT), &next); \
      masm.printf("truncateDoubleToInt64(" #INPUT ") failed\n");              \
      masm.breakpoint();                                                      \
      masm.bind(&next);                                                       \
    }

  TEST(0, 0);
  TEST(-0, 0);
  TEST(1, 1);
  TEST(9223372036854774784.0, 9223372036854774784);
  TEST(-9223372036854775808.0, 0x8000000000000000);
  TEST(9223372036854775808.0, 0x8000000000000000);
  TEST(JS::GenericNaN(), 0x8000000000000000);
  TEST(PositiveInfinity<double>(), 0x8000000000000000);
  TEST(NegativeInfinity<double>(), 0x8000000000000000);
#  undef TEST

  masm.freeStack(sizeof(int32_t));

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_truncateDoubleToInt64)

BEGIN_TEST(testJitMacroAssembler_truncateDoubleToUInt64) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
  AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
  FloatRegister input = allFloatRegs.takeAny();
  FloatRegister floatTemp = allFloatRegs.takeAny();
#  ifdef JS_NUNBOX32
  Register64 output(allRegs.takeAny(), allRegs.takeAny());
#  else
  Register64 output(allRegs.takeAny());
#  endif
  Register temp = allRegs.takeAny();

  masm.reserveStack(sizeof(int32_t));

#  define TEST(INPUT, OUTPUT)                                                 \
    {                                                                         \
      Label next;                                                             \
      masm.loadConstantDouble(double(INPUT), input);                          \
      masm.storeDouble(input, Operand(esp, 0));                               \
      masm.truncateDoubleToUInt64(Address(esp, 0), Address(esp, 0), temp,     \
                                  floatTemp);                                 \
      masm.branch64(Assembler::Equal, Address(esp, 0), Imm64(OUTPUT), &next); \
      masm.printf("truncateDoubleToUInt64(" #INPUT ") failed\n");             \
      masm.breakpoint();                                                      \
      masm.bind(&next);                                                       \
    }

  TEST(0, 0);
  TEST(1, 1);
  TEST(9223372036854774784.0, 9223372036854774784);
  TEST((uint64_t)0x8000000000000000, 0x8000000000000000);
  TEST((uint64_t)0x8000000000000001, 0x8000000000000000);
  TEST((uint64_t)0x8006004000000001, 0x8006004000000000);
  TEST(-0.0, 0);
  TEST(-0.5, 0);
  TEST(-0.99, 0);
  TEST(JS::GenericNaN(), 0x8000000000000000);
  TEST(PositiveInfinity<double>(), 0x8000000000000000);
  TEST(NegativeInfinity<double>(), 0x8000000000000000);
#  undef TEST

  masm.freeStack(sizeof(int32_t));

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_truncateDoubleToUInt64)

BEGIN_TEST(testJitMacroAssembler_branchDoubleNotInInt64Range) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
  AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
  FloatRegister input = allFloatRegs.takeAny();
#  ifdef JS_NUNBOX32
  Register64 output(allRegs.takeAny(), allRegs.takeAny());
#  else
  Register64 output(allRegs.takeAny());
#  endif
  Register temp = allRegs.takeAny();

  masm.reserveStack(sizeof(int32_t));

#  define TEST(INPUT, OUTPUT)                                           \
    {                                                                   \
      Label next;                                                       \
      masm.loadConstantDouble(double(INPUT), input);                    \
      masm.storeDouble(input, Operand(esp, 0));                         \
      if (OUTPUT) {                                                     \
        masm.branchDoubleNotInInt64Range(Address(esp, 0), temp, &next); \
      } else {                                                          \
        Label fail;                                                     \
        masm.branchDoubleNotInInt64Range(Address(esp, 0), temp, &fail); \
        masm.jump(&next);                                               \
        masm.bind(&fail);                                               \
      }                                                                 \
      masm.printf("branchDoubleNotInInt64Range(" #INPUT ") failed\n");  \
      masm.breakpoint();                                                \
      masm.bind(&next);                                                 \
    }

  TEST(0, false);
  TEST(-0, false);
  TEST(1, false);
  TEST(9223372036854774784.0, false);
  TEST(-9223372036854775808.0, true);
  TEST(9223372036854775808.0, true);
  TEST(JS::GenericNaN(), true);
  TEST(PositiveInfinity<double>(), true);
  TEST(NegativeInfinity<double>(), true);
#  undef TEST

  masm.freeStack(sizeof(int32_t));

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_branchDoubleNotInInt64Range)

BEGIN_TEST(testJitMacroAssembler_branchDoubleNotInUInt64Range) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
  AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
  FloatRegister input = allFloatRegs.takeAny();
#  ifdef JS_NUNBOX32
  Register64 output(allRegs.takeAny(), allRegs.takeAny());
#  else
  Register64 output(allRegs.takeAny());
#  endif
  Register temp = allRegs.takeAny();

  masm.reserveStack(sizeof(int32_t));

#  define TEST(INPUT, OUTPUT)                                            \
    {                                                                    \
      Label next;                                                        \
      masm.loadConstantDouble(double(INPUT), input);                     \
      masm.storeDouble(input, Operand(esp, 0));                          \
      if (OUTPUT) {                                                      \
        masm.branchDoubleNotInUInt64Range(Address(esp, 0), temp, &next); \
      } else {                                                           \
        Label fail;                                                      \
        masm.branchDoubleNotInUInt64Range(Address(esp, 0), temp, &fail); \
        masm.jump(&next);                                                \
        masm.bind(&fail);                                                \
      }                                                                  \
      masm.printf("branchDoubleNotInUInt64Range(" #INPUT ") failed\n");  \
      masm.breakpoint();                                                 \
      masm.bind(&next);                                                  \
    }

  TEST(0, false);
  TEST(1, false);
  TEST(9223372036854774784.0, false);
  TEST((uint64_t)0x8000000000000000, false);
  TEST((uint64_t)0x8000000000000001, false);
  TEST((uint64_t)0x8006004000000001, false);
  TEST(-0.0, true);
  TEST(-0.5, true);
  TEST(-0.99, true);
  TEST(JS::GenericNaN(), true);
  TEST(PositiveInfinity<double>(), true);
  TEST(NegativeInfinity<double>(), true);
#  undef TEST

  masm.freeStack(sizeof(int32_t));

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_branchDoubleNotInUInt64Range)

BEGIN_TEST(testJitMacroAssembler_lshift64) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
  AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
#  if defined(JS_CODEGEN_X86)
  Register shift = ecx;
  allRegs.take(shift);
#  elif defined(JS_CODEGEN_X64)
  Register shift = rcx;
  allRegs.take(shift);
#  else
  Register shift = allRegs.takeAny();
#  endif

#  ifdef JS_NUNBOX32
  Register64 input(allRegs.takeAny(), allRegs.takeAny());
#  else
  Register64 input(allRegs.takeAny());
#  endif

  masm.reserveStack(sizeof(int32_t));

#  define TEST(SHIFT, INPUT, OUTPUT)                                        \
    {                                                                       \
      Label next;                                                           \
      masm.move64(Imm64(INPUT), input);                                     \
      masm.move32(Imm32(SHIFT), shift);                                     \
      masm.lshift64(shift, input);                                          \
      masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next);         \
      masm.printf("lshift64(" #SHIFT ", " #INPUT ") failed\n");             \
      masm.breakpoint();                                                    \
      masm.bind(&next);                                                     \
    }                                                                       \
    {                                                                       \
      Label next;                                                           \
      masm.move64(Imm64(INPUT), input);                                     \
      masm.lshift64(Imm32(SHIFT & 0x3f), input);                            \
      masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next);         \
      masm.printf("lshift64(Imm32(" #SHIFT "&0x3f), " #INPUT ") failed\n"); \
      masm.breakpoint();                                                    \
      masm.bind(&next);                                                     \
    }

  TEST(0, 1, 1);
  TEST(1, 1, 2);
  TEST(2, 1, 4);
  TEST(32, 1, 0x0000000100000000);
  TEST(33, 1, 0x0000000200000000);
  TEST(0, -1, 0xffffffffffffffff);
  TEST(1, -1, 0xfffffffffffffffe);
  TEST(2, -1, 0xfffffffffffffffc);
  TEST(32, -1, 0xffffffff00000000);
  TEST(0xffffffff, 1, 0x8000000000000000);
  TEST(0xfffffffe, 1, 0x4000000000000000);
  TEST(0xfffffffd, 1, 0x2000000000000000);
  TEST(0x80000001, 1, 2);
#  undef TEST

  masm.freeStack(sizeof(int32_t));

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_lshift64)

BEGIN_TEST(testJitMacroAssembler_rshift64Arithmetic) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
  AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
#  if defined(JS_CODEGEN_X86)
  Register shift = ecx;
  allRegs.take(shift);
#  elif defined(JS_CODEGEN_X64)
  Register shift = rcx;
  allRegs.take(shift);
#  else
  Register shift = allRegs.takeAny();
#  endif

#  ifdef JS_NUNBOX32
  Register64 input(allRegs.takeAny(), allRegs.takeAny());
#  else
  Register64 input(allRegs.takeAny());
#  endif

  masm.reserveStack(sizeof(int32_t));

#  define TEST(SHIFT, INPUT, OUTPUT)                                      \
    {                                                                     \
      Label next;                                                         \
      masm.move64(Imm64(INPUT), input);                                   \
      masm.move32(Imm32(SHIFT), shift);                                   \
      masm.rshift64Arithmetic(shift, input);                              \
      masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next);       \
      masm.printf("rshift64Arithmetic(" #SHIFT ", " #INPUT ") failed\n"); \
      masm.breakpoint();                                                  \
      masm.bind(&next);                                                   \
    }                                                                     \
    {                                                                     \
      Label next;                                                         \
      masm.move64(Imm64(INPUT), input);                                   \
      masm.rshift64Arithmetic(Imm32(SHIFT & 0x3f), input);                \
      masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next);       \
      masm.printf("rshift64Arithmetic(Imm32(" #SHIFT "&0x3f), " #INPUT    \
                  ") failed\n");                                          \
      masm.breakpoint();                                                  \
      masm.bind(&next);                                                   \
    }

  TEST(0, 0x4000000000000000, 0x4000000000000000);
  TEST(1, 0x4000000000000000, 0x2000000000000000);
  TEST(2, 0x4000000000000000, 0x1000000000000000);
  TEST(32, 0x4000000000000000, 0x0000000040000000);
  TEST(0, 0x8000000000000000, 0x8000000000000000);
  TEST(1, 0x8000000000000000, 0xc000000000000000);
  TEST(2, 0x8000000000000000, 0xe000000000000000);
  TEST(32, 0x8000000000000000, 0xffffffff80000000);
  TEST(0xffffffff, 0x8000000000000000, 0xffffffffffffffff);
  TEST(0xfffffffe, 0x8000000000000000, 0xfffffffffffffffe);
  TEST(0xfffffffd, 0x8000000000000000, 0xfffffffffffffffc);
  TEST(0x80000001, 0x8000000000000000, 0xc000000000000000);
#  undef TEST

  masm.freeStack(sizeof(int32_t));

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_rshift64Arithmetic)

BEGIN_TEST(testJitMacroAssembler_rshift64) {
  TempAllocator tempAlloc(&cx->tempLifoAlloc());
  JitContext jcx(cx);
  StackMacroAssembler masm(cx, tempAlloc);
  AutoCreatedBy acb(masm, __func__);

  PrepareJit(masm);

  AllocatableGeneralRegisterSet allRegs(GeneralRegisterSet::All());
  AllocatableFloatRegisterSet allFloatRegs(FloatRegisterSet::All());
#  if defined(JS_CODEGEN_X86)
  Register shift = ecx;
  allRegs.take(shift);
#  elif defined(JS_CODEGEN_X64)
  Register shift = rcx;
  allRegs.take(shift);
#  else
  Register shift = allRegs.takeAny();
#  endif

#  ifdef JS_NUNBOX32
  Register64 input(allRegs.takeAny(), allRegs.takeAny());
#  else
  Register64 input(allRegs.takeAny());
#  endif

  masm.reserveStack(sizeof(int32_t));

#  define TEST(SHIFT, INPUT, OUTPUT)                                        \
    {                                                                       \
      Label next;                                                           \
      masm.move64(Imm64(INPUT), input);                                     \
      masm.move32(Imm32(SHIFT), shift);                                     \
      masm.rshift64(shift, input);                                          \
      masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next);         \
      masm.printf("rshift64(" #SHIFT ", " #INPUT ") failed\n");             \
      masm.breakpoint();                                                    \
      masm.bind(&next);                                                     \
    }                                                                       \
    {                                                                       \
      Label next;                                                           \
      masm.move64(Imm64(INPUT), input);                                     \
      masm.rshift64(Imm32(SHIFT & 0x3f), input);                            \
      masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next);         \
      masm.printf("rshift64(Imm32(" #SHIFT "&0x3f), " #INPUT ") failed\n"); \
      masm.breakpoint();                                                    \
      masm.bind(&next);                                                     \
    }

  TEST(0, 0x4000000000000000, 0x4000000000000000);
  TEST(1, 0x4000000000000000, 0x2000000000000000);
  TEST(2, 0x4000000000000000, 0x1000000000000000);
  TEST(32, 0x4000000000000000, 0x0000000040000000);
  TEST(0, 0x8000000000000000, 0x8000000000000000);
  TEST(1, 0x8000000000000000, 0x4000000000000000);
  TEST(2, 0x8000000000000000, 0x2000000000000000);
  TEST(32, 0x8000000000000000, 0x0000000080000000);
  TEST(0xffffffff, 0x8000000000000000, 0x0000000000000001);
  TEST(0xfffffffe, 0x8000000000000000, 0x0000000000000002);
  TEST(0xfffffffd, 0x8000000000000000, 0x0000000000000004);
  TEST(0x80000001, 0x8000000000000000, 0x4000000000000000);
#  undef TEST

  masm.freeStack(sizeof(int32_t));

  return ExecuteJit(cx, masm);
}
END_TEST(testJitMacroAssembler_rshift64)

#endif

Messung V0.5 in Prozent
C=97 H=90 G=93

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-09-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1126438
#Domains=1897691