mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 09:18:42 +09:00
Issue #3049 - Rename and wire loongarch64 baseline JIT backend
This commit is contained in:
parent
03088e2abc
commit
36b9acb8a5
38 changed files with 15074 additions and 65 deletions
|
|
@ -385,7 +385,7 @@ struct BaselineStackBuilder
|
|||
return virtualPointerAtStackOffset(priorOffset);
|
||||
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \
|
||||
defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
|
||||
defined(JS_CODEGEN_X64)
|
||||
defined(JS_CODEGEN_LOONGARCH64) || defined(JS_CODEGEN_X64)
|
||||
// On X64, ARM, ARM64, and MIPS, the frame pointer save location depends on
|
||||
// the caller of the rectifier frame.
|
||||
BufferPointer<RectifierFrameLayout> priorFrame =
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
# include "jit/arm/BaselineCompiler-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/BaselineCompiler-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/loongarch64/BaselineCompiler-loongarch64.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/BaselineCompiler-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
# include "jit/arm/CodeGenerator-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/CodeGenerator-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/none/CodeGenerator-none.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/CodeGenerator-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ extern "C" void sync_instruction_memory(caddr_t v, u_int len);
|
|||
|
||||
#if defined(__linux__) && \
|
||||
(defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)) && \
|
||||
!defined(JS_CODEGEN_LOONGARCH64) && \
|
||||
(!defined(JS_SIMULATOR_MIPS32) && !defined(JS_SIMULATOR_MIPS64))
|
||||
#include <sys/cachectl.h>
|
||||
#endif
|
||||
|
|
@ -220,6 +221,12 @@ class ExecutableAllocator
|
|||
{
|
||||
js::jit::Simulator::FlushICache(code, size);
|
||||
}
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
static void cacheFlush(void* code, size_t size)
|
||||
{
|
||||
intptr_t end = reinterpret_cast<intptr_t>(code) + size;
|
||||
__builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
|
||||
}
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
static void cacheFlush(void* code, size_t size)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ static inline bool
|
|||
IsIonEnabled(JSContext* cx)
|
||||
{
|
||||
// The ARM64 Ion engine is not yet implemented.
|
||||
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
|
||||
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_LOONGARCH64)
|
||||
return false;
|
||||
#else
|
||||
return cx->options().ion() &&
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
# include "jit/arm/Assembler-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/Assembler-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/loongarch64/Assembler-loongarch64.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/Assembler-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
|
|
@ -1927,6 +1927,8 @@ LAllocation::toRegister() const
|
|||
# include "jit/mips64/LIR-mips64.h"
|
||||
# endif
|
||||
# include "jit/mips-shared/LIR-mips-shared.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/none/LIR-none.h"
|
||||
#elif defined(JS_CODEGEN_NONE)
|
||||
# include "jit/none/LIR-none.h"
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
# include "jit/arm/LOpcodes-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/LOpcodes-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/none/LOpcodes-none.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/LOpcodes-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
# include "jit/arm/Lowering-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/Lowering-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/none/Lowering-none.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/Lowering-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
# include "jit/arm/MacroAssembler-arm-inl.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/MacroAssembler-arm64-inl.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/loongarch64/MacroAssembler-loongarch64-inl.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/MacroAssembler-mips32-inl.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
# include "jit/arm/MacroAssembler-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/MacroAssembler-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/loongarch64/MacroAssembler-loongarch64.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/MacroAssembler-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
@ -66,8 +68,8 @@ using mozilla::FloatingPoint;
|
|||
// architectures on each method declaration, such as PER_ARCH and
|
||||
// PER_SHARED_ARCH.
|
||||
|
||||
# define ALL_ARCH mips32, mips64, arm, arm64, x86, x64
|
||||
# define ALL_SHARED_ARCH arm, arm64, x86_shared, mips_shared
|
||||
# define ALL_ARCH mips32, mips64, loongarch64, arm, arm64, x86, x64
|
||||
# define ALL_SHARED_ARCH arm, arm64, loongarch64, x86_shared, mips_shared
|
||||
|
||||
// * How this macro works:
|
||||
//
|
||||
|
|
@ -110,6 +112,7 @@ using mozilla::FloatingPoint;
|
|||
# define DEFINED_ON_x86_shared
|
||||
# define DEFINED_ON_arm
|
||||
# define DEFINED_ON_arm64
|
||||
# define DEFINED_ON_loongarch64
|
||||
# define DEFINED_ON_mips32
|
||||
# define DEFINED_ON_mips64
|
||||
# define DEFINED_ON_mips_shared
|
||||
|
|
@ -132,6 +135,9 @@ using mozilla::FloatingPoint;
|
|||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# undef DEFINED_ON_arm64
|
||||
# define DEFINED_ON_arm64 define
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# undef DEFINED_ON_loongarch64
|
||||
# define DEFINED_ON_loongarch64 define
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# undef DEFINED_ON_mips32
|
||||
# define DEFINED_ON_mips32 define
|
||||
|
|
@ -419,13 +425,13 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
// Stack manipulation functions.
|
||||
|
||||
void PushRegsInMask(LiveRegisterSet set)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
void PushRegsInMask(LiveGeneralRegisterSet set);
|
||||
|
||||
void PopRegsInMask(LiveRegisterSet set);
|
||||
void PopRegsInMask(LiveGeneralRegisterSet set);
|
||||
void PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
void Push(const Operand op) DEFINED_ON(x86_shared);
|
||||
void Push(Register reg) PER_SHARED_ARCH;
|
||||
|
|
@ -497,8 +503,8 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
void callAndPushReturnAddress(Register reg) DEFINED_ON(x86_shared);
|
||||
void callAndPushReturnAddress(Label* label) DEFINED_ON(x86_shared);
|
||||
|
||||
void pushReturnAddress() DEFINED_ON(mips_shared, arm, arm64);
|
||||
void popReturnAddress() DEFINED_ON(mips_shared, arm, arm64);
|
||||
void pushReturnAddress() DEFINED_ON(mips_shared, loongarch64, arm, arm64);
|
||||
void popReturnAddress() DEFINED_ON(mips_shared, loongarch64, arm, arm64);
|
||||
|
||||
public:
|
||||
// ===============================================================
|
||||
|
|
@ -741,9 +747,9 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void xorPtr(Register src, Register dest) PER_ARCH;
|
||||
inline void xorPtr(Imm32 imm, Register dest) PER_ARCH;
|
||||
|
||||
inline void and64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
|
||||
inline void or64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
|
||||
inline void xor64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
|
||||
inline void and64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64, loongarch64);
|
||||
inline void or64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64, loongarch64);
|
||||
inline void xor64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64, loongarch64);
|
||||
|
||||
// ===============================================================
|
||||
// Arithmetic functions
|
||||
|
|
@ -759,14 +765,14 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void addPtr(Imm32 imm, Register src, Register dest) DEFINED_ON(arm64);
|
||||
inline void addPtr(ImmWord imm, Register dest) PER_ARCH;
|
||||
inline void addPtr(ImmPtr imm, Register dest);
|
||||
inline void addPtr(Imm32 imm, const Address& dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
|
||||
inline void addPtr(Imm32 imm, const Address& dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64, loongarch64);
|
||||
inline void addPtr(Imm32 imm, const AbsoluteAddress& dest) DEFINED_ON(x86, x64);
|
||||
inline void addPtr(const Address& src, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
|
||||
inline void addPtr(const Address& src, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64, loongarch64);
|
||||
|
||||
inline void add64(Register64 src, Register64 dest) PER_ARCH;
|
||||
inline void add64(Imm32 imm, Register64 dest) PER_ARCH;
|
||||
inline void add64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64);
|
||||
inline void add64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
|
||||
inline void add64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
|
||||
inline void add64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64, loongarch64);
|
||||
|
||||
inline void addFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
|
||||
|
||||
|
|
@ -778,14 +784,14 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void sub32(Imm32 imm, Register dest) PER_SHARED_ARCH;
|
||||
|
||||
inline void subPtr(Register src, Register dest) PER_ARCH;
|
||||
inline void subPtr(Register src, const Address& dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
|
||||
inline void subPtr(Register src, const Address& dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64, loongarch64);
|
||||
inline void subPtr(Imm32 imm, Register dest) PER_ARCH;
|
||||
inline void subPtr(ImmWord imm, Register dest) DEFINED_ON(x64);
|
||||
inline void subPtr(const Address& addr, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
|
||||
inline void subPtr(const Address& addr, Register dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64, loongarch64);
|
||||
|
||||
inline void sub64(Register64 src, Register64 dest) PER_ARCH;
|
||||
inline void sub64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64);
|
||||
inline void sub64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64);
|
||||
inline void sub64(Imm64 imm, Register64 dest) DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
|
||||
inline void sub64(const Operand& src, Register64 dest) DEFINED_ON(x64, mips64, loongarch64);
|
||||
|
||||
inline void subFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
|
||||
|
||||
|
|
@ -798,10 +804,10 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
|
||||
inline void mul64(const Operand& src, const Register64& dest) DEFINED_ON(x64);
|
||||
inline void mul64(const Operand& src, const Register64& dest, const Register temp)
|
||||
DEFINED_ON(x64, mips64);
|
||||
DEFINED_ON(x64, mips64, loongarch64);
|
||||
inline void mul64(Imm64 imm, const Register64& dest) PER_ARCH;
|
||||
inline void mul64(Imm64 imm, const Register64& dest, const Register temp)
|
||||
DEFINED_ON(x86, x64, arm, mips32, mips64);
|
||||
DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
|
||||
inline void mul64(const Register64& src, const Register64& dest, const Register temp)
|
||||
PER_ARCH;
|
||||
|
||||
|
|
@ -810,7 +816,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void mulFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
|
||||
inline void mulDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
|
||||
|
||||
inline void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64);
|
||||
inline void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) DEFINED_ON(mips_shared, arm, arm64, x86, x64, loongarch64);
|
||||
|
||||
// Perform an integer division, returning the integer part rounded toward zero.
|
||||
// rhs must not be zero, and the division must not overflow.
|
||||
|
|
@ -835,7 +841,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void dec32(RegisterOrInt32Constant* key);
|
||||
|
||||
inline void neg32(Register reg) PER_SHARED_ARCH;
|
||||
inline void neg64(Register64 reg) DEFINED_ON(x86, x64, arm, mips32, mips64);
|
||||
inline void neg64(Register64 reg) DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
|
||||
|
||||
inline void negateFloat(FloatRegister reg) PER_SHARED_ARCH;
|
||||
|
||||
|
|
@ -899,7 +905,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void rotateLeft64(Imm32 count, Register64 input, Register64 dest) DEFINED_ON(x64);
|
||||
inline void rotateLeft64(Register count, Register64 input, Register64 dest) DEFINED_ON(x64);
|
||||
inline void rotateLeft64(Imm32 count, Register64 input, Register64 dest, Register temp)
|
||||
DEFINED_ON(x86, x64, arm, mips32, mips64);
|
||||
DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
|
||||
inline void rotateLeft64(Register count, Register64 input, Register64 dest, Register temp)
|
||||
PER_ARCH;
|
||||
|
||||
|
|
@ -908,7 +914,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void rotateRight64(Imm32 count, Register64 input, Register64 dest) DEFINED_ON(x64);
|
||||
inline void rotateRight64(Register count, Register64 input, Register64 dest) DEFINED_ON(x64);
|
||||
inline void rotateRight64(Imm32 count, Register64 input, Register64 dest, Register temp)
|
||||
DEFINED_ON(x86, x64, arm, mips32, mips64);
|
||||
DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
|
||||
inline void rotateRight64(Register count, Register64 input, Register64 dest, Register temp)
|
||||
PER_ARCH;
|
||||
|
||||
|
|
@ -934,7 +940,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
|
||||
template <typename T1, typename T2>
|
||||
inline void cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest)
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64);
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loongarch64);
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest)
|
||||
|
|
@ -956,9 +962,9 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
Label* label);
|
||||
|
||||
inline void branch32(Condition cond, const AbsoluteAddress& lhs, Register rhs, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
inline void branch32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
|
||||
inline void branch32(Condition cond, const BaseIndex& lhs, Register rhs, Label* label)
|
||||
DEFINED_ON(x86_shared);
|
||||
|
|
@ -968,7 +974,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label) DEFINED_ON(x86_shared);
|
||||
|
||||
inline void branch32(Condition cond, wasm::SymbolicAddress lhs, Imm32 rhs, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
|
||||
// The supported condition are Equal, NotEqual, LessThan(orEqual), GreaterThan(orEqual),
|
||||
// Below(orEqual) and Above(orEqual).
|
||||
|
|
@ -977,7 +983,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void branch64(Condition cond, Register64 lhs, Imm64 val, Label* success,
|
||||
Label* fail = nullptr) PER_ARCH;
|
||||
inline void branch64(Condition cond, Register64 lhs, Register64 rhs, Label* success,
|
||||
Label* fail = nullptr) DEFINED_ON(x86, x64, arm, mips32, mips64);
|
||||
Label* fail = nullptr) DEFINED_ON(x86, x64, arm, mips32, mips64, loongarch64);
|
||||
// On x86 and x64 NotEqual and Equal conditions are allowed for the branch64 variants
|
||||
// with Address as lhs. On others only the NotEqual condition.
|
||||
inline void branch64(Condition cond, const Address& lhs, Imm64 val, Label* label) PER_ARCH;
|
||||
|
|
@ -1001,12 +1007,12 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void branchPtr(Condition cond, const Address& lhs, ImmWord rhs, Label* label) PER_SHARED_ARCH;
|
||||
|
||||
inline void branchPtr(Condition cond, const AbsoluteAddress& lhs, Register rhs, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
inline void branchPtr(Condition cond, const AbsoluteAddress& lhs, ImmWord rhs, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
|
||||
inline void branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rhs, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
|
||||
template <typename T>
|
||||
inline CodeOffsetJump branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label) PER_SHARED_ARCH;
|
||||
|
|
@ -1014,7 +1020,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline CodeOffsetJump branchPtrWithPatch(Condition cond, Address lhs, T rhs, RepatchLabel* label) PER_SHARED_ARCH;
|
||||
|
||||
void branchPtrInNurseryChunk(Condition cond, Register ptr, Register temp, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
void branchPtrInNurseryChunk(Condition cond, const Address& address, Register temp, Label* label)
|
||||
DEFINED_ON(x86);
|
||||
void branchValueIsNurseryObject(Condition cond, const Address& address, Register temp, Label* label) PER_ARCH;
|
||||
|
|
@ -1032,9 +1038,9 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
// which isn't implemented on all architectures.
|
||||
// E.g. the x64 variants will do this only in the int64_t range.
|
||||
inline void branchTruncateFloat32MaybeModUint32(FloatRegister src, Register dest, Label* fail)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
inline void branchTruncateDoubleMaybeModUint32(FloatRegister src, Register dest, Label* fail)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
|
||||
// Truncate a double/float32 to intptr and when it doesn't fit jump to the failure label.
|
||||
inline void branchTruncateFloat32ToPtr(FloatRegister src, Register dest, Label* fail)
|
||||
|
|
@ -1044,9 +1050,9 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
|
||||
// Truncate a double/float32 to int32 and when it doesn't fit jump to the failure label.
|
||||
inline void branchTruncateFloat32ToInt32(FloatRegister src, Register dest, Label* fail)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
inline void branchTruncateDoubleToInt32(FloatRegister src, Register dest, Label* fail)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
|
||||
inline void branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
|
||||
Label* label) PER_SHARED_ARCH;
|
||||
|
|
@ -1069,7 +1075,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void branchTest32(Condition cond, Register lhs, Imm32 rhs, L label) PER_SHARED_ARCH;
|
||||
inline void branchTest32(Condition cond, const Address& lhs, Imm32 rhh, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTest32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
|
||||
DEFINED_ON(arm, arm64, mips_shared, x86, x64, loongarch64);
|
||||
|
||||
template <class L>
|
||||
inline void branchTestPtr(Condition cond, Register lhs, Register rhs, L label) PER_SHARED_ARCH;
|
||||
|
|
@ -1132,7 +1138,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void branchTestUndefined(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestInt32(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestDouble(Condition cond, Register tag, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
inline void branchTestNumber(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestBoolean(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestString(Condition cond, Register tag, Label* label) PER_SHARED_ARCH;
|
||||
|
|
@ -1150,60 +1156,60 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void branchTestUndefined(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestUndefined(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestUndefined(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestInt32(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestInt32(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestInt32(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestDouble(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestDouble(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestDouble(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestNumber(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestBoolean(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestBoolean(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestBoolean(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestString(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestString(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestSymbol(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestSymbol(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestBigInt(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestBigInt(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestNull(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestNull(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestNull(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
// Clobbers the ScratchReg on x64.
|
||||
inline void branchTestObject(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestObject(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestObject(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestGCThing(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestGCThing(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
|
||||
inline void branchTestPrimitive(Condition cond, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestMagic(Condition cond, const Address& address, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestMagic(Condition cond, const BaseIndex& address, Label* label) PER_SHARED_ARCH;
|
||||
template <class L>
|
||||
inline void branchTestMagic(Condition cond, const ValueOperand& value, L label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
inline void branchTestMagic(Condition cond, const Address& valaddr, JSWhyMagic why, Label* label) PER_ARCH;
|
||||
|
||||
|
|
@ -1216,13 +1222,13 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
// Checks if given Value is evaluated to true or false in a condition.
|
||||
// The type of the value should match the type of the method.
|
||||
inline void branchTestInt32Truthy(bool truthy, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
inline void branchTestDoubleTruthy(bool truthy, FloatRegister reg, Label* label) PER_SHARED_ARCH;
|
||||
inline void branchTestBooleanTruthy(bool truthy, const ValueOperand& value, Label* label) PER_ARCH;
|
||||
inline void branchTestStringTruthy(bool truthy, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
inline void branchTestBigIntTruthy(bool truthy, const ValueOperand& value, Label* label)
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, x86_shared);
|
||||
DEFINED_ON(arm, arm64, mips32, mips64, loongarch64, x86_shared);
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -1294,9 +1300,9 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
// ========================================================================
|
||||
// Memory access primitives.
|
||||
inline void storeUncanonicalizedDouble(FloatRegister src, const Address& dest)
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64);
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loongarch64);
|
||||
inline void storeUncanonicalizedDouble(FloatRegister src, const BaseIndex& dest)
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64);
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loongarch64);
|
||||
inline void storeUncanonicalizedDouble(FloatRegister src, const Operand& dest)
|
||||
DEFINED_ON(x86_shared);
|
||||
|
||||
|
|
@ -1304,9 +1310,9 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
inline void storeDouble(FloatRegister src, const T& dest);
|
||||
|
||||
inline void storeUncanonicalizedFloat32(FloatRegister src, const Address& dest)
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64);
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loongarch64);
|
||||
inline void storeUncanonicalizedFloat32(FloatRegister src, const BaseIndex& dest)
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64);
|
||||
DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loongarch64);
|
||||
inline void storeUncanonicalizedFloat32(FloatRegister src, const Operand& dest)
|
||||
DEFINED_ON(x86_shared);
|
||||
|
||||
|
|
@ -1747,7 +1753,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
template <typename T> inline void addToStackPtr(T t);
|
||||
template <typename T> inline void addStackPtrTo(T t);
|
||||
|
||||
void subFromStackPtr(Imm32 imm32) DEFINED_ON(mips32, mips64, arm, x86, x64);
|
||||
void subFromStackPtr(Imm32 imm32) DEFINED_ON(mips32, mips64, loongarch64, arm, x86, x64);
|
||||
void subFromStackPtr(Register reg);
|
||||
|
||||
template <typename T>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
# include "jit/arm/MoveEmitter-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/MoveEmitter-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/mips64/MoveEmitter-mips64.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/MoveEmitter-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
# include "jit/arm/Architecture-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/Architecture-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/loongarch64/Architecture-loongarch64.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/Architecture-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
# include "jit/arm/SharedICHelpers-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/SharedICHelpers-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/loongarch64/SharedICHelpers-loongarch64.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
#include "jit/mips-shared/SharedICHelpers-mips-shared.h"
|
||||
#elif defined(JS_CODEGEN_NONE)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
# include "jit/arm/SharedICRegisters-arm.h"
|
||||
#elif defined(JS_CODEGEN_ARM64)
|
||||
# include "jit/arm64/SharedICRegisters-arm64.h"
|
||||
#elif defined(JS_CODEGEN_LOONGARCH64)
|
||||
# include "jit/loongarch64/SharedICRegisters-loongarch64.h"
|
||||
#elif defined(JS_CODEGEN_MIPS32)
|
||||
# include "jit/mips32/SharedICRegisters-mips32.h"
|
||||
#elif defined(JS_CODEGEN_MIPS64)
|
||||
|
|
|
|||
98
js/src/jit/loongarch64/Architecture-loongarch64.cpp
Normal file
98
js/src/jit/loongarch64/Architecture-loongarch64.cpp
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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 "jit/loongarch64/Architecture-loongarch64.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#ifdef JS_SIMULATOR
|
||||
# include "jit/loongarch64/Simulator-loongarch64.h"
|
||||
#endif
|
||||
#include "jit/RegisterSets.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
Registers::Code Registers::FromName(const char* name) {
|
||||
for (size_t i = 0; i < TotalPhys; i++) {
|
||||
if (strcmp(GetName(i), name) == 0) {
|
||||
return Code(i);
|
||||
}
|
||||
}
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
FloatRegisters::Code FloatRegisters::FromName(const char* name) {
|
||||
for (size_t i = 0; i < TotalPhys; i++) {
|
||||
if (strcmp(GetName(i), name) == 0) {
|
||||
return Code(i);
|
||||
}
|
||||
}
|
||||
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
FloatRegisterSet FloatRegister::ReduceSetForPush(const FloatRegisterSet& s) {
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
# error "Needs more careful logic if SIMD is enabled"
|
||||
#endif
|
||||
|
||||
LiveFloatRegisterSet ret;
|
||||
for (FloatRegisterIterator iter(s); iter.more(); ++iter) {
|
||||
ret.addUnchecked(FromCode((*iter).encoding()));
|
||||
}
|
||||
return ret.set();
|
||||
}
|
||||
|
||||
uint32_t FloatRegister::GetSizeInBytes(const FloatRegisterSet& s) {
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
# error "Needs more careful logic if SIMD is enabled"
|
||||
#endif
|
||||
|
||||
return s.size() * sizeof(double);
|
||||
}
|
||||
|
||||
uint32_t FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s) {
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
# error "Needs more careful logic if SIMD is enabled"
|
||||
#endif
|
||||
|
||||
return s.size() * sizeof(double);
|
||||
}
|
||||
|
||||
uint32_t FloatRegister::getRegisterDumpOffsetInBytes() {
|
||||
#ifdef ENABLE_WASM_SIMD
|
||||
# error "Needs more careful logic if SIMD is enabled"
|
||||
#endif
|
||||
|
||||
return encoding() * sizeof(double);
|
||||
}
|
||||
|
||||
bool CPUFlagsHaveBeenComputed() {
|
||||
// TODO(loongarch64): Add CPU flags support.
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t GetLOONGARCH64Flags() { return 0; }
|
||||
|
||||
void FlushICache(void* code, size_t size, bool codeIsThreadLocal) {
|
||||
#if defined(JS_SIMULATOR)
|
||||
js::jit::SimulatorProcess::FlushICache(code, size);
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
intptr_t end = reinterpret_cast<intptr_t>(code) + size;
|
||||
__builtin___clear_cache(reinterpret_cast<char*>(code),
|
||||
reinterpret_cast<char*>(end));
|
||||
|
||||
#else
|
||||
_flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
510
js/src/jit/loongarch64/Architecture-loongarch64.h
Normal file
510
js/src/jit/loongarch64/Architecture-loongarch64.h
Normal file
|
|
@ -0,0 +1,510 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
#ifndef jit_loongarch64_Architecture_loongarch64_h
|
||||
#define jit_loongarch64_Architecture_loongarch64_h
|
||||
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// LoongArch64 has 32 64-bit integer registers, r0 though r31.
|
||||
// The program counter is not accessible as a register.
|
||||
//
|
||||
// SIMD and scalar floating-point registers share a register bank.
|
||||
// Floating-point registers are f0 through f31.
|
||||
// 128 bit SIMD registers are vr0 through vr31.
|
||||
// e.g., f0 is the bottom 64 bits of vr0.
|
||||
|
||||
// LoongArch64 INT Register Convention:
|
||||
// Name Alias Usage
|
||||
// $r0 $zero Constant zero
|
||||
// $r1 $ra Return address
|
||||
// $r2 $tp TLS
|
||||
// $r3 $sp Stack pointer
|
||||
// $r4-$r11 $a0-$a7 Argument registers
|
||||
// $r4-$r5 $v0-$v1 Return values
|
||||
// $r12-$r20 $t0-$t8 Temporary registers
|
||||
// $r21 $x Reserved
|
||||
// $r22 $fp Frame pointer
|
||||
// $r23-$r31 $s0-$s8 Callee-saved registers
|
||||
|
||||
// LoongArch64 FP Register Convention:
|
||||
// Name Alias Usage
|
||||
// $f0-$f7 $fa0-$fa7 Argument registers
|
||||
// $f0-$f1 $fv0-$fv1 Return values
|
||||
// $f8-f23 $ft0-$ft15 Temporary registers
|
||||
// $f24-$f31 $fs0-$fs7 Callee-saved registers
|
||||
|
||||
class Registers {
|
||||
public:
|
||||
enum RegisterID {
|
||||
r0 = 0,
|
||||
r1,
|
||||
r2,
|
||||
r3,
|
||||
r4,
|
||||
r5,
|
||||
r6,
|
||||
r7,
|
||||
r8,
|
||||
r9,
|
||||
r10,
|
||||
r11,
|
||||
r12,
|
||||
r13,
|
||||
r14,
|
||||
r15,
|
||||
r16,
|
||||
r17,
|
||||
r18,
|
||||
r19,
|
||||
r20,
|
||||
r21,
|
||||
r22,
|
||||
r23,
|
||||
r24,
|
||||
r25,
|
||||
r26,
|
||||
r27,
|
||||
r28,
|
||||
r29,
|
||||
r30,
|
||||
r31,
|
||||
zero = r0,
|
||||
ra = r1,
|
||||
tp = r2,
|
||||
sp = r3,
|
||||
a0 = r4,
|
||||
a1 = r5,
|
||||
a2 = r6,
|
||||
a3 = r7,
|
||||
a4 = r8,
|
||||
a5 = r9,
|
||||
a6 = r10,
|
||||
a7 = r11,
|
||||
t0 = r12,
|
||||
t1 = r13,
|
||||
t2 = r14,
|
||||
t3 = r15,
|
||||
t4 = r16,
|
||||
t5 = r17,
|
||||
t6 = r18,
|
||||
t7 = r19,
|
||||
t8 = r20,
|
||||
rx = r21,
|
||||
fp = r22,
|
||||
s0 = r23,
|
||||
s1 = r24,
|
||||
s2 = r25,
|
||||
s3 = r26,
|
||||
s4 = r27,
|
||||
s5 = r28,
|
||||
s6 = r29,
|
||||
s7 = r30,
|
||||
s8 = r31,
|
||||
invalid_reg,
|
||||
};
|
||||
typedef uint8_t Code;
|
||||
typedef RegisterID Encoding;
|
||||
typedef uint32_t SetType;
|
||||
|
||||
static const Encoding StackPointer = sp;
|
||||
static const Encoding Invalid = invalid_reg;
|
||||
|
||||
// Content spilled during bailouts.
|
||||
union RegisterContent {
|
||||
uintptr_t r;
|
||||
};
|
||||
|
||||
static uint32_t SetSize(SetType x) {
|
||||
static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
|
||||
return mozilla::CountPopulation32(x);
|
||||
}
|
||||
static uint32_t FirstBit(SetType x) {
|
||||
return mozilla::CountTrailingZeroes32(x);
|
||||
}
|
||||
static uint32_t LastBit(SetType x) {
|
||||
return 31 - mozilla::CountLeadingZeroes32(x);
|
||||
}
|
||||
|
||||
static const char* GetName(uint32_t code) {
|
||||
static const char* const Names[] = {
|
||||
"zero", "ra", "tp", "sp", "a0", "a1", "a2", "a3", "a4", "a5", "a6",
|
||||
"a7", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "rx",
|
||||
"fp", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8"};
|
||||
static_assert(Total == sizeof(Names) / sizeof(Names[0]),
|
||||
"Table is the correct size");
|
||||
if ((code & 31) >= TotalPhys) {
|
||||
return "invalid";
|
||||
}
|
||||
return Names[code & 31];
|
||||
}
|
||||
|
||||
static Code FromName(const char* name);
|
||||
|
||||
static const uint32_t Total = 32;
|
||||
static const uint32_t TotalPhys = 32;
|
||||
static const uint32_t Allocatable =
|
||||
23; // No named special-function registers.
|
||||
|
||||
static const SetType AllMask = 0xFFFFFFFF;
|
||||
static const SetType NoneMask = 0x0;
|
||||
|
||||
static const SetType ArgRegMask =
|
||||
(1 << Registers::a0) | (1 << Registers::a1) | (1 << Registers::a2) |
|
||||
(1 << Registers::a3) | (1 << Registers::a4) | (1 << Registers::a5) |
|
||||
(1 << Registers::a6) | (1 << Registers::a7);
|
||||
|
||||
static const SetType VolatileMask =
|
||||
(1 << Registers::a0) | (1 << Registers::a1) | (1 << Registers::a2) |
|
||||
(1 << Registers::a3) | (1 << Registers::a4) | (1 << Registers::a5) |
|
||||
(1 << Registers::a6) | (1 << Registers::a7) | (1 << Registers::t0) |
|
||||
(1 << Registers::t1) | (1 << Registers::t2) | (1 << Registers::t3) |
|
||||
(1 << Registers::t4) | (1 << Registers::t5) | (1 << Registers::t6);
|
||||
|
||||
// We use this constant to save registers when entering functions. This
|
||||
// is why $ra is added here even though it is not "Non Volatile".
|
||||
static const SetType NonVolatileMask =
|
||||
(1 << Registers::ra) | (1 << Registers::fp) | (1 << Registers::s0) |
|
||||
(1 << Registers::s1) | (1 << Registers::s2) | (1 << Registers::s3) |
|
||||
(1 << Registers::s4) | (1 << Registers::s5) | (1 << Registers::s6) |
|
||||
(1 << Registers::s7) | (1 << Registers::s8);
|
||||
|
||||
static const SetType SingleByteRegs = VolatileMask | NonVolatileMask;
|
||||
|
||||
static const SetType NonAllocatableMask =
|
||||
(1 << Registers::zero) | // Always be zero.
|
||||
(1 << Registers::t7) | // First scratch register.
|
||||
(1 << Registers::t8) | // Second scratch register.
|
||||
(1 << Registers::rx) | // Reserved Register.
|
||||
(1 << Registers::ra) | (1 << Registers::tp) | (1 << Registers::sp);
|
||||
|
||||
static const SetType TempMask = VolatileMask & ~NonAllocatableMask;
|
||||
|
||||
static const SetType WrapperMask = VolatileMask;
|
||||
|
||||
// Registers returned from a JS -> JS call.
|
||||
static const SetType JSCallMask = (1 << Registers::a2);
|
||||
|
||||
// Registers returned from a JS -> C call.
|
||||
static const SetType CallMask = (1 << Registers::a0);
|
||||
|
||||
static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
|
||||
};
|
||||
|
||||
// Smallest integer type that can hold a register bitmask.
|
||||
typedef uint32_t PackedRegisterMask;
|
||||
|
||||
template <typename T>
|
||||
class TypedRegisterSet;
|
||||
|
||||
class FloatRegisters {
|
||||
public:
|
||||
enum FPRegisterID {
|
||||
f0 = 0,
|
||||
f1,
|
||||
f2,
|
||||
f3,
|
||||
f4,
|
||||
f5,
|
||||
f6,
|
||||
f7,
|
||||
f8,
|
||||
f9,
|
||||
f10,
|
||||
f11,
|
||||
f12,
|
||||
f13,
|
||||
f14,
|
||||
f15,
|
||||
f16,
|
||||
f17,
|
||||
f18,
|
||||
f19,
|
||||
f20,
|
||||
f21,
|
||||
f22,
|
||||
f23, // Scratch register.
|
||||
f24,
|
||||
f25,
|
||||
f26,
|
||||
f27,
|
||||
f28,
|
||||
f29,
|
||||
f30,
|
||||
f31,
|
||||
};
|
||||
|
||||
// Eight bits: (invalid << 7) | (kind << 5) | encoding
|
||||
typedef uint8_t Code;
|
||||
typedef FPRegisterID Encoding;
|
||||
typedef uint64_t SetType;
|
||||
|
||||
enum Kind : uint8_t { Double, Single, NumTypes };
|
||||
|
||||
static constexpr Code Invalid = 0x80;
|
||||
|
||||
static const char* GetName(uint32_t code) {
|
||||
static const char* const Names[] = {
|
||||
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
||||
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
|
||||
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
|
||||
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"};
|
||||
static_assert(TotalPhys == sizeof(Names) / sizeof(Names[0]),
|
||||
"Table is the correct size");
|
||||
if ((code & 31) >= TotalPhys) {
|
||||
return "invalid";
|
||||
}
|
||||
return Names[code & 31];
|
||||
}
|
||||
|
||||
static Code FromName(const char* name);
|
||||
|
||||
static const uint32_t TotalPhys = 32;
|
||||
static const uint32_t Total = TotalPhys * NumTypes;
|
||||
static const uint32_t Allocatable = 31; // Without f23, the scratch register.
|
||||
|
||||
static_assert(sizeof(SetType) * 8 >= Total,
|
||||
"SetType should be large enough to enumerate all registers.");
|
||||
|
||||
// Magic values which are used to duplicate a mask of physical register for
|
||||
// a specific type of register. A multiplication is used to copy and shift
|
||||
// the bits of the physical register mask.
|
||||
static const SetType SpreadSingle = SetType(1)
|
||||
<< (uint32_t(Single) * TotalPhys);
|
||||
static const SetType SpreadDouble = SetType(1)
|
||||
<< (uint32_t(Double) * TotalPhys);
|
||||
static const SetType Spread = SpreadSingle | SpreadDouble;
|
||||
|
||||
static const SetType AllPhysMask = ((SetType(1) << TotalPhys) - 1);
|
||||
static const SetType AllMask = AllPhysMask * Spread;
|
||||
static const SetType AllSingleMask = AllPhysMask * SpreadSingle;
|
||||
static const SetType AllDoubleMask = AllPhysMask * SpreadDouble;
|
||||
static const SetType NoneMask = SetType(0);
|
||||
|
||||
// TODO(loongarch64): Much less than ARM64 here.
|
||||
static const SetType NonVolatileMask =
|
||||
SetType((1 << FloatRegisters::f24) | (1 << FloatRegisters::f25) |
|
||||
(1 << FloatRegisters::f26) | (1 << FloatRegisters::f27) |
|
||||
(1 << FloatRegisters::f28) | (1 << FloatRegisters::f29) |
|
||||
(1 << FloatRegisters::f30) | (1 << FloatRegisters::f31)) *
|
||||
Spread;
|
||||
|
||||
static const SetType VolatileMask = AllMask & ~NonVolatileMask;
|
||||
|
||||
static const SetType WrapperMask = VolatileMask;
|
||||
|
||||
// f23 is the scratch register.
|
||||
static const SetType NonAllocatableMask =
|
||||
(SetType(1) << FloatRegisters::f23) * Spread;
|
||||
|
||||
static const SetType TempMask = VolatileMask & ~NonAllocatableMask;
|
||||
|
||||
static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
|
||||
|
||||
// Content spilled during bailouts.
|
||||
union RegisterContent {
|
||||
float s;
|
||||
double d;
|
||||
};
|
||||
|
||||
static constexpr Encoding encoding(Code c) {
|
||||
// assert() not available in constexpr function.
|
||||
// assert(c < Total);
|
||||
return Encoding(c & 31);
|
||||
}
|
||||
|
||||
static constexpr Kind kind(Code c) {
|
||||
// assert() not available in constexpr function.
|
||||
// assert(c < Total && ((c >> 5) & 3) < NumTypes);
|
||||
return Kind((c >> 5) & 3);
|
||||
}
|
||||
|
||||
static constexpr Code fromParts(uint32_t encoding, uint32_t kind,
|
||||
uint32_t invalid) {
|
||||
return Code((invalid << 7) | (kind << 5) | encoding);
|
||||
}
|
||||
};
|
||||
|
||||
static const uint32_t SpillSlotSize =
|
||||
std::max(sizeof(Registers::RegisterContent),
|
||||
sizeof(FloatRegisters::RegisterContent));
|
||||
|
||||
static const uint32_t ION_FRAME_SLACK_SIZE = 24;
|
||||
static const uint32_t ShadowStackSpace = 0;
|
||||
static const uint32_t SizeOfReturnAddressAfterCall = 0;
|
||||
|
||||
// When our only strategy for far jumps is to encode the offset directly, and
|
||||
// not insert any jump islands during assembly for even further jumps, then the
|
||||
// architecture restricts us to -2^27 .. 2^27-4, to fit into a signed 28-bit
|
||||
// value. We further reduce this range to allow the far-jump inserting code to
|
||||
// have some breathing room.
|
||||
static const uint32_t JumpImmediateRange = ((1 << 27) - (20 * 1024 * 1024));
|
||||
|
||||
struct FloatRegister {
|
||||
typedef FloatRegisters Codes;
|
||||
typedef Codes::Code Code;
|
||||
typedef Codes::Encoding Encoding;
|
||||
typedef Codes::SetType SetType;
|
||||
|
||||
static uint32_t SetSize(SetType x) {
|
||||
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
|
||||
x |= x >> FloatRegisters::TotalPhys;
|
||||
x &= FloatRegisters::AllPhysMask;
|
||||
return mozilla::CountPopulation32(x);
|
||||
}
|
||||
|
||||
static uint32_t FirstBit(SetType x) {
|
||||
static_assert(sizeof(SetType) == 8, "SetType");
|
||||
return mozilla::CountTrailingZeroes64(x);
|
||||
}
|
||||
static uint32_t LastBit(SetType x) {
|
||||
static_assert(sizeof(SetType) == 8, "SetType");
|
||||
return 63 - mozilla::CountLeadingZeroes64(x);
|
||||
}
|
||||
|
||||
private:
|
||||
// These fields only hold valid values: an invalid register is always
|
||||
// represented as a valid encoding and kind with the invalid_ bit set.
|
||||
uint8_t encoding_; // 32 encodings
|
||||
uint8_t kind_; // Double, Single; more later
|
||||
bool invalid_;
|
||||
|
||||
typedef Codes::Kind Kind;
|
||||
|
||||
public:
|
||||
union RegisterContent {
|
||||
float s;
|
||||
double d;
|
||||
};
|
||||
|
||||
constexpr FloatRegister(Encoding encoding, Kind kind)
|
||||
: encoding_(encoding), kind_(kind), invalid_(false) {
|
||||
// assert(uint32_t(encoding) < Codes::TotalPhys);
|
||||
}
|
||||
|
||||
explicit constexpr FloatRegister(uint32_t code)
|
||||
: encoding_(FloatRegisters::encoding(code)),
|
||||
kind_(FloatRegisters::kind(code)),
|
||||
invalid_(false) {}
|
||||
|
||||
constexpr FloatRegister()
|
||||
: encoding_(0), kind_(FloatRegisters::Double), invalid_(true) {}
|
||||
|
||||
static FloatRegister FromCode(uint32_t i) {
|
||||
MOZ_ASSERT(i < Codes::Total);
|
||||
return FloatRegister(FloatRegisters::encoding(i), FloatRegisters::kind(i));
|
||||
}
|
||||
|
||||
bool isSingle() const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
return kind_ == FloatRegisters::Single;
|
||||
}
|
||||
bool isDouble() const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
return kind_ == FloatRegisters::Double;
|
||||
}
|
||||
bool isSimd128() const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
return false;
|
||||
}
|
||||
bool isInvalid() const { return invalid_; }
|
||||
|
||||
FloatRegister asSingle() const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
return FloatRegister(Encoding(encoding_), FloatRegisters::Single);
|
||||
}
|
||||
FloatRegister asDouble() const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
return FloatRegister(Encoding(encoding_), FloatRegisters::Double);
|
||||
}
|
||||
FloatRegister asSimd128() const { MOZ_CRASH(); }
|
||||
|
||||
constexpr uint32_t size() const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
if (kind_ == FloatRegisters::Double) {
|
||||
return sizeof(double);
|
||||
}
|
||||
MOZ_ASSERT(kind_ == FloatRegisters::Single);
|
||||
return sizeof(float);
|
||||
}
|
||||
|
||||
constexpr Code code() const {
|
||||
// assert(!invalid_);
|
||||
return Codes::fromParts(encoding_, kind_, invalid_);
|
||||
}
|
||||
|
||||
constexpr Encoding encoding() const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
return Encoding(encoding_);
|
||||
}
|
||||
|
||||
const char* name() const { return FloatRegisters::GetName(uint32_t(encoding_)); }
|
||||
bool volatile_() const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
return !!((SetType(1) << code()) & FloatRegisters::VolatileMask);
|
||||
}
|
||||
constexpr bool operator!=(FloatRegister other) const {
|
||||
return code() != other.code();
|
||||
}
|
||||
constexpr bool operator==(FloatRegister other) const {
|
||||
return code() == other.code();
|
||||
}
|
||||
|
||||
bool aliases(FloatRegister other) const {
|
||||
return other.encoding_ == encoding_;
|
||||
}
|
||||
// Ensure that two floating point registers' types are equivalent.
|
||||
bool equiv(FloatRegister other) const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
return kind_ == other.kind_;
|
||||
}
|
||||
|
||||
uint32_t numAliased() const { return Codes::NumTypes; }
|
||||
uint32_t numAlignedAliased() const { return numAliased(); }
|
||||
|
||||
void aliased(uint32_t aliasIdx, FloatRegister* ret) const {
|
||||
MOZ_ASSERT(!invalid_);
|
||||
MOZ_ASSERT(aliasIdx < numAliased());
|
||||
*ret = FloatRegister(Encoding(encoding_),
|
||||
Kind((aliasIdx + kind_) % numAliased()));
|
||||
}
|
||||
void alignedAliased(uint32_t aliasIdx, FloatRegister* ret) const {
|
||||
MOZ_ASSERT(aliasIdx < numAliased());
|
||||
aliased(aliasIdx, ret);
|
||||
}
|
||||
SetType alignedOrDominatedAliasedSet() const {
|
||||
return Codes::Spread << encoding_;
|
||||
}
|
||||
|
||||
static Code FromName(const char* name) { return FloatRegisters::FromName(name); }
|
||||
static TypedRegisterSet<FloatRegister> ReduceSetForPush(
|
||||
const TypedRegisterSet<FloatRegister>& s);
|
||||
static uint32_t GetSizeInBytes(const TypedRegisterSet<FloatRegister>& s);
|
||||
static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>& s);
|
||||
uint32_t getRegisterDumpOffsetInBytes();
|
||||
};
|
||||
|
||||
// LoongArch doesn't have double registers that cannot be treated as float32.
|
||||
inline bool hasUnaliasedDouble() { return false; }
|
||||
|
||||
// LoongArch doesn't have double registers that alias multiple floats.
|
||||
inline bool hasMultiAlias() { return false; }
|
||||
|
||||
uint32_t GetLOONGARCH64Flags();
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
#endif /* jit_loongarch64_Architecture_loongarch64_h */
|
||||
2491
js/src/jit/loongarch64/Assembler-loongarch64.cpp
Normal file
2491
js/src/jit/loongarch64/Assembler-loongarch64.cpp
Normal file
File diff suppressed because it is too large
Load diff
1888
js/src/jit/loongarch64/Assembler-loongarch64.h
Normal file
1888
js/src/jit/loongarch64/Assembler-loongarch64.h
Normal file
File diff suppressed because it is too large
Load diff
27
js/src/jit/loongarch64/Bailouts-loongarch64.cpp
Normal file
27
js/src/jit/loongarch64/Bailouts-loongarch64.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "jit/loongarch64/Bailouts-loongarch64.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jscompartment.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& activations,
|
||||
BailoutStack* bailout)
|
||||
: machine_(bailout->machineState())
|
||||
{
|
||||
uint8_t* sp = bailout->parentStackPointer();
|
||||
framePointer_ = sp + bailout->frameSize();
|
||||
topFrameSize_ = framePointer_ - sp;
|
||||
|
||||
JSScript* script = ScriptFromCalleeToken(((JitFrameLayout*) framePointer_)->calleeToken());
|
||||
topIonScript_ = script->ionScript();
|
||||
|
||||
attachOnJitActivation(activations);
|
||||
snapshotOffset_ = bailout->snapshotOffset();
|
||||
}
|
||||
43
js/src/jit/loongarch64/Bailouts-loongarch64.h
Normal file
43
js/src/jit/loongarch64/Bailouts-loongarch64.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef jit_loongarch64_Bailouts_loongarch64_h
|
||||
#define jit_loongarch64_Bailouts_loongarch64_h
|
||||
|
||||
#include "jit/Bailouts.h"
|
||||
#include "jit/JitCompartment.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class BailoutStack
|
||||
{
|
||||
RegisterDump::FPUArray fpregs_;
|
||||
RegisterDump::GPRArray regs_;
|
||||
uintptr_t frameSize_;
|
||||
uintptr_t snapshotOffset_;
|
||||
|
||||
public:
|
||||
MachineState machineState() {
|
||||
return MachineState::FromBailout(regs_, fpregs_);
|
||||
}
|
||||
uint32_t snapshotOffset() const {
|
||||
return snapshotOffset_;
|
||||
}
|
||||
uint32_t frameSize() const {
|
||||
return frameSize_;
|
||||
}
|
||||
uint8_t* parentStackPointer() {
|
||||
return (uint8_t*)this + sizeof(BailoutStack);
|
||||
}
|
||||
static size_t offsetOfFrameSize() {
|
||||
return offsetof(BailoutStack, frameSize_);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
#endif /* jit_loongarch64_Bailouts_loongarch64_h */
|
||||
15
js/src/jit/loongarch64/BaselineCompiler-loongarch64.cpp
Normal file
15
js/src/jit/loongarch64/BaselineCompiler-loongarch64.cpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "jit/loongarch64/BaselineCompiler-loongarch64.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
BaselineCompilerLOONGARCH64::BaselineCompilerLOONGARCH64(JSContext* cx, TempAllocator& alloc,
|
||||
JSScript* script)
|
||||
: BaselineCompilerMIPSShared(cx, alloc, script)
|
||||
{
|
||||
}
|
||||
25
js/src/jit/loongarch64/BaselineCompiler-loongarch64.h
Normal file
25
js/src/jit/loongarch64/BaselineCompiler-loongarch64.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef jit_loongarch64_BaselineCompiler_loongarch64_h
|
||||
#define jit_loongarch64_BaselineCompiler_loongarch64_h
|
||||
|
||||
#include "jit/mips-shared/BaselineCompiler-mips-shared.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class BaselineCompilerLOONGARCH64 : public BaselineCompilerMIPSShared
|
||||
{
|
||||
protected:
|
||||
BaselineCompilerLOONGARCH64(JSContext* cx, TempAllocator& alloc, JSScript* script);
|
||||
};
|
||||
|
||||
typedef BaselineCompilerLOONGARCH64 BaselineCompilerSpecific;
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
#endif /* jit_loongarch64_BaselineCompiler_loongarch64_h */
|
||||
46
js/src/jit/loongarch64/BaselineIC-loongarch64.cpp
Normal file
46
js/src/jit/loongarch64/BaselineIC-loongarch64.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "jit/BaselineCompiler.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/Linker.h"
|
||||
#include "jit/SharedICHelpers.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// ICCompare_Int32
|
||||
|
||||
bool
|
||||
ICCompare_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
// Guard that R0 is an integer and R1 is an integer.
|
||||
Label failure;
|
||||
Label conditionTrue;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
|
||||
|
||||
// Compare payload regs of R0 and R1.
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
masm.unboxInt32(R1, ExtractTemp1);
|
||||
Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
|
||||
masm.ma_cmp_set(R0.valueReg(), ExtractTemp0, ExtractTemp1, cond);
|
||||
|
||||
masm.tagValue(JSVAL_TYPE_BOOLEAN, R0.valueReg(), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
1445
js/src/jit/loongarch64/MacroAssembler-loongarch64-inl.h
Normal file
1445
js/src/jit/loongarch64/MacroAssembler-loongarch64-inl.h
Normal file
File diff suppressed because it is too large
Load diff
5285
js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp
Normal file
5285
js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp
Normal file
File diff suppressed because it is too large
Load diff
1088
js/src/jit/loongarch64/MacroAssembler-loongarch64.h
Normal file
1088
js/src/jit/loongarch64/MacroAssembler-loongarch64.h
Normal file
File diff suppressed because it is too large
Load diff
190
js/src/jit/loongarch64/SharedIC-loongarch64.cpp
Normal file
190
js/src/jit/loongarch64/SharedIC-loongarch64.cpp
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "jsiter.h"
|
||||
|
||||
#include "jit/BaselineCompiler.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/Linker.h"
|
||||
#include "jit/SharedICHelpers.h"
|
||||
|
||||
#include "jsboolinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// ICBinaryArith_Int32
|
||||
|
||||
bool
|
||||
ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
// Guard that R0 is an integer and R1 is an integer.
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
|
||||
|
||||
// Add R0 and R1. Don't need to explicitly unbox, just use R2's valueReg.
|
||||
Register scratchReg = R2.valueReg();
|
||||
|
||||
Label goodMul, divTest1, divTest2;
|
||||
switch(op_) {
|
||||
case JSOP_ADD:
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
masm.unboxInt32(R1, ExtractTemp1);
|
||||
masm.ma_addTestOverflow(scratchReg, ExtractTemp0, ExtractTemp1, &failure);
|
||||
masm.boxValue(JSVAL_TYPE_INT32, scratchReg, R0.valueReg());
|
||||
break;
|
||||
case JSOP_SUB:
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
masm.unboxInt32(R1, ExtractTemp1);
|
||||
masm.ma_subTestOverflow(scratchReg, ExtractTemp0, ExtractTemp1, &failure);
|
||||
masm.boxValue(JSVAL_TYPE_INT32, scratchReg, R0.valueReg());
|
||||
break;
|
||||
case JSOP_MUL: {
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
masm.unboxInt32(R1, ExtractTemp1);
|
||||
masm.ma_mul_branch_overflow(scratchReg, ExtractTemp0, ExtractTemp1, &failure);
|
||||
|
||||
masm.ma_b(scratchReg, Imm32(0), &goodMul, Assembler::NotEqual, ShortJump);
|
||||
|
||||
// Result is -0 if operands have different signs.
|
||||
masm.as_xor(t8, ExtractTemp0, ExtractTemp1);
|
||||
masm.ma_b(t8, Imm32(0), &failure, Assembler::LessThan, ShortJump);
|
||||
|
||||
masm.bind(&goodMul);
|
||||
masm.boxValue(JSVAL_TYPE_INT32, scratchReg, R0.valueReg());
|
||||
break;
|
||||
}
|
||||
case JSOP_DIV:
|
||||
case JSOP_MOD: {
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
masm.unboxInt32(R1, ExtractTemp1);
|
||||
// Check for INT_MIN / -1, it results in a double.
|
||||
masm.ma_b(ExtractTemp0, Imm32(INT_MIN), &divTest1, Assembler::NotEqual, ShortJump);
|
||||
masm.ma_b(ExtractTemp1, Imm32(-1), &failure, Assembler::Equal, ShortJump);
|
||||
masm.bind(&divTest1);
|
||||
|
||||
// Check for division by zero
|
||||
masm.ma_b(ExtractTemp1, Imm32(0), &failure, Assembler::Equal, ShortJump);
|
||||
|
||||
// Check for 0 / X with X < 0 (results in -0).
|
||||
masm.ma_b(ExtractTemp0, Imm32(0), &divTest2, Assembler::NotEqual, ShortJump);
|
||||
masm.ma_b(ExtractTemp1, Imm32(0), &failure, Assembler::LessThan, ShortJump);
|
||||
masm.bind(&divTest2);
|
||||
|
||||
masm.as_div(ExtractTemp0, ExtractTemp1);
|
||||
|
||||
if (op_ == JSOP_DIV) {
|
||||
// Result is a double if the remainder != 0.
|
||||
masm.as_mfhi(scratchReg);
|
||||
masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::NotEqual, ShortJump);
|
||||
masm.as_mflo(scratchReg);
|
||||
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
|
||||
} else {
|
||||
Label done;
|
||||
// If X % Y == 0 and X < 0, the result is -0.
|
||||
masm.as_mfhi(scratchReg);
|
||||
masm.ma_b(scratchReg, Imm32(0), &done, Assembler::NotEqual, ShortJump);
|
||||
masm.ma_b(ExtractTemp0, Imm32(0), &failure, Assembler::LessThan, ShortJump);
|
||||
masm.bind(&done);
|
||||
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSOP_BITOR:
|
||||
masm.as_or(R0.valueReg() , R0.valueReg(), R1.valueReg());
|
||||
break;
|
||||
case JSOP_BITXOR:
|
||||
masm.as_xor(scratchReg, R0.valueReg(), R1.valueReg());
|
||||
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
|
||||
break;
|
||||
case JSOP_BITAND:
|
||||
masm.as_and(R0.valueReg() , R0.valueReg(), R1.valueReg());
|
||||
break;
|
||||
case JSOP_LSH:
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
masm.unboxInt32(R1, ExtractTemp1);
|
||||
// MIPS will only use 5 lowest bits in R1 as shift offset.
|
||||
masm.ma_sll(scratchReg, ExtractTemp0, ExtractTemp1);
|
||||
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
|
||||
break;
|
||||
case JSOP_RSH:
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
masm.unboxInt32(R1, ExtractTemp1);
|
||||
masm.ma_sra(scratchReg, ExtractTemp0, ExtractTemp1);
|
||||
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
|
||||
break;
|
||||
case JSOP_URSH:
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
masm.unboxInt32(R1, ExtractTemp1);
|
||||
masm.ma_srl(scratchReg, ExtractTemp0, ExtractTemp1);
|
||||
if (allowDouble_) {
|
||||
Label toUint;
|
||||
masm.ma_b(scratchReg, Imm32(0), &toUint, Assembler::LessThan, ShortJump);
|
||||
|
||||
// Move result and box for return.
|
||||
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&toUint);
|
||||
masm.convertUInt32ToDouble(scratchReg, FloatReg1);
|
||||
masm.boxDouble(FloatReg1, R0);
|
||||
} else {
|
||||
masm.ma_b(scratchReg, Imm32(0), &failure, Assembler::LessThan, ShortJump);
|
||||
// Move result for return.
|
||||
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
|
||||
}
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
switch (op) {
|
||||
case JSOP_BITNOT:
|
||||
masm.not32(R0.valueReg());
|
||||
masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
|
||||
break;
|
||||
case JSOP_NEG:
|
||||
masm.unboxInt32(R0, ExtractTemp0);
|
||||
// Guard against 0 and MIN_INT, both result in a double.
|
||||
masm.branchTest32(Assembler::Zero, ExtractTemp0, Imm32(INT32_MAX), &failure);
|
||||
|
||||
masm.neg32(ExtractTemp0);
|
||||
masm.tagValue(JSVAL_TYPE_INT32, ExtractTemp0, R0);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected op");
|
||||
return false;
|
||||
}
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
381
js/src/jit/loongarch64/SharedICHelpers-loongarch64.h
Normal file
381
js/src/jit/loongarch64/SharedICHelpers-loongarch64.h
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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/. */
|
||||
|
||||
#ifndef jit_loongarch64_SharedICHelpers_loongarch64_h
|
||||
#define jit_loongarch64_SharedICHelpers_loongarch64_h
|
||||
|
||||
#include "jit/BaselineFrame.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "jit/SharedICRegisters.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// Distance from sp to the top Value inside an IC stub (no return address on
|
||||
// the stack on LoongArch).
|
||||
static const size_t ICStackValueOffset = 0;
|
||||
|
||||
inline void
|
||||
EmitRestoreTailCallReg(MacroAssembler& masm)
|
||||
{
|
||||
// No-op on LoongArch because ra register is always holding the return address.
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitRepushTailCallReg(MacroAssembler& masm)
|
||||
{
|
||||
// No-op on LoongArch because ra register is always holding the return address.
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitCallIC(CodeOffset* patchOffset, MacroAssembler& masm)
|
||||
{
|
||||
// Move ICEntry offset into ICStubReg.
|
||||
CodeOffset offset = masm.movWithPatch(ImmWord(-1), ICStubReg);
|
||||
*patchOffset = offset;
|
||||
|
||||
// Load stub pointer into ICStubReg.
|
||||
masm.loadPtr(Address(ICStubReg, ICEntry::offsetOfFirstStub()), ICStubReg);
|
||||
|
||||
// Load stubcode pointer from BaselineStubEntry.
|
||||
// R2 won't be active when we call ICs, so we can use it as scratch.
|
||||
masm.loadPtr(Address(ICStubReg, ICStub::offsetOfStubCode()), R2.scratchReg());
|
||||
|
||||
// Call the stubcode via a direct jump-and-link
|
||||
masm.call(R2.scratchReg());
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitEnterTypeMonitorIC(MacroAssembler& masm,
|
||||
size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
|
||||
{
|
||||
// This is expected to be called from within an IC, when ICStubReg
|
||||
// is properly initialized to point to the stub.
|
||||
masm.loadPtr(Address(ICStubReg, (uint32_t) monitorStubOffset), ICStubReg);
|
||||
|
||||
// Load stubcode pointer from BaselineStubEntry.
|
||||
// R2 won't be active when we call ICs, so we can use it.
|
||||
masm.loadPtr(Address(ICStubReg, ICStub::offsetOfStubCode()), R2.scratchReg());
|
||||
|
||||
// Jump to the stubcode.
|
||||
masm.branch(R2.scratchReg());
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitReturnFromIC(MacroAssembler& masm)
|
||||
{
|
||||
masm.branch(ra);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitChangeICReturnAddress(MacroAssembler& masm, Register reg)
|
||||
{
|
||||
masm.movePtr(reg, ra);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitBaselineTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t argSize)
|
||||
{
|
||||
Register scratch = R2.scratchReg();
|
||||
|
||||
// Compute frame size.
|
||||
masm.movePtr(BaselineFrameReg, scratch);
|
||||
masm.addPtr(Imm32(BaselineFrame::FramePointerOffset), scratch);
|
||||
masm.subPtr(BaselineStackReg, scratch);
|
||||
|
||||
// Store frame size without VMFunction arguments for GC marking.
|
||||
masm.subPtr(Imm32(argSize), scratch);
|
||||
masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
|
||||
masm.addPtr(Imm32(argSize), scratch);
|
||||
|
||||
// Push frame descriptor and perform the tail call.
|
||||
// ICTailCallReg (ra) already contains the return address (as we
|
||||
// keep it there through the stub calls), but the VMWrapper code being
|
||||
// called expects the return address to also be pushed on the stack.
|
||||
MOZ_ASSERT(ICTailCallReg == ra);
|
||||
masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, ExitFrameLayout::Size());
|
||||
masm.subPtr(Imm32(sizeof(CommonFrameLayout)), StackPointer);
|
||||
masm.storePtr(scratch, Address(StackPointer, CommonFrameLayout::offsetOfDescriptor()));
|
||||
masm.storePtr(ra, Address(StackPointer, CommonFrameLayout::offsetOfReturnAddress()));
|
||||
|
||||
masm.branch(target);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
|
||||
{
|
||||
Register scratch = R2.scratchReg();
|
||||
|
||||
masm.loadPtr(Address(sp, stackSize), scratch);
|
||||
masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch);
|
||||
masm.addPtr(Imm32(stackSize + JitStubFrameLayout::Size() - sizeof(intptr_t)), scratch);
|
||||
|
||||
// Push frame descriptor and perform the tail call.
|
||||
MOZ_ASSERT(ICTailCallReg == ra);
|
||||
masm.makeFrameDescriptor(scratch, JitFrame_IonJS, ExitFrameLayout::Size());
|
||||
masm.push(scratch);
|
||||
masm.push(ICTailCallReg);
|
||||
masm.branch(target);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg, uint32_t headerSize)
|
||||
{
|
||||
// Compute stub frame size. We have to add two pointers: the stub reg and
|
||||
// previous frame pointer pushed by EmitEnterStubFrame.
|
||||
masm.movePtr(BaselineFrameReg, reg);
|
||||
masm.addPtr(Imm32(sizeof(intptr_t) * 2), reg);
|
||||
masm.subPtr(BaselineStackReg, reg);
|
||||
|
||||
masm.makeFrameDescriptor(reg, JitFrame_BaselineStub, headerSize);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
|
||||
{
|
||||
Register scratch = R2.scratchReg();
|
||||
EmitBaselineCreateStubFrameDescriptor(masm, scratch, ExitFrameLayout::Size());
|
||||
masm.push(scratch);
|
||||
masm.call(target);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitIonCallVM(JitCode* target, size_t stackSlots, MacroAssembler& masm)
|
||||
{
|
||||
uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonStub,
|
||||
ExitFrameLayout::Size());
|
||||
masm.Push(Imm32(descriptor));
|
||||
masm.callJit(target);
|
||||
|
||||
// Remove rest of the frame left on the stack. We remove the return address
|
||||
// which is implicitly popped when returning.
|
||||
size_t framePop = sizeof(ExitFrameLayout) - sizeof(void*);
|
||||
|
||||
// Pop arguments from framePushed.
|
||||
masm.implicitPop(stackSlots * sizeof(void*) + framePop);
|
||||
}
|
||||
|
||||
struct BaselineStubFrame {
|
||||
uintptr_t savedFrame;
|
||||
uintptr_t savedStub;
|
||||
uintptr_t returnAddress;
|
||||
uintptr_t descriptor;
|
||||
};
|
||||
|
||||
static const uint32_t STUB_FRAME_SIZE = sizeof(BaselineStubFrame);
|
||||
static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = offsetof(BaselineStubFrame, savedStub);
|
||||
|
||||
inline void
|
||||
EmitBaselineEnterStubFrame(MacroAssembler& masm, Register scratch)
|
||||
{
|
||||
MOZ_ASSERT(scratch != ICTailCallReg);
|
||||
|
||||
// Compute frame size.
|
||||
masm.movePtr(BaselineFrameReg, scratch);
|
||||
masm.addPtr(Imm32(BaselineFrame::FramePointerOffset), scratch);
|
||||
masm.subPtr(BaselineStackReg, scratch);
|
||||
|
||||
masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
|
||||
|
||||
// Note: when making changes here, don't forget to update
|
||||
// BaselineStubFrame if needed.
|
||||
|
||||
// Push frame descriptor and return address.
|
||||
masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
|
||||
masm.subPtr(Imm32(STUB_FRAME_SIZE), StackPointer);
|
||||
masm.storePtr(scratch, Address(StackPointer, offsetof(BaselineStubFrame, descriptor)));
|
||||
masm.storePtr(ICTailCallReg, Address(StackPointer,
|
||||
offsetof(BaselineStubFrame, returnAddress)));
|
||||
|
||||
// Save old frame pointer, stack pointer and stub reg.
|
||||
masm.storePtr(ICStubReg, Address(StackPointer,
|
||||
offsetof(BaselineStubFrame, savedStub)));
|
||||
masm.storePtr(BaselineFrameReg, Address(StackPointer,
|
||||
offsetof(BaselineStubFrame, savedFrame)));
|
||||
masm.movePtr(BaselineStackReg, BaselineFrameReg);
|
||||
|
||||
// Stack should remain aligned.
|
||||
masm.assertStackAlignment(sizeof(Value), 0);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitIonEnterStubFrame(MacroAssembler& masm, Register scratch)
|
||||
{
|
||||
MOZ_ASSERT(ICTailCallReg == ra);
|
||||
|
||||
// In LoongArch the ra register contains the return address,
|
||||
// but in jit frames we expect it to be on the stack. As a result
|
||||
// push the link register (which is actually part of the previous frame.
|
||||
// Therefore using push instead of Push).
|
||||
masm.push(ICTailCallReg);
|
||||
|
||||
masm.Push(ICStubReg);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
|
||||
{
|
||||
// Ion frames do not save and restore the frame pointer. If we called
|
||||
// into Ion, we have to restore the stack pointer from the frame descriptor.
|
||||
// If we performed a VM call, the descriptor has been popped already so
|
||||
// in that case we use the frame pointer.
|
||||
if (calledIntoIon) {
|
||||
masm.pop(ScratchRegister);
|
||||
masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), ScratchRegister);
|
||||
masm.addPtr(ScratchRegister, BaselineStackReg);
|
||||
} else {
|
||||
masm.movePtr(BaselineFrameReg, BaselineStackReg);
|
||||
}
|
||||
|
||||
masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, savedFrame)),
|
||||
BaselineFrameReg);
|
||||
masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, savedStub)),
|
||||
ICStubReg);
|
||||
|
||||
// Load the return address.
|
||||
masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, returnAddress)),
|
||||
ICTailCallReg);
|
||||
|
||||
// Discard the frame descriptor.
|
||||
masm.loadPtr(Address(StackPointer, offsetof(BaselineStubFrame, descriptor)), ScratchRegister);
|
||||
masm.addPtr(Imm32(STUB_FRAME_SIZE), StackPointer);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitIonLeaveStubFrame(MacroAssembler& masm)
|
||||
{
|
||||
masm.Pop(ICStubReg);
|
||||
masm.pop(ICTailCallReg); // See EmitIonEnterStubFrame for explanation on pop/Pop.
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitStowICValues(MacroAssembler& masm, int values)
|
||||
{
|
||||
MOZ_ASSERT(values >= 0 && values <= 2);
|
||||
switch(values) {
|
||||
case 1:
|
||||
// Stow R0
|
||||
masm.Push(R0);
|
||||
break;
|
||||
case 2:
|
||||
// Stow R0 and R1
|
||||
masm.Push(R0);
|
||||
masm.Push(R1);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitUnstowICValues(MacroAssembler& masm, int values, bool discard = false)
|
||||
{
|
||||
MOZ_ASSERT(values >= 0 && values <= 2);
|
||||
switch(values) {
|
||||
case 1:
|
||||
// Unstow R0.
|
||||
if (discard)
|
||||
masm.addPtr(Imm32(sizeof(Value)), BaselineStackReg);
|
||||
else
|
||||
masm.popValue(R0);
|
||||
break;
|
||||
case 2:
|
||||
// Unstow R0 and R1.
|
||||
if (discard) {
|
||||
masm.addPtr(Imm32(sizeof(Value) * 2), BaselineStackReg);
|
||||
} else {
|
||||
masm.popValue(R1);
|
||||
masm.popValue(R0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
masm.adjustFrame(-values * sizeof(Value));
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitCallTypeUpdateIC(MacroAssembler& masm, JitCode* code, uint32_t objectOffset)
|
||||
{
|
||||
// R0 contains the value that needs to be typechecked.
|
||||
// The object we're updating is a boxed Value on the stack, at offset
|
||||
// objectOffset from $sp, excluding the return address.
|
||||
|
||||
// Save the current ICStubReg to stack, as well as the TailCallReg,
|
||||
// since on LoongArch, the $ra is live.
|
||||
masm.subPtr(Imm32(2 * sizeof(intptr_t)), StackPointer);
|
||||
masm.storePtr(ICStubReg, Address(StackPointer, sizeof(intptr_t)));
|
||||
masm.storePtr(ICTailCallReg, Address(StackPointer, 0));
|
||||
|
||||
// This is expected to be called from within an IC, when ICStubReg
|
||||
// is properly initialized to point to the stub.
|
||||
masm.loadPtr(Address(ICStubReg, ICUpdatedStub::offsetOfFirstUpdateStub()),
|
||||
ICStubReg);
|
||||
|
||||
// Load stubcode pointer from ICStubReg into ICTailCallReg.
|
||||
masm.loadPtr(Address(ICStubReg, ICStub::offsetOfStubCode()), R2.scratchReg());
|
||||
|
||||
// Call the stubcode.
|
||||
masm.call(R2.scratchReg());
|
||||
|
||||
// Restore the old stub reg and tailcall reg.
|
||||
masm.loadPtr(Address(StackPointer, 0), ICTailCallReg);
|
||||
masm.loadPtr(Address(StackPointer, sizeof(intptr_t)), ICStubReg);
|
||||
masm.addPtr(Imm32(2 * sizeof(intptr_t)), StackPointer);
|
||||
|
||||
// The update IC will store 0 or 1 in R1.scratchReg() reflecting if the
|
||||
// value in R0 type-checked properly or not.
|
||||
Label success;
|
||||
masm.ma_b(R1.scratchReg(), Imm32(1), &success, Assembler::Equal, ShortJump);
|
||||
|
||||
// If the IC failed, then call the update fallback function.
|
||||
EmitBaselineEnterStubFrame(masm, R1.scratchReg());
|
||||
|
||||
masm.loadValue(Address(BaselineStackReg, STUB_FRAME_SIZE + objectOffset), R1);
|
||||
|
||||
masm.Push(R0);
|
||||
masm.Push(R1);
|
||||
masm.Push(ICStubReg);
|
||||
|
||||
// Load previous frame pointer, push BaselineFrame*.
|
||||
masm.loadPtr(Address(BaselineFrameReg, 0), R0.scratchReg());
|
||||
masm.pushBaselineFramePtr(R0.scratchReg(), R0.scratchReg());
|
||||
|
||||
EmitBaselineCallVM(code, masm);
|
||||
EmitBaselineLeaveStubFrame(masm);
|
||||
|
||||
// Success at end.
|
||||
masm.bind(&success);
|
||||
}
|
||||
|
||||
template <typename AddrType>
|
||||
inline void
|
||||
EmitPreBarrier(MacroAssembler& masm, const AddrType& addr, MIRType type)
|
||||
{
|
||||
// On LoongArch, $ra is clobbered by patchableCallPreBarrier. Save it first.
|
||||
masm.push(ra);
|
||||
masm.patchableCallPreBarrier(addr, type);
|
||||
masm.pop(ra);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitStubGuardFailure(MacroAssembler& masm)
|
||||
{
|
||||
// NOTE: This routine assumes that the stub guard code left the stack in
|
||||
// the same state it was in when it was entered.
|
||||
|
||||
// BaselineStubEntry points to the current stub.
|
||||
|
||||
// Load next stub into ICStubReg
|
||||
masm.loadPtr(Address(ICStubReg, ICStub::offsetOfNext()), ICStubReg);
|
||||
|
||||
// Load stubcode pointer from BaselineStubEntry into scratch register.
|
||||
masm.loadPtr(Address(ICStubReg, ICStub::offsetOfStubCode()), R2.scratchReg());
|
||||
|
||||
// Return address is already loaded, just jump to the next stubcode.
|
||||
MOZ_ASSERT(ICTailCallReg == ra);
|
||||
masm.branch(R2.scratchReg());
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
#endif /* jit_loongarch64_SharedICHelpers_loongarch64_h */
|
||||
53
js/src/jit/loongarch64/SharedICRegisters-loongarch64.h
Normal file
53
js/src/jit/loongarch64/SharedICRegisters-loongarch64.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
#ifndef jit_loongarch64_SharedICRegisters_loongarch64_h
|
||||
#define jit_loongarch64_SharedICRegisters_loongarch64_h
|
||||
|
||||
#include "jit/loongarch64/Assembler-loongarch64.h"
|
||||
#include "jit/Registers.h"
|
||||
#include "jit/RegisterSets.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// Must be a callee-saved register for preservation around generateEnterJIT().
|
||||
static constexpr Register BaselineFrameReg = s0;
|
||||
static constexpr Register BaselineStackReg = sp;
|
||||
|
||||
// ValueOperands R0, R1, and R2.
|
||||
// R0 == JSReturnReg, and R2 uses registers not preserved across calls. R1 value
|
||||
// should be preserved across calls.
|
||||
static constexpr ValueOperand R0(a2);
|
||||
static constexpr ValueOperand R1(s1);
|
||||
static constexpr ValueOperand R2(a0);
|
||||
|
||||
// ICTailCallReg and ICStubReg
|
||||
// These use registers that are not preserved across calls.
|
||||
static constexpr Register ICTailCallReg = ra;
|
||||
static constexpr Register ICStubReg = t0;
|
||||
|
||||
// ExtractTemps must be callee-save registers:
|
||||
// ICSetProp_Native::Compiler::generateStubCode() stores the object
|
||||
// in ExtractTemp0, but then calls callTypeUpdateIC(), which clobbers
|
||||
// caller-save registers.
|
||||
static constexpr Register ExtractTemp0 = s7;
|
||||
static constexpr Register ExtractTemp1 = s8;
|
||||
|
||||
// Note that ICTailCallReg is actually just the link register.
|
||||
// In LoongArch code emission, we do not clobber ICTailCallReg since we keep
|
||||
// the return address for calls there.
|
||||
|
||||
// FloatReg0 must be equal to ReturnFloatReg.
|
||||
static constexpr FloatRegister FloatReg0 = f0;
|
||||
static constexpr FloatRegister FloatReg1 = f1;
|
||||
static constexpr FloatRegister FloatReg2 = f2;
|
||||
static constexpr FloatRegister FloatReg3 = f3;
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
#endif /* jit_loongarch64_SharedICRegisters_loongarch64_h */
|
||||
1362
js/src/jit/loongarch64/Trampoline-loongarch64.cpp
Normal file
1362
js/src/jit/loongarch64/Trampoline-loongarch64.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -17,7 +17,8 @@
|
|||
#include "wasm/WasmTypes.h"
|
||||
|
||||
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \
|
||||
defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
|
||||
defined(JS_CODEGEN_LOONGARCH64)
|
||||
// Push return addresses callee-side.
|
||||
# define JS_USE_LINK_REGISTER
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ LIRGeneratorShared::defineSinCos(LInstructionHelper<2, Ops, Temps> *lir, MDefini
|
|||
#elif defined(JS_CODEGEN_ARM64)
|
||||
lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE,
|
||||
LFloatReg(FloatRegister(FloatRegisters::d1, FloatRegisters::Double))));
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || defined(JS_CODEGEN_LOONGARCH64)
|
||||
lir->setDef(1, LDefinition(vreg + VREG_INCREMENT, LDefinition::DOUBLE, LFloatReg(f2)));
|
||||
#elif defined(JS_CODEGEN_NONE)
|
||||
MOZ_CRASH();
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ PodSet(T* aDst, const T& aSrc, size_t aNElem)
|
|||
# define JS_SWEPT_CODE_PATTERN 0xED // IN instruction, crashes in user mode.
|
||||
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
|
||||
# define JS_SWEPT_CODE_PATTERN 0xA3 // undefined instruction
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || defined(JS_CODEGEN_LOONGARCH64)
|
||||
# define JS_SWEPT_CODE_PATTERN 0x01 // undefined instruction
|
||||
#else
|
||||
# error "JS_SWEPT_CODE_PATTERN not defined for this platform"
|
||||
|
|
|
|||
|
|
@ -524,6 +524,24 @@ elif CONFIG['JS_CODEGEN_ARM64']:
|
|||
'jit/arm64/vixl/MozSimulator-vixl.cpp',
|
||||
'jit/arm64/vixl/Simulator-vixl.cpp'
|
||||
]
|
||||
elif CONFIG['JS_CODEGEN_LOONGARCH64']:
|
||||
jit_ioncheck1_deunified_sources += [
|
||||
'jit/mips-shared/Bailouts-mips-shared.cpp',
|
||||
'jit/mips-shared/BaselineCompiler-mips-shared.cpp',
|
||||
'jit/mips-shared/BaselineIC-mips-shared.cpp',
|
||||
'jit/mips-shared/MoveEmitter-mips-shared.cpp',
|
||||
]
|
||||
jit_ioncheck2_deunified_sources += [
|
||||
'jit/loongarch64/Architecture-loongarch64.cpp',
|
||||
'jit/loongarch64/Assembler-loongarch64.cpp',
|
||||
'jit/loongarch64/Bailouts-loongarch64.cpp',
|
||||
'jit/loongarch64/BaselineCompiler-loongarch64.cpp',
|
||||
'jit/loongarch64/BaselineIC-loongarch64.cpp',
|
||||
'jit/loongarch64/MacroAssembler-loongarch64.cpp',
|
||||
'jit/mips64/MoveEmitter-mips64.cpp',
|
||||
'jit/loongarch64/SharedIC-loongarch64.cpp',
|
||||
'jit/loongarch64/Trampoline-loongarch64.cpp',
|
||||
]
|
||||
elif CONFIG['JS_CODEGEN_MIPS32'] or CONFIG['JS_CODEGEN_MIPS64']:
|
||||
jit_ioncheck1_deunified_sources += [
|
||||
'jit/mips-shared/Architecture-mips-shared.cpp',
|
||||
|
|
|
|||
|
|
@ -976,6 +976,10 @@ arm*-*)
|
|||
ENABLE_ION=1
|
||||
AC_DEFINE(JS_CPU_ARM)
|
||||
;;
|
||||
loongarch64*-*)
|
||||
ENABLE_ION=1
|
||||
AC_DEFINE(JS_CPU_LOONGARCH64)
|
||||
;;
|
||||
sparc-*)
|
||||
dnl ENABLE_ION=0
|
||||
AC_DEFINE(JS_CPU_SPARC)
|
||||
|
|
@ -1781,6 +1785,9 @@ elif test "$CPU_ARCH" = "arm"; then
|
|||
|
||||
dnl ARM platforms may trap on unaligned accesses; catch the signal and
|
||||
dnl recover.
|
||||
elif test "$CPU_ARCH" = "loongarch64"; then
|
||||
AC_DEFINE(JS_CODEGEN_LOONGARCH64)
|
||||
JS_CODEGEN_LOONGARCH64=1
|
||||
elif test "$CPU_ARCH" = "mips" || test "$CPU_ARCH" = "mips32" || test "$CPU_ARCH" = "mips64"; then
|
||||
if test ! "$HAVE_64BIT_BUILD"; then
|
||||
AC_DEFINE(JS_CODEGEN_MIPS32)
|
||||
|
|
@ -1798,6 +1805,7 @@ AC_SUBST(JS_SIMULATOR_MIPS32)
|
|||
AC_SUBST(JS_SIMULATOR_MIPS64)
|
||||
AC_SUBST(JS_CODEGEN_ARM)
|
||||
AC_SUBST(JS_CODEGEN_ARM64)
|
||||
AC_SUBST(JS_CODEGEN_LOONGARCH64)
|
||||
AC_SUBST(JS_CODEGEN_MIPS32)
|
||||
AC_SUBST(JS_CODEGEN_MIPS64)
|
||||
AC_SUBST(JS_CODEGEN_X86)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ wasm::HasCompilerSupport(ExclusiveContext* cx)
|
|||
return false;
|
||||
#endif
|
||||
|
||||
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
|
||||
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_LOONGARCH64)
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ struct macos_aarch64_context {
|
|||
# define PC_sig(p) R15_sig(p)
|
||||
#elif defined(__aarch64__)
|
||||
# define PC_sig(p) EPC_sig(p)
|
||||
#elif defined(JS_CPU_MIPS)
|
||||
#elif defined(JS_CPU_MIPS) || defined(JS_CPU_LOONGARCH64)
|
||||
# define PC_sig(p) EPC_sig(p)
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue