зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1863794 - Generate ABIFunctionType code using build script. r=jandem
Today adding a new ABIFunctionType requires: 1. Adding a new option to the enum 2. Updating all the simulators to handle redirects of this type (1) is easy after we added some constexpr code for constructing these types. (2) is really painful, because it requires building on multiple platforms to test, and requires knowledge of all ABI's to get details about registers/stack/etc correct. This patch adds a build-time step which will generate (1) and (2) from a declarative YAML file. The interesting piece is (2) which has to understand the ABI rules and simulator data structures for generating the code. It's tricky code, but think it's easier to maintain and prove correct in one place vs. in a big simulator switch. A data point for this is that implementing this uncovered a few cases where our hand-written code was technically incorrect (although practically not an issue yet). Depends on D193111 Differential Revision: https://phabricator.services.mozilla.com/D193112
This commit is contained in:
Родитель
343cd58824
Коммит
9c5801d32d
|
@ -63,6 +63,7 @@ included_inclnames_to_ignore = set(
|
|||
"frontend/smoosh_generated.h", # generated in $OBJDIR
|
||||
"gc/StatsPhasesGenerated.h", # generated in $OBJDIR
|
||||
"gc/StatsPhasesGenerated.inc", # generated in $OBJDIR
|
||||
"jit/ABIFunctionTypeGenerated.h", # generated in $OBJDIR"
|
||||
"jit/AtomicOperationsGenerated.h", # generated in $OBJDIR
|
||||
"jit/CacheIROpsGenerated.h", # generated in $OBJDIR
|
||||
"jit/LIROpsGenerated.h", # generated in $OBJDIR
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- 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_ABIFunctionType_h
|
||||
#define jit_ABIFunctionType_h
|
||||
|
||||
#include <initializer_list>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jit/ABIFunctionTypeGenerated.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
enum ABIArgType {
|
||||
// A pointer sized integer
|
||||
ArgType_General = 0x1,
|
||||
// A 32-bit integer
|
||||
ArgType_Int32 = 0x2,
|
||||
// A 64-bit integer
|
||||
ArgType_Int64 = 0x3,
|
||||
// A 32-bit floating point number
|
||||
ArgType_Float32 = 0x4,
|
||||
// A 64-bit floating point number
|
||||
ArgType_Float64 = 0x5,
|
||||
|
||||
RetType_Shift = 0x0,
|
||||
ArgType_Shift = 0x3,
|
||||
ArgType_Mask = 0x7
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
static constexpr uint64_t MakeABIFunctionType(
|
||||
ABIArgType ret, std::initializer_list<ABIArgType> args) {
|
||||
uint64_t abiType = 0;
|
||||
for (auto arg : args) {
|
||||
abiType <<= ArgType_Shift;
|
||||
abiType |= (uint64_t)arg;
|
||||
}
|
||||
abiType <<= ArgType_Shift;
|
||||
abiType |= (uint64_t)ret;
|
||||
return abiType;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
enum ABIFunctionType : uint64_t {
|
||||
// The enum must be explicitly typed to avoid UB: some validly constructed
|
||||
// members are larger than any explicitly declared members.
|
||||
ABI_FUNCTION_TYPE_ENUM
|
||||
};
|
||||
|
||||
static constexpr ABIFunctionType MakeABIFunctionType(
|
||||
ABIArgType ret, std::initializer_list<ABIArgType> args) {
|
||||
return ABIFunctionType(detail::MakeABIFunctionType(ret, args));
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
#endif /* jit_ABIFunctionType_h */
|
|
@ -0,0 +1,271 @@
|
|||
# The definitions in here are processed by GenerateABIFunctionType.py to
|
||||
# generate the ABIFunctionType enum and simulator code for handling these
|
||||
# function types.
|
||||
#
|
||||
# The name field is optional and will be autogenerated if omitted. New
|
||||
# additions should generally use the autogenerated name.
|
||||
|
||||
# VM functions that take 0-9 non-double arguments
|
||||
# and return a non-double value.
|
||||
- name: General0
|
||||
ret: General
|
||||
args: []
|
||||
- name: General1
|
||||
ret: General
|
||||
args: [General]
|
||||
- name: General2
|
||||
ret: General
|
||||
args: [General, General]
|
||||
- name: General3
|
||||
ret: General
|
||||
args: [General, General, General]
|
||||
- name: General4
|
||||
ret: General
|
||||
args: [General, General, General, General]
|
||||
- name: General5
|
||||
ret: General
|
||||
args: [General, General, General, General, General]
|
||||
- name: General6
|
||||
ret: General
|
||||
args: [General, General, General, General, General, General]
|
||||
- name: General7
|
||||
ret: General
|
||||
args: [General, General, General, General, General, General, General]
|
||||
- name: General8
|
||||
ret: General
|
||||
args: [General, General, General, General, General, General, General, General]
|
||||
|
||||
# int64 f(double)
|
||||
- name: Int64_Double
|
||||
ret: Int64
|
||||
args: [Float64]
|
||||
|
||||
# double f()
|
||||
- name: Double_None
|
||||
ret: Float64
|
||||
args: []
|
||||
|
||||
# int f(double)
|
||||
- name: Int_Double
|
||||
ret: General
|
||||
args: [Float64]
|
||||
|
||||
# int f(float32)
|
||||
- name: Int_Float32
|
||||
ret: General
|
||||
args: [Float32]
|
||||
|
||||
# float f(float)
|
||||
- ret: Float32
|
||||
args: [Float32]
|
||||
|
||||
# float f(int, int)
|
||||
- name: Float32_IntInt
|
||||
ret: Float32
|
||||
args: [General, General]
|
||||
|
||||
# double f(double)
|
||||
- name: Double_Double
|
||||
ret: Float64
|
||||
args: [Float64]
|
||||
|
||||
# double f(int)
|
||||
- name: Double_Int
|
||||
ret: Float64
|
||||
args: [General]
|
||||
|
||||
# double f(int, int)
|
||||
- name: Double_IntInt
|
||||
ret: Float64
|
||||
args: [General, General]
|
||||
|
||||
# double f(double, int)
|
||||
- name: Double_DoubleInt
|
||||
ret: Float64
|
||||
args: [Float64, General]
|
||||
|
||||
# double f(double, double)
|
||||
- name: Double_DoubleDouble
|
||||
ret: Float64
|
||||
args: [Float64, Float64]
|
||||
|
||||
# float f(float, float)
|
||||
- ret: Float32
|
||||
args: [Float32, Float32]
|
||||
|
||||
# double f(int, double)
|
||||
- name: Double_IntDouble
|
||||
ret: Float64
|
||||
args: [General, Float64]
|
||||
|
||||
# int f(int, double)
|
||||
- name: Int_IntDouble
|
||||
ret: General
|
||||
args: [General, Float64]
|
||||
|
||||
# int f(double, int)
|
||||
- name: Int_DoubleInt
|
||||
ret: General
|
||||
args: [Float64, General]
|
||||
|
||||
# double f(double, double, double)
|
||||
- name: Double_DoubleDoubleDouble
|
||||
ret: Float64
|
||||
args: [Float64, Float64, Float64]
|
||||
|
||||
# double f(double, double, double, double)
|
||||
- name: Double_DoubleDoubleDoubleDouble
|
||||
ret: Float64
|
||||
args: [Float64, Float64, Float64, Float64]
|
||||
|
||||
# int f(double, int, int)
|
||||
- name: Int_DoubleIntInt
|
||||
ret: General
|
||||
args: [Float64, General, General]
|
||||
|
||||
# int f(int, double, int, int)
|
||||
- name: Int_IntDoubleIntInt
|
||||
ret: General
|
||||
args: [General, Float64, General, General]
|
||||
|
||||
- name: Int_GeneralGeneralGeneralInt64
|
||||
ret: General
|
||||
args: [General, General, General, Int64]
|
||||
|
||||
- name: Int_GeneralGeneralInt64Int64
|
||||
ret: General
|
||||
args: [General, General, Int64, Int64]
|
||||
|
||||
# int32_t f(...) variants
|
||||
- ret: General
|
||||
args: [General, Int32]
|
||||
|
||||
- ret: General
|
||||
args: [General, Int32, General]
|
||||
|
||||
- ret: General
|
||||
args: [General, Int32, Int32]
|
||||
|
||||
- ret: General
|
||||
args: [General, Int32, Int32, General, Int32]
|
||||
|
||||
|
||||
# int32_t f(...) variants
|
||||
- ret: Int32
|
||||
args: [General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, General, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, General, Int32, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, General, Int32, General, Int32, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, General, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, General, Int32, Int32, Int32, General, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Float32, Float32, Float32, Float32, Int32, Int32, Int32, Int32, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Float32, Float32, Int32, Float32, Float32, Int32, Float32, Int32, Int32, Int32, Int32, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Float32, Float32, Int32, Int32, Int32, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, General, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, General, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32, Int32, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32, Int32, Int32, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32, Int32, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32, Int32, Int32, Int32, Int32, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int32, Int64, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int32, Int64, Int64, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int32, Int32, Int32, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int32, Int64, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int32, Int64, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int64, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int64, Int64]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int64, Int64, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int64, Int64, General, General]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int64, Int64, Int32]
|
||||
|
||||
- ret: Int32
|
||||
args: [General, Int64, Int64, Int64, Int32, Int32]
|
||||
|
||||
# Functions that return Int64 are tricky because SpiderMonkey's ReturnRegI64
|
||||
# does not match the ABI int64 return register on x86. Wasm only!
|
||||
- ret: Int64
|
||||
args: [General]
|
||||
|
||||
- ret: Int64
|
||||
args: [General, General]
|
||||
|
||||
- ret: Int64
|
||||
args: [Int32, Int32, Int32, Int32]
|
||||
|
||||
- ret: Int64
|
||||
args: [General, Int32]
|
||||
|
||||
- ret: Int64
|
||||
args: [General, Int64]
|
||||
|
||||
- ret: Int64
|
||||
args: [General, Int64, Int32]
|
|
@ -0,0 +1,339 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
import buildconfig
|
||||
import six
|
||||
import yaml
|
||||
from mozbuild.preprocessor import Preprocessor
|
||||
|
||||
HEADER_TEMPLATE = """\
|
||||
/* 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 %(includeguard)s
|
||||
#define %(includeguard)s
|
||||
|
||||
/* This file is generated by jit/GenerateABIFunctionType.py. Do not edit! */
|
||||
|
||||
%(contents)s
|
||||
|
||||
#endif // %(includeguard)s
|
||||
"""
|
||||
|
||||
|
||||
def generate_header(c_out, includeguard, contents):
|
||||
c_out.write(
|
||||
HEADER_TEMPLATE
|
||||
% {
|
||||
"includeguard": includeguard,
|
||||
"contents": contents,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def load_yaml(yaml_path):
|
||||
# First invoke preprocessor.py so that we can use #ifdef JS_SIMULATOR in
|
||||
# the YAML file.
|
||||
pp = Preprocessor()
|
||||
pp.context.update(buildconfig.defines["ALLDEFINES"])
|
||||
pp.out = six.StringIO()
|
||||
pp.do_filter("substitution")
|
||||
pp.do_include(yaml_path)
|
||||
contents = pp.out.getvalue()
|
||||
|
||||
# Load into an OrderedDict to ensure order is preserved. Note: Python 3.7+
|
||||
# also preserves ordering for normal dictionaries.
|
||||
# Code based on https://stackoverflow.com/a/21912744.
|
||||
class OrderedLoader(yaml.Loader):
|
||||
pass
|
||||
|
||||
def construct_mapping(loader, node):
|
||||
loader.flatten_mapping(node)
|
||||
return OrderedDict(loader.construct_pairs(node))
|
||||
|
||||
tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
|
||||
OrderedLoader.add_constructor(tag, construct_mapping)
|
||||
return yaml.load(contents, OrderedLoader)
|
||||
|
||||
|
||||
def cpp_arg_type(arg_type):
|
||||
if arg_type == "General":
|
||||
return "intptr_t"
|
||||
elif arg_type == "Int32":
|
||||
return "int32_t"
|
||||
elif arg_type == "Int64":
|
||||
return "int64_t"
|
||||
elif arg_type == "Float32":
|
||||
return "float"
|
||||
elif arg_type == "Float64":
|
||||
return "double"
|
||||
else:
|
||||
raise ValueError(arg_type)
|
||||
|
||||
|
||||
def func_type_name(func_type):
|
||||
if "name" in func_type:
|
||||
return func_type["name"]
|
||||
|
||||
# Autogenerate a name like `General_GeneralGeneral` if none is specified
|
||||
return f"{func_type['ret']}_{''.join(func_type['args'])}"
|
||||
|
||||
|
||||
def func_type_has_floats(func_type):
|
||||
for arg in func_type["args"]:
|
||||
if arg == "Float32" or arg == "Float64":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Generate the ARM32 argument loading for a func type for when soft-FP is enabled
|
||||
def arm32_soft_fp_args(func_type):
|
||||
# This must match ABIArgGenerator::softNext() in Assembler-arm.cpp
|
||||
contents = ""
|
||||
numIntArgRegs = 4
|
||||
intRegIndex = 0
|
||||
stackOffset = 0
|
||||
for i, arg in enumerate(func_type["args"]):
|
||||
if i != 0:
|
||||
contents += ", "
|
||||
|
||||
if arg == "General":
|
||||
if intRegIndex == numIntArgRegs:
|
||||
contents += f"stack_pointer[{stackOffset}]"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"a{intRegIndex}"
|
||||
intRegIndex += 1
|
||||
elif arg == "Int32":
|
||||
if intRegIndex == numIntArgRegs:
|
||||
contents += f"stack_pointer[{stackOffset}]"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"a{intRegIndex}"
|
||||
intRegIndex += 1
|
||||
elif arg == "Int64":
|
||||
intRegIndex += intRegIndex % 2
|
||||
if intRegIndex == numIntArgRegs:
|
||||
stackOffset += stackOffset % 2
|
||||
contents += f"MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}])"
|
||||
stackOffset += 2
|
||||
else:
|
||||
contents += f"MakeInt64(a{intRegIndex}, a{intRegIndex+1})"
|
||||
intRegIndex += 2
|
||||
elif arg == "Float32":
|
||||
if intRegIndex == numIntArgRegs:
|
||||
contents += f"mozilla::BitwiseCast<float>(stack_pointer[{stackOffset}])"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"mozilla::BitwiseCast<float>(a{intRegIndex})"
|
||||
intRegIndex += 1
|
||||
elif arg == "Float64":
|
||||
intRegIndex += intRegIndex % 2
|
||||
if intRegIndex == numIntArgRegs:
|
||||
stackOffset += stackOffset % 2
|
||||
contents += f"mozilla::BitwiseCast<double>(MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}]))"
|
||||
stackOffset += 2
|
||||
else:
|
||||
contents += f"mozilla::BitwiseCast<double>(MakeInt64(a{intRegIndex}, a{intRegIndex + 1}))"
|
||||
intRegIndex += 2
|
||||
assert intRegIndex <= numIntArgRegs
|
||||
return contents
|
||||
|
||||
|
||||
# Generate the ARM32 argument loading for a func type for when hard-FP is enabled
|
||||
def arm32_hard_fp_args(func_type):
|
||||
# This must match ABIArgGenerator::hardNext() in Assembler-arm.cpp
|
||||
contents = ""
|
||||
numIntArgRegs = 4
|
||||
numFloatArgRegs = 16
|
||||
intRegIndex = 0
|
||||
floatRegIndex = 0
|
||||
stackOffset = 0
|
||||
for i, arg in enumerate(func_type["args"]):
|
||||
if i != 0:
|
||||
contents += ", "
|
||||
|
||||
if arg == "General":
|
||||
if intRegIndex == numIntArgRegs:
|
||||
contents += f"stack_pointer[{stackOffset}]"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"a{intRegIndex}"
|
||||
intRegIndex += 1
|
||||
elif arg == "Int32":
|
||||
if intRegIndex == numIntArgRegs:
|
||||
contents += f"stack_pointer[{stackOffset}]"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"a{intRegIndex}"
|
||||
intRegIndex += 1
|
||||
elif arg == "Int64":
|
||||
intRegIndex += intRegIndex % 2
|
||||
if intRegIndex == numIntArgRegs:
|
||||
stackOffset += stackOffset % 2
|
||||
contents += f"MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}])"
|
||||
stackOffset += 2
|
||||
else:
|
||||
contents += f"MakeInt64(a{intRegIndex}, a{intRegIndex+1})"
|
||||
intRegIndex += 2
|
||||
elif arg == "Float32":
|
||||
if floatRegIndex == numFloatArgRegs:
|
||||
contents += f"mozilla::BitwiseCast<float>(stack_pointer[{stackOffset}])"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"s{floatRegIndex}"
|
||||
floatRegIndex += 1
|
||||
elif arg == "Float64":
|
||||
floatRegIndex += floatRegIndex % 2
|
||||
if floatRegIndex == numFloatArgRegs:
|
||||
stackOffset += stackOffset % 2
|
||||
contents += f"mozilla::BitwiseCast<double>(MakeInt64(stack_pointer[{stackOffset}], stack_pointer[{stackOffset + 1}]))"
|
||||
stackOffset += 2
|
||||
else:
|
||||
contents += f"d{round(floatRegIndex / 2)}"
|
||||
floatRegIndex += 2
|
||||
assert intRegIndex <= numIntArgRegs
|
||||
assert floatRegIndex <= numFloatArgRegs
|
||||
return contents
|
||||
|
||||
|
||||
def arm32_simulator_dispatch(func_types):
|
||||
contents = ""
|
||||
for func_type in func_types:
|
||||
hard_fp_args = arm32_hard_fp_args(func_type)
|
||||
soft_fp_args = arm32_soft_fp_args(func_type)
|
||||
ret = func_type["ret"]
|
||||
|
||||
contents += f"case js::jit::Args_{func_type_name(func_type)}: {{\\\n"
|
||||
contents += f" auto target = reinterpret_cast<Prototype_{func_type_name(func_type)}>(external);\\\n"
|
||||
contents += f" {cpp_arg_type(ret)} ret;\\\n"
|
||||
if func_type_has_floats(func_type):
|
||||
contents += " if (UseHardFpABI()) {\\\n"
|
||||
contents += f" ret = target({hard_fp_args});\\\n"
|
||||
contents += " } else {\\\n"
|
||||
contents += f" ret = target({soft_fp_args});\\\n"
|
||||
contents += " }\\\n"
|
||||
else:
|
||||
# No float args means we don't need to check the float ABI and
|
||||
# either generated args will do.
|
||||
contents += f" ret = target({soft_fp_args});\\\n"
|
||||
contents += " scratchVolatileRegisters((void*)target);\\\n"
|
||||
if ret == "General" or ret == "Int32" or ret == "Int64":
|
||||
contents += " setCallResult(ret);\\\n"
|
||||
elif ret == "Float32":
|
||||
contents += " setCallResultFloat(ret);\\\n"
|
||||
elif ret == "Float64":
|
||||
contents += " setCallResultDouble(ret);\\\n"
|
||||
contents += " break;\\\n"
|
||||
contents += "}\\\n"
|
||||
return contents
|
||||
|
||||
|
||||
# Generate the ARM64 argument loading for a func type
|
||||
def arm64_args(func_type):
|
||||
# This must match ABIArgGenerator::next() in Assembler-arm64.cpp
|
||||
contents = ""
|
||||
numIntArgRegs = 8
|
||||
numFloatArgRegs = 8
|
||||
intRegIndex = 0
|
||||
floatRegIndex = 0
|
||||
stackOffset = 0
|
||||
for i, arg in enumerate(func_type["args"]):
|
||||
if i != 0:
|
||||
contents += ", "
|
||||
|
||||
if arg == "General":
|
||||
if intRegIndex == numIntArgRegs:
|
||||
contents += f"sp[{stackOffset}]"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"x{intRegIndex}"
|
||||
intRegIndex += 1
|
||||
elif arg == "Int32":
|
||||
if intRegIndex == numIntArgRegs:
|
||||
contents += f"sp[{stackOffset}]"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"x{intRegIndex}"
|
||||
intRegIndex += 1
|
||||
elif arg == "Int64":
|
||||
if intRegIndex == numIntArgRegs:
|
||||
contents += f"sp[{stackOffset}]"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"x{intRegIndex}"
|
||||
intRegIndex += 1
|
||||
elif arg == "Float32":
|
||||
if floatRegIndex == numFloatArgRegs:
|
||||
contents += f"mozilla::BitwiseCast<float>(sp[{stackOffset}])"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"s{floatRegIndex}"
|
||||
floatRegIndex += 1
|
||||
elif arg == "Float64":
|
||||
if floatRegIndex == numFloatArgRegs:
|
||||
contents += f"mozilla::BitwiseCast<double>(sp[{stackOffset}])"
|
||||
stackOffset += 1
|
||||
else:
|
||||
contents += f"d{floatRegIndex}"
|
||||
floatRegIndex += 1
|
||||
assert intRegIndex <= numIntArgRegs
|
||||
assert floatRegIndex <= numFloatArgRegs
|
||||
return contents
|
||||
|
||||
|
||||
def arm64_simulator_dispatch(func_types):
|
||||
contents = ""
|
||||
for func_type in func_types:
|
||||
args = arm64_args(func_type)
|
||||
contents += f"case js::jit::Args_{func_type_name(func_type)}: {{\\\n"
|
||||
contents += f" auto target = reinterpret_cast<Prototype_{func_type_name(func_type)}>(nativeFn);\\\n"
|
||||
contents += f" auto ret = target({args});\\\n"
|
||||
ret = func_type["ret"]
|
||||
if ret == "General":
|
||||
contents += " setGPR64Result(ret);\\\n"
|
||||
elif ret == "Int32":
|
||||
contents += " setGPR32Result(ret);\\\n"
|
||||
elif ret == "Int64":
|
||||
contents += " setGPR64Result(ret);\\\n"
|
||||
elif ret == "Float32":
|
||||
contents += " setFP32Result(ret);\\\n"
|
||||
elif ret == "Float64":
|
||||
contents += " setFP64Result(ret);\\\n"
|
||||
contents += " break;\\\n"
|
||||
contents += "}\\\n"
|
||||
return contents
|
||||
|
||||
|
||||
def main(c_out, yaml_path):
|
||||
func_types = load_yaml(yaml_path)
|
||||
|
||||
# Define the ABIFunctionType enum
|
||||
contents = "#define ABI_FUNCTION_TYPE_ENUM \\\n"
|
||||
for func_type in func_types:
|
||||
name = "Args_" + func_type_name(func_type)
|
||||
args = ", ".join(f"ArgType_{p}" for p in func_type["args"])
|
||||
ret = f"ArgType_{func_type['ret']}"
|
||||
|
||||
contents += f" {name} = detail::MakeABIFunctionType({ret}, {{{args}}}),\\\n"
|
||||
contents += "\n"
|
||||
|
||||
# Define the prototypes of the types
|
||||
contents += "#define ABI_FUNCTION_TYPE_SIM_PROTOTYPES \\\n"
|
||||
for func_type in func_types:
|
||||
name = "Prototype_" + func_type_name(func_type)
|
||||
args = ", ".join(cpp_arg_type(p) for p in func_type["args"])
|
||||
ret = cpp_arg_type(func_type["ret"])
|
||||
|
||||
contents += f" typedef {ret} (*{name})({args});\\\n"
|
||||
contents += "\n"
|
||||
|
||||
contents += "#define ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH \\\n"
|
||||
contents += arm64_simulator_dispatch(func_types)
|
||||
contents += "\n"
|
||||
|
||||
contents += "#define ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH \\\n"
|
||||
contents += arm32_simulator_dispatch(func_types)
|
||||
contents += "\n"
|
||||
|
||||
generate_header(c_out, "jit_ABIFunctionTypeGenerated_h", contents)
|
|
@ -10,12 +10,13 @@
|
|||
#include "mozilla/HashFunctions.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "NamespaceImports.h"
|
||||
|
||||
#include "jit/ABIFunctionType.h"
|
||||
|
||||
#include "js/ScalarType.h" // js::Scalar::Type
|
||||
#include "js/Value.h"
|
||||
|
||||
|
@ -762,284 +763,6 @@ static constexpr bool NeedsPostBarrier(MIRType type) {
|
|||
|
||||
#endif // DEBUG
|
||||
|
||||
enum ABIArgType {
|
||||
// A pointer sized integer
|
||||
ArgType_General = 0x1,
|
||||
// A 32-bit integer
|
||||
ArgType_Int32 = 0x2,
|
||||
// A 64-bit integer
|
||||
ArgType_Int64 = 0x3,
|
||||
// A 32-bit floating point number
|
||||
ArgType_Float32 = 0x4,
|
||||
// A 64-bit floating point number
|
||||
ArgType_Float64 = 0x5,
|
||||
|
||||
RetType_Shift = 0x0,
|
||||
ArgType_Shift = 0x3,
|
||||
ArgType_Mask = 0x7
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
static constexpr uint64_t MakeABIFunctionType(
|
||||
ABIArgType ret, std::initializer_list<ABIArgType> args) {
|
||||
uint64_t abiType = (uint64_t)ret << RetType_Shift;
|
||||
int i = 1;
|
||||
for (auto arg : args) {
|
||||
abiType |= ((uint64_t)arg << (ArgType_Shift * i));
|
||||
i++;
|
||||
}
|
||||
return abiType;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
enum ABIFunctionType : uint64_t {
|
||||
// The enum must be explicitly typed to avoid UB: some validly constructed
|
||||
// members are larger than any explicitly declared members.
|
||||
|
||||
// VM functions that take 0-9 non-double arguments
|
||||
// and return a non-double value.
|
||||
Args_General0 = ArgType_General << RetType_Shift,
|
||||
Args_General1 = Args_General0 | (ArgType_General << (ArgType_Shift * 1)),
|
||||
Args_General2 = Args_General1 | (ArgType_General << (ArgType_Shift * 2)),
|
||||
Args_General3 = Args_General2 | (ArgType_General << (ArgType_Shift * 3)),
|
||||
Args_General4 = Args_General3 | (ArgType_General << (ArgType_Shift * 4)),
|
||||
Args_General5 = Args_General4 | (ArgType_General << (ArgType_Shift * 5)),
|
||||
Args_General6 = Args_General5 | (ArgType_General << (ArgType_Shift * 6)),
|
||||
Args_General7 = Args_General6 | (ArgType_General << (ArgType_Shift * 7)),
|
||||
Args_General8 = Args_General7 | (ArgType_General << (ArgType_Shift * 8)),
|
||||
|
||||
// int64 f(double)
|
||||
Args_Int64_Double =
|
||||
(ArgType_Int64 << RetType_Shift) | (ArgType_Float64 << ArgType_Shift),
|
||||
|
||||
// double f()
|
||||
Args_Double_None = ArgType_Float64 << RetType_Shift,
|
||||
|
||||
// int f(double)
|
||||
Args_Int_Double = Args_General0 | (ArgType_Float64 << ArgType_Shift),
|
||||
|
||||
// int f(float32)
|
||||
Args_Int_Float32 = Args_General0 | (ArgType_Float32 << ArgType_Shift),
|
||||
|
||||
// float f(float)
|
||||
Args_Float32_Float32 =
|
||||
(ArgType_Float32 << RetType_Shift) | (ArgType_Float32 << ArgType_Shift),
|
||||
|
||||
// float f(int, int)
|
||||
Args_Float32_IntInt = (ArgType_Float32 << RetType_Shift) |
|
||||
(ArgType_General << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2)),
|
||||
|
||||
// double f(double)
|
||||
Args_Double_Double = Args_Double_None | (ArgType_Float64 << ArgType_Shift),
|
||||
|
||||
// double f(int)
|
||||
Args_Double_Int = Args_Double_None | (ArgType_General << ArgType_Shift),
|
||||
|
||||
// double f(int, int)
|
||||
Args_Double_IntInt =
|
||||
Args_Double_Int | (ArgType_General << (ArgType_Shift * 2)),
|
||||
|
||||
// double f(double, int)
|
||||
Args_Double_DoubleInt = Args_Double_None |
|
||||
(ArgType_General << (ArgType_Shift * 1)) |
|
||||
(ArgType_Float64 << (ArgType_Shift * 2)),
|
||||
|
||||
// double f(double, double)
|
||||
Args_Double_DoubleDouble =
|
||||
Args_Double_Double | (ArgType_Float64 << (ArgType_Shift * 2)),
|
||||
|
||||
// float f(float, float)
|
||||
Args_Float32_Float32Float32 =
|
||||
Args_Float32_Float32 | (ArgType_Float32 << (ArgType_Shift * 2)),
|
||||
|
||||
// double f(int, double)
|
||||
Args_Double_IntDouble = Args_Double_None |
|
||||
(ArgType_Float64 << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2)),
|
||||
|
||||
// int f(int, double)
|
||||
Args_Int_IntDouble = Args_General0 |
|
||||
(ArgType_Float64 << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2)),
|
||||
|
||||
// int f(double, int)
|
||||
Args_Int_DoubleInt = Args_General0 |
|
||||
(ArgType_General << (ArgType_Shift * 1)) |
|
||||
(ArgType_Float64 << (ArgType_Shift * 2)),
|
||||
|
||||
// double f(double, double, double)
|
||||
Args_Double_DoubleDoubleDouble =
|
||||
Args_Double_DoubleDouble | (ArgType_Float64 << (ArgType_Shift * 3)),
|
||||
|
||||
// double f(double, double, double, double)
|
||||
Args_Double_DoubleDoubleDoubleDouble =
|
||||
Args_Double_DoubleDoubleDouble | (ArgType_Float64 << (ArgType_Shift * 4)),
|
||||
|
||||
// int f(double, int, int)
|
||||
Args_Int_DoubleIntInt = Args_General0 |
|
||||
(ArgType_General << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2)) |
|
||||
(ArgType_Float64 << (ArgType_Shift * 3)),
|
||||
|
||||
// int f(int, double, int, int)
|
||||
Args_Int_IntDoubleIntInt = Args_General0 |
|
||||
(ArgType_General << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2)) |
|
||||
(ArgType_Float64 << (ArgType_Shift * 3)) |
|
||||
(ArgType_General << (ArgType_Shift * 4)),
|
||||
|
||||
Args_Int_GeneralGeneralGeneralInt64 =
|
||||
Args_General0 | (ArgType_General << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2)) |
|
||||
(ArgType_General << (ArgType_Shift * 3)) |
|
||||
(ArgType_Int64 << (ArgType_Shift * 4)),
|
||||
|
||||
Args_Int_GeneralGeneralInt64Int64 = Args_General0 |
|
||||
(ArgType_General << (ArgType_Shift * 1)) |
|
||||
(ArgType_General << (ArgType_Shift * 2)) |
|
||||
(ArgType_Int64 << (ArgType_Shift * 3)) |
|
||||
(ArgType_Int64 << (ArgType_Shift * 4)),
|
||||
|
||||
// int32_t f(...) variants
|
||||
Args_Int32_General =
|
||||
detail::MakeABIFunctionType(ArgType_Int32, {ArgType_General}),
|
||||
Args_Int32_GeneralInt32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32Int32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int32, ArgType_Int32, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32Int32Int32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32Int32Int32Int32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_Int32, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32Int32Int32Int32General = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_Int32, ArgType_General}),
|
||||
Args_Int32_GeneralGeneralInt32General = detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_General, ArgType_Int32, ArgType_General}),
|
||||
Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 =
|
||||
detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_General, ArgType_Int32, ArgType_General,
|
||||
ArgType_Int32, ArgType_Int32, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32Int32Int32Int32Int32Int32General =
|
||||
detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int32, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_Int32, ArgType_Int32, ArgType_General}),
|
||||
Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General =
|
||||
detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int32, ArgType_Float32, ArgType_Float32,
|
||||
ArgType_Int32, ArgType_Int32, ArgType_Int32, ArgType_General}),
|
||||
Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General =
|
||||
detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int32, ArgType_Float32, ArgType_Float32,
|
||||
ArgType_Float32, ArgType_Float32, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_Int32, ArgType_General}),
|
||||
Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General =
|
||||
detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int32, ArgType_Float32, ArgType_Float32,
|
||||
ArgType_Int32, ArgType_Float32, ArgType_Float32, ArgType_Int32,
|
||||
ArgType_Float32, ArgType_Int32, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_General}),
|
||||
Args_Int32_GeneralInt32Int32Int32General = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_General}),
|
||||
Args_Int32_GeneralInt32Int32General = detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int32, ArgType_Int32, ArgType_General}),
|
||||
Args_Int32_GeneralInt32Int32Int64Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int64, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32GeneralInt32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int32, ArgType_General, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32GeneralInt32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_General,
|
||||
ArgType_Int32, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt32Int64Int64Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int32, ArgType_Int64,
|
||||
ArgType_Int64, ArgType_Int32}),
|
||||
Args_Int32_GeneralGeneral = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_General}),
|
||||
Args_Int32_GeneralGeneralGeneral = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_General, ArgType_General}),
|
||||
Args_Int32_GeneralGeneralInt32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_General, ArgType_Int32, ArgType_Int32}),
|
||||
|
||||
// general f(...) variants
|
||||
Args_General_GeneralInt32 = detail::MakeABIFunctionType(
|
||||
ArgType_General, {ArgType_General, ArgType_Int32}),
|
||||
Args_General_GeneralInt32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_General, {ArgType_General, ArgType_Int32, ArgType_Int32}),
|
||||
Args_General_GeneralInt32General = detail::MakeABIFunctionType(
|
||||
ArgType_General, {ArgType_General, ArgType_Int32, ArgType_General}),
|
||||
Args_General_GeneralInt32Int32GeneralInt32 = detail::MakeABIFunctionType(
|
||||
ArgType_General, {ArgType_General, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_General, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt64Int32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int64, ArgType_Int32, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt64Int32Int32Int32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int64, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_Int32, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt64Int32Int64Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int64, ArgType_Int32,
|
||||
ArgType_Int64, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt64Int32Int64General = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int64, ArgType_Int32,
|
||||
ArgType_Int64, ArgType_General}),
|
||||
Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 =
|
||||
detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_General, ArgType_Int32, ArgType_Int32,
|
||||
ArgType_Int32, ArgType_General, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt64Int64Int64 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int64, ArgType_Int64, ArgType_Int64}),
|
||||
Args_Int32_GeneralInt64Int64Int64Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int64, ArgType_Int64,
|
||||
ArgType_Int64, ArgType_Int32}),
|
||||
Args_Int32_GeneralInt64Int64General = detail::MakeABIFunctionType(
|
||||
ArgType_Int32,
|
||||
{ArgType_General, ArgType_Int64, ArgType_Int64, ArgType_General}),
|
||||
Args_Int32_GeneralInt64Int64Int64General = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int64, ArgType_Int64,
|
||||
ArgType_Int64, ArgType_General}),
|
||||
Args_Int32_GeneralInt64Int64Int64Int32Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int32, {ArgType_General, ArgType_Int64, ArgType_Int64,
|
||||
ArgType_Int64, ArgType_Int32, ArgType_Int32}),
|
||||
|
||||
// Functions that return Int64 are tricky because SpiderMonkey's ReturnRegI64
|
||||
// does not match the ABI int64 return register on x86. Wasm only!
|
||||
Args_Int64_General =
|
||||
detail::MakeABIFunctionType(ArgType_Int64, {ArgType_General}),
|
||||
Args_Int64_GeneralInt32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int64, {ArgType_General, ArgType_Int32}),
|
||||
Args_Int64_GeneralInt64 = detail::MakeABIFunctionType(
|
||||
ArgType_Int64, {ArgType_General, ArgType_Int64}),
|
||||
Args_Int64_GeneralInt64Int32 = detail::MakeABIFunctionType(
|
||||
ArgType_Int64, {ArgType_General, ArgType_Int64, ArgType_Int32}),
|
||||
|
||||
};
|
||||
|
||||
static constexpr ABIFunctionType MakeABIFunctionType(
|
||||
ABIArgType ret, std::initializer_list<ABIArgType> args) {
|
||||
return ABIFunctionType(detail::MakeABIFunctionType(ret, args));
|
||||
}
|
||||
|
||||
// Rounding modes for round instructions.
|
||||
enum class RoundingMode { Down, Up, NearestTiesToEven, TowardsZero };
|
||||
|
||||
|
|
|
@ -2309,147 +2309,7 @@ void Simulator::handleVList(SimInstruction* instr) {
|
|||
}
|
||||
}
|
||||
|
||||
// Note: With the code below we assume that all runtime calls return a 64 bits
|
||||
// result. If they don't, the r1 result register contains a bogus value, which
|
||||
// is fine because it is caller-saved.
|
||||
typedef int64_t (*Prototype_General0)();
|
||||
typedef int64_t (*Prototype_General1)(int32_t arg0);
|
||||
typedef int64_t (*Prototype_General2)(int32_t arg0, int32_t arg1);
|
||||
typedef int64_t (*Prototype_General3)(int32_t arg0, int32_t arg1, int32_t arg2);
|
||||
typedef int64_t (*Prototype_General4)(int32_t arg0, int32_t arg1, int32_t arg2,
|
||||
int32_t arg3);
|
||||
typedef int64_t (*Prototype_General5)(int32_t arg0, int32_t arg1, int32_t arg2,
|
||||
int32_t arg3, int32_t arg4);
|
||||
typedef int64_t (*Prototype_General6)(int32_t arg0, int32_t arg1, int32_t arg2,
|
||||
int32_t arg3, int32_t arg4, int32_t arg5);
|
||||
typedef int64_t (*Prototype_General7)(int32_t arg0, int32_t arg1, int32_t arg2,
|
||||
int32_t arg3, int32_t arg4, int32_t arg5,
|
||||
int32_t arg6);
|
||||
typedef int64_t (*Prototype_General8)(int32_t arg0, int32_t arg1, int32_t arg2,
|
||||
int32_t arg3, int32_t arg4, int32_t arg5,
|
||||
int32_t arg6, int32_t arg7);
|
||||
typedef int64_t (*Prototype_GeneralGeneralGeneralInt64)(int32_t arg0,
|
||||
int32_t arg1,
|
||||
int32_t arg2,
|
||||
int64_t arg3);
|
||||
typedef int64_t (*Prototype_GeneralGeneralInt64Int64)(int32_t arg0,
|
||||
int32_t arg1,
|
||||
int64_t arg2,
|
||||
int64_t arg3);
|
||||
|
||||
typedef double (*Prototype_Double_None)();
|
||||
typedef double (*Prototype_Double_Double)(double arg0);
|
||||
typedef double (*Prototype_Double_Int)(int32_t arg0);
|
||||
typedef double (*Prototype_Double_IntInt)(int32_t arg0, int32_t arg1);
|
||||
typedef int32_t (*Prototype_Int_Double)(double arg0);
|
||||
typedef int64_t (*Prototype_Int64_Double)(double arg0);
|
||||
typedef int32_t (*Prototype_Int_DoubleIntInt)(double arg0, int32_t arg1,
|
||||
int32_t arg2);
|
||||
typedef int32_t (*Prototype_Int_IntDoubleIntInt)(int32_t arg0, double arg1,
|
||||
int32_t arg2, int32_t arg3);
|
||||
|
||||
typedef int32_t (*Prototype_Int_Float32)(float arg0);
|
||||
typedef float (*Prototype_Float32_Float32)(float arg0);
|
||||
typedef float (*Prototype_Float32_Float32Float32)(float arg0, float arg1);
|
||||
typedef float (*Prototype_Float32_IntInt)(int arg0, int arg1);
|
||||
|
||||
typedef double (*Prototype_Double_DoubleInt)(double arg0, int32_t arg1);
|
||||
typedef double (*Prototype_Double_IntDouble)(int32_t arg0, double arg1);
|
||||
typedef double (*Prototype_Double_DoubleDouble)(double arg0, double arg1);
|
||||
typedef int32_t (*Prototype_Int_IntDouble)(int32_t arg0, double arg1);
|
||||
typedef int32_t (*Prototype_Int_DoubleInt)(double arg0, int32_t arg1);
|
||||
|
||||
typedef double (*Prototype_Double_DoubleDoubleDouble)(double arg0, double arg1,
|
||||
double arg2);
|
||||
typedef double (*Prototype_Double_DoubleDoubleDoubleDouble)(double arg0,
|
||||
double arg1,
|
||||
double arg2,
|
||||
double arg3);
|
||||
|
||||
typedef int32_t (*Prototype_Int32_General)(int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32)(int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32)(int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32)(int32_t, int32_t,
|
||||
int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32Int32)(int32_t, int32_t,
|
||||
int32_t, int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32Int32Int32)(
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32Int32General)(
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32Int32Int32Int32General)(
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (
|
||||
*Prototype_Int32_GeneralInt32Float32Float32Int32Int32Int32General)(
|
||||
int32_t, int32_t, float, float, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (
|
||||
*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(
|
||||
int32_t, int32_t, float, float, float, float, int32_t, int32_t, int32_t,
|
||||
int32_t, int32_t);
|
||||
typedef int32_t (
|
||||
*Prototype_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General)(
|
||||
int32_t, int32_t, float, float, int32_t, float, float, int32_t, float,
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32General)(
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32General)(int32_t, int32_t,
|
||||
int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int64Int32)(int32_t, int32_t,
|
||||
int32_t, int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32GeneralInt32)(int32_t, int32_t,
|
||||
int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32GeneralInt32Int32)(
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int64Int64Int32)(int32_t, int32_t,
|
||||
int64_t, int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneral)(int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(int32_t, int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(int32_t, int32_t,
|
||||
int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int32)(int32_t, int64_t,
|
||||
int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int32Int32Int32)(
|
||||
int32_t, int64_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int32Int32)(int32_t, int64_t,
|
||||
int32_t, int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int64Int32)(int32_t, int64_t,
|
||||
int32_t, int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int64General)(
|
||||
int32_t, int64_t, int32_t, int64_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64Int64)(int32_t, int64_t,
|
||||
int64_t, int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64Int64Int32)(int32_t, int64_t,
|
||||
int64_t, int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64General)(int32_t, int64_t,
|
||||
int64_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64Int64General)(
|
||||
int32_t, int64_t, int64_t, int64_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64Int64Int32Int32)(
|
||||
int32_t, int64_t, int64_t, int64_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_General_GeneralInt32)(int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_General_GeneralInt32Int32)(int32_t, int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_General_GeneralInt32General)(int32_t, int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(int32_t, int32_t,
|
||||
int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(
|
||||
int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
|
||||
typedef int64_t (*Prototype_Int64_General)(int32_t);
|
||||
typedef int64_t (*Prototype_Int64_GeneralInt32)(int32_t, int32_t);
|
||||
typedef int64_t (*Prototype_Int64_GeneralInt64)(int32_t, int64_t);
|
||||
typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(int32_t, int64_t, int32_t);
|
||||
ABI_FUNCTION_TYPE_SIM_PROTOTYPES
|
||||
|
||||
// Fill the volatile registers with scratch values.
|
||||
//
|
||||
|
@ -2459,7 +2319,12 @@ typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(int32_t, int64_t, int32_t);
|
|||
// so for now the simulator does not scratch any float registers for these
|
||||
// calls. Should try to narrow it further in future.
|
||||
//
|
||||
void Simulator::scratchVolatileRegisters(bool scratchFloat) {
|
||||
void Simulator::scratchVolatileRegisters(void* target) {
|
||||
// The ARM backend makes calls to __aeabi_idivmod and
|
||||
// __aeabi_uidivmod assuming that the float registers are
|
||||
// non-volatile as a performance optimization, so the float
|
||||
// registers must not be scratch when calling these.
|
||||
bool scratchFloat = target != __aeabi_idivmod && target != __aeabi_uidivmod;
|
||||
int32_t scratch_value = 0xa5a5a5a5 ^ uint32_t(icount_);
|
||||
set_register(r0, scratch_value);
|
||||
set_register(r1, scratch_value);
|
||||
|
@ -2491,21 +2356,23 @@ void Simulator::softwareInterrupt(SimInstruction* instr) {
|
|||
switch (svc) {
|
||||
case kCallRtRedirected: {
|
||||
Redirection* redirection = Redirection::FromSwiInstruction(instr);
|
||||
int32_t arg0 = get_register(r0);
|
||||
int32_t arg1 = get_register(r1);
|
||||
int32_t arg2 = get_register(r2);
|
||||
int32_t arg3 = get_register(r3);
|
||||
int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
|
||||
int32_t arg4 = stack_pointer[0];
|
||||
int32_t arg5 = stack_pointer[1];
|
||||
int32_t arg6 = stack_pointer[2];
|
||||
int32_t arg7 = stack_pointer[3];
|
||||
int32_t arg8 = stack_pointer[4];
|
||||
int32_t arg9 = stack_pointer[5];
|
||||
int32_t arg10 = stack_pointer[6];
|
||||
int32_t arg11 = stack_pointer[7];
|
||||
int32_t arg12 = stack_pointer[8];
|
||||
int32_t arg13 = stack_pointer[9];
|
||||
int32_t a0 = get_register(r0);
|
||||
int32_t a1 = get_register(r1);
|
||||
int32_t a2 = get_register(r2);
|
||||
int32_t a3 = get_register(r3);
|
||||
float s0, s1, s2, s3, s4;
|
||||
get_float_from_s_register(0, &s0);
|
||||
get_float_from_s_register(0, &s1);
|
||||
get_float_from_s_register(0, &s2);
|
||||
get_float_from_s_register(0, &s3);
|
||||
get_float_from_s_register(0, &s4);
|
||||
double d0, d1, d2, d3, d4;
|
||||
get_double_from_d_register(0, &d0);
|
||||
get_double_from_d_register(1, &d1);
|
||||
get_double_from_d_register(2, &d2);
|
||||
get_double_from_d_register(3, &d3);
|
||||
get_double_from_d_register(4, &d4);
|
||||
|
||||
int32_t saved_lr = get_register(lr);
|
||||
intptr_t external =
|
||||
|
@ -2522,751 +2389,7 @@ void Simulator::softwareInterrupt(SimInstruction* instr) {
|
|||
}
|
||||
|
||||
switch (redirection->type()) {
|
||||
case Args_General0: {
|
||||
Prototype_General0 target =
|
||||
reinterpret_cast<Prototype_General0>(external);
|
||||
int64_t result = target();
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General1: {
|
||||
Prototype_General1 target =
|
||||
reinterpret_cast<Prototype_General1>(external);
|
||||
int64_t result = target(arg0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General2: {
|
||||
Prototype_General2 target =
|
||||
reinterpret_cast<Prototype_General2>(external);
|
||||
int64_t result = target(arg0, arg1);
|
||||
// The ARM backend makes calls to __aeabi_idivmod and
|
||||
// __aeabi_uidivmod assuming that the float registers are
|
||||
// non-volatile as a performance optimization, so the float
|
||||
// registers must not be scratch when calling these.
|
||||
bool scratchFloat =
|
||||
target != __aeabi_idivmod && target != __aeabi_uidivmod;
|
||||
scratchVolatileRegisters(/* scratchFloat = */ scratchFloat);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General3: {
|
||||
Prototype_General3 target =
|
||||
reinterpret_cast<Prototype_General3>(external);
|
||||
int64_t result = target(arg0, arg1, arg2);
|
||||
scratchVolatileRegisters(/* scratchFloat = true*/);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General4: {
|
||||
Prototype_General4 target =
|
||||
reinterpret_cast<Prototype_General4>(external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3);
|
||||
scratchVolatileRegisters(/* scratchFloat = true*/);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General5: {
|
||||
Prototype_General5 target =
|
||||
reinterpret_cast<Prototype_General5>(external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General6: {
|
||||
Prototype_General6 target =
|
||||
reinterpret_cast<Prototype_General6>(external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General7: {
|
||||
Prototype_General7 target =
|
||||
reinterpret_cast<Prototype_General7>(external);
|
||||
int32_t arg6 = stack_pointer[2];
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General8: {
|
||||
Prototype_General8 target =
|
||||
reinterpret_cast<Prototype_General8>(external);
|
||||
int32_t arg6 = stack_pointer[2];
|
||||
int32_t arg7 = stack_pointer[3];
|
||||
int64_t result =
|
||||
target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int_GeneralGeneralGeneralInt64: {
|
||||
Prototype_GeneralGeneralGeneralInt64 target =
|
||||
reinterpret_cast<Prototype_GeneralGeneralGeneralInt64>(external);
|
||||
// The int64 arg is not split across register and stack
|
||||
int64_t result = target(arg0, arg1, arg2, MakeInt64(arg4, arg5));
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int_GeneralGeneralInt64Int64: {
|
||||
Prototype_GeneralGeneralInt64Int64 target =
|
||||
reinterpret_cast<Prototype_GeneralGeneralInt64Int64>(external);
|
||||
int64_t result =
|
||||
target(arg0, arg1, MakeInt64(arg2, arg3), MakeInt64(arg4, arg5));
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int64_Double: {
|
||||
double dval0, dval1;
|
||||
int32_t ival;
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_Int64_Double target =
|
||||
reinterpret_cast<Prototype_Int64_Double>(external);
|
||||
int64_t result = target(dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Double_None: {
|
||||
Prototype_Double_None target =
|
||||
reinterpret_cast<Prototype_Double_None>(external);
|
||||
double dresult = target();
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
case Args_Int_Double: {
|
||||
double dval0, dval1;
|
||||
int32_t ival;
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_Int_Double target =
|
||||
reinterpret_cast<Prototype_Int_Double>(external);
|
||||
int32_t res = target(dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
set_register(r0, res);
|
||||
break;
|
||||
}
|
||||
case Args_Int_Float32: {
|
||||
float fval0;
|
||||
if (UseHardFpABI()) {
|
||||
get_float_from_s_register(0, &fval0);
|
||||
} else {
|
||||
fval0 = mozilla::BitwiseCast<float>(arg0);
|
||||
}
|
||||
auto target = reinterpret_cast<Prototype_Int_Float32>(external);
|
||||
int32_t res = target(fval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
set_register(r0, res);
|
||||
break;
|
||||
}
|
||||
case Args_Double_Double: {
|
||||
double dval0, dval1;
|
||||
int32_t ival;
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_Double_Double target =
|
||||
reinterpret_cast<Prototype_Double_Double>(external);
|
||||
double dresult = target(dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
case Args_Float32_Float32: {
|
||||
float fval0;
|
||||
if (UseHardFpABI()) {
|
||||
get_float_from_s_register(0, &fval0);
|
||||
} else {
|
||||
fval0 = mozilla::BitwiseCast<float>(arg0);
|
||||
}
|
||||
Prototype_Float32_Float32 target =
|
||||
reinterpret_cast<Prototype_Float32_Float32>(external);
|
||||
float fresult = target(fval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultFloat(fresult);
|
||||
break;
|
||||
}
|
||||
case Args_Float32_Float32Float32: {
|
||||
float fval0, fval1;
|
||||
if (UseHardFpABI()) {
|
||||
get_float_from_s_register(0, &fval0);
|
||||
get_float_from_s_register(1, &fval1);
|
||||
} else {
|
||||
fval0 = mozilla::BitwiseCast<float>(arg0);
|
||||
fval1 = mozilla::BitwiseCast<float>(arg1);
|
||||
}
|
||||
Prototype_Float32_Float32Float32 target =
|
||||
reinterpret_cast<Prototype_Float32_Float32Float32>(external);
|
||||
float fresult = target(fval0, fval1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultFloat(fresult);
|
||||
break;
|
||||
}
|
||||
case Args_Float32_IntInt: {
|
||||
Prototype_Float32_IntInt target =
|
||||
reinterpret_cast<Prototype_Float32_IntInt>(external);
|
||||
float fresult = target(arg0, arg1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultFloat(fresult);
|
||||
break;
|
||||
}
|
||||
case Args_Double_Int: {
|
||||
Prototype_Double_Int target =
|
||||
reinterpret_cast<Prototype_Double_Int>(external);
|
||||
double dresult = target(arg0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
case Args_Double_IntInt: {
|
||||
Prototype_Double_IntInt target =
|
||||
reinterpret_cast<Prototype_Double_IntInt>(external);
|
||||
double dresult = target(arg0, arg1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
case Args_Double_DoubleInt: {
|
||||
double dval0, dval1;
|
||||
int32_t ival;
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_Double_DoubleInt target =
|
||||
reinterpret_cast<Prototype_Double_DoubleInt>(external);
|
||||
double dresult = target(dval0, ival);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
case Args_Double_DoubleDouble: {
|
||||
double dval0, dval1;
|
||||
int32_t ival;
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_Double_DoubleDouble target =
|
||||
reinterpret_cast<Prototype_Double_DoubleDouble>(external);
|
||||
double dresult = target(dval0, dval1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
case Args_Double_IntDouble: {
|
||||
int32_t ival = get_register(0);
|
||||
double dval0;
|
||||
if (UseHardFpABI()) {
|
||||
get_double_from_d_register(0, &dval0);
|
||||
} else {
|
||||
dval0 = get_double_from_register_pair(2);
|
||||
}
|
||||
Prototype_Double_IntDouble target =
|
||||
reinterpret_cast<Prototype_Double_IntDouble>(external);
|
||||
double dresult = target(ival, dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
case Args_Int_IntDouble: {
|
||||
int32_t ival = get_register(0);
|
||||
double dval0;
|
||||
if (UseHardFpABI()) {
|
||||
get_double_from_d_register(0, &dval0);
|
||||
} else {
|
||||
dval0 = get_double_from_register_pair(2);
|
||||
}
|
||||
Prototype_Int_IntDouble target =
|
||||
reinterpret_cast<Prototype_Int_IntDouble>(external);
|
||||
int32_t result = target(ival, dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
set_register(r0, result);
|
||||
break;
|
||||
}
|
||||
case Args_Int_DoubleInt: {
|
||||
double dval;
|
||||
int32_t result;
|
||||
Prototype_Int_DoubleInt target =
|
||||
reinterpret_cast<Prototype_Int_DoubleInt>(external);
|
||||
if (UseHardFpABI()) {
|
||||
get_double_from_d_register(0, &dval);
|
||||
result = target(dval, arg0);
|
||||
} else {
|
||||
dval = get_double_from_register_pair(0);
|
||||
result = target(dval, arg2);
|
||||
}
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
set_register(r0, result);
|
||||
break;
|
||||
}
|
||||
case Args_Int_DoubleIntInt: {
|
||||
double dval;
|
||||
int32_t result;
|
||||
Prototype_Int_DoubleIntInt target =
|
||||
reinterpret_cast<Prototype_Int_DoubleIntInt>(external);
|
||||
if (UseHardFpABI()) {
|
||||
get_double_from_d_register(0, &dval);
|
||||
result = target(dval, arg0, arg1);
|
||||
} else {
|
||||
dval = get_double_from_register_pair(0);
|
||||
result = target(dval, arg2, arg3);
|
||||
}
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
set_register(r0, result);
|
||||
break;
|
||||
}
|
||||
case Args_Int_IntDoubleIntInt: {
|
||||
double dval;
|
||||
int32_t result;
|
||||
Prototype_Int_IntDoubleIntInt target =
|
||||
reinterpret_cast<Prototype_Int_IntDoubleIntInt>(external);
|
||||
if (UseHardFpABI()) {
|
||||
get_double_from_d_register(0, &dval);
|
||||
result = target(arg0, dval, arg1, arg2);
|
||||
} else {
|
||||
dval = get_double_from_register_pair(2);
|
||||
result = target(arg0, dval, arg4, arg5);
|
||||
}
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
set_register(r0, result);
|
||||
break;
|
||||
}
|
||||
case Args_Double_DoubleDoubleDouble: {
|
||||
double dval0, dval1, dval2;
|
||||
int32_t ival;
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
// the last argument is on stack
|
||||
getFpFromStack(stack_pointer, &dval2);
|
||||
Prototype_Double_DoubleDoubleDouble target =
|
||||
reinterpret_cast<Prototype_Double_DoubleDoubleDouble>(external);
|
||||
double dresult = target(dval0, dval1, dval2);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
case Args_Double_DoubleDoubleDoubleDouble: {
|
||||
double dval0, dval1, dval2, dval3;
|
||||
int32_t ival;
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
// the two last arguments are on stack
|
||||
getFpFromStack(stack_pointer, &dval2);
|
||||
getFpFromStack(stack_pointer + 2, &dval3);
|
||||
Prototype_Double_DoubleDoubleDoubleDouble target =
|
||||
reinterpret_cast<Prototype_Double_DoubleDoubleDoubleDouble>(
|
||||
external);
|
||||
double dresult = target(dval0, dval1, dval2, dval3);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
|
||||
case Args_Int32_General: {
|
||||
Prototype_Int32_General target =
|
||||
reinterpret_cast<Prototype_Int32_General>(external);
|
||||
int64_t result = target(arg0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32: {
|
||||
Prototype_Int32_GeneralInt32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32>(external);
|
||||
int64_t result = target(arg0, arg1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32: {
|
||||
Prototype_Int32_GeneralInt32Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32>(external);
|
||||
int64_t result = target(arg0, arg1, arg2);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32Int32: {
|
||||
Prototype_Int32_GeneralInt32Int32Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32Int32Int32: {
|
||||
Prototype_Int32_GeneralInt32Int32Int32Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32Int32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32Int32Int32Int32: {
|
||||
Prototype_Int32_GeneralInt32Int32Int32Int32Int32 target =
|
||||
reinterpret_cast<
|
||||
Prototype_Int32_GeneralInt32Int32Int32Int32Int32>(external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32Int32Int32General: {
|
||||
Prototype_Int32_GeneralInt32Int32Int32Int32General target =
|
||||
reinterpret_cast<
|
||||
Prototype_Int32_GeneralInt32Int32Int32Int32General>(external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32Int32Int32Int32Int32General: {
|
||||
Prototype_Int32_GeneralInt32Int32Int32Int32Int32Int32General target =
|
||||
reinterpret_cast<
|
||||
Prototype_Int32_GeneralInt32Int32Int32Int32Int32Int32General>(
|
||||
external);
|
||||
int64_t result =
|
||||
target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {
|
||||
float fval0, fval1;
|
||||
if (UseHardFpABI()) {
|
||||
get_float_from_s_register(2, &fval0);
|
||||
get_float_from_s_register(3, &fval1);
|
||||
} else {
|
||||
fval0 = mozilla::BitwiseCast<float>(arg2);
|
||||
fval1 = mozilla::BitwiseCast<float>(arg3);
|
||||
}
|
||||
Prototype_Int32_GeneralInt32Float32Float32Int32Int32Int32General
|
||||
target = reinterpret_cast<
|
||||
Prototype_Int32_GeneralInt32Float32Float32Int32Int32Int32General>(
|
||||
external);
|
||||
int64_t result =
|
||||
target(arg0, arg1, fval0, fval1, arg4, arg5, arg6, arg7);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {
|
||||
float fval0, fval1, fval2, fval3;
|
||||
if (UseHardFpABI()) {
|
||||
get_float_from_s_register(2, &fval0);
|
||||
get_float_from_s_register(3, &fval1);
|
||||
get_float_from_s_register(4, &fval2);
|
||||
get_float_from_s_register(5, &fval3);
|
||||
} else {
|
||||
fval0 = mozilla::BitwiseCast<float>(arg2);
|
||||
fval1 = mozilla::BitwiseCast<float>(arg3);
|
||||
fval2 = mozilla::BitwiseCast<float>(arg4);
|
||||
fval3 = mozilla::BitwiseCast<float>(arg5);
|
||||
}
|
||||
Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General
|
||||
target = reinterpret_cast<
|
||||
Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, fval0, fval1, fval2, fval3, arg6,
|
||||
arg7, arg8, arg9, arg10);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {
|
||||
float fval0, fval1, fval2, fval3, fval4;
|
||||
if (UseHardFpABI()) {
|
||||
get_float_from_s_register(2, &fval0);
|
||||
get_float_from_s_register(3, &fval1);
|
||||
get_float_from_s_register(5, &fval2);
|
||||
get_float_from_s_register(6, &fval3);
|
||||
get_float_from_s_register(8, &fval4);
|
||||
} else {
|
||||
fval0 = mozilla::BitwiseCast<float>(arg2);
|
||||
fval1 = mozilla::BitwiseCast<float>(arg3);
|
||||
fval2 = mozilla::BitwiseCast<float>(arg5);
|
||||
fval3 = mozilla::BitwiseCast<float>(arg6);
|
||||
fval4 = mozilla::BitwiseCast<float>(arg8);
|
||||
}
|
||||
Prototype_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General
|
||||
target = reinterpret_cast<
|
||||
Prototype_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General>(
|
||||
external);
|
||||
int64_t result =
|
||||
target(arg0, arg1, fval0, fval1, arg4, fval2, fval3, arg7, fval4,
|
||||
arg9, arg10, arg11, arg12, arg13);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32Int32General: {
|
||||
Prototype_Int32_GeneralInt32Int32Int32General target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32General>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32General: {
|
||||
Prototype_Int32_GeneralInt32Int32General target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32General>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int32Int64Int32: {
|
||||
Prototype_Int32_GeneralInt32Int32Int64Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int64Int32>(
|
||||
external);
|
||||
int64_t result =
|
||||
target(arg0, arg1, arg2, MakeInt64(arg4, arg5), arg6);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32GeneralInt32: {
|
||||
Prototype_Int32_GeneralInt32GeneralInt32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32GeneralInt32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32GeneralInt32Int32: {
|
||||
Prototype_Int32_GeneralInt32GeneralInt32Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32GeneralInt32Int32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt32Int64Int64Int32: {
|
||||
Prototype_Int32_GeneralInt32Int64Int64Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int64Int64Int32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, MakeInt64(arg2, arg3),
|
||||
MakeInt64(arg4, arg5), arg6);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralGeneral: {
|
||||
Prototype_Int32_GeneralGeneral target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralGeneral>(external);
|
||||
int64_t result = target(arg0, arg1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralGeneralGeneral: {
|
||||
Prototype_Int32_GeneralGeneralGeneral target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralGeneralGeneral>(external);
|
||||
int64_t result = target(arg0, arg1, arg2);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralGeneralInt32Int32: {
|
||||
Prototype_Int32_GeneralGeneralInt32Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralGeneralInt32Int32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int32Int32: {
|
||||
Prototype_Int32_GeneralInt64Int32Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int32Int32>(
|
||||
external);
|
||||
int64_t result = target(arg0, MakeInt64(arg2, arg3), arg4, arg5);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int32Int32Int32Int32: {
|
||||
Prototype_Int32_GeneralInt64Int32Int32Int32Int32 target =
|
||||
reinterpret_cast<
|
||||
Prototype_Int32_GeneralInt64Int32Int32Int32Int32>(external);
|
||||
int64_t result =
|
||||
target(arg0, MakeInt64(arg2, arg3), arg4, arg5, arg6, arg7);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int32Int64Int32: {
|
||||
Prototype_Int32_GeneralInt64Int32Int64Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int32Int64Int32>(
|
||||
external);
|
||||
int64_t result = target(arg0, MakeInt64(arg2, arg3), arg4,
|
||||
MakeInt64(arg6, arg7), arg8);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int32Int64General: {
|
||||
Prototype_Int32_GeneralInt64Int32Int64General target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int32Int64General>(
|
||||
external);
|
||||
int64_t result = target(arg0, MakeInt64(arg2, arg3), arg4,
|
||||
MakeInt64(arg6, arg7), arg8);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int64Int64: {
|
||||
Prototype_Int32_GeneralInt64Int64Int64 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int64Int64>(
|
||||
external);
|
||||
int64_t result = target(arg0, MakeInt64(arg2, arg3),
|
||||
MakeInt64(arg4, arg5), MakeInt64(arg6, arg7));
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int64Int64Int32: {
|
||||
Prototype_Int32_GeneralInt64Int64Int64Int32 target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int64Int64Int32>(
|
||||
external);
|
||||
int64_t result =
|
||||
target(arg0, MakeInt64(arg2, arg3), MakeInt64(arg4, arg5),
|
||||
MakeInt64(arg6, arg7), arg8);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int64General: {
|
||||
Prototype_Int32_GeneralInt64Int64General target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int64General>(
|
||||
external);
|
||||
int64_t result =
|
||||
target(arg0, MakeInt64(arg2, arg3), MakeInt64(arg4, arg5), arg6);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int64Int64General: {
|
||||
Prototype_Int32_GeneralInt64Int64Int64General target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int64Int64General>(
|
||||
external);
|
||||
int64_t result =
|
||||
target(arg0, MakeInt64(arg2, arg3), MakeInt64(arg4, arg5),
|
||||
MakeInt64(arg6, arg7), arg8);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int32_GeneralInt64Int64Int64Int32Int32: {
|
||||
Prototype_Int32_GeneralInt64Int64Int64Int32Int32 target =
|
||||
reinterpret_cast<
|
||||
Prototype_Int32_GeneralInt64Int64Int64Int32Int32>(external);
|
||||
int64_t result =
|
||||
target(arg0, MakeInt64(arg2, arg3), MakeInt64(arg4, arg5),
|
||||
MakeInt64(arg6, arg7), arg8, arg9);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General_GeneralInt32: {
|
||||
Prototype_General_GeneralInt32 target =
|
||||
reinterpret_cast<Prototype_General_GeneralInt32>(external);
|
||||
int64_t result = target(arg0, arg1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General_GeneralInt32Int32: {
|
||||
Prototype_General_GeneralInt32Int32 target =
|
||||
reinterpret_cast<Prototype_General_GeneralInt32Int32>(external);
|
||||
int64_t result = target(arg0, arg1, arg2);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General_GeneralInt32General: {
|
||||
Prototype_General_GeneralInt32General target =
|
||||
reinterpret_cast<Prototype_General_GeneralInt32General>(external);
|
||||
int64_t result = target(arg0, arg1, arg2);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {
|
||||
Prototype_General_GeneralInt32Int32GeneralInt32 target =
|
||||
reinterpret_cast<Prototype_General_GeneralInt32Int32GeneralInt32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralGeneralInt32General: {
|
||||
Prototype_Int32_GeneralGeneralInt32General target =
|
||||
reinterpret_cast<Prototype_Int32_GeneralGeneralInt32General>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32: {
|
||||
Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32 target =
|
||||
reinterpret_cast<
|
||||
Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
// So many Generals, but no Colonels or Sargeants anywhere to be seen.
|
||||
case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {
|
||||
Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32 target =
|
||||
reinterpret_cast<
|
||||
Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32>(
|
||||
external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int64_General: {
|
||||
Prototype_Int64_General target =
|
||||
reinterpret_cast<Prototype_Int64_General>(external);
|
||||
int64_t result = target(arg0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int64_GeneralInt32: {
|
||||
Prototype_Int64_GeneralInt32 target =
|
||||
reinterpret_cast<Prototype_Int64_GeneralInt32>(external);
|
||||
int64_t result = target(arg0, arg1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int64_GeneralInt64: {
|
||||
Prototype_Int64_GeneralInt64 target =
|
||||
reinterpret_cast<Prototype_Int64_GeneralInt64>(external);
|
||||
int64_t result = target(arg0, MakeInt64(arg2, arg3));
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Int64_GeneralInt64Int32: {
|
||||
Prototype_Int64_GeneralInt64Int32 target =
|
||||
reinterpret_cast<Prototype_Int64_GeneralInt64Int32>(external);
|
||||
int64_t result = target(arg0, MakeInt64(arg2, arg3), arg4);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
|
||||
ABI_FUNCTION_TYPE_ARM32_SIM_DISPATCH
|
||||
default:
|
||||
MOZ_CRASH("call");
|
||||
}
|
||||
|
|
|
@ -472,7 +472,7 @@ class Simulator {
|
|||
void setCallResultDouble(double result);
|
||||
void setCallResultFloat(float result);
|
||||
void setCallResult(int64_t res);
|
||||
void scratchVolatileRegisters(bool scratchFloat = true);
|
||||
void scratchVolatileRegisters(void* target = nullptr);
|
||||
|
||||
template <class ReturnType, int register_size>
|
||||
void getFromVFPRegister(int reg_index, ReturnType* out);
|
||||
|
|
|
@ -487,226 +487,7 @@ void Simulator::setFP64Result(double result) {
|
|||
set_dreg(0, result);
|
||||
}
|
||||
|
||||
|
||||
typedef int64_t (*Prototype_General0)();
|
||||
typedef int64_t (*Prototype_General1)(int64_t arg0);
|
||||
typedef int64_t (*Prototype_General2)(int64_t arg0, int64_t arg1);
|
||||
typedef int64_t (*Prototype_General3)(int64_t arg0, int64_t arg1, int64_t arg2);
|
||||
typedef int64_t (*Prototype_General4)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3);
|
||||
typedef int64_t (*Prototype_General5)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3,
|
||||
int64_t arg4);
|
||||
typedef int64_t (*Prototype_General6)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3,
|
||||
int64_t arg4, int64_t arg5);
|
||||
typedef int64_t (*Prototype_General7)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3,
|
||||
int64_t arg4, int64_t arg5, int64_t arg6);
|
||||
typedef int64_t (*Prototype_General8)(int64_t arg0, int64_t arg1, int64_t arg2, int64_t arg3,
|
||||
int64_t arg4, int64_t arg5, int64_t arg6, int64_t arg7);
|
||||
typedef int64_t (*Prototype_GeneralGeneralGeneralInt64)(int64_t arg0, int64_t arg1, int64_t arg2,
|
||||
int64_t arg3);
|
||||
typedef int64_t (*Prototype_GeneralGeneralInt64Int64)(int64_t arg0, int64_t arg1, int64_t arg2,
|
||||
int64_t arg3);
|
||||
|
||||
typedef int64_t (*Prototype_Int_Double)(double arg0);
|
||||
typedef int64_t (*Prototype_Int_IntDouble)(int64_t arg0, double arg1);
|
||||
typedef int64_t (*Prototype_Int_DoubleInt)(double arg0, int64_t arg1);
|
||||
typedef int64_t (*Prototype_Int_DoubleIntInt)(double arg0, uint64_t arg1, uint64_t arg2);
|
||||
typedef int64_t (*Prototype_Int_IntDoubleIntInt)(uint64_t arg0, double arg1,
|
||||
uint64_t arg2, uint64_t arg3);
|
||||
|
||||
typedef float (*Prototype_Float32_Float32)(float arg0);
|
||||
typedef int64_t (*Prototype_Int_Float32)(float arg0);
|
||||
typedef float (*Prototype_Float32_Float32Float32)(float arg0, float arg1);
|
||||
|
||||
typedef double (*Prototype_Double_None)();
|
||||
typedef double (*Prototype_Double_Double)(double arg0);
|
||||
typedef double (*Prototype_Double_Int)(int64_t arg0);
|
||||
typedef double (*Prototype_Double_DoubleInt)(double arg0, int64_t arg1);
|
||||
typedef double (*Prototype_Double_IntDouble)(int64_t arg0, double arg1);
|
||||
typedef double (*Prototype_Double_DoubleDouble)(double arg0, double arg1);
|
||||
typedef double (*Prototype_Double_DoubleDoubleDouble)(double arg0, double arg1, double arg2);
|
||||
typedef double (*Prototype_Double_DoubleDoubleDoubleDouble)(double arg0, double arg1,
|
||||
double arg2, double arg3);
|
||||
|
||||
typedef int32_t (*Prototype_Int32_General)(int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32)(int64_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32)(int64_t, int32_t, int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32Int32)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32Int32Int32)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32Int32General)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32Int32Int32Int32General)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Int32Int32Int32General)(int64_t,
|
||||
int32_t,
|
||||
float,
|
||||
float,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General)(int64_t,
|
||||
int32_t,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General)(int64_t,
|
||||
int32_t,
|
||||
float,
|
||||
float,
|
||||
int32_t,
|
||||
float,
|
||||
float,
|
||||
int32_t,
|
||||
float,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int32General)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32General)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int32Int64Int32)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int64Int64)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32GeneralInt32)(int64_t,
|
||||
int32_t,
|
||||
int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32GeneralInt32Int32)(int64_t,
|
||||
int32_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt32Int64Int64Int32)(int64_t,
|
||||
int32_t,
|
||||
int64_t,
|
||||
int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneral)(int64_t, int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralGeneral)(int64_t,
|
||||
int64_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32)(int64_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int32Int32)(int64_t, int64_t,
|
||||
int32_t, int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int32)(int64_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int32Int32Int32)(int64_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int64Int32)(int64_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int32Int64General)(int64_t, int64_t,
|
||||
int32_t, int64_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64Int64)(int64_t, int64_t,
|
||||
int64_t, int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64Int64Int32)(int64_t,
|
||||
int64_t,
|
||||
int64_t,
|
||||
int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64General)(int64_t, int64_t,
|
||||
int64_t, int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64Int64General)(int64_t, int64_t,
|
||||
int64_t, int64_t,
|
||||
int64_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralInt64Int64Int64Int32Int32)(int64_t,
|
||||
int64_t,
|
||||
int64_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int64_t (*Prototype_General_GeneralInt32)(int64_t, int32_t);
|
||||
typedef int64_t (*Prototype_General_GeneralInt32Int32)(int64_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int64_t (*Prototype_General_GeneralInt32General)(int64_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int64_t (*Prototype_General_GeneralInt32Int32GeneralInt32)(int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32)(
|
||||
int64_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32)(
|
||||
int64_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int32_t,
|
||||
int64_t,
|
||||
int32_t);
|
||||
typedef int32_t (*Prototype_Int32_GeneralGeneralInt32General)(int64_t,
|
||||
int64_t,
|
||||
int32_t,
|
||||
int64_t);
|
||||
typedef int64_t (*Prototype_Int64_General)(int64_t);
|
||||
typedef int64_t (*Prototype_Int64_GeneralInt32)(int64_t, int32_t);
|
||||
typedef int64_t (*Prototype_Int64_GeneralInt64)(int64_t, int64_t);
|
||||
typedef int64_t (*Prototype_Int64_GeneralInt64Int32)(int64_t, int64_t, int32_t);
|
||||
ABI_FUNCTION_TYPE_SIM_PROTOTYPES
|
||||
|
||||
// Simulator support for callWithABI().
|
||||
void
|
||||
|
@ -736,6 +517,8 @@ Simulator::VisitCallRedirection(const Instruction* instr)
|
|||
DebugOnly<int64_t> x29 = xreg(29);
|
||||
DebugOnly<int64_t> savedSP = get_sp();
|
||||
|
||||
// Get the SP for reading stack arguments
|
||||
int64_t* sp = reinterpret_cast<int64_t*>(get_sp());
|
||||
// Remember LR for returning from the "call".
|
||||
int64_t savedLR = xreg(30);
|
||||
|
||||
|
@ -752,7 +535,6 @@ Simulator::VisitCallRedirection(const Instruction* instr)
|
|||
int64_t x5 = xreg(5);
|
||||
int64_t x6 = xreg(6);
|
||||
int64_t x7 = xreg(7);
|
||||
int64_t x8 = xreg(8);
|
||||
double d0 = dreg(0);
|
||||
double d1 = dreg(1);
|
||||
double d2 = dreg(2);
|
||||
|
@ -765,414 +547,7 @@ Simulator::VisitCallRedirection(const Instruction* instr)
|
|||
|
||||
// Dispatch the call and set the return value.
|
||||
switch (redir->type()) {
|
||||
// Cases with int64_t return type.
|
||||
case js::jit::Args_General0: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General0>(nativeFn)();
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General1: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General1>(nativeFn)(x0);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General2: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General2>(nativeFn)(x0, x1);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General3: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General3>(nativeFn)(x0, x1, x2);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General4: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General4>(nativeFn)(x0, x1, x2, x3);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General5: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General5>(nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General6: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General6>(nativeFn)(x0, x1, x2, x3, x4, x5);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General7: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General7>(nativeFn)(x0, x1, x2, x3, x4, x5, x6);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General8: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General8>(nativeFn)(x0, x1, x2, x3, x4, x5, x6, x7);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int_GeneralGeneralGeneralInt64: {
|
||||
int64_t ret = reinterpret_cast<Prototype_GeneralGeneralGeneralInt64>(nativeFn)(x0, x1, x2, x3);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int_GeneralGeneralInt64Int64: {
|
||||
int64_t ret = reinterpret_cast<Prototype_GeneralGeneralInt64Int64>(nativeFn)(x0, x1, x2, x3);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
// Cases with GPR return type. This can be int32 or int64, but int64 is a safer assumption.
|
||||
case js::jit::Args_Int_Double: {
|
||||
int64_t ret = reinterpret_cast<Prototype_Int_Double>(nativeFn)(d0);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int_IntDouble: {
|
||||
int64_t ret = reinterpret_cast<Prototype_Int_IntDouble>(nativeFn)(x0, d0);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case js::jit::Args_Int_DoubleInt: {
|
||||
int64_t ret = reinterpret_cast<Prototype_Int_DoubleInt>(nativeFn)(d0, x0);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case js::jit::Args_Int_IntDoubleIntInt: {
|
||||
int64_t ret = reinterpret_cast<Prototype_Int_IntDoubleIntInt>(nativeFn)(x0, d0, x1, x2);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case js::jit::Args_Int_DoubleIntInt: {
|
||||
int64_t ret = reinterpret_cast<Prototype_Int_DoubleIntInt>(nativeFn)(d0, x0, x1);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
// Cases with float return type.
|
||||
case js::jit::Args_Float32_Float32: {
|
||||
float ret = reinterpret_cast<Prototype_Float32_Float32>(nativeFn)(s0);
|
||||
setFP32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int_Float32: {
|
||||
int64_t ret = reinterpret_cast<Prototype_Int_Float32>(nativeFn)(s0);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Float32_Float32Float32: {
|
||||
float ret = reinterpret_cast<Prototype_Float32_Float32Float32>(nativeFn)(s0, s1);
|
||||
setFP32Result(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
// Cases with double return type.
|
||||
case js::jit::Args_Double_None: {
|
||||
double ret = reinterpret_cast<Prototype_Double_None>(nativeFn)();
|
||||
setFP64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Double_Double: {
|
||||
double ret = reinterpret_cast<Prototype_Double_Double>(nativeFn)(d0);
|
||||
setFP64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Double_Int: {
|
||||
double ret = reinterpret_cast<Prototype_Double_Int>(nativeFn)(x0);
|
||||
setFP64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Double_DoubleInt: {
|
||||
double ret = reinterpret_cast<Prototype_Double_DoubleInt>(nativeFn)(d0, x0);
|
||||
setFP64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Double_DoubleDouble: {
|
||||
double ret = reinterpret_cast<Prototype_Double_DoubleDouble>(nativeFn)(d0, d1);
|
||||
setFP64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Double_DoubleDoubleDouble: {
|
||||
double ret = reinterpret_cast<Prototype_Double_DoubleDoubleDouble>(nativeFn)(d0, d1, d2);
|
||||
setFP64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Double_DoubleDoubleDoubleDouble: {
|
||||
double ret = reinterpret_cast<Prototype_Double_DoubleDoubleDoubleDouble>(nativeFn)(d0, d1, d2, d3);
|
||||
setFP64Result(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case js::jit::Args_Double_IntDouble: {
|
||||
double ret = reinterpret_cast<Prototype_Double_IntDouble>(nativeFn)(x0, d0);
|
||||
setFP64Result(ret);
|
||||
break;
|
||||
}
|
||||
|
||||
case js::jit::Args_Int32_General: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_General>(nativeFn)(x0);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32>(nativeFn)(x0, x1);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt32Int32>(
|
||||
nativeFn)(x0, x1, x2);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32Int32: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32>(
|
||||
nativeFn)(x0, x1, x2, x3);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32Int32Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32Int32Int32Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32Int32Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4, x5);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32Int32Int32General: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32Int32General>(
|
||||
nativeFn)(x0, x1, x2, x3, x4, x5);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32Int32Int32Int32Int32General: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32Int32Int32Int32General>(
|
||||
nativeFn)(x0, x1, x2, x3, x4, x5, x6, x7);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Int32Int32General: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Float32Float32Int32Int32Int32General>(
|
||||
nativeFn)(x0, x1, s0, s1, x2, x3, x4, x5);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Float32Float32Float32Float32Int32Int32Int32Int32General>(
|
||||
nativeFn)(x0, x1, s0, s1, s2, s3, x2, x3, x4, x5, x6);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Float32Float32Int32Float32Float32Int32Float32Int32Int32Int32Int32General>(
|
||||
nativeFn)(x0, x1, s0, s1, x2, s2, s3, x3, s4, x4, x5, x6, x7, x8);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32Int32General: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int32General>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32General: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt32Int32General>(
|
||||
nativeFn)(x0, x1, x2, x3);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int32Int64Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int32Int64Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32GeneralInt32: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt32GeneralInt32>(
|
||||
nativeFn)(x0, x1, x2, x3);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32GeneralInt32Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32GeneralInt32Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt32Int64Int64Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt32Int64Int64Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralGeneral: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralGeneral>(nativeFn)(x0, x1);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralGeneralGeneral: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralGeneralGeneral>(
|
||||
nativeFn)(x0, x1, x2);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralGeneralInt32Int32: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralGeneralInt32Int32>(
|
||||
nativeFn)(x0, x1, x2, x3);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int32Int32: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt64Int32Int32>(
|
||||
nativeFn)(x0, x1, x2, x3);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int32Int32Int32Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int32Int32Int32Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4, x5);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int32Int64Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int32Int64Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int32Int64General: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt64Int32Int64General>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int64Int64: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt64Int64Int64>(
|
||||
nativeFn)(x0, x1, x2, x3);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int64Int64Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int64Int64Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int64General: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt64Int64General>(
|
||||
nativeFn)(x0, x1, x2, x3);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int64Int64General: {
|
||||
int32_t ret = reinterpret_cast<Prototype_Int32_GeneralInt64Int64Int64General>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralInt64Int64Int64Int32Int32: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralInt64Int64Int64Int32Int32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4, x5);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General_GeneralInt32: {
|
||||
int64_t ret =
|
||||
reinterpret_cast<Prototype_General_GeneralInt32>(nativeFn)(x0, x1);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General_GeneralInt32Int32: {
|
||||
int64_t ret = reinterpret_cast<Prototype_General_GeneralInt32Int32>(
|
||||
nativeFn)(x0, x1, x2);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General_GeneralInt32General: {
|
||||
int64_t ret =
|
||||
reinterpret_cast<Prototype_General_GeneralInt32General>(
|
||||
nativeFn)(x0, x1, x2);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_General_GeneralInt32Int32GeneralInt32: {
|
||||
int64_t ret =
|
||||
reinterpret_cast<Prototype_General_GeneralInt32Int32GeneralInt32>(
|
||||
nativeFn)(x0, x1, x2, x3, x4);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralGeneralInt32GeneralInt32Int32Int32: {
|
||||
int32_t ret = reinterpret_cast<
|
||||
Prototype_Int32_GeneralGeneralInt32GeneralInt32Int32Int32>(nativeFn)(
|
||||
x0, x1, x2, x3, x4, x5, x6);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralGeneralInt32Int32Int32GeneralInt32: {
|
||||
int32_t ret = reinterpret_cast<
|
||||
Prototype_Int32_GeneralGeneralInt32Int32Int32GeneralInt32>(nativeFn)(
|
||||
x0, x1, x2, x3, x4, x5, x6);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int32_GeneralGeneralInt32General: {
|
||||
int32_t ret =
|
||||
reinterpret_cast<Prototype_Int32_GeneralGeneralInt32General>(
|
||||
nativeFn)(x0, x1, x2, x3);
|
||||
setGPR32Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int64_General: {
|
||||
int64_t ret =
|
||||
reinterpret_cast<Prototype_Int64_General>(
|
||||
nativeFn)(x0);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int64_GeneralInt32: {
|
||||
int64_t ret =
|
||||
reinterpret_cast<Prototype_Int64_GeneralInt32>(nativeFn)(x0, x1);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int64_GeneralInt64: {
|
||||
int64_t ret =
|
||||
reinterpret_cast<Prototype_Int64_GeneralInt64>(
|
||||
nativeFn)(x0, x1);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
case js::jit::Args_Int64_GeneralInt64Int32: {
|
||||
int64_t ret = reinterpret_cast<Prototype_Int64_GeneralInt64Int32>(
|
||||
nativeFn)(x0, x1, x2);
|
||||
setGPR64Result(ret);
|
||||
break;
|
||||
}
|
||||
ABI_FUNCTION_TYPE_ARM64_SIM_DISPATCH
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Unknown function type.");
|
||||
|
|
|
@ -260,6 +260,13 @@ elif CONFIG["JS_CODEGEN_WASM32"]:
|
|||
"wasm32/Trampoline-wasm32.cpp",
|
||||
]
|
||||
|
||||
# Generate jit/ABIFunctionTypeGenerated.h from jit/ABIFunctionType.yaml
|
||||
GeneratedFile(
|
||||
"ABIFunctionTypeGenerated.h",
|
||||
script="GenerateABIFunctionType.py",
|
||||
inputs=["ABIFunctionType.yaml"],
|
||||
)
|
||||
|
||||
# Generate jit/MIROpsGenerated.h from jit/MIROps.yaml
|
||||
GeneratedFile(
|
||||
"MIROpsGenerated.h",
|
||||
|
|
|
@ -453,10 +453,13 @@ ABIArgType ToABIType(MIRType type) {
|
|||
ABIFunctionType ToABIType(const SymbolicAddressSignature& sig) {
|
||||
MOZ_ASSERT_IF(sig.failureMode != FailureMode::Infallible,
|
||||
ToABIType(sig.failureMode) == ToABIType(sig.retType));
|
||||
int abiType = ToABIType(sig.retType) << RetType_Shift;
|
||||
int abiType = 0;
|
||||
for (int i = 0; i < sig.numArgs; i++) {
|
||||
abiType |= (ToABIType(sig.argTypes[i]) << (ArgType_Shift * (i + 1)));
|
||||
abiType <<= ArgType_Shift;
|
||||
abiType |= ToABIType(sig.argTypes[i]);
|
||||
}
|
||||
abiType <<= ArgType_Shift;
|
||||
abiType |= ToABIType(sig.retType);
|
||||
return ABIFunctionType(abiType);
|
||||
}
|
||||
#endif
|
||||
|
@ -1125,16 +1128,16 @@ void* wasm::AddressOf(SymbolicAddress imm, ABIFunctionType* abiType) {
|
|||
*abiType = Args_General0;
|
||||
return FuncCast(AllocateBigIntTenuredNoGC, *abiType);
|
||||
case SymbolicAddress::DivI64:
|
||||
*abiType = Args_General4;
|
||||
*abiType = Args_Int64_Int32Int32Int32Int32;
|
||||
return FuncCast(DivI64, *abiType);
|
||||
case SymbolicAddress::UDivI64:
|
||||
*abiType = Args_General4;
|
||||
*abiType = Args_Int64_Int32Int32Int32Int32;
|
||||
return FuncCast(UDivI64, *abiType);
|
||||
case SymbolicAddress::ModI64:
|
||||
*abiType = Args_General4;
|
||||
*abiType = Args_Int64_Int32Int32Int32Int32;
|
||||
return FuncCast(ModI64, *abiType);
|
||||
case SymbolicAddress::UModI64:
|
||||
*abiType = Args_General4;
|
||||
*abiType = Args_Int64_Int32Int32Int32Int32;
|
||||
return FuncCast(UModI64, *abiType);
|
||||
case SymbolicAddress::TruncateDoubleToUint64:
|
||||
*abiType = Args_Int64_Double;
|
||||
|
@ -1162,10 +1165,10 @@ void* wasm::AddressOf(SymbolicAddress imm, ABIFunctionType* abiType) {
|
|||
return FuncCast(Int64ToFloat32, *abiType);
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
case SymbolicAddress::aeabi_idivmod:
|
||||
*abiType = Args_General2;
|
||||
*abiType = Args_Int64_GeneralGeneral;
|
||||
return FuncCast(__aeabi_idivmod, *abiType);
|
||||
case SymbolicAddress::aeabi_uidivmod:
|
||||
*abiType = Args_General2;
|
||||
*abiType = Args_Int64_GeneralGeneral;
|
||||
return FuncCast(__aeabi_uidivmod, *abiType);
|
||||
#endif
|
||||
case SymbolicAddress::ModD:
|
||||
|
@ -1977,35 +1980,38 @@ static Maybe<ABIFunctionType> ToBuiltinABIFunctionType(
|
|||
return Nothing();
|
||||
}
|
||||
|
||||
uint32_t abiType;
|
||||
switch (results[0].kind()) {
|
||||
case ValType::F32:
|
||||
abiType = ArgType_Float32 << RetType_Shift;
|
||||
break;
|
||||
case ValType::F64:
|
||||
abiType = ArgType_Float64 << RetType_Shift;
|
||||
break;
|
||||
default:
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
if ((args.length() + 1) > (sizeof(uint32_t) * 8 / ArgType_Shift)) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
uint32_t abiType = 0;
|
||||
for (size_t i = 0; i < args.length(); i++) {
|
||||
switch (args[i].kind()) {
|
||||
case ValType::F32:
|
||||
abiType |= (ArgType_Float32 << (ArgType_Shift * (i + 1)));
|
||||
abiType <<= ArgType_Shift;
|
||||
abiType |= ArgType_Float32;
|
||||
break;
|
||||
case ValType::F64:
|
||||
abiType |= (ArgType_Float64 << (ArgType_Shift * (i + 1)));
|
||||
abiType <<= ArgType_Shift;
|
||||
abiType |= ArgType_Float64;
|
||||
break;
|
||||
default:
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
abiType <<= ArgType_Shift;
|
||||
switch (results[0].kind()) {
|
||||
case ValType::F32:
|
||||
abiType |= ArgType_Float32;
|
||||
break;
|
||||
case ValType::F64:
|
||||
abiType |= ArgType_Float64;
|
||||
break;
|
||||
default:
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
return Some(ABIFunctionType(abiType));
|
||||
}
|
||||
|
||||
|
|
|
@ -2428,8 +2428,10 @@ struct ABIFunctionArgs {
|
|||
MIRType operator[](size_t i) const {
|
||||
MOZ_ASSERT(i < len);
|
||||
uint64_t abi = uint64_t(abiType);
|
||||
while (i--) {
|
||||
size_t argAtLSB = len - 1;
|
||||
while (argAtLSB != i) {
|
||||
abi = abi >> ArgType_Shift;
|
||||
argAtLSB--;
|
||||
}
|
||||
return ToMIRType(ABIArgType(abi & ArgType_Mask));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче