diff --git a/src/coreclr/jit/target.h b/src/coreclr/jit/target.h index bfa443dc1f4a5f..3bdf8c8d065615 100644 --- a/src/coreclr/jit/target.h +++ b/src/coreclr/jit/target.h @@ -619,20 +619,20 @@ static uint32_t BitScanForward(const regMaskTP& mask) #ifdef TARGET_XARCH - #define JMP_DIST_SMALL_MAX_NEG (-128) - #define JMP_DIST_SMALL_MAX_POS (+127) +#define JMP_DIST_SMALL_MAX_NEG (-128) +#define JMP_DIST_SMALL_MAX_POS (+127) - #define JCC_DIST_SMALL_MAX_NEG (-128) - #define JCC_DIST_SMALL_MAX_POS (+127) +#define JCC_DIST_SMALL_MAX_NEG (-128) +#define JCC_DIST_SMALL_MAX_POS (+127) - #define JMP_SIZE_SMALL (2) - #define JMP_SIZE_LARGE (5) +#define JMP_SIZE_SMALL (2) +#define JMP_SIZE_LARGE (5) - #define JCC_SIZE_SMALL (2) - #define JCC_SIZE_LARGE (6) +#define JCC_SIZE_SMALL (2) +#define JCC_SIZE_LARGE (6) - #define PUSH_INST_SIZE (5) - #define CALL_INST_SIZE (5) +#define PUSH_INST_SIZE (5) +#define CALL_INST_SIZE (5) #endif // TARGET_XARCH @@ -649,12 +649,12 @@ static_assert((FEATURE_TAILCALL_OPT == 0) || (FEATURE_FASTTAILCALL == 1)); /*****************************************************************************/ #if CPU_HAS_BYTE_REGS - #define RBM_BYTE_REGS (RBM_EAX|RBM_ECX|RBM_EDX|RBM_EBX) - #define BYTE_REG_COUNT 4 - #define RBM_NON_BYTE_REGS (RBM_ESI|RBM_EDI) +#define RBM_BYTE_REGS (RBM_EAX|RBM_ECX|RBM_EDX|RBM_EBX) +#define BYTE_REG_COUNT 4 +#define RBM_NON_BYTE_REGS (RBM_ESI|RBM_EDI) #else - #define RBM_BYTE_REGS RBM_ALLINT - #define RBM_NON_BYTE_REGS RBM_NONE +#define RBM_BYTE_REGS RBM_ALLINT +#define RBM_NON_BYTE_REGS RBM_NONE #endif // clang-format on diff --git a/src/coreclr/jit/targetamd64.h b/src/coreclr/jit/targetamd64.h index 9b287dd6906605..d0f8fe23831d78 100644 --- a/src/coreclr/jit/targetamd64.h +++ b/src/coreclr/jit/targetamd64.h @@ -7,290 +7,290 @@ #endif // clang-format off - #define CORINFO_ARCH_TARGET CORINFO_ARCH_X64 +#define CORINFO_ARCH_TARGET CORINFO_ARCH_X64 - // TODO-AMD64-CQ: Fine tune the following xxBlk threshold values: - #define CPU_LOAD_STORE_ARCH 0 - #define CPU_HAS_BYTE_REGS 0 +// TODO-AMD64-CQ: Fine tune the following xxBlk threshold values: +#define CPU_LOAD_STORE_ARCH 0 +#define CPU_HAS_BYTE_REGS 0 - #define CPOBJ_NONGC_SLOTS_LIMIT 4 // For CpObj code generation, this is the threshold of the number - // of contiguous non-gc slots that trigger generating rep movsq instead of - // sequences of movsq instructions +#define CPOBJ_NONGC_SLOTS_LIMIT 4 // For CpObj code generation, this is the threshold of the number + // of contiguous non-gc slots that trigger generating rep movsq instead of + // sequences of movsq instructions #ifdef FEATURE_SIMD - #define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned +#define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned #if defined(UNIX_AMD64_ABI) - #define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 0 // Whether SIMD registers are partially saved at calls +#define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 0 // Whether SIMD registers are partially saved at calls #else // !UNIX_AMD64_ABI - #define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 1 // Whether SIMD registers are partially saved at calls +#define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 1 // Whether SIMD registers are partially saved at calls #endif // !UNIX_AMD64_ABI #endif - #define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog - #define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers - #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp - #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. - #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). +#define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog +#define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers +#define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp +#define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. +#define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). #ifdef UNIX_AMD64_ABI - #define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies - #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register - #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register - #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register - #define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers - #define MAX_PASS_MULTIREG_BYTES 32 // Maximum size of a struct that could be passed in more than one register (Max is two SIMD16s) - #define MAX_RET_MULTIREG_BYTES 32 // Maximum size of a struct that could be returned in more than one register (Max is two SIMD16s) - #define MAX_ARG_REG_COUNT 2 // Maximum registers used to pass a single argument in multiple registers. - #define MAX_RET_REG_COUNT 4 // Maximum registers used to return a value. - - #define MAX_MULTIREG_COUNT 4 // Maximum number of registers defined by a single instruction (including calls). - // This is also the maximum number of registers for a MultiReg node. +#define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies +#define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register +#define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register +#define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register +#define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers +#define MAX_PASS_MULTIREG_BYTES 32 // Maximum size of a struct that could be passed in more than one register (Max is two SIMD16s) +#define MAX_RET_MULTIREG_BYTES 32 // Maximum size of a struct that could be returned in more than one register (Max is two SIMD16s) +#define MAX_ARG_REG_COUNT 2 // Maximum registers used to pass a single argument in multiple registers. +#define MAX_RET_REG_COUNT 4 // Maximum registers used to return a value. + +#define MAX_MULTIREG_COUNT 4 // Maximum number of registers defined by a single instruction (including calls). + // This is also the maximum number of registers for a MultiReg node. #else // !UNIX_AMD64_ABI - #define WINDOWS_AMD64_ABI // Uses the Windows ABI for AMD64 - #define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies - #define FEATURE_MULTIREG_ARGS_OR_RET 0 // Support for passing and/or returning single values in more than one register - #define FEATURE_MULTIREG_ARGS 0 // Support for passing a single argument in more than one register - #define FEATURE_MULTIREG_RET 0 // Support for returning a single value in more than one register - #define FEATURE_MULTIREG_STRUCT_PROMOTE 0 // True when we want to promote fields of a multireg struct into registers - #define MAX_PASS_MULTIREG_BYTES 0 // No multireg arguments - #define MAX_RET_MULTIREG_BYTES 0 // No multireg return values - #define MAX_ARG_REG_COUNT 1 // Maximum registers used to pass a single argument (no arguments are passed using multiple registers) - #define MAX_RET_REG_COUNT 1 // Maximum registers used to return a value. - - #define MAX_MULTIREG_COUNT 2 // Maximum number of registers defined by a single instruction (including calls). - // This is also the maximum number of registers for a MultiReg node. - // Note that this must be greater than 1 so that GenTreeLclVar can have an array of - // MAX_MULTIREG_COUNT - 1. +#define WINDOWS_AMD64_ABI // Uses the Windows ABI for AMD64 +#define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies +#define FEATURE_MULTIREG_ARGS_OR_RET 0 // Support for passing and/or returning single values in more than one register +#define FEATURE_MULTIREG_ARGS 0 // Support for passing a single argument in more than one register +#define FEATURE_MULTIREG_RET 0 // Support for returning a single value in more than one register +#define FEATURE_MULTIREG_STRUCT_PROMOTE 0 // True when we want to promote fields of a multireg struct into registers +#define MAX_PASS_MULTIREG_BYTES 0 // No multireg arguments +#define MAX_RET_MULTIREG_BYTES 0 // No multireg return values +#define MAX_ARG_REG_COUNT 1 // Maximum registers used to pass a single argument (no arguments are passed using multiple registers) +#define MAX_RET_REG_COUNT 1 // Maximum registers used to return a value. + +#define MAX_MULTIREG_COUNT 2 // Maximum number of registers defined by a single instruction (including calls). + // This is also the maximum number of registers for a MultiReg node. + // Note that this must be greater than 1 so that GenTreeLclVar can have an array of + // MAX_MULTIREG_COUNT - 1. #endif // !UNIX_AMD64_ABI - #define NOGC_WRITE_BARRIERS 0 // We DO-NOT have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers - #define USER_ARGS_COME_LAST 1 - #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#define NOGC_WRITE_BARRIERS 0 // We DO-NOT have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers +#define USER_ARGS_COME_LAST 1 +#define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #ifdef UNIX_AMD64_ABI - #define ETW_EBP_FRAMED 1 // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods +#define ETW_EBP_FRAMED 1 // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods #else // !UNIX_AMD64_ABI - #define ETW_EBP_FRAMED 0 // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods +#define ETW_EBP_FRAMED 0 // if 1 we cannot use EBP as a scratch register and must create EBP based frames for most methods #endif // !UNIX_AMD64_ABI - #define CSE_CONSTS 1 // Enable if we want to CSE constants - #define EMIT_TRACK_STACK_DEPTH 1 - #define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that +#define CSE_CONSTS 1 // Enable if we want to CSE constants +#define EMIT_TRACK_STACK_DEPTH 1 +#define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that - #define RBM_LOWFLOAT (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM3 | RBM_XMM4 | RBM_XMM5 | RBM_XMM6 | RBM_XMM7 | RBM_XMM8 | RBM_XMM9 | RBM_XMM10 | RBM_XMM11 | RBM_XMM12 | RBM_XMM13 | RBM_XMM14 | RBM_XMM15 ) - #define RBM_HIGHFLOAT (RBM_XMM16 | RBM_XMM17 | RBM_XMM18 | RBM_XMM19 | RBM_XMM20 | RBM_XMM21 | RBM_XMM22 | RBM_XMM23 | RBM_XMM24 | RBM_XMM25 | RBM_XMM26 | RBM_XMM27 | RBM_XMM28 | RBM_XMM29 | RBM_XMM30 | RBM_XMM31) - #define CNT_HIGHFLOAT 16 +#define RBM_LOWFLOAT (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM3 | RBM_XMM4 | RBM_XMM5 | RBM_XMM6 | RBM_XMM7 | RBM_XMM8 | RBM_XMM9 | RBM_XMM10 | RBM_XMM11 | RBM_XMM12 | RBM_XMM13 | RBM_XMM14 | RBM_XMM15 ) +#define RBM_HIGHFLOAT (RBM_XMM16 | RBM_XMM17 | RBM_XMM18 | RBM_XMM19 | RBM_XMM20 | RBM_XMM21 | RBM_XMM22 | RBM_XMM23 | RBM_XMM24 | RBM_XMM25 | RBM_XMM26 | RBM_XMM27 | RBM_XMM28 | RBM_XMM29 | RBM_XMM30 | RBM_XMM31) +#define CNT_HIGHFLOAT 16 - #define RBM_ALLFLOAT_INIT RBM_LOWFLOAT +#define RBM_ALLFLOAT_INIT RBM_LOWFLOAT - #define RBM_ALLFLOAT get_RBM_ALLFLOAT() +#define RBM_ALLFLOAT get_RBM_ALLFLOAT() - #define RBM_ALLDOUBLE RBM_ALLFLOAT - #define REG_FP_FIRST REG_XMM0 - #define REG_FP_LAST REG_XMM31 - #define FIRST_FP_ARGREG REG_XMM0 +#define RBM_ALLDOUBLE RBM_ALLFLOAT +#define REG_FP_FIRST REG_XMM0 +#define REG_FP_LAST REG_XMM31 +#define FIRST_FP_ARGREG REG_XMM0 - #define REG_MASK_FIRST REG_K0 - #define REG_MASK_LAST REG_K7 +#define REG_MASK_FIRST REG_K0 +#define REG_MASK_LAST REG_K7 - #define RBM_ALLMASK_INIT (0) - #define RBM_ALLMASK_EVEX (RBM_K1 | RBM_K2 | RBM_K3 | RBM_K4 | RBM_K5 | RBM_K6 | RBM_K7) - #define RBM_ALLMASK get_RBM_ALLMASK() +#define RBM_ALLMASK_INIT (0) +#define RBM_ALLMASK_EVEX (RBM_K1 | RBM_K2 | RBM_K3 | RBM_K4 | RBM_K5 | RBM_K6 | RBM_K7) +#define RBM_ALLMASK get_RBM_ALLMASK() - #define CNT_MASK_REGS 8 +#define CNT_MASK_REGS 8 #ifdef UNIX_AMD64_ABI - #define LAST_FP_ARGREG REG_XMM7 +#define LAST_FP_ARGREG REG_XMM7 #else // !UNIX_AMD64_ABI - #define LAST_FP_ARGREG REG_XMM3 +#define LAST_FP_ARGREG REG_XMM3 #endif // !UNIX_AMD64_ABI - #define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set - #define REGNUM_BITS 7 // number of bits in a REG_* - #define REGSIZE_BYTES 8 // number of bytes in one register - #define XMM_REGSIZE_BYTES 16 // XMM register size in bytes - #define YMM_REGSIZE_BYTES 32 // YMM register size in bytes - #define ZMM_REGSIZE_BYTES 64 // ZMM register size in bytes +#define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set +#define REGNUM_BITS 7 // number of bits in a REG_* +#define REGSIZE_BYTES 8 // number of bytes in one register +#define XMM_REGSIZE_BYTES 16 // XMM register size in bytes +#define YMM_REGSIZE_BYTES 32 // YMM register size in bytes +#define ZMM_REGSIZE_BYTES 64 // ZMM register size in bytes - #define CODE_ALIGN 1 // code alignment requirement - #define STACK_ALIGN 16 // stack alignment requirement - #define STACK_ALIGN_SHIFT 4 // Shift-right amount to convert size in bytes to size in STACK_ALIGN units == log2(STACK_ALIGN) +#define CODE_ALIGN 1 // code alignment requirement +#define STACK_ALIGN 16 // stack alignment requirement +#define STACK_ALIGN_SHIFT 4 // Shift-right amount to convert size in bytes to size in STACK_ALIGN units == log2(STACK_ALIGN) #if ETW_EBP_FRAMED - #define RBM_ETW_FRAMED_EBP RBM_NONE - #define RBM_ETW_FRAMED_EBP_LIST - #define REG_ETW_FRAMED_EBP_LIST - #define REG_ETW_FRAMED_EBP_COUNT 0 +#define RBM_ETW_FRAMED_EBP RBM_NONE +#define RBM_ETW_FRAMED_EBP_LIST +#define REG_ETW_FRAMED_EBP_LIST +#define REG_ETW_FRAMED_EBP_COUNT 0 #else // !ETW_EBP_FRAMED - #define RBM_ETW_FRAMED_EBP RBM_EBP - #define RBM_ETW_FRAMED_EBP_LIST RBM_EBP, - #define REG_ETW_FRAMED_EBP_LIST REG_EBP, - #define REG_ETW_FRAMED_EBP_COUNT 1 +#define RBM_ETW_FRAMED_EBP RBM_EBP +#define RBM_ETW_FRAMED_EBP_LIST RBM_EBP, +#define REG_ETW_FRAMED_EBP_LIST REG_EBP, +#define REG_ETW_FRAMED_EBP_COUNT 1 #endif // !ETW_EBP_FRAMED #ifdef UNIX_AMD64_ABI - #define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. +#define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. - #define RBM_INT_CALLEE_SAVED (RBM_EBX|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15) - #define RBM_INT_CALLEE_TRASH_INIT (RBM_EAX|RBM_RDI|RBM_RSI|RBM_EDX|RBM_ECX|RBM_R8|RBM_R9|RBM_R10|RBM_R11) - #define RBM_FLT_CALLEE_SAVED (0) +#define RBM_INT_CALLEE_SAVED (RBM_EBX|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15) +#define RBM_INT_CALLEE_TRASH_INIT (RBM_EAX|RBM_RDI|RBM_RSI|RBM_EDX|RBM_ECX|RBM_R8|RBM_R9|RBM_R10|RBM_R11) +#define RBM_FLT_CALLEE_SAVED (0) /* NOTE: Sync with variable name defined in compiler.h */ - #define RBM_FLT_CALLEE_TRASH_INIT (RBM_XMM0|RBM_XMM1|RBM_XMM2|RBM_XMM3|RBM_XMM4|RBM_XMM5|RBM_XMM6|RBM_XMM7| \ +#define RBM_FLT_CALLEE_TRASH_INIT (RBM_XMM0|RBM_XMM1|RBM_XMM2|RBM_XMM3|RBM_XMM4|RBM_XMM5|RBM_XMM6|RBM_XMM7| \ RBM_XMM8|RBM_XMM9|RBM_XMM10|RBM_XMM11|RBM_XMM12|RBM_XMM13|RBM_XMM14|RBM_XMM15) - #define REG_PROFILER_ENTER_ARG_0 REG_R14 - #define RBM_PROFILER_ENTER_ARG_0 RBM_R14 - #define REG_PROFILER_ENTER_ARG_1 REG_R15 - #define RBM_PROFILER_ENTER_ARG_1 RBM_R15 +#define REG_PROFILER_ENTER_ARG_0 REG_R14 +#define RBM_PROFILER_ENTER_ARG_0 RBM_R14 +#define REG_PROFILER_ENTER_ARG_1 REG_R15 +#define RBM_PROFILER_ENTER_ARG_1 RBM_R15 - #define REG_DEFAULT_PROFILER_CALL_TARGET REG_R11 +#define REG_DEFAULT_PROFILER_CALL_TARGET REG_R11 #else // !UNIX_AMD64_ABI #define MIN_ARG_AREA_FOR_CALL (4 * REGSIZE_BYTES) // Minimum required outgoing argument space for a call. - #define RBM_INT_CALLEE_SAVED (RBM_EBX|RBM_ESI|RBM_EDI|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15) - #define RBM_INT_CALLEE_TRASH_INIT (RBM_EAX|RBM_ECX|RBM_EDX|RBM_R8|RBM_R9|RBM_R10|RBM_R11) - #define RBM_FLT_CALLEE_SAVED (RBM_XMM6|RBM_XMM7|RBM_XMM8|RBM_XMM9|RBM_XMM10|RBM_XMM11|RBM_XMM12|RBM_XMM13|RBM_XMM14|RBM_XMM15) +#define RBM_INT_CALLEE_SAVED (RBM_EBX|RBM_ESI|RBM_EDI|RBM_ETW_FRAMED_EBP|RBM_R12|RBM_R13|RBM_R14|RBM_R15) +#define RBM_INT_CALLEE_TRASH_INIT (RBM_EAX|RBM_ECX|RBM_EDX|RBM_R8|RBM_R9|RBM_R10|RBM_R11) +#define RBM_FLT_CALLEE_SAVED (RBM_XMM6|RBM_XMM7|RBM_XMM8|RBM_XMM9|RBM_XMM10|RBM_XMM11|RBM_XMM12|RBM_XMM13|RBM_XMM14|RBM_XMM15) /* NOTE: Sync with variable name defined in compiler.h */ - #define RBM_FLT_CALLEE_TRASH_INIT (RBM_XMM0|RBM_XMM1|RBM_XMM2|RBM_XMM3|RBM_XMM4|RBM_XMM5) +#define RBM_FLT_CALLEE_TRASH_INIT (RBM_XMM0|RBM_XMM1|RBM_XMM2|RBM_XMM3|RBM_XMM4|RBM_XMM5) #endif // !UNIX_AMD64_ABI - #define RBM_FLT_CALLEE_TRASH get_RBM_FLT_CALLEE_TRASH() +#define RBM_FLT_CALLEE_TRASH get_RBM_FLT_CALLEE_TRASH() /* NOTE: Sync with variable name defined in compiler.h */ - #define RBM_MSK_CALLEE_TRASH_INIT (0) - #define RBM_MSK_CALLEE_TRASH_EVEX RBM_ALLMASK_EVEX - - #define RBM_MSK_CALLEE_SAVED (0) - #define RBM_MSK_CALLEE_TRASH get_RBM_MSK_CALLEE_TRASH() - - #define RBM_OSR_INT_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_EBP) - - #define REG_FLT_CALLEE_SAVED_FIRST REG_XMM6 - #define REG_FLT_CALLEE_SAVED_LAST REG_XMM15 - - #define RBM_LOWINT RBM_ALLINT_INIT - #define RBM_HIGHINT (RBM_R16|RBM_R17|RBM_R18|RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28|RBM_R29|RBM_R30|RBM_R31) - - #define RBM_ALLINT_INIT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH_INIT) - #define RBM_ALLINT get_RBM_ALLINT() - #define RBM_INT_CALLEE_TRASH_ALL (RBM_INT_CALLEE_TRASH_INIT | RBM_HIGHINT) - #define RBM_ALLINT_ALL (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH_ALL) - #define RBM_INT_CALLEE_TRASH get_RBM_INT_CALLEE_TRASH() - - #define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH | RBM_MSK_CALLEE_TRASH) - #define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED | RBM_MSK_CALLEE_SAVED) - - // AMD64 write barrier ABI (see vm\amd64\JitHelpers_Fast.asm, vm\amd64\JitHelpers_Fast.S): - // CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): - // The usual amd64 calling convention is observed. - // TODO-CQ: could this be optimized? - // CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): - // On entry: - // rsi: the source address (points to object reference to write) - // rdi: the destination address (object reference written here) - // On exit: - // rcx: trashed - // rdi: incremented by 8 - // rsi: incremented by 8 - // rax: trashed when FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP is defined - // TODO-CQ: the above description matches the comments for the amd64 assembly code of JIT_ByRefWriteBarrier, - // however the defines below assume the normal calling convention *except* for rdi/rsi. If we could - // reduce the number of trashed variables, we could improve code quality. - // - - #define REG_WRITE_BARRIER_DST REG_ARG_0 - #define RBM_WRITE_BARRIER_DST RBM_ARG_0 - - #define REG_WRITE_BARRIER_SRC REG_ARG_1 - #define RBM_WRITE_BARRIER_SRC RBM_ARG_1 - - #define RBM_CALLEE_TRASH_NOGC RBM_CALLEE_TRASH - - // Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_TRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF (RBM_RAX | RBM_RCX) - - // Registers killed by CORINFO_HELP_ASSIGN_BYREF. - #define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_RSI | RBM_RDI | RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF) - - // We have two register classifications - // * callee trash: aka volatile or caller saved - // * callee saved: aka non-volatile - // - // Callee trash are used for passing arguments, returning results, and are freely - // mutable by the method. Because of this, the caller is responsible for saving - // them if they are in use prior to making a call. This saving doesn't need to - // happen for leaf methods (that is methods which don't themselves make any calls) - // and can be done by spilling to the stack or to a callee saved register. This - // means they are cheaper to use but can have higher overall cost if there are - // many calls to be made with values in callee trash registers needing to live - // across the call boundary. - // - // Callee saved don't have any special uses but have to be spilled prior to usage - // and restored prior to returning back to the caller, so they have an inherently - // higher baseline cost. This cost can be offset by re-using the register across - // call boundaries to reduce the overall amount of spilling required. - // - // Given this, we order the registers here to prefer callee trash first and then - // callee save. This allows us to use the registers we've already been assumed - // to overwrite first and then to use those with a higher consumption cost. It - // is up to the register allocator to preference using any callee saved registers - // for values that are frequently live across call boundaries. - // - // Within those two groups registers are generally preferenced in numerical order - // based on the encoding. This helps avoid using larger encodings unneccesarily since - // higher numbered registers typically take more bytes to encode. - // - // For integer registers, the numerical order is eax, ecx, edx, ebx, esp, ebp, - // esi, edi. You then also have r8-r15 which take an additional byte to encode. We - // deviate from the numerical order slightly because esp, ebp, r12, and r13 have - // special encoding requirements. In particular, esp is used by the stack and isn't - // generally usable, instead it can only be used to access locals occupying stack - // space. Both esp and r12 take an additional byte to encode the addressing form of - // the instruction. ebp and r13 likewise can take additional bytes to encode certain - // addressing modes, in particular those with displacements. Because of this ebp is - // always ordered last of the base 8 registers. r13 and then r12 are likewise last - // of the upper 8 registers. This helps reduce the total number of emitted bytes - // quite significantly across typical usages. - // - // There are some other minor deviations based on special uses for particular registers - // on a given platform which give additional size savings for the typical case. - // - // For simd registers, the numerical order is xmm0-xmm7. You then have xmm8-xmm15 - // which take an additional byte to encode and can also have xmm16-xmm31 for EVEX - // when the hardware supports it. There are no additional hidden costs for these. +#define RBM_MSK_CALLEE_TRASH_INIT (0) +#define RBM_MSK_CALLEE_TRASH_EVEX RBM_ALLMASK_EVEX + +#define RBM_MSK_CALLEE_SAVED (0) +#define RBM_MSK_CALLEE_TRASH get_RBM_MSK_CALLEE_TRASH() + +#define RBM_OSR_INT_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_EBP) + +#define REG_FLT_CALLEE_SAVED_FIRST REG_XMM6 +#define REG_FLT_CALLEE_SAVED_LAST REG_XMM15 + +#define RBM_LOWINT RBM_ALLINT_INIT +#define RBM_HIGHINT (RBM_R16|RBM_R17|RBM_R18|RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28|RBM_R29|RBM_R30|RBM_R31) + +#define RBM_ALLINT_INIT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH_INIT) +#define RBM_ALLINT get_RBM_ALLINT() +#define RBM_INT_CALLEE_TRASH_ALL (RBM_INT_CALLEE_TRASH_INIT | RBM_HIGHINT) +#define RBM_ALLINT_ALL (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH_ALL) +#define RBM_INT_CALLEE_TRASH get_RBM_INT_CALLEE_TRASH() + +#define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH | RBM_MSK_CALLEE_TRASH) +#define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED | RBM_MSK_CALLEE_SAVED) + +// AMD64 write barrier ABI (see vm\amd64\JitHelpers_Fast.asm, vm\amd64\JitHelpers_Fast.S): +// CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): +// The usual amd64 calling convention is observed. +// TODO-CQ: could this be optimized? +// CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): +// On entry: +// rsi: the source address (points to object reference to write) +// rdi: the destination address (object reference written here) +// On exit: +// rcx: trashed +// rdi: incremented by 8 +// rsi: incremented by 8 +// rax: trashed when FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP is defined +// TODO-CQ: the above description matches the comments for the amd64 assembly code of JIT_ByRefWriteBarrier, +// however the defines below assume the normal calling convention *except* for rdi/rsi. If we could +// reduce the number of trashed variables, we could improve code quality. +// + +#define REG_WRITE_BARRIER_DST REG_ARG_0 +#define RBM_WRITE_BARRIER_DST RBM_ARG_0 + +#define REG_WRITE_BARRIER_SRC REG_ARG_1 +#define RBM_WRITE_BARRIER_SRC RBM_ARG_1 + +#define RBM_CALLEE_TRASH_NOGC RBM_CALLEE_TRASH + +// Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_TRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF (RBM_RAX | RBM_RCX) + +// Registers killed by CORINFO_HELP_ASSIGN_BYREF. +#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_RSI | RBM_RDI | RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF) + +// We have two register classifications +// * callee trash: aka volatile or caller saved +// * callee saved: aka non-volatile +// +// Callee trash are used for passing arguments, returning results, and are freely +// mutable by the method. Because of this, the caller is responsible for saving +// them if they are in use prior to making a call. This saving doesn't need to +// happen for leaf methods (that is methods which don't themselves make any calls) +// and can be done by spilling to the stack or to a callee saved register. This +// means they are cheaper to use but can have higher overall cost if there are +// many calls to be made with values in callee trash registers needing to live +// across the call boundary. +// +// Callee saved don't have any special uses but have to be spilled prior to usage +// and restored prior to returning back to the caller, so they have an inherently +// higher baseline cost. This cost can be offset by re-using the register across +// call boundaries to reduce the overall amount of spilling required. +// +// Given this, we order the registers here to prefer callee trash first and then +// callee save. This allows us to use the registers we've already been assumed +// to overwrite first and then to use those with a higher consumption cost. It +// is up to the register allocator to preference using any callee saved registers +// for values that are frequently live across call boundaries. +// +// Within those two groups registers are generally preferenced in numerical order +// based on the encoding. This helps avoid using larger encodings unneccesarily since +// higher numbered registers typically take more bytes to encode. +// +// For integer registers, the numerical order is eax, ecx, edx, ebx, esp, ebp, +// esi, edi. You then also have r8-r15 which take an additional byte to encode. We +// deviate from the numerical order slightly because esp, ebp, r12, and r13 have +// special encoding requirements. In particular, esp is used by the stack and isn't +// generally usable, instead it can only be used to access locals occupying stack +// space. Both esp and r12 take an additional byte to encode the addressing form of +// the instruction. ebp and r13 likewise can take additional bytes to encode certain +// addressing modes, in particular those with displacements. Because of this ebp is +// always ordered last of the base 8 registers. r13 and then r12 are likewise last +// of the upper 8 registers. This helps reduce the total number of emitted bytes +// quite significantly across typical usages. +// +// There are some other minor deviations based on special uses for particular registers +// on a given platform which give additional size savings for the typical case. +// +// For simd registers, the numerical order is xmm0-xmm7. You then have xmm8-xmm15 +// which take an additional byte to encode and can also have xmm16-xmm31 for EVEX +// when the hardware supports it. There are no additional hidden costs for these. #ifdef UNIX_AMD64_ABI - #define REG_VAR_ORDER_CALLEE_TRASH REG_EAX,REG_ECX,REG_EDX,REG_EDI,REG_ESI,REG_R8,REG_R9,REG_R10,REG_R11,REG_R16,REG_R17,REG_R18,REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28,REG_R29,REG_R30,REG_R31 - #define REG_VAR_ORDER_CALLEE_SAVED REG_EBX,REG_ETW_FRAMED_EBP_LIST REG_R15,REG_R14,REG_R13,REG_R12 +#define REG_VAR_ORDER_CALLEE_TRASH REG_EAX,REG_ECX,REG_EDX,REG_EDI,REG_ESI,REG_R8,REG_R9,REG_R10,REG_R11,REG_R16,REG_R17,REG_R18,REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28,REG_R29,REG_R30,REG_R31 +#define REG_VAR_ORDER_CALLEE_SAVED REG_EBX,REG_ETW_FRAMED_EBP_LIST REG_R15,REG_R14,REG_R13,REG_R12 - #define REG_VAR_ORDER_FLT_CALLEE_TRASH REG_XMM0,REG_XMM1,REG_XMM2,REG_XMM3,REG_XMM4,REG_XMM5,REG_XMM6,REG_XMM7, \ +#define REG_VAR_ORDER_FLT_CALLEE_TRASH REG_XMM0,REG_XMM1,REG_XMM2,REG_XMM3,REG_XMM4,REG_XMM5,REG_XMM6,REG_XMM7, \ REG_XMM8,REG_XMM9,REG_XMM10,REG_XMM11,REG_XMM12,REG_XMM13,REG_XMM14, \ REG_XMM15 - #define REG_VAR_ORDER_FLT_CALLEE_SAVED +#define REG_VAR_ORDER_FLT_CALLEE_SAVED - #define REG_VAR_ORDER_FLT_EVEX_CALLEE_TRASH REG_VAR_ORDER_FLT_CALLEE_TRASH,REG_XMM16,REG_XMM17,REG_XMM18,REG_XMM19,\ +#define REG_VAR_ORDER_FLT_EVEX_CALLEE_TRASH REG_VAR_ORDER_FLT_CALLEE_TRASH,REG_XMM16,REG_XMM17,REG_XMM18,REG_XMM19,\ REG_XMM20,REG_XMM21,REG_XMM22,REG_XMM23,REG_XMM24,REG_XMM25,REG_XMM26, \ REG_XMM27,REG_XMM28,REG_XMM29,REG_XMM30,REG_XMM31 - #define REG_VAR_ORDER_FLT_EVEX_CALLEE_SAVED REG_VAR_ORDER_FLT_CALLEE_SAVED +#define REG_VAR_ORDER_FLT_EVEX_CALLEE_SAVED REG_VAR_ORDER_FLT_CALLEE_SAVED #else // !UNIX_AMD64_ABI - #define REG_VAR_ORDER_CALLEE_TRASH REG_EAX,REG_ECX,REG_EDX,REG_R8,REG_R10,REG_R9,REG_R11,REG_R16,REG_R17,REG_R18,REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28,REG_R29,REG_R30,REG_R31 - #define REG_VAR_ORDER_CALLEE_SAVED REG_EBX,REG_ESI,REG_EDI,REG_ETW_FRAMED_EBP_LIST REG_R14,REG_R15,REG_R13,REG_R12 +#define REG_VAR_ORDER_CALLEE_TRASH REG_EAX,REG_ECX,REG_EDX,REG_R8,REG_R10,REG_R9,REG_R11,REG_R16,REG_R17,REG_R18,REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28,REG_R29,REG_R30,REG_R31 +#define REG_VAR_ORDER_CALLEE_SAVED REG_EBX,REG_ESI,REG_EDI,REG_ETW_FRAMED_EBP_LIST REG_R14,REG_R15,REG_R13,REG_R12 - #define REG_VAR_ORDER_FLT_CALLEE_TRASH REG_XMM0,REG_XMM1,REG_XMM2,REG_XMM3,REG_XMM4,REG_XMM5 - #define REG_VAR_ORDER_FLT_CALLEE_SAVED REG_XMM6,REG_XMM7,REG_XMM8,REG_XMM9,REG_XMM10,REG_XMM11,REG_XMM12, \ +#define REG_VAR_ORDER_FLT_CALLEE_TRASH REG_XMM0,REG_XMM1,REG_XMM2,REG_XMM3,REG_XMM4,REG_XMM5 +#define REG_VAR_ORDER_FLT_CALLEE_SAVED REG_XMM6,REG_XMM7,REG_XMM8,REG_XMM9,REG_XMM10,REG_XMM11,REG_XMM12, \ REG_XMM13,REG_XMM14,REG_XMM15 - #define REG_VAR_ORDER_FLT_EVEX_CALLEE_TRASH REG_VAR_ORDER_FLT_CALLEE_TRASH,REG_XMM16,REG_XMM17,REG_XMM18,REG_XMM19,\ +#define REG_VAR_ORDER_FLT_EVEX_CALLEE_TRASH REG_VAR_ORDER_FLT_CALLEE_TRASH,REG_XMM16,REG_XMM17,REG_XMM18,REG_XMM19,\ REG_XMM20,REG_XMM21,REG_XMM22,REG_XMM23,REG_XMM24,REG_XMM25,REG_XMM26, \ REG_XMM27,REG_XMM28,REG_XMM29,REG_XMM30,REG_XMM31 - #define REG_VAR_ORDER_FLT_EVEX_CALLEE_SAVED REG_VAR_ORDER_FLT_CALLEE_SAVED +#define REG_VAR_ORDER_FLT_EVEX_CALLEE_SAVED REG_VAR_ORDER_FLT_CALLEE_SAVED #endif // !UNIX_AMD64_ABI #define REG_VAR_ORDER REG_VAR_ORDER_CALLEE_TRASH,REG_VAR_ORDER_CALLEE_SAVED @@ -299,112 +299,112 @@ #define REG_VAR_ORDER_MSK REG_K1,REG_K2,REG_K3,REG_K4,REG_K5,REG_K6,REG_K7 #ifdef UNIX_AMD64_ABI - #define CNT_CALLEE_SAVED (5 + REG_ETW_FRAMED_EBP_COUNT) - #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) +#define CNT_CALLEE_SAVED (5 + REG_ETW_FRAMED_EBP_COUNT) +#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) - #define CNT_CALLEE_TRASH_INT_INIT (9) - #define CNT_CALLEE_TRASH_HIGHINT (16) +#define CNT_CALLEE_TRASH_INT_INIT (9) +#define CNT_CALLEE_TRASH_HIGHINT (16) - #define CNT_CALLEE_SAVED_FLOAT (0) - #define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) +#define CNT_CALLEE_SAVED_FLOAT (0) +#define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) - #define CNT_CALLEE_TRASH_FLOAT_INIT (16) - #define CNT_CALLEE_TRASH_HIGHFLOAT (16) +#define CNT_CALLEE_TRASH_FLOAT_INIT (16) +#define CNT_CALLEE_TRASH_HIGHFLOAT (16) - // For SysV we have more volatile registers so we do not save any callee saves for EnC. - #define RBM_ENC_CALLEE_SAVED 0 +// For SysV we have more volatile registers so we do not save any callee saves for EnC. +#define RBM_ENC_CALLEE_SAVED 0 #else // !UNIX_AMD64_ABI - #define CNT_CALLEE_SAVED (7 + REG_ETW_FRAMED_EBP_COUNT) - #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) +#define CNT_CALLEE_SAVED (7 + REG_ETW_FRAMED_EBP_COUNT) +#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED) - #define CNT_CALLEE_TRASH_INT_INIT (7) - #define CNT_CALLEE_TRASH_HIGHINT (16) +#define CNT_CALLEE_TRASH_INT_INIT (7) +#define CNT_CALLEE_TRASH_HIGHINT (16) - #define CNT_CALLEE_SAVED_FLOAT (10) - #define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) +#define CNT_CALLEE_SAVED_FLOAT (10) +#define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) - #define CNT_CALLEE_TRASH_FLOAT_INIT (6) - #define CNT_CALLEE_TRASH_HIGHFLOAT (16) +#define CNT_CALLEE_TRASH_FLOAT_INIT (6) +#define CNT_CALLEE_TRASH_HIGHFLOAT (16) - // Callee-preserved registers we always save and allow use of for EnC code, since there are quite few volatile registers. - #define RBM_ENC_CALLEE_SAVED (RBM_RSI | RBM_RDI) +// Callee-preserved registers we always save and allow use of for EnC code, since there are quite few volatile registers. +#define RBM_ENC_CALLEE_SAVED (RBM_RSI | RBM_RDI) #endif // !UNIX_AMD64_ABI - #define CNT_CALLEE_TRASH_FLOAT get_CNT_CALLEE_TRASH_FLOAT() - #define CNT_CALLEE_TRASH get_CNT_CALLEE_TRASH_INT() +#define CNT_CALLEE_TRASH_FLOAT get_CNT_CALLEE_TRASH_FLOAT() +#define CNT_CALLEE_TRASH get_CNT_CALLEE_TRASH_INT() - #define CNT_CALLEE_SAVED_MASK (0) - #define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) +#define CNT_CALLEE_SAVED_MASK (0) +#define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) - #define CNT_CALLEE_TRASH_MASK_INIT (0) - #define CNT_CALLEE_TRASH_MASK_EVEX (7) - #define CNT_CALLEE_TRASH_MASK get_CNT_CALLEE_TRASH_MASK() +#define CNT_CALLEE_TRASH_MASK_INIT (0) +#define CNT_CALLEE_TRASH_MASK_EVEX (7) +#define CNT_CALLEE_TRASH_MASK get_CNT_CALLEE_TRASH_MASK() - #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED*REGSIZE_BYTES) - #define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT*16) +#define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED*REGSIZE_BYTES) +#define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT*16) - // register to hold shift amount - #define REG_SHIFT REG_ECX - #define RBM_SHIFT RBM_ECX +// register to hold shift amount +#define REG_SHIFT REG_ECX +#define RBM_SHIFT RBM_ECX - // This is a general scratch register that does not conflict with the argument registers - #define REG_SCRATCH REG_EAX +// This is a general scratch register that does not conflict with the argument registers +#define REG_SCRATCH REG_EAX // Where is the exception object on entry to the handler block? #ifdef UNIX_AMD64_ABI - #define REG_EXCEPTION_OBJECT REG_EDI - #define RBM_EXCEPTION_OBJECT RBM_EDI +#define REG_EXCEPTION_OBJECT REG_EDI +#define RBM_EXCEPTION_OBJECT RBM_EDI #else // !UNIX_AMD64_ABI - #define REG_EXCEPTION_OBJECT REG_ECX - #define RBM_EXCEPTION_OBJECT RBM_ECX +#define REG_EXCEPTION_OBJECT REG_ECX +#define RBM_EXCEPTION_OBJECT RBM_ECX #endif // !UNIX_AMD64_ABI - #define REG_JUMP_THUNK_PARAM REG_EAX - #define RBM_JUMP_THUNK_PARAM RBM_EAX - - // Register to be used for emitting helper calls whose call target is an indir of an - // absolute memory address in case of Rel32 overflow i.e. a data address could not be - // encoded as PC-relative 32-bit offset. - // - // Notes: - // 1) that RAX is callee trash register that is not used for passing parameter and - // also results in smaller instruction encoding. - // 2) Profiler Leave callback requires the return value to be preserved - // in some form. We can use custom calling convention for Leave callback. - // For e.g return value could be preserved in rcx so that it is available for - // profiler. - #define REG_DEFAULT_HELPER_CALL_TARGET REG_RAX - #define RBM_DEFAULT_HELPER_CALL_TARGET RBM_RAX - - #define REG_R2R_INDIRECT_PARAM REG_RAX // Indirection cell for R2R fast tailcall +#define REG_JUMP_THUNK_PARAM REG_EAX +#define RBM_JUMP_THUNK_PARAM RBM_EAX + +// Register to be used for emitting helper calls whose call target is an indir of an +// absolute memory address in case of Rel32 overflow i.e. a data address could not be +// encoded as PC-relative 32-bit offset. +// +// Notes: +// 1) that RAX is callee trash register that is not used for passing parameter and +// also results in smaller instruction encoding. +// 2) Profiler Leave callback requires the return value to be preserved +// in some form. We can use custom calling convention for Leave callback. +// For e.g return value could be preserved in rcx so that it is available for +// profiler. +#define REG_DEFAULT_HELPER_CALL_TARGET REG_RAX +#define RBM_DEFAULT_HELPER_CALL_TARGET RBM_RAX + +#define REG_R2R_INDIRECT_PARAM REG_RAX // Indirection cell for R2R fast tailcall // See ImportThunk.Kind.DelayLoadHelperWithExistingIndirectionCell in crossgen2. - #define RBM_R2R_INDIRECT_PARAM RBM_RAX +#define RBM_R2R_INDIRECT_PARAM RBM_RAX - // GenericPInvokeCalliHelper VASigCookie Parameter - #define REG_PINVOKE_COOKIE_PARAM REG_R11 - #define RBM_PINVOKE_COOKIE_PARAM RBM_R11 +// GenericPInvokeCalliHelper VASigCookie Parameter +#define REG_PINVOKE_COOKIE_PARAM REG_R11 +#define RBM_PINVOKE_COOKIE_PARAM RBM_R11 - // GenericPInvokeCalliHelper unmanaged target Parameter - #define REG_PINVOKE_TARGET_PARAM REG_R10 - #define RBM_PINVOKE_TARGET_PARAM RBM_R10 +// GenericPInvokeCalliHelper unmanaged target Parameter +#define REG_PINVOKE_TARGET_PARAM REG_R10 +#define RBM_PINVOKE_TARGET_PARAM RBM_R10 - // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) - #define REG_SECRET_STUB_PARAM REG_R10 - #define RBM_SECRET_STUB_PARAM RBM_R10 +// IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) +#define REG_SECRET_STUB_PARAM REG_R10 +#define RBM_SECRET_STUB_PARAM RBM_R10 - // The following defines are useful for iterating a regNumber - #define REG_FIRST REG_EAX - #define REG_INT_FIRST REG_EAX - #define REG_INT_LAST REG_R31 - #define REG_INT_COUNT (get_REG_INT_LAST() - REG_INT_FIRST + 1) - #define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) - #define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) +// The following defines are useful for iterating a regNumber +#define REG_FIRST REG_EAX +#define REG_INT_FIRST REG_EAX +#define REG_INT_LAST REG_R31 +#define REG_INT_COUNT (get_REG_INT_LAST() - REG_INT_FIRST + 1) +#define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) +#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) - // Which register are int and long values returned in ? - #define REG_INTRET REG_EAX - #define RBM_INTRET RBM_EAX +// Which register are int and long values returned in ? +#define REG_INTRET REG_EAX +#define RBM_INTRET RBM_EAX - #define RBM_LNGRET RBM_EAX +#define RBM_LNGRET RBM_EAX #ifdef UNIX_AMD64_ABI #define REG_INTRET_1 REG_RDX @@ -415,10 +415,10 @@ #endif // UNIX_AMD64_ABI - #define REG_FLOATRET REG_XMM0 - #define RBM_FLOATRET RBM_XMM0 - #define REG_DOUBLERET REG_XMM0 - #define RBM_DOUBLERET RBM_XMM0 +#define REG_FLOATRET REG_XMM0 +#define RBM_FLOATRET RBM_XMM0 +#define REG_DOUBLERET REG_XMM0 +#define RBM_DOUBLERET RBM_XMM0 #ifdef UNIX_AMD64_ABI #define REG_FLOATRET_1 REG_XMM1 @@ -428,158 +428,158 @@ #define RBM_DOUBLERET_1 RBM_XMM1 #endif // UNIX_AMD64_ABI - #define REG_FPBASE REG_EBP - #define RBM_FPBASE RBM_EBP - #define STR_FPBASE "rbp" - #define REG_SPBASE REG_ESP - #define RBM_SPBASE RBM_ESP - #define STR_SPBASE "rsp" +#define REG_FPBASE REG_EBP +#define RBM_FPBASE RBM_EBP +#define STR_FPBASE "rbp" +#define REG_SPBASE REG_ESP +#define RBM_SPBASE RBM_ESP +#define STR_SPBASE "rsp" - #define FIRST_ARG_STACK_OFFS (REGSIZE_BYTES) // return address +#define FIRST_ARG_STACK_OFFS (REGSIZE_BYTES) // return address #ifdef UNIX_AMD64_ABI - #define MAX_REG_ARG 6 - #define MAX_FLOAT_REG_ARG 8 - #define REG_ARG_FIRST REG_EDI - #define REG_ARG_LAST REG_R9 - #define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots - - #define REG_ARG_0 REG_EDI - #define REG_ARG_1 REG_ESI - #define REG_ARG_2 REG_EDX - #define REG_ARG_3 REG_ECX - #define REG_ARG_4 REG_R8 - #define REG_ARG_5 REG_R9 +#define MAX_REG_ARG 6 +#define MAX_FLOAT_REG_ARG 8 +#define REG_ARG_FIRST REG_EDI +#define REG_ARG_LAST REG_R9 +#define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots + +#define REG_ARG_0 REG_EDI +#define REG_ARG_1 REG_ESI +#define REG_ARG_2 REG_EDX +#define REG_ARG_3 REG_ECX +#define REG_ARG_4 REG_R8 +#define REG_ARG_5 REG_R9 extern const regNumber intArgRegs [MAX_REG_ARG]; extern const regMaskTP intArgMasks[MAX_REG_ARG]; extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG]; extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG]; - #define RBM_ARG_0 RBM_RDI - #define RBM_ARG_1 RBM_RSI - #define RBM_ARG_2 RBM_EDX - #define RBM_ARG_3 RBM_ECX - #define RBM_ARG_4 RBM_R8 - #define RBM_ARG_5 RBM_R9 +#define RBM_ARG_0 RBM_RDI +#define RBM_ARG_1 RBM_RSI +#define RBM_ARG_2 RBM_EDX +#define RBM_ARG_3 RBM_ECX +#define RBM_ARG_4 RBM_R8 +#define RBM_ARG_5 RBM_R9 #else // !UNIX_AMD64_ABI - #define MAX_REG_ARG 4 - #define MAX_FLOAT_REG_ARG 4 - #define REG_ARG_FIRST REG_ECX - #define REG_ARG_LAST REG_R9 - #define INIT_ARG_STACK_SLOT 4 // 4 outgoing reserved stack slots +#define MAX_REG_ARG 4 +#define MAX_FLOAT_REG_ARG 4 +#define REG_ARG_FIRST REG_ECX +#define REG_ARG_LAST REG_R9 +#define INIT_ARG_STACK_SLOT 4 // 4 outgoing reserved stack slots - #define REG_ARG_0 REG_ECX - #define REG_ARG_1 REG_EDX - #define REG_ARG_2 REG_R8 - #define REG_ARG_3 REG_R9 +#define REG_ARG_0 REG_ECX +#define REG_ARG_1 REG_EDX +#define REG_ARG_2 REG_R8 +#define REG_ARG_3 REG_R9 extern const regNumber intArgRegs [MAX_REG_ARG]; extern const regMaskTP intArgMasks[MAX_REG_ARG]; extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG]; extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG]; - #define RBM_ARG_0 RBM_ECX - #define RBM_ARG_1 RBM_EDX - #define RBM_ARG_2 RBM_R8 - #define RBM_ARG_3 RBM_R9 +#define RBM_ARG_0 RBM_ECX +#define RBM_ARG_1 RBM_EDX +#define RBM_ARG_2 RBM_R8 +#define RBM_ARG_3 RBM_R9 #endif // !UNIX_AMD64_ABI - #define REG_FLTARG_0 REG_XMM0 - #define REG_FLTARG_1 REG_XMM1 - #define REG_FLTARG_2 REG_XMM2 - #define REG_FLTARG_3 REG_XMM3 +#define REG_FLTARG_0 REG_XMM0 +#define REG_FLTARG_1 REG_XMM1 +#define REG_FLTARG_2 REG_XMM2 +#define REG_FLTARG_3 REG_XMM3 - #define RBM_FLTARG_0 RBM_XMM0 - #define RBM_FLTARG_1 RBM_XMM1 - #define RBM_FLTARG_2 RBM_XMM2 - #define RBM_FLTARG_3 RBM_XMM3 +#define RBM_FLTARG_0 RBM_XMM0 +#define RBM_FLTARG_1 RBM_XMM1 +#define RBM_FLTARG_2 RBM_XMM2 +#define RBM_FLTARG_3 RBM_XMM3 #ifdef UNIX_AMD64_ABI - #define REG_FLTARG_4 REG_XMM4 - #define REG_FLTARG_5 REG_XMM5 - #define REG_FLTARG_6 REG_XMM6 - #define REG_FLTARG_7 REG_XMM7 - - #define RBM_FLTARG_4 RBM_XMM4 - #define RBM_FLTARG_5 RBM_XMM5 - #define RBM_FLTARG_6 RBM_XMM6 - #define RBM_FLTARG_7 RBM_XMM7 - - #define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5) - #define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7) +#define REG_FLTARG_4 REG_XMM4 +#define REG_FLTARG_5 REG_XMM5 +#define REG_FLTARG_6 REG_XMM6 +#define REG_FLTARG_7 REG_XMM7 + +#define RBM_FLTARG_4 RBM_XMM4 +#define RBM_FLTARG_5 RBM_XMM5 +#define RBM_FLTARG_6 RBM_XMM6 +#define RBM_FLTARG_7 RBM_XMM7 + +#define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5) +#define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7) #else // !UNIX_AMD64_ABI - #define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3) - #define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3) +#define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3) +#define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3) #endif // !UNIX_AMD64_ABI - // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper. +// The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper. #ifdef UNIX_AMD64_ABI - // See vm\amd64\unixasmhelpers.S for more details. - // - // On Unix a struct of size >=9 and <=16 bytes in size is returned in two return registers. - // The return registers could be any two from the set { RAX, RDX, XMM0, XMM1 }. - // STOP_FOR_GC helper preserves all the 4 possible return registers. - #define RBM_STOP_FOR_GC_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET | RBM_FLOATRET_1 | RBM_INTRET_1)) - - // The registers trashed by profiler enter/leave/tailcall hook - // See vm\amd64\asmhelpers.S for more details. - #define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS)) - #define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET | RBM_FLOATRET_1 | RBM_INTRET_1)) - #define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH +// See vm\amd64\unixasmhelpers.S for more details. +// +// On Unix a struct of size >=9 and <=16 bytes in size is returned in two return registers. +// The return registers could be any two from the set { RAX, RDX, XMM0, XMM1 }. +// STOP_FOR_GC helper preserves all the 4 possible return registers. +#define RBM_STOP_FOR_GC_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET | RBM_FLOATRET_1 | RBM_INTRET_1)) + +// The registers trashed by profiler enter/leave/tailcall hook +// See vm\amd64\asmhelpers.S for more details. +#define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS)) +#define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET | RBM_FLOATRET_1 | RBM_INTRET_1)) +#define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH #else - // See vm\amd64\asmhelpers.asm for more details. - #define RBM_STOP_FOR_GC_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET)) +// See vm\amd64\asmhelpers.asm for more details. +#define RBM_STOP_FOR_GC_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET)) - #define RBM_PROFILER_ENTER_TRASH RBM_CALLEE_TRASH - #define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET)) - #define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH +#define RBM_PROFILER_ENTER_TRASH RBM_CALLEE_TRASH +#define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_FLOATRET | RBM_INTRET)) +#define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH #endif - // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. - #define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH +// The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. +#define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH - #define RBM_INTERFACELOOKUP_FOR_SLOT_TRASH (RBM_RAX | RBM_R10 | RBM_R11) +#define RBM_INTERFACELOOKUP_FOR_SLOT_TRASH (RBM_RAX | RBM_R10 | RBM_R11) - #define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_R10 | RBM_RCX)) - #define RBM_VALIDATE_INDIRECT_CALL_TRASH_ALL (RBM_INT_CALLEE_TRASH_ALL & ~(RBM_R10 | RBM_RCX)) - #define REG_VALIDATE_INDIRECT_CALL_ADDR REG_RCX - #define REG_DISPATCH_INDIRECT_CALL_ADDR REG_RAX +#define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_R10 | RBM_RCX)) +#define RBM_VALIDATE_INDIRECT_CALL_TRASH_ALL (RBM_INT_CALLEE_TRASH_ALL & ~(RBM_R10 | RBM_RCX)) +#define REG_VALIDATE_INDIRECT_CALL_ADDR REG_RCX +#define REG_DISPATCH_INDIRECT_CALL_ADDR REG_RAX - #define REG_ASYNC_CONTINUATION_RET REG_RCX - #define RBM_ASYNC_CONTINUATION_RET RBM_RCX +#define REG_ASYNC_CONTINUATION_RET REG_RCX +#define RBM_ASYNC_CONTINUATION_RET RBM_RCX - // Pointer-sized string move instructions - #define INS_movsp INS_movsq - #define INS_r_movsp INS_r_movsq - #define INS_stosp INS_stosq - #define INS_r_stosp INS_r_stosq +// Pointer-sized string move instructions +#define INS_movsp INS_movsq +#define INS_r_movsp INS_r_movsq +#define INS_stosp INS_stosq +#define INS_r_stosp INS_r_stosq - // AMD64 uses FEATURE_FIXED_OUT_ARGS so this can be zero. - #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 +// AMD64 uses FEATURE_FIXED_OUT_ARGS so this can be zero. +#define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 - #define REG_STACK_PROBE_HELPER_ARG REG_R11 - #define RBM_STACK_PROBE_HELPER_ARG RBM_R11 +#define REG_STACK_PROBE_HELPER_ARG REG_R11 +#define RBM_STACK_PROBE_HELPER_ARG RBM_R11 #ifdef UNIX_AMD64_ABI - #define RBM_STACK_PROBE_HELPER_TRASH RBM_NONE +#define RBM_STACK_PROBE_HELPER_TRASH RBM_NONE #else // !UNIX_AMD64_ABI - #define RBM_STACK_PROBE_HELPER_TRASH RBM_RAX +#define RBM_STACK_PROBE_HELPER_TRASH RBM_RAX #endif // !UNIX_AMD64_ABI #ifdef UNIX_AMD64_ABI - #define SWIFT_SUPPORT - #define REG_SWIFT_ERROR REG_R12 - #define RBM_SWIFT_ERROR RBM_R12 - #define REG_SWIFT_SELF REG_R13 - #define RBM_SWIFT_SELF RBM_R13 - - #define REG_SWIFT_INTRET_ORDER REG_RAX,REG_RDX,REG_RCX,REG_R8 - #define REG_SWIFT_FLOATRET_ORDER REG_XMM0,REG_XMM1,REG_XMM2,REG_XMM3 - #define REG_SWIFT_ARG_RET_BUFF REG_RAX - #define RBM_SWIFT_ARG_RET_BUFF RBM_RAX - #define SWIFT_RET_BUFF_ARGNUM MAX_REG_ARG +#define SWIFT_SUPPORT +#define REG_SWIFT_ERROR REG_R12 +#define RBM_SWIFT_ERROR RBM_R12 +#define REG_SWIFT_SELF REG_R13 +#define RBM_SWIFT_SELF RBM_R13 + +#define REG_SWIFT_INTRET_ORDER REG_RAX,REG_RDX,REG_RCX,REG_R8 +#define REG_SWIFT_FLOATRET_ORDER REG_XMM0,REG_XMM1,REG_XMM2,REG_XMM3 +#define REG_SWIFT_ARG_RET_BUFF REG_RAX +#define RBM_SWIFT_ARG_RET_BUFF RBM_RAX +#define SWIFT_RET_BUFF_ARGNUM MAX_REG_ARG #endif // UNIX_AMD64_ABI // clang-format on diff --git a/src/coreclr/jit/targetarm.h b/src/coreclr/jit/targetarm.h index 45916963be4740..b4a7d00cd1b0f2 100644 --- a/src/coreclr/jit/targetarm.h +++ b/src/coreclr/jit/targetarm.h @@ -7,80 +7,80 @@ #endif // clang-format off - #define CORINFO_ARCH_TARGET CORINFO_ARCH_ARM - - // TODO-ARM-CQ: Use shift for division by power of 2 - // TODO-ARM-CQ: Check for sdiv/udiv at runtime and generate it if available - #define USE_HELPERS_FOR_INT_DIV 1 // BeagleBoard (ARMv7A) doesn't support SDIV/UDIV - #define CPU_LOAD_STORE_ARCH 1 - #define CPU_HAS_BYTE_REGS 0 - - #define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog - #define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers - #define FEATURE_MULTIREG_STRUCT_PROMOTE 0 // True when we want to promote fields of a multireg struct into registers - #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp - #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. - #define FEATURE_IMPLICIT_BYREFS 0 // Support for struct parameters passed via pointers to shadow copies - #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register (including HFA support) - #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register (including passing HFAs) - #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register (including HFA returns) - #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). - #define MAX_PASS_MULTIREG_BYTES 32 // Maximum size of a struct that could be passed in more than one register (Max is an HFA of 4 doubles) - #define MAX_RET_MULTIREG_BYTES 32 // Maximum size of a struct that could be returned in more than one register (Max is an HFA of 4 doubles) - #define MAX_ARG_REG_COUNT 4 // Maximum registers used to pass a single argument in multiple registers. (max is 4 floats or doubles using an HFA) - #define MAX_RET_REG_COUNT 4 // Maximum registers used to return a value. - - #define MAX_MULTIREG_COUNT 4 // Maximum number of registers defined by a single instruction (including calls). - // This is also the maximum number of registers for a MultiReg node. - - #define NOGC_WRITE_BARRIERS 0 // We DO-NOT have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers - #define USER_ARGS_COME_LAST 1 - #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target - #define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods - - #define CSE_CONSTS 1 // Enable if we want to CSE constants - #define LOWER_DECOMPOSE_LONGS 1 // Decompose TYP_LONG operations into (typically two) TYP_INT ones - #define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really - // need to track stack depth, but this is currently necessary to get GC information reported at call sites. - #define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that - - #define REG_FP_FIRST REG_F0 - #define REG_FP_LAST REG_F31 - #define FIRST_FP_ARGREG REG_F0 - #define LAST_FP_ARGREG REG_F15 - - #define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set - #define REGNUM_BITS 6 // number of bits in a REG_* - #define REGSIZE_BYTES 4 // number of bytes in one register - #define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. - - #define CODE_ALIGN 2 // code alignment requirement - #define STACK_ALIGN 8 // stack alignment requirement - - #define RBM_INT_CALLEE_SAVED (RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10) - #define RBM_INT_CALLEE_TRASH (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R12|RBM_LR) - #define RBM_FLT_CALLEE_SAVED (RBM_F16|RBM_F17|RBM_F18|RBM_F19|RBM_F20|RBM_F21|RBM_F22|RBM_F23|RBM_F24|RBM_F25|RBM_F26|RBM_F27|RBM_F28|RBM_F29|RBM_F30|RBM_F31) - #define RBM_FLT_CALLEE_TRASH (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7|RBM_F8|RBM_F9|RBM_F10|RBM_F11|RBM_F12|RBM_F13|RBM_F14|RBM_F15) - - #define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED) - #define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH) - - #define REG_DEFAULT_HELPER_CALL_TARGET REG_R12 - #define RBM_DEFAULT_HELPER_CALL_TARGET RBM_R12 - - #define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) - #define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH) - #define RBM_ALLDOUBLE (RBM_F0|RBM_F2|RBM_F4|RBM_F6|RBM_F8|RBM_F10|RBM_F12|RBM_F14|RBM_F16|RBM_F18|RBM_F20|RBM_F22|RBM_F24|RBM_F26|RBM_F28|RBM_F30) - - // Double registers on ARM take two registers in odd/even pairs, e.g. f0 and f1, f2 and f3, etc. Mostly, we refer - // to double registers by their low, even, part. Sometimes we need to know that the high, odd, part is unused in - // a bitmask, say, hence we have this definition. - #define RBM_ALLDOUBLE_HIGH (RBM_F1|RBM_F3|RBM_F5|RBM_F7|RBM_F9|RBM_F11|RBM_F13|RBM_F15|RBM_F17|RBM_F19|RBM_F21|RBM_F23|RBM_F25|RBM_F27|RBM_F29|RBM_F31) - - #define REG_VAR_ORDER REG_R3,REG_R2,REG_R1,REG_R0,REG_R4,REG_LR,REG_R12,\ +#define CORINFO_ARCH_TARGET CORINFO_ARCH_ARM + +// TODO-ARM-CQ: Use shift for division by power of 2 +// TODO-ARM-CQ: Check for sdiv/udiv at runtime and generate it if available +#define USE_HELPERS_FOR_INT_DIV 1 // BeagleBoard (ARMv7A) doesn't support SDIV/UDIV +#define CPU_LOAD_STORE_ARCH 1 +#define CPU_HAS_BYTE_REGS 0 + +#define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog +#define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers +#define FEATURE_MULTIREG_STRUCT_PROMOTE 0 // True when we want to promote fields of a multireg struct into registers +#define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp +#define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. +#define FEATURE_IMPLICIT_BYREFS 0 // Support for struct parameters passed via pointers to shadow copies +#define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register (including HFA support) +#define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register (including passing HFAs) +#define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register (including HFA returns) +#define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). +#define MAX_PASS_MULTIREG_BYTES 32 // Maximum size of a struct that could be passed in more than one register (Max is an HFA of 4 doubles) +#define MAX_RET_MULTIREG_BYTES 32 // Maximum size of a struct that could be returned in more than one register (Max is an HFA of 4 doubles) +#define MAX_ARG_REG_COUNT 4 // Maximum registers used to pass a single argument in multiple registers. (max is 4 floats or doubles using an HFA) +#define MAX_RET_REG_COUNT 4 // Maximum registers used to return a value. + +#define MAX_MULTIREG_COUNT 4 // Maximum number of registers defined by a single instruction (including calls). + // This is also the maximum number of registers for a MultiReg node. + +#define NOGC_WRITE_BARRIERS 0 // We DO-NOT have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers +#define USER_ARGS_COME_LAST 1 +#define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods + +#define CSE_CONSTS 1 // Enable if we want to CSE constants +#define LOWER_DECOMPOSE_LONGS 1 // Decompose TYP_LONG operations into (typically two) TYP_INT ones +#define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really + // need to track stack depth, but this is currently necessary to get GC information reported at call sites. +#define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that + +#define REG_FP_FIRST REG_F0 +#define REG_FP_LAST REG_F31 +#define FIRST_FP_ARGREG REG_F0 +#define LAST_FP_ARGREG REG_F15 + +#define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set +#define REGNUM_BITS 6 // number of bits in a REG_* +#define REGSIZE_BYTES 4 // number of bytes in one register +#define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. + +#define CODE_ALIGN 2 // code alignment requirement +#define STACK_ALIGN 8 // stack alignment requirement + +#define RBM_INT_CALLEE_SAVED (RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10) +#define RBM_INT_CALLEE_TRASH (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R12|RBM_LR) +#define RBM_FLT_CALLEE_SAVED (RBM_F16|RBM_F17|RBM_F18|RBM_F19|RBM_F20|RBM_F21|RBM_F22|RBM_F23|RBM_F24|RBM_F25|RBM_F26|RBM_F27|RBM_F28|RBM_F29|RBM_F30|RBM_F31) +#define RBM_FLT_CALLEE_TRASH (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7|RBM_F8|RBM_F9|RBM_F10|RBM_F11|RBM_F12|RBM_F13|RBM_F14|RBM_F15) + +#define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED) +#define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH) + +#define REG_DEFAULT_HELPER_CALL_TARGET REG_R12 +#define RBM_DEFAULT_HELPER_CALL_TARGET RBM_R12 + +#define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) +#define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH) +#define RBM_ALLDOUBLE (RBM_F0|RBM_F2|RBM_F4|RBM_F6|RBM_F8|RBM_F10|RBM_F12|RBM_F14|RBM_F16|RBM_F18|RBM_F20|RBM_F22|RBM_F24|RBM_F26|RBM_F28|RBM_F30) + +// Double registers on ARM take two registers in odd/even pairs, e.g. f0 and f1, f2 and f3, etc. Mostly, we refer +// to double registers by their low, even, part. Sometimes we need to know that the high, odd, part is unused in +// a bitmask, say, hence we have this definition. +#define RBM_ALLDOUBLE_HIGH (RBM_F1|RBM_F3|RBM_F5|RBM_F7|RBM_F9|RBM_F11|RBM_F13|RBM_F15|RBM_F17|RBM_F19|RBM_F21|RBM_F23|RBM_F25|RBM_F27|RBM_F29|RBM_F31) + +#define REG_VAR_ORDER REG_R3,REG_R2,REG_R1,REG_R0,REG_R4,REG_LR,REG_R12,\ REG_R5,REG_R6,REG_R7,REG_R8,REG_R9,REG_R10 - #define REG_VAR_ORDER_FLT REG_F8, REG_F9, REG_F10, REG_F11, \ +#define REG_VAR_ORDER_FLT REG_F8, REG_F9, REG_F10, REG_F11, \ REG_F12, REG_F13, REG_F14, REG_F15, \ REG_F6, REG_F7, REG_F4, REG_F5, \ REG_F2, REG_F3, REG_F0, REG_F1, \ @@ -89,246 +89,246 @@ REG_F24, REG_F25, REG_F26, REG_F27, \ REG_F28, REG_F29, REG_F30, REG_F31, - #define RBM_LOW_REGS (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7) - #define RBM_HIGH_REGS (RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_SP|RBM_LR|RBM_PC) +#define RBM_LOW_REGS (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7) +#define RBM_HIGH_REGS (RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_SP|RBM_LR|RBM_PC) - #define CNT_CALLEE_SAVED (8) - #define CNT_CALLEE_TRASH (6) - #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) +#define CNT_CALLEE_SAVED (8) +#define CNT_CALLEE_TRASH (6) +#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) - #define CNT_CALLEE_SAVED_FLOAT (16) - #define CNT_CALLEE_TRASH_FLOAT (16) - #define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) +#define CNT_CALLEE_SAVED_FLOAT (16) +#define CNT_CALLEE_TRASH_FLOAT (16) +#define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) - #define CNT_CALLEE_SAVED_MASK (0) - #define CNT_CALLEE_TRASH_MASK (0) - #define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) +#define CNT_CALLEE_SAVED_MASK (0) +#define CNT_CALLEE_TRASH_MASK (0) +#define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) - #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED*REGSIZE_BYTES) - #define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT*sizeof(float)) +#define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED*REGSIZE_BYTES) +#define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT*sizeof(float)) - // Temporary registers used for the GS cookie check. - #define RBM_GSCOOKIE_TMP (RBM_R12 | RBM_LR) +// Temporary registers used for the GS cookie check. +#define RBM_GSCOOKIE_TMP (RBM_R12 | RBM_LR) - // register to hold shift amount; no special register is required on the ARM - #define REG_SHIFT REG_NA - #define RBM_SHIFT RBM_ALLINT +// register to hold shift amount; no special register is required on the ARM +#define REG_SHIFT REG_NA +#define RBM_SHIFT RBM_ALLINT - // register to hold shift amount when shifting 64-bit values (this uses a helper call) - #define REG_SHIFT_LNG REG_R2 // REG_ARG_2 - #define RBM_SHIFT_LNG RBM_R2 // RBM_ARG_2 +// register to hold shift amount when shifting 64-bit values (this uses a helper call) +#define REG_SHIFT_LNG REG_R2 // REG_ARG_2 +#define RBM_SHIFT_LNG RBM_R2 // RBM_ARG_2 - // This is a general scratch register that does not conflict with the argument registers - #define REG_SCRATCH REG_LR +// This is a general scratch register that does not conflict with the argument registers +#define REG_SCRATCH REG_LR - // This is a general register that can be optionally reserved for other purposes during codegen - #define REG_OPT_RSVD REG_R10 - #define RBM_OPT_RSVD RBM_R10 +// This is a general register that can be optionally reserved for other purposes during codegen +#define REG_OPT_RSVD REG_R10 +#define RBM_OPT_RSVD RBM_R10 - // We reserve R9 to store SP on entry for stack unwinding when localloc is used - // This needs to stay in sync with the ARM version of InlinedCallFrame::UpdateRegDisplay code. - #define REG_SAVED_LOCALLOC_SP REG_R9 - #define RBM_SAVED_LOCALLOC_SP RBM_R9 +// We reserve R9 to store SP on entry for stack unwinding when localloc is used +// This needs to stay in sync with the ARM version of InlinedCallFrame::UpdateRegDisplay code. +#define REG_SAVED_LOCALLOC_SP REG_R9 +#define RBM_SAVED_LOCALLOC_SP RBM_R9 - // Where is the exception object on entry to the handler block? - #define REG_EXCEPTION_OBJECT REG_R0 - #define RBM_EXCEPTION_OBJECT RBM_R0 +// Where is the exception object on entry to the handler block? +#define REG_EXCEPTION_OBJECT REG_R0 +#define RBM_EXCEPTION_OBJECT RBM_R0 - #define REG_JUMP_THUNK_PARAM REG_R12 - #define RBM_JUMP_THUNK_PARAM RBM_R12 +#define REG_JUMP_THUNK_PARAM REG_R12 +#define RBM_JUMP_THUNK_PARAM RBM_R12 - // ARM write barrier ABI (see vm\arm\asmhelpers.asm, vm\arm\asmhelpers.S): - // CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): - // On entry: - // r0: the destination address of the store - // r1: the object reference to be stored - // On exit: - // r0: trashed - // r3: trashed - // r12: trashed +// ARM write barrier ABI (see vm\arm\asmhelpers.asm, vm\arm\asmhelpers.S): +// CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): +// On entry: +// r0: the destination address of the store +// r1: the object reference to be stored +// On exit: +// r0: trashed +// r3: trashed +// r12: trashed // CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): - // On entry: - // r0: the destination address (object reference written here) - // r1: the source address (points to object reference to write) - // On exit: - // r0: incremented by 4 - // r1: incremented by 4 - // r2: trashed - // r3: trashed - // r12: trashed - - #define REG_WRITE_BARRIER_DST REG_ARG_0 - #define RBM_WRITE_BARRIER_DST RBM_ARG_0 - - #define REG_WRITE_BARRIER_SRC REG_ARG_1 - #define RBM_WRITE_BARRIER_SRC RBM_ARG_1 - - #define REG_WRITE_BARRIER_DST_BYREF REG_ARG_0 - #define RBM_WRITE_BARRIER_DST_BYREF RBM_ARG_0 - - #define REG_WRITE_BARRIER_SRC_BYREF REG_ARG_1 - #define RBM_WRITE_BARRIER_SRC_BYREF RBM_ARG_1 - - #define RBM_CALLEE_TRASH_NOGC (RBM_R2|RBM_R3|RBM_LR|RBM_DEFAULT_HELPER_CALL_TARGET) - - // Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_R0|RBM_R3|RBM_LR|RBM_DEFAULT_HELPER_CALL_TARGET) - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_WRITEBARRIER - - // Registers killed by CORINFO_HELP_ASSIGN_BYREF. - #define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. - // Note that r0 and r1 are still valid byref pointers after this helper call, despite their value being changed. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC - - // GenericPInvokeCalliHelper VASigCookie Parameter - #define REG_PINVOKE_COOKIE_PARAM REG_R4 - #define RBM_PINVOKE_COOKIE_PARAM RBM_R4 - - // GenericPInvokeCalliHelper unmanaged target Parameter - #define REG_PINVOKE_TARGET_PARAM REG_R12 - #define RBM_PINVOKE_TARGET_PARAM RBM_R12 - - // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) - #define REG_SECRET_STUB_PARAM REG_R12 - #define RBM_SECRET_STUB_PARAM RBM_R12 - - // R2R indirect call. Use the same registers as VSD - #define REG_R2R_INDIRECT_PARAM REG_R4 - #define RBM_R2R_INDIRECT_PARAM RBM_R4 - - // JMP Indirect call register - #define REG_INDIRECT_CALL_TARGET_REG REG_R12 - - // Registers used by PInvoke frame setup - #define REG_PINVOKE_FRAME REG_R4 - #define RBM_PINVOKE_FRAME RBM_R4 - #define REG_PINVOKE_TCB REG_R5 - #define RBM_PINVOKE_TCB RBM_R5 - #define REG_PINVOKE_SCRATCH REG_R6 - #define RBM_PINVOKE_SCRATCH RBM_R6 - - // The following defines are useful for iterating a regNumber - #define REG_FIRST REG_R0 - #define REG_INT_FIRST REG_R0 - #define REG_INT_LAST REG_LR - #define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) - #define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) - #define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) - - // The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks - #define REG_PROFILER_ENTER_ARG REG_R0 - #define RBM_PROFILER_ENTER_ARG RBM_R0 - #define REG_PROFILER_RET_SCRATCH REG_R2 - #define RBM_PROFILER_RET_SCRATCH RBM_R2 - - // The registers trashed by profiler enter/leave/tailcall hook - // See vm\arm\asmhelpers.asm for more details. - #define RBM_PROFILER_ENTER_TRASH RBM_NONE - // While REG_PROFILER_RET_SCRATCH is not trashed by the method, the register allocator must - // consider it killed by the return. - #define RBM_PROFILER_LEAVE_TRASH RBM_PROFILER_RET_SCRATCH - #define RBM_PROFILER_TAILCALL_TRASH RBM_NONE - - // Which register are int and long values returned in ? - #define REG_INTRET REG_R0 - #define RBM_INTRET RBM_R0 - #define RBM_LNGRET (RBM_R1|RBM_R0) - #define REG_LNGRET_LO REG_R0 - #define REG_LNGRET_HI REG_R1 - #define RBM_LNGRET_LO RBM_R0 - #define RBM_LNGRET_HI RBM_R1 - - #define REG_FLOATRET REG_F0 - #define RBM_FLOATRET RBM_F0 - #define RBM_DOUBLERET (RBM_F0|RBM_F1) - - // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper (JIT_RareDisableHelper). - // See vm\arm\amshelpers.asm for more details. - #define RBM_STOP_FOR_GC_TRASH (RBM_CALLEE_TRASH & ~(RBM_LNGRET|RBM_R7|RBM_R8|RBM_R11|RBM_DOUBLERET|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7)) - - // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. - #define RBM_INIT_PINVOKE_FRAME_TRASH (RBM_CALLEE_TRASH | RBM_PINVOKE_TCB | RBM_PINVOKE_SCRATCH) - - #define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH) - #define REG_VALIDATE_INDIRECT_CALL_ADDR REG_R0 - - #define REG_ASYNC_CONTINUATION_RET REG_R2 - #define RBM_ASYNC_CONTINUATION_RET RBM_R2 - - #define REG_FPBASE REG_R11 - #define RBM_FPBASE RBM_R11 - #define STR_FPBASE "r11" - #define REG_SPBASE REG_SP - #define RBM_SPBASE RBM_SP - #define STR_SPBASE "sp" - - #define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address - - #define MAX_REG_ARG 4 - #define MAX_FLOAT_REG_ARG 16 - #define MAX_HFA_RET_SLOTS 8 - - #define REG_ARG_FIRST REG_R0 - #define REG_ARG_LAST REG_R3 - #define REG_ARG_FP_FIRST REG_F0 - #define REG_ARG_FP_LAST REG_F7 - #define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots - - #define REG_ARG_0 REG_R0 - #define REG_ARG_1 REG_R1 - #define REG_ARG_2 REG_R2 - #define REG_ARG_3 REG_R3 +// On entry: +// r0: the destination address (object reference written here) +// r1: the source address (points to object reference to write) +// On exit: +// r0: incremented by 4 +// r1: incremented by 4 +// r2: trashed +// r3: trashed +// r12: trashed + +#define REG_WRITE_BARRIER_DST REG_ARG_0 +#define RBM_WRITE_BARRIER_DST RBM_ARG_0 + +#define REG_WRITE_BARRIER_SRC REG_ARG_1 +#define RBM_WRITE_BARRIER_SRC RBM_ARG_1 + +#define REG_WRITE_BARRIER_DST_BYREF REG_ARG_0 +#define RBM_WRITE_BARRIER_DST_BYREF RBM_ARG_0 + +#define REG_WRITE_BARRIER_SRC_BYREF REG_ARG_1 +#define RBM_WRITE_BARRIER_SRC_BYREF RBM_ARG_1 + +#define RBM_CALLEE_TRASH_NOGC (RBM_R2|RBM_R3|RBM_LR|RBM_DEFAULT_HELPER_CALL_TARGET) + +// Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_R0|RBM_R3|RBM_LR|RBM_DEFAULT_HELPER_CALL_TARGET) + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_WRITEBARRIER + +// Registers killed by CORINFO_HELP_ASSIGN_BYREF. +#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. +// Note that r0 and r1 are still valid byref pointers after this helper call, despite their value being changed. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC + +// GenericPInvokeCalliHelper VASigCookie Parameter +#define REG_PINVOKE_COOKIE_PARAM REG_R4 +#define RBM_PINVOKE_COOKIE_PARAM RBM_R4 + +// GenericPInvokeCalliHelper unmanaged target Parameter +#define REG_PINVOKE_TARGET_PARAM REG_R12 +#define RBM_PINVOKE_TARGET_PARAM RBM_R12 + +// IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) +#define REG_SECRET_STUB_PARAM REG_R12 +#define RBM_SECRET_STUB_PARAM RBM_R12 + +// R2R indirect call. Use the same registers as VSD +#define REG_R2R_INDIRECT_PARAM REG_R4 +#define RBM_R2R_INDIRECT_PARAM RBM_R4 + +// JMP Indirect call register +#define REG_INDIRECT_CALL_TARGET_REG REG_R12 + +// Registers used by PInvoke frame setup +#define REG_PINVOKE_FRAME REG_R4 +#define RBM_PINVOKE_FRAME RBM_R4 +#define REG_PINVOKE_TCB REG_R5 +#define RBM_PINVOKE_TCB RBM_R5 +#define REG_PINVOKE_SCRATCH REG_R6 +#define RBM_PINVOKE_SCRATCH RBM_R6 + +// The following defines are useful for iterating a regNumber +#define REG_FIRST REG_R0 +#define REG_INT_FIRST REG_R0 +#define REG_INT_LAST REG_LR +#define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) +#define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) +#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) + +// The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks +#define REG_PROFILER_ENTER_ARG REG_R0 +#define RBM_PROFILER_ENTER_ARG RBM_R0 +#define REG_PROFILER_RET_SCRATCH REG_R2 +#define RBM_PROFILER_RET_SCRATCH RBM_R2 + +// The registers trashed by profiler enter/leave/tailcall hook +// See vm\arm\asmhelpers.asm for more details. +#define RBM_PROFILER_ENTER_TRASH RBM_NONE +// While REG_PROFILER_RET_SCRATCH is not trashed by the method, the register allocator must +// consider it killed by the return. +#define RBM_PROFILER_LEAVE_TRASH RBM_PROFILER_RET_SCRATCH +#define RBM_PROFILER_TAILCALL_TRASH RBM_NONE + +// Which register are int and long values returned in ? +#define REG_INTRET REG_R0 +#define RBM_INTRET RBM_R0 +#define RBM_LNGRET (RBM_R1|RBM_R0) +#define REG_LNGRET_LO REG_R0 +#define REG_LNGRET_HI REG_R1 +#define RBM_LNGRET_LO RBM_R0 +#define RBM_LNGRET_HI RBM_R1 + +#define REG_FLOATRET REG_F0 +#define RBM_FLOATRET RBM_F0 +#define RBM_DOUBLERET (RBM_F0|RBM_F1) + +// The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper (JIT_RareDisableHelper). +// See vm\arm\amshelpers.asm for more details. +#define RBM_STOP_FOR_GC_TRASH (RBM_CALLEE_TRASH & ~(RBM_LNGRET|RBM_R7|RBM_R8|RBM_R11|RBM_DOUBLERET|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7)) + +// The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. +#define RBM_INIT_PINVOKE_FRAME_TRASH (RBM_CALLEE_TRASH | RBM_PINVOKE_TCB | RBM_PINVOKE_SCRATCH) + +#define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH) +#define REG_VALIDATE_INDIRECT_CALL_ADDR REG_R0 + +#define REG_ASYNC_CONTINUATION_RET REG_R2 +#define RBM_ASYNC_CONTINUATION_RET RBM_R2 + +#define REG_FPBASE REG_R11 +#define RBM_FPBASE RBM_R11 +#define STR_FPBASE "r11" +#define REG_SPBASE REG_SP +#define RBM_SPBASE RBM_SP +#define STR_SPBASE "sp" + +#define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address + +#define MAX_REG_ARG 4 +#define MAX_FLOAT_REG_ARG 16 +#define MAX_HFA_RET_SLOTS 8 + +#define REG_ARG_FIRST REG_R0 +#define REG_ARG_LAST REG_R3 +#define REG_ARG_FP_FIRST REG_F0 +#define REG_ARG_FP_LAST REG_F7 +#define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots + +#define REG_ARG_0 REG_R0 +#define REG_ARG_1 REG_R1 +#define REG_ARG_2 REG_R2 +#define REG_ARG_3 REG_R3 extern const regNumber intArgRegs [MAX_REG_ARG]; extern const regMaskTP intArgMasks[MAX_REG_ARG]; - #define RBM_ARG_0 RBM_R0 - #define RBM_ARG_1 RBM_R1 - #define RBM_ARG_2 RBM_R2 - #define RBM_ARG_3 RBM_R3 +#define RBM_ARG_0 RBM_R0 +#define RBM_ARG_1 RBM_R1 +#define RBM_ARG_2 RBM_R2 +#define RBM_ARG_3 RBM_R3 - #define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3) - #define RBM_FLTARG_REGS (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7|RBM_F8|RBM_F9|RBM_F10|RBM_F11|RBM_F12|RBM_F13|RBM_F14|RBM_F15) +#define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3) +#define RBM_FLTARG_REGS (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7|RBM_F8|RBM_F9|RBM_F10|RBM_F11|RBM_F12|RBM_F13|RBM_F14|RBM_F15) extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG]; extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG]; - #define LBL_DIST_SMALL_MAX_NEG (0) - #define LBL_DIST_SMALL_MAX_POS (+1020) - #define LBL_DIST_MED_MAX_NEG (-4095) - #define LBL_DIST_MED_MAX_POS (+4096) +#define LBL_DIST_SMALL_MAX_NEG (0) +#define LBL_DIST_SMALL_MAX_POS (+1020) +#define LBL_DIST_MED_MAX_NEG (-4095) +#define LBL_DIST_MED_MAX_POS (+4096) - #define JMP_DIST_SMALL_MAX_NEG (-2048) - #define JMP_DIST_SMALL_MAX_POS (+2046) +#define JMP_DIST_SMALL_MAX_NEG (-2048) +#define JMP_DIST_SMALL_MAX_POS (+2046) - #define CALL_DIST_MAX_NEG (-16777216) - #define CALL_DIST_MAX_POS (+16777214) +#define CALL_DIST_MAX_NEG (-16777216) +#define CALL_DIST_MAX_POS (+16777214) - #define JCC_DIST_SMALL_MAX_NEG (-256) - #define JCC_DIST_SMALL_MAX_POS (+254) +#define JCC_DIST_SMALL_MAX_NEG (-256) +#define JCC_DIST_SMALL_MAX_POS (+254) - #define JCC_DIST_MEDIUM_MAX_NEG (-1048576) - #define JCC_DIST_MEDIUM_MAX_POS (+1048574) +#define JCC_DIST_MEDIUM_MAX_NEG (-1048576) +#define JCC_DIST_MEDIUM_MAX_POS (+1048574) - #define LBL_SIZE_SMALL (2) +#define LBL_SIZE_SMALL (2) - #define JMP_SIZE_SMALL (2) - #define JMP_SIZE_LARGE (4) +#define JMP_SIZE_SMALL (2) +#define JMP_SIZE_LARGE (4) - #define JCC_SIZE_SMALL (2) - #define JCC_SIZE_MEDIUM (4) - #define JCC_SIZE_LARGE (6) +#define JCC_SIZE_SMALL (2) +#define JCC_SIZE_MEDIUM (4) +#define JCC_SIZE_LARGE (6) - // The first thing in an ARM32 prolog pushes LR to the stack, so this can be 0. - #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 +// The first thing in an ARM32 prolog pushes LR to the stack, so this can be 0. +#define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 - #define REG_STACK_PROBE_HELPER_ARG REG_R4 - #define RBM_STACK_PROBE_HELPER_ARG RBM_R4 - #define REG_STACK_PROBE_HELPER_CALL_TARGET REG_R5 - #define RBM_STACK_PROBE_HELPER_CALL_TARGET RBM_R5 - #define RBM_STACK_PROBE_HELPER_TRASH (RBM_R5 | RBM_LR) +#define REG_STACK_PROBE_HELPER_ARG REG_R4 +#define RBM_STACK_PROBE_HELPER_ARG RBM_R4 +#define REG_STACK_PROBE_HELPER_CALL_TARGET REG_R5 +#define RBM_STACK_PROBE_HELPER_CALL_TARGET RBM_R5 +#define RBM_STACK_PROBE_HELPER_TRASH (RBM_R5 | RBM_LR) // clang-format on diff --git a/src/coreclr/jit/targetarm64.h b/src/coreclr/jit/targetarm64.h index 70b21b9288c378..3f26dfab09ee93 100644 --- a/src/coreclr/jit/targetarm64.h +++ b/src/coreclr/jit/targetarm64.h @@ -7,101 +7,101 @@ #endif // clang-format off - #define CORINFO_ARCH_TARGET CORINFO_ARCH_ARM64 +#define CORINFO_ARCH_TARGET CORINFO_ARCH_ARM64 - #define CPU_LOAD_STORE_ARCH 1 - #define CPU_HAS_BYTE_REGS 0 +#define CPU_LOAD_STORE_ARCH 1 +#define CPU_HAS_BYTE_REGS 0 #ifdef FEATURE_SIMD - #define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned - #define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 1 // Whether SIMD registers are partially saved at calls +#define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned +#define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 1 // Whether SIMD registers are partially saved at calls #endif // FEATURE_SIMD - #define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog - #define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers - #define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers - #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp - #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. - #define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies - #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register - #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register - #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register - #define MAX_PASS_SINGLEREG_BYTES 16 // Maximum size of a struct passed in a single register (16-byte vector). - #define MAX_PASS_MULTIREG_BYTES 64 // Maximum size of a struct that could be passed in more than one register (max is 4 16-byte vectors using an HVA) - #define MAX_RET_MULTIREG_BYTES 64 // Maximum size of a struct that could be returned in more than one register (Max is an HVA of 4 16-byte vectors) - #define MAX_ARG_REG_COUNT 4 // Maximum registers used to pass a single argument in multiple registers. (max is 4 128-bit vectors using an HVA) - #define MAX_RET_REG_COUNT 4 // Maximum registers used to return a value. - - #define MAX_MULTIREG_COUNT 4 // Maximum number of registers defined by a single instruction (including calls). - // This is also the maximum number of registers for a MultiReg node. - - #define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers - #define USER_ARGS_COME_LAST 1 - #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target - #define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods - - #define CSE_CONSTS 1 // Enable if we want to CSE constants - #define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really - // need to track stack depth, but this is currently necessary to get GC information reported at call sites. - #define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that - - #define REG_FP_FIRST REG_V0 - #define REG_FP_LAST REG_V31 - #define FIRST_FP_ARGREG REG_V0 - #define LAST_FP_ARGREG REG_V15 - #define REG_PREDICATE_FIRST REG_P0 - #define REG_PREDICATE_LAST REG_P15 - #define REG_PREDICATE_LOW_LAST REG_P7 // Some instructions can only use the first half of the predicate registers. - #define REG_PREDICATE_HIGH_FIRST REG_P8 // Similarly, some instructions can only use the second half of the predicate registers. - #define REG_PREDICATE_HIGH_LAST REG_P15 - - #define REG_MASK_FIRST REG_PREDICATE_FIRST - #define REG_MASK_LAST REG_PREDICATE_LAST +#define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog +#define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers +#define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers +#define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp +#define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. +#define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies +#define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register +#define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register +#define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register +#define MAX_PASS_SINGLEREG_BYTES 16 // Maximum size of a struct passed in a single register (16-byte vector). +#define MAX_PASS_MULTIREG_BYTES 64 // Maximum size of a struct that could be passed in more than one register (max is 4 16-byte vectors using an HVA) +#define MAX_RET_MULTIREG_BYTES 64 // Maximum size of a struct that could be returned in more than one register (Max is an HVA of 4 16-byte vectors) +#define MAX_ARG_REG_COUNT 4 // Maximum registers used to pass a single argument in multiple registers. (max is 4 128-bit vectors using an HVA) +#define MAX_RET_REG_COUNT 4 // Maximum registers used to return a value. + +#define MAX_MULTIREG_COUNT 4 // Maximum number of registers defined by a single instruction (including calls). + // This is also the maximum number of registers for a MultiReg node. + +#define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers +#define USER_ARGS_COME_LAST 1 +#define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods + +#define CSE_CONSTS 1 // Enable if we want to CSE constants +#define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really + // need to track stack depth, but this is currently necessary to get GC information reported at call sites. +#define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that + +#define REG_FP_FIRST REG_V0 +#define REG_FP_LAST REG_V31 +#define FIRST_FP_ARGREG REG_V0 +#define LAST_FP_ARGREG REG_V15 +#define REG_PREDICATE_FIRST REG_P0 +#define REG_PREDICATE_LAST REG_P15 +#define REG_PREDICATE_LOW_LAST REG_P7 // Some instructions can only use the first half of the predicate registers. +#define REG_PREDICATE_HIGH_FIRST REG_P8 // Similarly, some instructions can only use the second half of the predicate registers. +#define REG_PREDICATE_HIGH_LAST REG_P15 + +#define REG_MASK_FIRST REG_PREDICATE_FIRST +#define REG_MASK_LAST REG_PREDICATE_LAST static_assert(REG_PREDICATE_HIGH_LAST == REG_PREDICATE_LAST); - #define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set - #define REGNUM_BITS 7 // number of bits in a REG_* - #define REGSIZE_BYTES 8 // number of bytes in one general purpose register - #define FP_REGSIZE_BYTES 16 // number of bytes in one FP/SIMD register - #define FPSAVE_REGSIZE_BYTES 8 // number of bytes in one FP/SIMD register that are saved/restored, for callee-saved registers +#define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set +#define REGNUM_BITS 7 // number of bits in a REG_* +#define REGSIZE_BYTES 8 // number of bytes in one general purpose register +#define FP_REGSIZE_BYTES 16 // number of bytes in one FP/SIMD register +#define FPSAVE_REGSIZE_BYTES 8 // number of bytes in one FP/SIMD register that are saved/restored, for callee-saved registers - #define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. +#define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. - #define CODE_ALIGN 4 // code alignment requirement - #define STACK_ALIGN 16 // stack alignment requirement +#define CODE_ALIGN 4 // code alignment requirement +#define STACK_ALIGN 16 // stack alignment requirement - #define RBM_INT_CALLEE_SAVED (RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28) - #define RBM_INT_CALLEE_TRASH (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_IP0|RBM_IP1|RBM_LR) - #define RBM_FLT_CALLEE_SAVED (RBM_V8|RBM_V9|RBM_V10|RBM_V11|RBM_V12|RBM_V13|RBM_V14|RBM_V15) - #define RBM_FLT_CALLEE_TRASH (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7|RBM_V16|RBM_V17|RBM_V18|RBM_V19|RBM_V20|RBM_V21|RBM_V22|RBM_V23|RBM_V24|RBM_V25|RBM_V26|RBM_V27|RBM_V28|RBM_V29|RBM_V30|RBM_V31) +#define RBM_INT_CALLEE_SAVED (RBM_R19|RBM_R20|RBM_R21|RBM_R22|RBM_R23|RBM_R24|RBM_R25|RBM_R26|RBM_R27|RBM_R28) +#define RBM_INT_CALLEE_TRASH (RBM_R0|RBM_R1|RBM_R2|RBM_R3|RBM_R4|RBM_R5|RBM_R6|RBM_R7|RBM_R8|RBM_R9|RBM_R10|RBM_R11|RBM_R12|RBM_R13|RBM_R14|RBM_R15|RBM_IP0|RBM_IP1|RBM_LR) +#define RBM_FLT_CALLEE_SAVED (RBM_V8|RBM_V9|RBM_V10|RBM_V11|RBM_V12|RBM_V13|RBM_V14|RBM_V15) +#define RBM_FLT_CALLEE_TRASH (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7|RBM_V16|RBM_V17|RBM_V18|RBM_V19|RBM_V20|RBM_V21|RBM_V22|RBM_V23|RBM_V24|RBM_V25|RBM_V26|RBM_V27|RBM_V28|RBM_V29|RBM_V30|RBM_V31) - #define RBM_LOWMASK (RBM_P0|RBM_P1|RBM_P2|RBM_P3|RBM_P4|RBM_P5|RBM_P6|RBM_P7) - #define RBM_HIGHMASK (RBM_P8|RBM_P9|RBM_P10| RBM_P11|RBM_P12|RBM_P13|RBM_P14|RBM_P15) - #define RBM_ALLMASK (RBM_LOWMASK|RBM_HIGHMASK) +#define RBM_LOWMASK (RBM_P0|RBM_P1|RBM_P2|RBM_P3|RBM_P4|RBM_P5|RBM_P6|RBM_P7) +#define RBM_HIGHMASK (RBM_P8|RBM_P9|RBM_P10| RBM_P11|RBM_P12|RBM_P13|RBM_P14|RBM_P15) +#define RBM_ALLMASK (RBM_LOWMASK|RBM_HIGHMASK) - #define RBM_MSK_CALLEE_SAVED (0) - #define RBM_MSK_CALLEE_TRASH RBM_ALLMASK +#define RBM_MSK_CALLEE_SAVED (0) +#define RBM_MSK_CALLEE_TRASH RBM_ALLMASK - #define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED) - #define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH | RBM_MSK_CALLEE_TRASH) +#define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED) +#define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH | RBM_MSK_CALLEE_TRASH) - #define REG_DEFAULT_HELPER_CALL_TARGET REG_R12 - #define RBM_DEFAULT_HELPER_CALL_TARGET RBM_R12 +#define REG_DEFAULT_HELPER_CALL_TARGET REG_R12 +#define RBM_DEFAULT_HELPER_CALL_TARGET RBM_R12 - #define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) - #define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH) - #define RBM_ALLDOUBLE RBM_ALLFLOAT +#define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) +#define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH) +#define RBM_ALLDOUBLE RBM_ALLFLOAT - // REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED - #define REG_VAR_ORDER REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, \ +// REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED +#define REG_VAR_ORDER REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, \ REG_R6, REG_R7, REG_R8, REG_R9, REG_R10, \ REG_R11, REG_R13, REG_R14, \ REG_R12, REG_R15, REG_IP0, REG_IP1, \ REG_R19,REG_R20,REG_R21,REG_R22,REG_R23,REG_R24,REG_R25,REG_R26,REG_R27,REG_R28,\ REG_LR - #define REG_VAR_ORDER_FLT REG_V16, REG_V17, REG_V18, REG_V19, \ +#define REG_VAR_ORDER_FLT REG_V16, REG_V17, REG_V18, REG_V19, \ REG_V20, REG_V21, REG_V22, REG_V23, \ REG_V24, REG_V25, REG_V26, REG_V27, \ REG_V28, REG_V29, REG_V30, REG_V31, \ @@ -110,283 +110,283 @@ REG_V12, REG_V13, REG_V14, REG_V15, \ REG_V3, REG_V2, REG_V1, REG_V0 - #define CNT_CALLEE_SAVED (11) - #define CNT_CALLEE_TRASH (17) - #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) - - #define CNT_CALLEE_SAVED_FLOAT (8) - #define CNT_CALLEE_TRASH_FLOAT (24) - #define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) - - #define CNT_CALLEE_SAVED_MASK (4) - #define CNT_CALLEE_TRASH_MASK (8) - #define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) - - #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED * REGSIZE_BYTES) - #define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES) - - // On ARM64 we do not use any additional callee-saves for ENC - // since there are so many volatile registers available, and - // callee saves have to be aggressively saved by ENC codegen - // because a future version could use them. - #define RBM_ENC_CALLEE_SAVED 0 - - // Temporary registers used for the GS cookie check. - #define RBM_GSCOOKIE_TMP (RBM_IP0 | RBM_IP1) - - // register to hold shift amount; no special register is required on ARM64. - #define REG_SHIFT REG_NA - #define RBM_SHIFT RBM_ALLINT - - // This is a general scratch register that does not conflict with the argument registers - #define REG_SCRATCH REG_R9 - - // This is a general register that can be optionally reserved for other purposes during codegen - #define REG_OPT_RSVD REG_IP1 - #define RBM_OPT_RSVD RBM_IP1 - - // Where is the exception object on entry to the handler block? - #define REG_EXCEPTION_OBJECT REG_R0 - #define RBM_EXCEPTION_OBJECT RBM_R0 - - #define REG_JUMP_THUNK_PARAM REG_R12 - #define RBM_JUMP_THUNK_PARAM RBM_R12 - - // ARM64 write barrier ABI (see vm\arm64\asmhelpers.asm, vm\arm64\asmhelpers.S): - // CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): - // On entry: - // x14: the destination address of the store - // x15: the object reference to be stored - // On exit: - // x12: trashed - // x14: incremented by 8 - // x15: trashed - // x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP - // CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): - // On entry: - // x13: the source address (points to object reference to write) - // x14: the destination address (object reference written here) - // On exit: - // x12: trashed - // x13: incremented by 8 - // x14: incremented by 8 - // x15: trashed - // x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP - // - // Note that while x17 (ip1) is currently only trashed under FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP, - // it is expected to be set in the future for R2R. Consider it trashed to avoid later breaking changes. - - #define REG_WRITE_BARRIER_DST REG_R14 - #define RBM_WRITE_BARRIER_DST RBM_R14 - - #define REG_WRITE_BARRIER_SRC REG_R15 - #define RBM_WRITE_BARRIER_SRC RBM_R15 - - #define REG_WRITE_BARRIER_DST_BYREF REG_R14 - #define RBM_WRITE_BARRIER_DST_BYREF RBM_R14 - - #define REG_WRITE_BARRIER_SRC_BYREF REG_R13 - #define RBM_WRITE_BARRIER_SRC_BYREF RBM_R13 - - #define RBM_CALLEE_TRASH_NOGC (RBM_R12|RBM_R15|RBM_IP0|RBM_IP1|RBM_DEFAULT_HELPER_CALL_TARGET) - - // Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_R14|RBM_CALLEE_TRASH_NOGC) - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC - - // Registers killed by CORINFO_HELP_ASSIGN_BYREF. - #define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. - // Note that x13 and x14 are still valid byref pointers after this helper call, despite their value being changed. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC - - // GenericPInvokeCalliHelper VASigCookie Parameter - #define REG_PINVOKE_COOKIE_PARAM REG_R15 - #define RBM_PINVOKE_COOKIE_PARAM RBM_R15 - - // GenericPInvokeCalliHelper unmanaged target Parameter - #define REG_PINVOKE_TARGET_PARAM REG_R12 - #define RBM_PINVOKE_TARGET_PARAM RBM_R12 - - // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) - #define REG_SECRET_STUB_PARAM REG_R12 - #define RBM_SECRET_STUB_PARAM RBM_R12 - - // R2R indirect call. Use the same registers as VSD - #define REG_R2R_INDIRECT_PARAM REG_R11 - #define RBM_R2R_INDIRECT_PARAM RBM_R11 - - // JMP Indirect call register - #define REG_INDIRECT_CALL_TARGET_REG REG_IP0 - - // The following defines are useful for iterating a regNumber - #define REG_FIRST REG_R0 - #define REG_INT_FIRST REG_R0 - #define REG_INT_LAST REG_ZR - #define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) - #define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) - #define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) - - // The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks - #define REG_PROFILER_ENTER_ARG_FUNC_ID REG_R10 - #define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_R10 - #define REG_PROFILER_ENTER_ARG_CALLER_SP REG_R11 - #define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_R11 - #define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_R10 - #define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_R10 - #define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_R11 - #define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_R11 - - // The registers trashed by profiler enter/leave/tailcall hook - #define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_ARG_RET_BUFF|RBM_FLTARG_REGS|RBM_FP)) - #define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_ARG_RET_BUFF|RBM_FLTARG_REGS|RBM_FP)) - #define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH - - // Which register are int and long values returned in ? - #define REG_INTRET REG_R0 - #define RBM_INTRET RBM_R0 - #define RBM_LNGRET RBM_R0 - // second return register for 16-byte structs - #define REG_INTRET_1 REG_R1 - #define RBM_INTRET_1 RBM_R1 - - #define REG_FLOATRET REG_V0 - #define RBM_FLOATRET RBM_V0 - #define RBM_DOUBLERET RBM_V0 - - // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper - #define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH - - // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. - #define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH - - #define RBM_INTERFACELOOKUP_FOR_SLOT_TRASH (RBM_R12 | RBM_R13 | RBM_R14 | RBM_R15) - #define RBM_INTERFACELOOKUP_FOR_SLOT_RETURN RBM_R15 - #define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8 | RBM_R15)) - #define REG_VALIDATE_INDIRECT_CALL_ADDR REG_R15 - #define REG_DISPATCH_INDIRECT_CALL_ADDR REG_R9 - - #define REG_ASYNC_CONTINUATION_RET REG_R2 - #define RBM_ASYNC_CONTINUATION_RET RBM_R2 - - #define REG_FPBASE REG_FP - #define RBM_FPBASE RBM_FP - #define STR_FPBASE "fp" - #define REG_SPBASE REG_SP - #define RBM_SPBASE RBM_ZR // reuse the RBM for REG_ZR - #define STR_SPBASE "sp" - - #define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address - - // On ARM64 the calling convention defines REG_R8 (x8) as an additional argument register. - // It isn't allocated for the normal user arguments, so it isn't counted by MAX_REG_ARG. - // Whether we use this register to pass the RetBuff is controlled by the function hasFixedRetBuffReg(). - // It is considered to be the next integer argnum, which is 8. - // - #define REG_ARG_RET_BUFF REG_R8 - #define RBM_ARG_RET_BUFF RBM_R8 - #define RET_BUFF_ARGNUM 8 - - #define MAX_REG_ARG 8 - #define MAX_FLOAT_REG_ARG 8 - - #define REG_ARG_FIRST REG_R0 - #define REG_ARG_LAST REG_R7 - #define REG_ARG_FP_FIRST REG_V0 - #define REG_ARG_FP_LAST REG_V7 - #define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots - - #define REG_ARG_0 REG_R0 - #define REG_ARG_1 REG_R1 - #define REG_ARG_2 REG_R2 - #define REG_ARG_3 REG_R3 - #define REG_ARG_4 REG_R4 - #define REG_ARG_5 REG_R5 - #define REG_ARG_6 REG_R6 - #define REG_ARG_7 REG_R7 +#define CNT_CALLEE_SAVED (11) +#define CNT_CALLEE_TRASH (17) +#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) + +#define CNT_CALLEE_SAVED_FLOAT (8) +#define CNT_CALLEE_TRASH_FLOAT (24) +#define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) + +#define CNT_CALLEE_SAVED_MASK (4) +#define CNT_CALLEE_TRASH_MASK (8) +#define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) + +#define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED * REGSIZE_BYTES) +#define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES) + +// On ARM64 we do not use any additional callee-saves for ENC +// since there are so many volatile registers available, and +// callee saves have to be aggressively saved by ENC codegen +// because a future version could use them. +#define RBM_ENC_CALLEE_SAVED 0 + +// Temporary registers used for the GS cookie check. +#define RBM_GSCOOKIE_TMP (RBM_IP0 | RBM_IP1) + +// register to hold shift amount; no special register is required on ARM64. +#define REG_SHIFT REG_NA +#define RBM_SHIFT RBM_ALLINT + +// This is a general scratch register that does not conflict with the argument registers +#define REG_SCRATCH REG_R9 + +// This is a general register that can be optionally reserved for other purposes during codegen +#define REG_OPT_RSVD REG_IP1 +#define RBM_OPT_RSVD RBM_IP1 + +// Where is the exception object on entry to the handler block? +#define REG_EXCEPTION_OBJECT REG_R0 +#define RBM_EXCEPTION_OBJECT RBM_R0 + +#define REG_JUMP_THUNK_PARAM REG_R12 +#define RBM_JUMP_THUNK_PARAM RBM_R12 + +// ARM64 write barrier ABI (see vm\arm64\asmhelpers.asm, vm\arm64\asmhelpers.S): +// CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): +// On entry: +// x14: the destination address of the store +// x15: the object reference to be stored +// On exit: +// x12: trashed +// x14: incremented by 8 +// x15: trashed +// x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +// CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): +// On entry: +// x13: the source address (points to object reference to write) +// x14: the destination address (object reference written here) +// On exit: +// x12: trashed +// x13: incremented by 8 +// x14: incremented by 8 +// x15: trashed +// x17: trashed (ip1) if FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +// +// Note that while x17 (ip1) is currently only trashed under FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP, +// it is expected to be set in the future for R2R. Consider it trashed to avoid later breaking changes. + +#define REG_WRITE_BARRIER_DST REG_R14 +#define RBM_WRITE_BARRIER_DST RBM_R14 + +#define REG_WRITE_BARRIER_SRC REG_R15 +#define RBM_WRITE_BARRIER_SRC RBM_R15 + +#define REG_WRITE_BARRIER_DST_BYREF REG_R14 +#define RBM_WRITE_BARRIER_DST_BYREF RBM_R14 + +#define REG_WRITE_BARRIER_SRC_BYREF REG_R13 +#define RBM_WRITE_BARRIER_SRC_BYREF RBM_R13 + +#define RBM_CALLEE_TRASH_NOGC (RBM_R12|RBM_R15|RBM_IP0|RBM_IP1|RBM_DEFAULT_HELPER_CALL_TARGET) + +// Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_R14|RBM_CALLEE_TRASH_NOGC) + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC + +// Registers killed by CORINFO_HELP_ASSIGN_BYREF. +#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. +// Note that x13 and x14 are still valid byref pointers after this helper call, despite their value being changed. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC + +// GenericPInvokeCalliHelper VASigCookie Parameter +#define REG_PINVOKE_COOKIE_PARAM REG_R15 +#define RBM_PINVOKE_COOKIE_PARAM RBM_R15 + +// GenericPInvokeCalliHelper unmanaged target Parameter +#define REG_PINVOKE_TARGET_PARAM REG_R12 +#define RBM_PINVOKE_TARGET_PARAM RBM_R12 + +// IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) +#define REG_SECRET_STUB_PARAM REG_R12 +#define RBM_SECRET_STUB_PARAM RBM_R12 + +// R2R indirect call. Use the same registers as VSD +#define REG_R2R_INDIRECT_PARAM REG_R11 +#define RBM_R2R_INDIRECT_PARAM RBM_R11 + +// JMP Indirect call register +#define REG_INDIRECT_CALL_TARGET_REG REG_IP0 + +// The following defines are useful for iterating a regNumber +#define REG_FIRST REG_R0 +#define REG_INT_FIRST REG_R0 +#define REG_INT_LAST REG_ZR +#define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) +#define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) +#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) + +// The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks +#define REG_PROFILER_ENTER_ARG_FUNC_ID REG_R10 +#define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_R10 +#define REG_PROFILER_ENTER_ARG_CALLER_SP REG_R11 +#define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_R11 +#define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_R10 +#define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_R10 +#define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_R11 +#define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_R11 + +// The registers trashed by profiler enter/leave/tailcall hook +#define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_ARG_RET_BUFF|RBM_FLTARG_REGS|RBM_FP)) +#define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_ARG_RET_BUFF|RBM_FLTARG_REGS|RBM_FP)) +#define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH + +// Which register are int and long values returned in ? +#define REG_INTRET REG_R0 +#define RBM_INTRET RBM_R0 +#define RBM_LNGRET RBM_R0 +// second return register for 16-byte structs +#define REG_INTRET_1 REG_R1 +#define RBM_INTRET_1 RBM_R1 + +#define REG_FLOATRET REG_V0 +#define RBM_FLOATRET RBM_V0 +#define RBM_DOUBLERET RBM_V0 + +// The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper +#define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH + +// The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. +#define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH + +#define RBM_INTERFACELOOKUP_FOR_SLOT_TRASH (RBM_R12 | RBM_R13 | RBM_R14 | RBM_R15) +#define RBM_INTERFACELOOKUP_FOR_SLOT_RETURN RBM_R15 +#define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8 | RBM_R15)) +#define REG_VALIDATE_INDIRECT_CALL_ADDR REG_R15 +#define REG_DISPATCH_INDIRECT_CALL_ADDR REG_R9 + +#define REG_ASYNC_CONTINUATION_RET REG_R2 +#define RBM_ASYNC_CONTINUATION_RET RBM_R2 + +#define REG_FPBASE REG_FP +#define RBM_FPBASE RBM_FP +#define STR_FPBASE "fp" +#define REG_SPBASE REG_SP +#define RBM_SPBASE RBM_ZR // reuse the RBM for REG_ZR +#define STR_SPBASE "sp" + +#define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address + +// On ARM64 the calling convention defines REG_R8 (x8) as an additional argument register. +// It isn't allocated for the normal user arguments, so it isn't counted by MAX_REG_ARG. +// Whether we use this register to pass the RetBuff is controlled by the function hasFixedRetBuffReg(). +// It is considered to be the next integer argnum, which is 8. +// +#define REG_ARG_RET_BUFF REG_R8 +#define RBM_ARG_RET_BUFF RBM_R8 +#define RET_BUFF_ARGNUM 8 + +#define MAX_REG_ARG 8 +#define MAX_FLOAT_REG_ARG 8 + +#define REG_ARG_FIRST REG_R0 +#define REG_ARG_LAST REG_R7 +#define REG_ARG_FP_FIRST REG_V0 +#define REG_ARG_FP_LAST REG_V7 +#define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots + +#define REG_ARG_0 REG_R0 +#define REG_ARG_1 REG_R1 +#define REG_ARG_2 REG_R2 +#define REG_ARG_3 REG_R3 +#define REG_ARG_4 REG_R4 +#define REG_ARG_5 REG_R5 +#define REG_ARG_6 REG_R6 +#define REG_ARG_7 REG_R7 extern const regNumber intArgRegs [MAX_REG_ARG]; extern const regMaskTP intArgMasks[MAX_REG_ARG]; - #define RBM_ARG_0 RBM_R0 - #define RBM_ARG_1 RBM_R1 - #define RBM_ARG_2 RBM_R2 - #define RBM_ARG_3 RBM_R3 - #define RBM_ARG_4 RBM_R4 - #define RBM_ARG_5 RBM_R5 - #define RBM_ARG_6 RBM_R6 - #define RBM_ARG_7 RBM_R7 - - #define REG_FLTARG_0 REG_V0 - #define REG_FLTARG_1 REG_V1 - #define REG_FLTARG_2 REG_V2 - #define REG_FLTARG_3 REG_V3 - #define REG_FLTARG_4 REG_V4 - #define REG_FLTARG_5 REG_V5 - #define REG_FLTARG_6 REG_V6 - #define REG_FLTARG_7 REG_V7 - - #define RBM_FLTARG_0 RBM_V0 - #define RBM_FLTARG_1 RBM_V1 - #define RBM_FLTARG_2 RBM_V2 - #define RBM_FLTARG_3 RBM_V3 - #define RBM_FLTARG_4 RBM_V4 - #define RBM_FLTARG_5 RBM_V5 - #define RBM_FLTARG_6 RBM_V6 - #define RBM_FLTARG_7 RBM_V7 - - #define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5|RBM_ARG_6|RBM_ARG_7) - #define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7) +#define RBM_ARG_0 RBM_R0 +#define RBM_ARG_1 RBM_R1 +#define RBM_ARG_2 RBM_R2 +#define RBM_ARG_3 RBM_R3 +#define RBM_ARG_4 RBM_R4 +#define RBM_ARG_5 RBM_R5 +#define RBM_ARG_6 RBM_R6 +#define RBM_ARG_7 RBM_R7 + +#define REG_FLTARG_0 REG_V0 +#define REG_FLTARG_1 REG_V1 +#define REG_FLTARG_2 REG_V2 +#define REG_FLTARG_3 REG_V3 +#define REG_FLTARG_4 REG_V4 +#define REG_FLTARG_5 REG_V5 +#define REG_FLTARG_6 REG_V6 +#define REG_FLTARG_7 REG_V7 + +#define RBM_FLTARG_0 RBM_V0 +#define RBM_FLTARG_1 RBM_V1 +#define RBM_FLTARG_2 RBM_V2 +#define RBM_FLTARG_3 RBM_V3 +#define RBM_FLTARG_4 RBM_V4 +#define RBM_FLTARG_5 RBM_V5 +#define RBM_FLTARG_6 RBM_V6 +#define RBM_FLTARG_7 RBM_V7 + +#define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5|RBM_ARG_6|RBM_ARG_7) +#define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7) extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG]; extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG]; - #define LBL_DIST_SMALL_MAX_NEG (-1048576) - #define LBL_DIST_SMALL_MAX_POS (+1048575) +#define LBL_DIST_SMALL_MAX_NEG (-1048576) +#define LBL_DIST_SMALL_MAX_POS (+1048575) - #define LBL_SIZE_SMALL (4) +#define LBL_SIZE_SMALL (4) - #define JCC_DIST_SMALL_MAX_NEG (-1048576) - #define JCC_DIST_SMALL_MAX_POS (+1048575) +#define JCC_DIST_SMALL_MAX_NEG (-1048576) +#define JCC_DIST_SMALL_MAX_POS (+1048575) - #define TB_DIST_SMALL_MAX_NEG (-32768) - #define TB_DIST_SMALL_MAX_POS (+32767) +#define TB_DIST_SMALL_MAX_NEG (-32768) +#define TB_DIST_SMALL_MAX_POS (+32767) - #define JCC_SIZE_SMALL (4) - #define JCC_SIZE_LARGE (8) +#define JCC_SIZE_SMALL (4) +#define JCC_SIZE_LARGE (8) - #define LDC_DIST_SMALL_MAX_NEG (-1048576) - #define LDC_DIST_SMALL_MAX_POS (+1048575) +#define LDC_DIST_SMALL_MAX_NEG (-1048576) +#define LDC_DIST_SMALL_MAX_POS (+1048575) - #define LDC_SIZE_SMALL (4) +#define LDC_SIZE_SMALL (4) - #define JMP_SIZE_SMALL (4) +#define JMP_SIZE_SMALL (4) - // The number of bytes from the end the last probed page that must also be probed, to allow for some - // small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word - // on the stack guard page, and must be touched before any further "SUB SP". - // For arm64, this is the maximum prolog establishment pre-indexed (that is SP pre-decrement) offset. - #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 512 +// The number of bytes from the end the last probed page that must also be probed, to allow for some +// small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word +// on the stack guard page, and must be touched before any further "SUB SP". +// For arm64, this is the maximum prolog establishment pre-indexed (that is SP pre-decrement) offset. +#define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 512 - // Some "Advanced SIMD / SVE scalar x indexed element" and "Advanced SIMD / SVE vector x indexed element" instructions (e.g. "MLA (by element)") - // have encoding that restricts what registers that can be used for the indexed element when the element size is H (i.e. 2 bytes). - #define RBM_ASIMD_INDEXED_H_ELEMENT_ALLOWED_REGS (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7|RBM_V8|RBM_V9|RBM_V10|RBM_V11|RBM_V12|RBM_V13|RBM_V14|RBM_V15) - #define RBM_SVE_INDEXED_S_ELEMENT_ALLOWED_REGS (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7) - #define RBM_SVE_INDEXED_D_ELEMENT_ALLOWED_REGS RBM_ASIMD_INDEXED_H_ELEMENT_ALLOWED_REGS +// Some "Advanced SIMD / SVE scalar x indexed element" and "Advanced SIMD / SVE vector x indexed element" instructions (e.g. "MLA (by element)") +// have encoding that restricts what registers that can be used for the indexed element when the element size is H (i.e. 2 bytes). +#define RBM_ASIMD_INDEXED_H_ELEMENT_ALLOWED_REGS (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7|RBM_V8|RBM_V9|RBM_V10|RBM_V11|RBM_V12|RBM_V13|RBM_V14|RBM_V15) +#define RBM_SVE_INDEXED_S_ELEMENT_ALLOWED_REGS (RBM_V0|RBM_V1|RBM_V2|RBM_V3|RBM_V4|RBM_V5|RBM_V6|RBM_V7) +#define RBM_SVE_INDEXED_D_ELEMENT_ALLOWED_REGS RBM_ASIMD_INDEXED_H_ELEMENT_ALLOWED_REGS - #define REG_ZERO_INIT_FRAME_REG1 REG_R9 - #define REG_ZERO_INIT_FRAME_REG2 REG_R10 - #define REG_ZERO_INIT_FRAME_SIMD REG_V16 +#define REG_ZERO_INIT_FRAME_REG1 REG_R9 +#define REG_ZERO_INIT_FRAME_REG2 REG_R10 +#define REG_ZERO_INIT_FRAME_SIMD REG_V16 - #define SWIFT_SUPPORT - #define REG_SWIFT_ERROR REG_R21 - #define RBM_SWIFT_ERROR RBM_R21 - #define REG_SWIFT_SELF REG_R20 - #define RBM_SWIFT_SELF RBM_R20 - #define REG_SWIFT_INTRET_ORDER REG_R0,REG_R1,REG_R2,REG_R3 - #define REG_SWIFT_FLOATRET_ORDER REG_V0,REG_V1,REG_V2,REG_V3 +#define SWIFT_SUPPORT +#define REG_SWIFT_ERROR REG_R21 +#define RBM_SWIFT_ERROR RBM_R21 +#define REG_SWIFT_SELF REG_R20 +#define RBM_SWIFT_SELF RBM_R20 +#define REG_SWIFT_INTRET_ORDER REG_R0,REG_R1,REG_R2,REG_R3 +#define REG_SWIFT_FLOATRET_ORDER REG_V0,REG_V1,REG_V2,REG_V3 // clang-format on diff --git a/src/coreclr/jit/targetloongarch64.h b/src/coreclr/jit/targetloongarch64.h index b87539e5aea69f..46aab2c7fe5aeb 100644 --- a/src/coreclr/jit/targetloongarch64.h +++ b/src/coreclr/jit/targetloongarch64.h @@ -11,315 +11,315 @@ // It can be used only manually and very carefully!!! // clang-format off - #define CORINFO_ARCH_TARGET CORINFO_ARCH_LOONGARCH64 +#define CORINFO_ARCH_TARGET CORINFO_ARCH_LOONGARCH64 - #define CPU_LOAD_STORE_ARCH 1 - #define CPU_HAS_FP_SUPPORT 1 - #define CPU_HAS_BYTE_REGS 0 +#define CPU_LOAD_STORE_ARCH 1 +#define CPU_HAS_FP_SUPPORT 1 +#define CPU_HAS_BYTE_REGS 0 #ifdef FEATURE_SIMD #pragma error("SIMD Unimplemented yet LOONGARCH") - #define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned - #define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 1 // Whether SIMD registers are partially saved at calls +#define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned +#define FEATURE_PARTIAL_SIMD_CALLEE_SAVE 1 // Whether SIMD registers are partially saved at calls #endif // FEATURE_SIMD - #define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog - #define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers - #define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers - #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp - #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. - #define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies - #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register - #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register - #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register - #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (8-byte). - #define MAX_PASS_MULTIREG_BYTES 16 // Maximum size of a struct that could be passed in more than one register - #define MAX_RET_MULTIREG_BYTES 16 // Maximum size of a struct that could be returned in more than one register (Max is an HFA of 2 doubles) - #define MAX_ARG_REG_COUNT 2 // Maximum registers used to pass a single argument in multiple registers. - #define MAX_RET_REG_COUNT 2 // Maximum registers used to return a value. - #define MAX_MULTIREG_COUNT 2 // Maximum number of registers defined by a single instruction (including calls). +#define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog +#define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers +#define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers +#define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp +#define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. +#define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies +#define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register +#define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register +#define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register +#define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (8-byte). +#define MAX_PASS_MULTIREG_BYTES 16 // Maximum size of a struct that could be passed in more than one register +#define MAX_RET_MULTIREG_BYTES 16 // Maximum size of a struct that could be returned in more than one register (Max is an HFA of 2 doubles) +#define MAX_ARG_REG_COUNT 2 // Maximum registers used to pass a single argument in multiple registers. +#define MAX_RET_REG_COUNT 2 // Maximum registers used to return a value. +#define MAX_MULTIREG_COUNT 2 // Maximum number of registers defined by a single instruction (including calls). // This is also the maximum number of registers for a MultiReg node. - #define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers - #define USER_ARGS_COME_LAST 1 - #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target - #define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods - - #define CSE_CONSTS 1 // Enable if we want to CSE constants - #define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really - // need to track stack depth, but this is currently necessary to get GC information reported at call sites. - #define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that - - #define REG_FP_FIRST REG_F0 - #define REG_FP_LAST REG_F31 - #define FIRST_FP_ARGREG REG_F0 - #define LAST_FP_ARGREG REG_F7 - - #define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set - #define REGNUM_BITS 6 // number of bits in a REG_* within registerloongarch64.h - #define REGSIZE_BYTES 8 // number of bytes in one general purpose register - #define FP_REGSIZE_BYTES 8 // number of bytes in one FP register - #define FPSAVE_REGSIZE_BYTES 8 // number of bytes in one FP register that are saved/restored. - - #define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. - - #define CODE_ALIGN 4 // code alignment requirement - #define STACK_ALIGN 16 // stack alignment requirement - - #define FIRST_INT_CALLEE_SAVED REG_S0 - #define LAST_INT_CALLEE_SAVED REG_S8 - #define RBM_INT_CALLEE_SAVED (RBM_S0|RBM_S1|RBM_S2|RBM_S3|RBM_S4|RBM_S5|RBM_S6|RBM_S7|RBM_S8) - #define RBM_INT_CALLEE_TRASH (RBM_A0|RBM_A1|RBM_A2|RBM_A3|RBM_A4|RBM_A5|RBM_A6|RBM_A7|RBM_T0|RBM_T1|RBM_T2|RBM_T3|RBM_T4|RBM_T5|RBM_T6|RBM_T7|RBM_T8) - #define FIRST_FLT_CALLEE_SAVED REG_F24 - #define LAST_FLT_CALLEE_SAVED REG_F31 - #define RBM_FLT_CALLEE_SAVED (RBM_F24|RBM_F25|RBM_F26|RBM_F27|RBM_F28|RBM_F29|RBM_F30|RBM_F31) - #define RBM_FLT_CALLEE_TRASH (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7) - - #define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED) - #define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH) - - #define REG_DEFAULT_HELPER_CALL_TARGET REG_T4 - #define RBM_DEFAULT_HELPER_CALL_TARGET RBM_T4 - - #define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) - #define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH) - #define RBM_ALLDOUBLE RBM_ALLFLOAT - - // REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED - #define REG_VAR_ORDER REG_A0,REG_A1,REG_A2,REG_A3,REG_A4,REG_A5,REG_A6,REG_A7, \ +#define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers +#define USER_ARGS_COME_LAST 1 +#define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods + +#define CSE_CONSTS 1 // Enable if we want to CSE constants +#define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really + // need to track stack depth, but this is currently necessary to get GC information reported at call sites. +#define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that + +#define REG_FP_FIRST REG_F0 +#define REG_FP_LAST REG_F31 +#define FIRST_FP_ARGREG REG_F0 +#define LAST_FP_ARGREG REG_F7 + +#define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set +#define REGNUM_BITS 6 // number of bits in a REG_* within registerloongarch64.h +#define REGSIZE_BYTES 8 // number of bytes in one general purpose register +#define FP_REGSIZE_BYTES 8 // number of bytes in one FP register +#define FPSAVE_REGSIZE_BYTES 8 // number of bytes in one FP register that are saved/restored. + +#define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. + +#define CODE_ALIGN 4 // code alignment requirement +#define STACK_ALIGN 16 // stack alignment requirement + +#define FIRST_INT_CALLEE_SAVED REG_S0 +#define LAST_INT_CALLEE_SAVED REG_S8 +#define RBM_INT_CALLEE_SAVED (RBM_S0|RBM_S1|RBM_S2|RBM_S3|RBM_S4|RBM_S5|RBM_S6|RBM_S7|RBM_S8) +#define RBM_INT_CALLEE_TRASH (RBM_A0|RBM_A1|RBM_A2|RBM_A3|RBM_A4|RBM_A5|RBM_A6|RBM_A7|RBM_T0|RBM_T1|RBM_T2|RBM_T3|RBM_T4|RBM_T5|RBM_T6|RBM_T7|RBM_T8) +#define FIRST_FLT_CALLEE_SAVED REG_F24 +#define LAST_FLT_CALLEE_SAVED REG_F31 +#define RBM_FLT_CALLEE_SAVED (RBM_F24|RBM_F25|RBM_F26|RBM_F27|RBM_F28|RBM_F29|RBM_F30|RBM_F31) +#define RBM_FLT_CALLEE_TRASH (RBM_F0|RBM_F1|RBM_F2|RBM_F3|RBM_F4|RBM_F5|RBM_F6|RBM_F7) + +#define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED) +#define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH) + +#define REG_DEFAULT_HELPER_CALL_TARGET REG_T4 +#define RBM_DEFAULT_HELPER_CALL_TARGET RBM_T4 + +#define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) +#define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH) +#define RBM_ALLDOUBLE RBM_ALLFLOAT + +// REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED +#define REG_VAR_ORDER REG_A0,REG_A1,REG_A2,REG_A3,REG_A4,REG_A5,REG_A6,REG_A7, \ REG_T0,REG_T1,REG_T2,REG_T3,REG_T4,REG_T5,REG_T6,REG_T7,REG_T8, \ REG_S0,REG_S1,REG_S2,REG_S3,REG_S4,REG_S5,REG_S6,REG_S7,REG_S8 - #define REG_VAR_ORDER_FLT REG_F12,REG_F13,REG_F14,REG_F15,REG_F16,REG_F17,REG_F18,REG_F19, \ +#define REG_VAR_ORDER_FLT REG_F12,REG_F13,REG_F14,REG_F15,REG_F16,REG_F17,REG_F18,REG_F19, \ REG_F2,REG_F3,REG_F4,REG_F5,REG_F6,REG_F7,REG_F8,REG_F9,REG_F10, \ REG_F20,REG_F21,REG_F22,REG_F23, \ REG_F24,REG_F25,REG_F26,REG_F27,REG_F28,REG_F29,REG_F30,REG_F31, \ REG_F1,REG_F0 - #define CNT_CALLEE_SAVED (10) //s0-s8,fp. - #define CNT_CALLEE_TRASH (17) - #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) +#define CNT_CALLEE_SAVED (10) //s0-s8,fp. +#define CNT_CALLEE_TRASH (17) +#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) - #define CNT_CALLEE_SAVED_FLOAT (8) - #define CNT_CALLEE_TRASH_FLOAT (24) - #define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) +#define CNT_CALLEE_SAVED_FLOAT (8) +#define CNT_CALLEE_TRASH_FLOAT (24) +#define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) - #define CNT_CALLEE_SAVED_MASK (0) - #define CNT_CALLEE_TRASH_MASK (0) - #define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) +#define CNT_CALLEE_SAVED_MASK (0) +#define CNT_CALLEE_TRASH_MASK (0) +#define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) - #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED * REGSIZE_BYTES) - #define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES) - - #define REG_TMP_0 REG_T0 - - // Temporary registers used for the GS cookie check. - #define RBM_GSCOOKIE_TMP (RBM_T0 | RBM_T1) - - // register to hold shift amount; no special register is required on LOONGARCH64. - #define REG_SHIFT REG_NA - #define RBM_SHIFT RBM_ALLINT - - // This is a general scratch register that does not conflict with the argument registers - #define REG_SCRATCH REG_T0 - - // This is a float scratch register that does not conflict with the argument registers - #define REG_SCRATCH_FLT REG_F11 - - // Where is the exception object on entry to the handler block? - #define REG_EXCEPTION_OBJECT REG_A0 - #define RBM_EXCEPTION_OBJECT RBM_A0 - - #define REG_JUMP_THUNK_PARAM REG_T2 - #define RBM_JUMP_THUNK_PARAM RBM_T2 - - // LOONGARCH64 write barrier ABI (see vm/loongarch64/asmhelpers.S): - // CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): - // On entry: - // t6: the destination address of the store - // t7: the object reference to be stored - // On exit: - // t0: trashed - // t1: trashed - // t3: trashed - // t4: trashed - // t6: incremented by 8 - // t7: trashed - // CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): - // On entry: - // t8: the source address (points to object reference to write) - // t6: the destination address (object reference written here) - // On exit: - // t8: incremented by 8 - // t6: incremented by 8 - // - - #define REG_WRITE_BARRIER_DST REG_T6 - #define RBM_WRITE_BARRIER_DST RBM_T6 - - #define REG_WRITE_BARRIER_SRC REG_T7 - #define RBM_WRITE_BARRIER_SRC RBM_T7 - - #define REG_WRITE_BARRIER_DST_BYREF REG_T6 - #define RBM_WRITE_BARRIER_DST_BYREF RBM_T6 - - #define REG_WRITE_BARRIER_SRC_BYREF REG_T8 - #define RBM_WRITE_BARRIER_SRC_BYREF RBM_T8 - - #define RBM_CALLEE_TRASH_NOGC (RBM_T0|RBM_T1|RBM_T3|RBM_T4|RBM_T7|RBM_DEFAULT_HELPER_CALL_TARGET) - - // Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_WRITE_BARRIER_DST|RBM_CALLEE_TRASH_NOGC) - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC - - // Registers killed by CORINFO_HELP_ASSIGN_BYREF. - #define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. - // Note that a0 and a1 are still valid byref pointers after this helper call, despite their value being changed. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC - - // GenericPInvokeCalliHelper VASigCookie Parameter - #define REG_PINVOKE_COOKIE_PARAM REG_T3 - #define RBM_PINVOKE_COOKIE_PARAM RBM_T3 - - // GenericPInvokeCalliHelper unmanaged target Parameter - #define REG_PINVOKE_TARGET_PARAM REG_T2 - #define RBM_PINVOKE_TARGET_PARAM RBM_T2 - - // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) - #define REG_SECRET_STUB_PARAM REG_T2 - #define RBM_SECRET_STUB_PARAM RBM_T2 - - // R2R indirect call. Use the same registers as VSD - #define REG_R2R_INDIRECT_PARAM REG_T8 - #define RBM_R2R_INDIRECT_PARAM RBM_T8 - - #define REG_INDIRECT_CALL_TARGET_REG REG_T6 - - // The following defines are useful for iterating a regNumber - #define REG_FIRST REG_R0 - #define REG_INT_FIRST REG_R0 - #define REG_INT_LAST REG_S8 - #define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) - #define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) - #define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) - - // The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks - #define REG_PROFILER_ENTER_ARG_FUNC_ID REG_T1 - #define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_T1 - #define REG_PROFILER_ENTER_ARG_CALLER_SP REG_T2 - #define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_T2 - #define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_PROFILER_ENTER_ARG_FUNC_ID - #define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_PROFILER_ENTER_ARG_FUNC_ID - #define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_PROFILER_ENTER_ARG_CALLER_SP - #define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_PROFILER_ENTER_ARG_CALLER_SP - - // The registers trashed by profiler enter/leave/tailcall hook - #define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS|RBM_FP)) - #define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS|RBM_FP)) - #define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH - - // Which register are int and long values returned in ? - #define REG_INTRET REG_A0 - #define RBM_INTRET RBM_A0 - #define REG_LNGRET REG_A0 - #define RBM_LNGRET RBM_A0 - // second return register for 16-byte structs - #define REG_INTRET_1 REG_A1 - #define RBM_INTRET_1 RBM_A1 - - #define REG_FLOATRET REG_F0 - #define RBM_FLOATRET RBM_F0 - #define RBM_DOUBLERET RBM_F0 - #define REG_FLOATRET_1 REG_F1 - #define RBM_FLOATRET_1 RBM_F1 - #define RBM_DOUBLERET_1 RBM_F1 - - // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper - #define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH - - // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. - #define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH - - #define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_A0 | RBM_A1 | RBM_A2 | RBM_A3 | RBM_A4 | RBM_A5 | RBM_A6 | RBM_A7 | RBM_T3)) - #define REG_VALIDATE_INDIRECT_CALL_ADDR REG_T3 - #define REG_DISPATCH_INDIRECT_CALL_ADDR REG_T0 - - #define REG_ASYNC_CONTINUATION_RET REG_A2 - #define RBM_ASYNC_CONTINUATION_RET RBM_A2 - - #define REG_FPBASE REG_FP - #define RBM_FPBASE RBM_FP - #define STR_FPBASE "fp" - #define REG_SPBASE REG_SP - #define RBM_SPBASE RBM_SP - #define STR_SPBASE "sp" - - #define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address - - #define MAX_REG_ARG 8 - #define MAX_FLOAT_REG_ARG 8 - - #define REG_ARG_FIRST REG_A0 - #define REG_ARG_LAST REG_A7 - #define REG_ARG_FP_FIRST REG_F0 - #define REG_ARG_FP_LAST REG_F7 - #define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots - - #define REG_ARG_0 REG_A0 - #define REG_ARG_1 REG_A1 - #define REG_ARG_2 REG_A2 - #define REG_ARG_3 REG_A3 - #define REG_ARG_4 REG_A4 - #define REG_ARG_5 REG_A5 - #define REG_ARG_6 REG_A6 - #define REG_ARG_7 REG_A7 +#define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED * REGSIZE_BYTES) +#define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES) + +#define REG_TMP_0 REG_T0 + +// Temporary registers used for the GS cookie check. +#define RBM_GSCOOKIE_TMP (RBM_T0 | RBM_T1) + +// register to hold shift amount; no special register is required on LOONGARCH64. +#define REG_SHIFT REG_NA +#define RBM_SHIFT RBM_ALLINT + +// This is a general scratch register that does not conflict with the argument registers +#define REG_SCRATCH REG_T0 + +// This is a float scratch register that does not conflict with the argument registers +#define REG_SCRATCH_FLT REG_F11 + +// Where is the exception object on entry to the handler block? +#define REG_EXCEPTION_OBJECT REG_A0 +#define RBM_EXCEPTION_OBJECT RBM_A0 + +#define REG_JUMP_THUNK_PARAM REG_T2 +#define RBM_JUMP_THUNK_PARAM RBM_T2 + +// LOONGARCH64 write barrier ABI (see vm/loongarch64/asmhelpers.S): +// CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): +// On entry: +// t6: the destination address of the store +// t7: the object reference to be stored +// On exit: +// t0: trashed +// t1: trashed +// t3: trashed +// t4: trashed +// t6: incremented by 8 +// t7: trashed +// CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): +// On entry: +// t8: the source address (points to object reference to write) +// t6: the destination address (object reference written here) +// On exit: +// t8: incremented by 8 +// t6: incremented by 8 +// + +#define REG_WRITE_BARRIER_DST REG_T6 +#define RBM_WRITE_BARRIER_DST RBM_T6 + +#define REG_WRITE_BARRIER_SRC REG_T7 +#define RBM_WRITE_BARRIER_SRC RBM_T7 + +#define REG_WRITE_BARRIER_DST_BYREF REG_T6 +#define RBM_WRITE_BARRIER_DST_BYREF RBM_T6 + +#define REG_WRITE_BARRIER_SRC_BYREF REG_T8 +#define RBM_WRITE_BARRIER_SRC_BYREF RBM_T8 + +#define RBM_CALLEE_TRASH_NOGC (RBM_T0|RBM_T1|RBM_T3|RBM_T4|RBM_T7|RBM_DEFAULT_HELPER_CALL_TARGET) + +// Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_WRITE_BARRIER_DST|RBM_CALLEE_TRASH_NOGC) + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC + +// Registers killed by CORINFO_HELP_ASSIGN_BYREF. +#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. +// Note that a0 and a1 are still valid byref pointers after this helper call, despite their value being changed. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC + +// GenericPInvokeCalliHelper VASigCookie Parameter +#define REG_PINVOKE_COOKIE_PARAM REG_T3 +#define RBM_PINVOKE_COOKIE_PARAM RBM_T3 + +// GenericPInvokeCalliHelper unmanaged target Parameter +#define REG_PINVOKE_TARGET_PARAM REG_T2 +#define RBM_PINVOKE_TARGET_PARAM RBM_T2 + +// IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) +#define REG_SECRET_STUB_PARAM REG_T2 +#define RBM_SECRET_STUB_PARAM RBM_T2 + +// R2R indirect call. Use the same registers as VSD +#define REG_R2R_INDIRECT_PARAM REG_T8 +#define RBM_R2R_INDIRECT_PARAM RBM_T8 + +#define REG_INDIRECT_CALL_TARGET_REG REG_T6 + +// The following defines are useful for iterating a regNumber +#define REG_FIRST REG_R0 +#define REG_INT_FIRST REG_R0 +#define REG_INT_LAST REG_S8 +#define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) +#define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) +#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) + +// The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks +#define REG_PROFILER_ENTER_ARG_FUNC_ID REG_T1 +#define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_T1 +#define REG_PROFILER_ENTER_ARG_CALLER_SP REG_T2 +#define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_T2 +#define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_PROFILER_ENTER_ARG_FUNC_ID +#define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_PROFILER_ENTER_ARG_FUNC_ID +#define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_PROFILER_ENTER_ARG_CALLER_SP +#define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_PROFILER_ENTER_ARG_CALLER_SP + +// The registers trashed by profiler enter/leave/tailcall hook +#define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS|RBM_FP)) +#define RBM_PROFILER_LEAVE_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS|RBM_FP)) +#define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH + +// Which register are int and long values returned in ? +#define REG_INTRET REG_A0 +#define RBM_INTRET RBM_A0 +#define REG_LNGRET REG_A0 +#define RBM_LNGRET RBM_A0 +// second return register for 16-byte structs +#define REG_INTRET_1 REG_A1 +#define RBM_INTRET_1 RBM_A1 + +#define REG_FLOATRET REG_F0 +#define RBM_FLOATRET RBM_F0 +#define RBM_DOUBLERET RBM_F0 +#define REG_FLOATRET_1 REG_F1 +#define RBM_FLOATRET_1 RBM_F1 +#define RBM_DOUBLERET_1 RBM_F1 + +// The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper +#define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH + +// The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. +#define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH + +#define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_A0 | RBM_A1 | RBM_A2 | RBM_A3 | RBM_A4 | RBM_A5 | RBM_A6 | RBM_A7 | RBM_T3)) +#define REG_VALIDATE_INDIRECT_CALL_ADDR REG_T3 +#define REG_DISPATCH_INDIRECT_CALL_ADDR REG_T0 + +#define REG_ASYNC_CONTINUATION_RET REG_A2 +#define RBM_ASYNC_CONTINUATION_RET RBM_A2 + +#define REG_FPBASE REG_FP +#define RBM_FPBASE RBM_FP +#define STR_FPBASE "fp" +#define REG_SPBASE REG_SP +#define RBM_SPBASE RBM_SP +#define STR_SPBASE "sp" + +#define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address + +#define MAX_REG_ARG 8 +#define MAX_FLOAT_REG_ARG 8 + +#define REG_ARG_FIRST REG_A0 +#define REG_ARG_LAST REG_A7 +#define REG_ARG_FP_FIRST REG_F0 +#define REG_ARG_FP_LAST REG_F7 +#define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots + +#define REG_ARG_0 REG_A0 +#define REG_ARG_1 REG_A1 +#define REG_ARG_2 REG_A2 +#define REG_ARG_3 REG_A3 +#define REG_ARG_4 REG_A4 +#define REG_ARG_5 REG_A5 +#define REG_ARG_6 REG_A6 +#define REG_ARG_7 REG_A7 extern const regNumber intArgRegs [MAX_REG_ARG]; extern const regMaskTP intArgMasks[MAX_REG_ARG]; - #define RBM_ARG_0 RBM_A0 - #define RBM_ARG_1 RBM_A1 - #define RBM_ARG_2 RBM_A2 - #define RBM_ARG_3 RBM_A3 - #define RBM_ARG_4 RBM_A4 - #define RBM_ARG_5 RBM_A5 - #define RBM_ARG_6 RBM_A6 - #define RBM_ARG_7 RBM_A7 - - #define REG_FLTARG_0 REG_F0 - #define REG_FLTARG_1 REG_F1 - #define REG_FLTARG_2 REG_F2 - #define REG_FLTARG_3 REG_F3 - #define REG_FLTARG_4 REG_F4 - #define REG_FLTARG_5 REG_F5 - #define REG_FLTARG_6 REG_F6 - #define REG_FLTARG_7 REG_F7 - - #define RBM_FLTARG_0 RBM_F0 - #define RBM_FLTARG_1 RBM_F1 - #define RBM_FLTARG_2 RBM_F2 - #define RBM_FLTARG_3 RBM_F3 - #define RBM_FLTARG_4 RBM_F4 - #define RBM_FLTARG_5 RBM_F5 - #define RBM_FLTARG_6 RBM_F6 - #define RBM_FLTARG_7 RBM_F7 - - #define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5|RBM_ARG_6|RBM_ARG_7) - #define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7) +#define RBM_ARG_0 RBM_A0 +#define RBM_ARG_1 RBM_A1 +#define RBM_ARG_2 RBM_A2 +#define RBM_ARG_3 RBM_A3 +#define RBM_ARG_4 RBM_A4 +#define RBM_ARG_5 RBM_A5 +#define RBM_ARG_6 RBM_A6 +#define RBM_ARG_7 RBM_A7 + +#define REG_FLTARG_0 REG_F0 +#define REG_FLTARG_1 REG_F1 +#define REG_FLTARG_2 REG_F2 +#define REG_FLTARG_3 REG_F3 +#define REG_FLTARG_4 REG_F4 +#define REG_FLTARG_5 REG_F5 +#define REG_FLTARG_6 REG_F6 +#define REG_FLTARG_7 REG_F7 + +#define RBM_FLTARG_0 RBM_F0 +#define RBM_FLTARG_1 RBM_F1 +#define RBM_FLTARG_2 RBM_F2 +#define RBM_FLTARG_3 RBM_F3 +#define RBM_FLTARG_4 RBM_F4 +#define RBM_FLTARG_5 RBM_F5 +#define RBM_FLTARG_6 RBM_F6 +#define RBM_FLTARG_7 RBM_F7 + +#define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1|RBM_ARG_2|RBM_ARG_3|RBM_ARG_4|RBM_ARG_5|RBM_ARG_6|RBM_ARG_7) +#define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3|RBM_FLTARG_4|RBM_FLTARG_5|RBM_FLTARG_6|RBM_FLTARG_7) extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG]; extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG]; - #define B_DIST_SMALL_MAX_NEG (-131072) - #define B_DIST_SMALL_MAX_POS (+131071) +#define B_DIST_SMALL_MAX_NEG (-131072) +#define B_DIST_SMALL_MAX_POS (+131071) - #define OFFSET_DIST_SMALL_MAX_NEG (-2048) - #define OFFSET_DIST_SMALL_MAX_POS (+2047) +#define OFFSET_DIST_SMALL_MAX_NEG (-2048) +#define OFFSET_DIST_SMALL_MAX_POS (+2047) - #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 +#define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 // clang-format on diff --git a/src/coreclr/jit/targetriscv64.h b/src/coreclr/jit/targetriscv64.h index 2390af929fe498..3e43bc65f1074d 100644 --- a/src/coreclr/jit/targetriscv64.h +++ b/src/coreclr/jit/targetriscv64.h @@ -7,280 +7,280 @@ #endif // clang-format off - #define CORINFO_ARCH_TARGET CORINFO_ARCH_RISCV64 +#define CORINFO_ARCH_TARGET CORINFO_ARCH_RISCV64 - #define CPU_LOAD_STORE_ARCH 1 - #define CPU_HAS_FP_SUPPORT 1 - #define CPU_HAS_BYTE_REGS 0 +#define CPU_LOAD_STORE_ARCH 1 +#define CPU_HAS_FP_SUPPORT 1 +#define CPU_HAS_BYTE_REGS 0 #ifdef FEATURE_SIMD #pragma error("SIMD Unimplemented yet RISCV64") #endif // FEATURE_SIMD - #define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog - #define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers - #define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers - #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp - #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. - #define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies - #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register - #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register - #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register - #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (8-byte vector). - #define MAX_PASS_MULTIREG_BYTES 16 // Maximum size of a struct that could be passed in more than one register - #define MAX_RET_MULTIREG_BYTES 16 // Maximum size of a struct that could be returned in more than one register (Max is an HFA or 2 doubles) - #define MAX_ARG_REG_COUNT 2 // Maximum registers used to pass a single argument in multiple registers. - #define MAX_RET_REG_COUNT 2 // Maximum registers used to return a value. - #define MAX_MULTIREG_COUNT 2 // Maximum number of registers defined by a single instruction (including calls). - // This is also the maximum number of registers for a MultiReg node. - - #define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers - #define USER_ARGS_COME_LAST 1 - #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target - #define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods - - #define CSE_CONSTS 1 // Enable if we want to CSE constants - #define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really - // need to track stack depth, but this is currently necessary to get GC information reported at call sites. - #define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that - - #define REG_FP_FIRST REG_FT0 - #define REG_FP_LAST REG_FT11 - #define FIRST_FP_ARGREG REG_FA0 - #define LAST_FP_ARGREG REG_FA7 - - #define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set - #define REGNUM_BITS 6 // number of bits in a REG_* - #define REGSIZE_BYTES 8 // number of bytes in one general purpose register - #define FP_REGSIZE_BYTES 8 // number of bytes in one FP/SIMD register - #define FPSAVE_REGSIZE_BYTES 8 // number of bytes in one FP/SIMD register that are saved/restored, for callee-saved registers - - #define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. - - #define CODE_ALIGN 2 // code alignment requirement - #define STACK_ALIGN 16 // stack alignment requirement - - #define FIRST_INT_CALLEE_SAVED REG_S1 - #define LAST_INT_CALLEE_SAVED REG_S11 - #define RBM_INT_CALLEE_SAVED (RBM_S1|RBM_S2|RBM_S3|RBM_S4|RBM_S5|RBM_S6|RBM_S7|RBM_S8|RBM_S9|RBM_S10|RBM_S11) - #define RBM_INT_CALLEE_TRASH (RBM_A0|RBM_A1|RBM_A2|RBM_A3|RBM_A4|RBM_A5|RBM_A6|RBM_A7|RBM_T0|RBM_T1|RBM_T2|RBM_T3|RBM_T4|RBM_T5|RBM_T6) - #define FIRST_FLT_CALLEE_SAVED REG_FS0 - #define LAST_FLT_CALLEE_SAVED REG_FS11 - #define RBM_FLT_CALLEE_SAVED (RBM_FS0|RBM_FS1|RBM_FS2|RBM_FS3|RBM_FS4|RBM_FS5|RBM_FS6|RBM_FS7|RBM_FS8|RBM_FS9|RBM_FS10|RBM_FS11) - #define RBM_FLT_CALLEE_TRASH (RBM_FA0|RBM_FA1|RBM_FA2|RBM_FA3|RBM_FA4|RBM_FA5|RBM_FA6|RBM_FA7|RBM_FT0|RBM_FT1|RBM_FT2|RBM_FT3|RBM_FT4|RBM_FT5|RBM_FT6|RBM_FT7|RBM_FT8|RBM_FT9|RBM_FT10|RBM_FT11) - - #define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED) - #define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH) - - #define REG_DEFAULT_HELPER_CALL_TARGET REG_T2 - #define RBM_DEFAULT_HELPER_CALL_TARGET RBM_T2 - - #define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) - #define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH) - #define RBM_ALLDOUBLE RBM_ALLFLOAT - - // REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED - #define REG_VAR_ORDER REG_A0,REG_A1,REG_A2,REG_A3,REG_A4,REG_A5,REG_A6,REG_A7, \ +#define FEATURE_FIXED_OUT_ARGS 1 // Preallocate the outgoing arg area in the prolog +#define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers +#define FEATURE_MULTIREG_STRUCT_PROMOTE 1 // True when we want to promote fields of a multireg struct into registers +#define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp +#define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. +#define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies +#define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register +#define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register +#define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register +#define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (8-byte vector). +#define MAX_PASS_MULTIREG_BYTES 16 // Maximum size of a struct that could be passed in more than one register +#define MAX_RET_MULTIREG_BYTES 16 // Maximum size of a struct that could be returned in more than one register (Max is an HFA or 2 doubles) +#define MAX_ARG_REG_COUNT 2 // Maximum registers used to pass a single argument in multiple registers. +#define MAX_RET_REG_COUNT 2 // Maximum registers used to return a value. +#define MAX_MULTIREG_COUNT 2 // Maximum number of registers defined by a single instruction (including calls). + // This is also the maximum number of registers for a MultiReg node. + +#define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the RBM_CALLEE_TRASH registers +#define USER_ARGS_COME_LAST 1 +#define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#define ETW_EBP_FRAMED 1 // if 1 we cannot use REG_FP as a scratch register and must setup the frame pointer for most methods + +#define CSE_CONSTS 1 // Enable if we want to CSE constants +#define EMIT_TRACK_STACK_DEPTH 1 // This is something of a workaround. For both ARM and AMD64, the frame size is fixed, so we don't really + // need to track stack depth, but this is currently necessary to get GC information reported at call sites. +#define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that + +#define REG_FP_FIRST REG_FT0 +#define REG_FP_LAST REG_FT11 +#define FIRST_FP_ARGREG REG_FA0 +#define LAST_FP_ARGREG REG_FA7 + +#define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set +#define REGNUM_BITS 6 // number of bits in a REG_* +#define REGSIZE_BYTES 8 // number of bytes in one general purpose register +#define FP_REGSIZE_BYTES 8 // number of bytes in one FP/SIMD register +#define FPSAVE_REGSIZE_BYTES 8 // number of bytes in one FP/SIMD register that are saved/restored, for callee-saved registers + +#define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. + +#define CODE_ALIGN 2 // code alignment requirement +#define STACK_ALIGN 16 // stack alignment requirement + +#define FIRST_INT_CALLEE_SAVED REG_S1 +#define LAST_INT_CALLEE_SAVED REG_S11 +#define RBM_INT_CALLEE_SAVED (RBM_S1|RBM_S2|RBM_S3|RBM_S4|RBM_S5|RBM_S6|RBM_S7|RBM_S8|RBM_S9|RBM_S10|RBM_S11) +#define RBM_INT_CALLEE_TRASH (RBM_A0|RBM_A1|RBM_A2|RBM_A3|RBM_A4|RBM_A5|RBM_A6|RBM_A7|RBM_T0|RBM_T1|RBM_T2|RBM_T3|RBM_T4|RBM_T5|RBM_T6) +#define FIRST_FLT_CALLEE_SAVED REG_FS0 +#define LAST_FLT_CALLEE_SAVED REG_FS11 +#define RBM_FLT_CALLEE_SAVED (RBM_FS0|RBM_FS1|RBM_FS2|RBM_FS3|RBM_FS4|RBM_FS5|RBM_FS6|RBM_FS7|RBM_FS8|RBM_FS9|RBM_FS10|RBM_FS11) +#define RBM_FLT_CALLEE_TRASH (RBM_FA0|RBM_FA1|RBM_FA2|RBM_FA3|RBM_FA4|RBM_FA5|RBM_FA6|RBM_FA7|RBM_FT0|RBM_FT1|RBM_FT2|RBM_FT3|RBM_FT4|RBM_FT5|RBM_FT6|RBM_FT7|RBM_FT8|RBM_FT9|RBM_FT10|RBM_FT11) + +#define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED) +#define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH) + +#define REG_DEFAULT_HELPER_CALL_TARGET REG_T2 +#define RBM_DEFAULT_HELPER_CALL_TARGET RBM_T2 + +#define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) +#define RBM_ALLFLOAT (RBM_FLT_CALLEE_SAVED | RBM_FLT_CALLEE_TRASH) +#define RBM_ALLDOUBLE RBM_ALLFLOAT + +// REG_VAR_ORDER is: (CALLEE_TRASH & ~CALLEE_TRASH_NOGC), CALLEE_TRASH_NOGC, CALLEE_SAVED +#define REG_VAR_ORDER REG_A0,REG_A1,REG_A2,REG_A3,REG_A4,REG_A5,REG_A6,REG_A7, \ REG_T0,REG_T1,REG_T2,REG_T3,REG_T4,REG_T5,REG_T6, \ REG_S1,REG_S2,REG_S3,REG_S4,REG_S5,REG_S6,REG_S7,REG_S8,REG_S9,REG_S10,REG_S11 - #define REG_VAR_ORDER_FLT REG_FT4, REG_FT5, REG_FT6, REG_FT7, REG_FT8, REG_FT9, REG_FT10, REG_FT11, \ +#define REG_VAR_ORDER_FLT REG_FT4, REG_FT5, REG_FT6, REG_FT7, REG_FT8, REG_FT9, REG_FT10, REG_FT11, \ REG_FA2, REG_FA3, REG_FA4, REG_FA5, REG_FA6, REG_FA7, \ REG_FT0, REG_FT1, REG_FT2, REG_FT3, \ REG_FS6, REG_FS7, REG_FS8, REG_FS9, REG_FS10, REG_FS11, REG_FS2, REG_FS3, REG_FS4, REG_FS5, REG_FS0, REG_FS1, \ REG_FA1, REG_FA0 - #define CNT_CALLEE_SAVED (11) - #define CNT_CALLEE_TRASH (15) - #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) +#define CNT_CALLEE_SAVED (11) +#define CNT_CALLEE_TRASH (15) +#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) - #define CNT_CALLEE_SAVED_FLOAT (12) - #define CNT_CALLEE_TRASH_FLOAT (20) - #define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) +#define CNT_CALLEE_SAVED_FLOAT (12) +#define CNT_CALLEE_TRASH_FLOAT (20) +#define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) - #define CNT_CALLEE_SAVED_MASK (0) - #define CNT_CALLEE_TRASH_MASK (0) - #define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) +#define CNT_CALLEE_SAVED_MASK (0) +#define CNT_CALLEE_TRASH_MASK (0) +#define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) - #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED * REGSIZE_BYTES) - #define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES) +#define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED * REGSIZE_BYTES) +#define CALLEE_SAVED_FLOAT_MAXSZ (CNT_CALLEE_SAVED_FLOAT * FPSAVE_REGSIZE_BYTES) - #define REG_TMP_0 REG_T0 +#define REG_TMP_0 REG_T0 - // Temporary registers used for the GS cookie check. - #define RBM_GSCOOKIE_TMP (RBM_T0 | RBM_T1) +// Temporary registers used for the GS cookie check. +#define RBM_GSCOOKIE_TMP (RBM_T0 | RBM_T1) - // register to hold shift amount; no special register is required on ARM64. - #define REG_SHIFT REG_NA - #define RBM_SHIFT RBM_ALLINT +// register to hold shift amount; no special register is required on ARM64. +#define REG_SHIFT REG_NA +#define RBM_SHIFT RBM_ALLINT - // This is a general scratch register that does not conflict with the argument registers - #define REG_SCRATCH REG_T0 +// This is a general scratch register that does not conflict with the argument registers +#define REG_SCRATCH REG_T0 - // This is a general register that can be optionally reserved for other purposes during codegen - #define REG_OPT_RSVD REG_T6 - #define RBM_OPT_RSVD RBM_T6 +// This is a general register that can be optionally reserved for other purposes during codegen +#define REG_OPT_RSVD REG_T6 +#define RBM_OPT_RSVD RBM_T6 - // Where is the exception object on entry to the handler block? - #define REG_EXCEPTION_OBJECT REG_A0 - #define RBM_EXCEPTION_OBJECT RBM_A0 +// Where is the exception object on entry to the handler block? +#define REG_EXCEPTION_OBJECT REG_A0 +#define RBM_EXCEPTION_OBJECT RBM_A0 - #define REG_JUMP_THUNK_PARAM REG_T2 - #define RBM_JUMP_THUNK_PARAM RBM_T2 +#define REG_JUMP_THUNK_PARAM REG_T2 +#define RBM_JUMP_THUNK_PARAM RBM_T2 - #define REG_WRITE_BARRIER_DST REG_T3 - #define RBM_WRITE_BARRIER_DST RBM_T3 +#define REG_WRITE_BARRIER_DST REG_T3 +#define RBM_WRITE_BARRIER_DST RBM_T3 - #define REG_WRITE_BARRIER_SRC REG_T4 - #define RBM_WRITE_BARRIER_SRC RBM_T4 +#define REG_WRITE_BARRIER_SRC REG_T4 +#define RBM_WRITE_BARRIER_SRC RBM_T4 - #define REG_WRITE_BARRIER_DST_BYREF REG_T3 - #define RBM_WRITE_BARRIER_DST_BYREF RBM_T3 +#define REG_WRITE_BARRIER_DST_BYREF REG_T3 +#define RBM_WRITE_BARRIER_DST_BYREF RBM_T3 - #define REG_WRITE_BARRIER_SRC_BYREF REG_T5 - #define RBM_WRITE_BARRIER_SRC_BYREF RBM_T5 +#define REG_WRITE_BARRIER_SRC_BYREF REG_T5 +#define RBM_WRITE_BARRIER_SRC_BYREF RBM_T5 - #define RBM_CALLEE_TRASH_NOGC (RBM_T0|RBM_T1|RBM_T2|RBM_T4|RBM_T6|RBM_DEFAULT_HELPER_CALL_TARGET) +#define RBM_CALLEE_TRASH_NOGC (RBM_T0|RBM_T1|RBM_T2|RBM_T4|RBM_T6|RBM_DEFAULT_HELPER_CALL_TARGET) - // Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_WRITE_BARRIER_DST|RBM_CALLEE_TRASH_NOGC) +// Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_WRITE_BARRIER_DST|RBM_CALLEE_TRASH_NOGC) - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_CALLEE_TRASH_NOGC - // Registers killed by CORINFO_HELP_ASSIGN_BYREF. - #define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. - // Note that t3 and t5 are still valid byref pointers after this helper call, despite their value being changed. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC - - // GenericPInvokeCalliHelper VASigCookie Parameter - #define REG_PINVOKE_COOKIE_PARAM REG_T3 - #define RBM_PINVOKE_COOKIE_PARAM RBM_T3 - - // GenericPInvokeCalliHelper unmanaged target Parameter - #define REG_PINVOKE_TARGET_PARAM REG_T2 - #define RBM_PINVOKE_TARGET_PARAM RBM_T2 - - // IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) - #define REG_SECRET_STUB_PARAM REG_T2 - #define RBM_SECRET_STUB_PARAM RBM_T2 - - // R2R indirect call. Use the same registers as VSD - #define REG_R2R_INDIRECT_PARAM REG_T5 - #define RBM_R2R_INDIRECT_PARAM RBM_T5 - - // JMP Indirect call register - #define REG_INDIRECT_CALL_TARGET_REG REG_T5 - - // The following defines are useful for iterating a regNumber - #define REG_FIRST REG_R0 - #define REG_INT_FIRST REG_R0 - #define REG_INT_LAST REG_T6 - #define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) - #define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) - #define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) - - // The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks - #define REG_PROFILER_ENTER_ARG_FUNC_ID REG_T0 - #define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_T0 - #define REG_PROFILER_ENTER_ARG_CALLER_SP REG_T1 - #define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_T1 - #define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_PROFILER_ENTER_ARG_FUNC_ID - #define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_PROFILER_ENTER_ARG_FUNC_ID - #define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_PROFILER_ENTER_ARG_CALLER_SP - #define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_PROFILER_ENTER_ARG_CALLER_SP - - // The registers trashed by profiler enter/leave/tailcall hook - #define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS|RBM_FP)) - #define RBM_PROFILER_LEAVE_TRASH RBM_PROFILER_ENTER_TRASH - #define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH - - // Which register are int and long values returned in ? - #define REG_INTRET REG_A0 - #define RBM_INTRET RBM_A0 - #define REG_LNGRET REG_A0 - #define RBM_LNGRET RBM_A0 - // second return register for 16-byte structs - #define REG_INTRET_1 REG_A1 - #define RBM_INTRET_1 RBM_A1 - - #define REG_FLOATRET REG_FA0 - #define RBM_FLOATRET RBM_FA0 - #define RBM_DOUBLERET RBM_FA0 - #define REG_FLOATRET_1 REG_FA1 - #define RBM_FLOATRET_1 RBM_FA1 - #define RBM_DOUBLERET_1 RBM_FA1 - - // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper - #define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH - - // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. - #define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH - - #define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_A0 | RBM_A1 | RBM_A2 | RBM_A3 | RBM_A4 | RBM_A5 | RBM_A6 | RBM_A7 | RBM_T3)) - #define REG_VALIDATE_INDIRECT_CALL_ADDR REG_T3 - #define REG_DISPATCH_INDIRECT_CALL_ADDR REG_T0 - - #define REG_ASYNC_CONTINUATION_RET REG_A2 - #define RBM_ASYNC_CONTINUATION_RET RBM_A2 - - #define REG_FPBASE REG_FP - #define RBM_FPBASE RBM_FP - #define STR_FPBASE "fp" - #define REG_SPBASE REG_SP - #define RBM_SPBASE RBM_SP // reuse the RBM for REG_ZR - #define STR_SPBASE "sp" - - #define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address - - #define MAX_REG_ARG 8 - #define MAX_FLOAT_REG_ARG 8 - - #define REG_ARG_FIRST REG_A0 - #define REG_ARG_LAST REG_A7 - #define REG_ARG_FP_FIRST REG_FA0 - #define REG_ARG_FP_LAST REG_FA7 - #define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots - - #define REG_ARG_0 REG_A0 - #define REG_ARG_1 REG_A1 - #define REG_ARG_2 REG_A2 - #define REG_ARG_3 REG_A3 - #define REG_ARG_4 REG_A4 - #define REG_ARG_5 REG_A5 - #define REG_ARG_6 REG_A6 - #define REG_ARG_7 REG_A7 +// Registers killed by CORINFO_HELP_ASSIGN_BYREF. +#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_WRITE_BARRIER_DST_BYREF | RBM_WRITE_BARRIER_SRC_BYREF | RBM_CALLEE_TRASH_NOGC) + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. +// Note that t3 and t5 are still valid byref pointers after this helper call, despite their value being changed. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_CALLEE_TRASH_NOGC + +// GenericPInvokeCalliHelper VASigCookie Parameter +#define REG_PINVOKE_COOKIE_PARAM REG_T3 +#define RBM_PINVOKE_COOKIE_PARAM RBM_T3 + +// GenericPInvokeCalliHelper unmanaged target Parameter +#define REG_PINVOKE_TARGET_PARAM REG_T2 +#define RBM_PINVOKE_TARGET_PARAM RBM_T2 + +// IL stub's secret MethodDesc parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) +#define REG_SECRET_STUB_PARAM REG_T2 +#define RBM_SECRET_STUB_PARAM RBM_T2 + +// R2R indirect call. Use the same registers as VSD +#define REG_R2R_INDIRECT_PARAM REG_T5 +#define RBM_R2R_INDIRECT_PARAM RBM_T5 + +// JMP Indirect call register +#define REG_INDIRECT_CALL_TARGET_REG REG_T5 + +// The following defines are useful for iterating a regNumber +#define REG_FIRST REG_R0 +#define REG_INT_FIRST REG_R0 +#define REG_INT_LAST REG_T6 +#define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) +#define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) +#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) + +// The following registers are used in emitting Enter/Leave/Tailcall profiler callbacks +#define REG_PROFILER_ENTER_ARG_FUNC_ID REG_T0 +#define RBM_PROFILER_ENTER_ARG_FUNC_ID RBM_T0 +#define REG_PROFILER_ENTER_ARG_CALLER_SP REG_T1 +#define RBM_PROFILER_ENTER_ARG_CALLER_SP RBM_T1 +#define REG_PROFILER_LEAVE_ARG_FUNC_ID REG_PROFILER_ENTER_ARG_FUNC_ID +#define RBM_PROFILER_LEAVE_ARG_FUNC_ID RBM_PROFILER_ENTER_ARG_FUNC_ID +#define REG_PROFILER_LEAVE_ARG_CALLER_SP REG_PROFILER_ENTER_ARG_CALLER_SP +#define RBM_PROFILER_LEAVE_ARG_CALLER_SP RBM_PROFILER_ENTER_ARG_CALLER_SP + +// The registers trashed by profiler enter/leave/tailcall hook +#define RBM_PROFILER_ENTER_TRASH (RBM_CALLEE_TRASH & ~(RBM_ARG_REGS|RBM_FLTARG_REGS|RBM_FP)) +#define RBM_PROFILER_LEAVE_TRASH RBM_PROFILER_ENTER_TRASH +#define RBM_PROFILER_TAILCALL_TRASH RBM_PROFILER_LEAVE_TRASH + +// Which register are int and long values returned in ? +#define REG_INTRET REG_A0 +#define RBM_INTRET RBM_A0 +#define REG_LNGRET REG_A0 +#define RBM_LNGRET RBM_A0 +// second return register for 16-byte structs +#define REG_INTRET_1 REG_A1 +#define RBM_INTRET_1 RBM_A1 + +#define REG_FLOATRET REG_FA0 +#define RBM_FLOATRET RBM_FA0 +#define RBM_DOUBLERET RBM_FA0 +#define REG_FLOATRET_1 REG_FA1 +#define RBM_FLOATRET_1 RBM_FA1 +#define RBM_DOUBLERET_1 RBM_FA1 + +// The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper +#define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH + +// The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. +#define RBM_INIT_PINVOKE_FRAME_TRASH RBM_CALLEE_TRASH + +#define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~(RBM_A0 | RBM_A1 | RBM_A2 | RBM_A3 | RBM_A4 | RBM_A5 | RBM_A6 | RBM_A7 | RBM_T3)) +#define REG_VALIDATE_INDIRECT_CALL_ADDR REG_T3 +#define REG_DISPATCH_INDIRECT_CALL_ADDR REG_T0 + +#define REG_ASYNC_CONTINUATION_RET REG_A2 +#define RBM_ASYNC_CONTINUATION_RET RBM_A2 + +#define REG_FPBASE REG_FP +#define RBM_FPBASE RBM_FP +#define STR_FPBASE "fp" +#define REG_SPBASE REG_SP +#define RBM_SPBASE RBM_SP // reuse the RBM for REG_ZR +#define STR_SPBASE "sp" + +#define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved FP and return address + +#define MAX_REG_ARG 8 +#define MAX_FLOAT_REG_ARG 8 + +#define REG_ARG_FIRST REG_A0 +#define REG_ARG_LAST REG_A7 +#define REG_ARG_FP_FIRST REG_FA0 +#define REG_ARG_FP_LAST REG_FA7 +#define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots + +#define REG_ARG_0 REG_A0 +#define REG_ARG_1 REG_A1 +#define REG_ARG_2 REG_A2 +#define REG_ARG_3 REG_A3 +#define REG_ARG_4 REG_A4 +#define REG_ARG_5 REG_A5 +#define REG_ARG_6 REG_A6 +#define REG_ARG_7 REG_A7 extern const regNumber intArgRegs [MAX_REG_ARG]; extern const regMaskTP intArgMasks[MAX_REG_ARG]; - #define RBM_ARG_0 RBM_A0 - #define RBM_ARG_1 RBM_A1 - #define RBM_ARG_2 RBM_A2 - #define RBM_ARG_3 RBM_A3 - #define RBM_ARG_4 RBM_A4 - #define RBM_ARG_5 RBM_A5 - #define RBM_ARG_6 RBM_A6 - #define RBM_ARG_7 RBM_A7 +#define RBM_ARG_0 RBM_A0 +#define RBM_ARG_1 RBM_A1 +#define RBM_ARG_2 RBM_A2 +#define RBM_ARG_3 RBM_A3 +#define RBM_ARG_4 RBM_A4 +#define RBM_ARG_5 RBM_A5 +#define RBM_ARG_6 RBM_A6 +#define RBM_ARG_7 RBM_A7 - #define RBM_ARG_REGS (RBM_A0|RBM_A1|RBM_A2|RBM_A3|RBM_A4|RBM_A5|RBM_A6|RBM_A7) - #define RBM_FLTARG_REGS (RBM_FA0|RBM_FA1|RBM_FA2|RBM_FA3|RBM_FA4|RBM_FA5|RBM_FA6|RBM_FA7) +#define RBM_ARG_REGS (RBM_A0|RBM_A1|RBM_A2|RBM_A3|RBM_A4|RBM_A5|RBM_A6|RBM_A7) +#define RBM_FLTARG_REGS (RBM_FA0|RBM_FA1|RBM_FA2|RBM_FA3|RBM_FA4|RBM_FA5|RBM_FA6|RBM_FA7) extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG]; extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG]; - #define J_DIST_SMALL_MAX_NEG (-(1 << 20)) - #define J_DIST_SMALL_MAX_POS (+(1 << 20) - 1) +#define J_DIST_SMALL_MAX_NEG (-(1 << 20)) +#define J_DIST_SMALL_MAX_POS (+(1 << 20) - 1) - #define B_DIST_SMALL_MAX_NEG (-4096) - #define B_DIST_SMALL_MAX_POS (+4095) +#define B_DIST_SMALL_MAX_NEG (-4096) +#define B_DIST_SMALL_MAX_POS (+4095) - // The number of bytes from the end the last probed page that must also be probed, to allow for some - // small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word - // on the stack guard page, and must be touched before any further "SUB SP". - #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 +// The number of bytes from the end the last probed page that must also be probed, to allow for some +// small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word +// on the stack guard page, and must be touched before any further "SUB SP". +#define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 // clang-format on diff --git a/src/coreclr/jit/targetx86.h b/src/coreclr/jit/targetx86.h index 997ab9b3a93e0f..05991d2ad03438 100644 --- a/src/coreclr/jit/targetx86.h +++ b/src/coreclr/jit/targetx86.h @@ -7,347 +7,347 @@ #endif // clang-format off - #define CORINFO_ARCH_TARGET CORINFO_ARCH_X86 +#define CORINFO_ARCH_TARGET CORINFO_ARCH_X86 - #define CPU_LOAD_STORE_ARCH 0 - #define CPU_HAS_BYTE_REGS 1 +#define CPU_LOAD_STORE_ARCH 0 +#define CPU_HAS_BYTE_REGS 1 - #define CPOBJ_NONGC_SLOTS_LIMIT 4 // For CpObj code generation, this is the threshold of the number - // of contiguous non-gc slots that trigger generating rep movsq instead of - // sequences of movsq instructions +#define CPOBJ_NONGC_SLOTS_LIMIT 4 // For CpObj code generation, this is the threshold of the number + // of contiguous non-gc slots that trigger generating rep movsq instead of + // sequences of movsq instructions #ifdef FEATURE_SIMD - #define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned +#define ALIGN_SIMD_TYPES 1 // whether SIMD type locals are to be aligned #endif // FEATURE_SIMD - #define FEATURE_FIXED_OUT_ARGS 0 // X86 uses push instructions to pass args - #define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers - #define FEATURE_MULTIREG_STRUCT_PROMOTE 0 // True when we want to promote fields of a multireg struct into registers - #define FEATURE_FASTTAILCALL 0 // Tail calls made as epilog+jmp - #define FEATURE_TAILCALL_OPT 0 // opportunistic Tail calls (without ".tail" prefix) made as fast tail calls. - // the flags need to be set - #define FEATURE_IMPLICIT_BYREFS 0 // Support for struct parameters passed via pointers to shadow copies - #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register - #define FEATURE_MULTIREG_ARGS 0 // Support for passing a single argument in more than one register - #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register - #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). - #define MAX_PASS_MULTIREG_BYTES 0 // No multireg arguments - #define MAX_RET_MULTIREG_BYTES 8 // Maximum size of a struct that could be returned in more than one register - - #define MAX_ARG_REG_COUNT 1 // Maximum registers used to pass an argument. - #define MAX_RET_REG_COUNT 2 // Maximum registers used to return a value. - - #define MAX_MULTIREG_COUNT 2 // Maximum number of registers defined by a single instruction (including calls). +#define FEATURE_FIXED_OUT_ARGS 0 // X86 uses push instructions to pass args +#define FEATURE_STRUCTPROMOTE 1 // JIT Optimization to promote fields of structs into registers +#define FEATURE_MULTIREG_STRUCT_PROMOTE 0 // True when we want to promote fields of a multireg struct into registers +#define FEATURE_FASTTAILCALL 0 // Tail calls made as epilog+jmp +#define FEATURE_TAILCALL_OPT 0 // opportunistic Tail calls (without ".tail" prefix) made as fast tail calls. + // the flags need to be set +#define FEATURE_IMPLICIT_BYREFS 0 // Support for struct parameters passed via pointers to shadow copies +#define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register +#define FEATURE_MULTIREG_ARGS 0 // Support for passing a single argument in more than one register +#define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register +#define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). +#define MAX_PASS_MULTIREG_BYTES 0 // No multireg arguments +#define MAX_RET_MULTIREG_BYTES 8 // Maximum size of a struct that could be returned in more than one register + +#define MAX_ARG_REG_COUNT 1 // Maximum registers used to pass an argument. +#define MAX_RET_REG_COUNT 2 // Maximum registers used to return a value. + +#define MAX_MULTIREG_COUNT 2 // Maximum number of registers defined by a single instruction (including calls). // This is also the maximum number of registers for a MultiReg node. #ifdef FEATURE_USE_ASM_GC_WRITE_BARRIERS - #define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the - // RBM_CALLEE_TRASH registers +#define NOGC_WRITE_BARRIERS 1 // We have specialized WriteBarrier JIT Helpers that DO-NOT trash the + // RBM_CALLEE_TRASH registers #else - #define NOGC_WRITE_BARRIERS 0 // Do not modify this -- modify the definition above. (If we're not using - // ASM barriers we definitely don't have NOGC barriers). +#define NOGC_WRITE_BARRIERS 0 // Do not modify this -- modify the definition above. (If we're not using + // ASM barriers we definitely don't have NOGC barriers). #endif - #define USER_ARGS_COME_LAST 0 - #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this - // target - #define ETW_EBP_FRAMED 1 // if 1 we cannot use EBP as a scratch register and must create EBP based - // frames for most methods - - #define CSE_CONSTS 1 // Enable if we want to CSE constants - #define LOWER_DECOMPOSE_LONGS 1 // Decompose TYP_LONG operations into (typically two) TYP_INT ones - #define EMIT_TRACK_STACK_DEPTH 1 - #define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that - - // The following defines are useful for iterating a regNumber - #define REG_FIRST REG_EAX - #define REG_INT_FIRST REG_EAX - #define REG_INT_LAST REG_EDI - #define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) - #define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) - #define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) - - #define REG_FP_FIRST REG_XMM0 - #define REG_FP_LAST REG_XMM7 - - #define REG_MASK_FIRST REG_K0 - #define REG_MASK_LAST REG_K7 - #define CNT_MASK_REGS 8 - - #define FIRST_FP_ARGREG REG_XMM0 - #define LAST_FP_ARGREG REG_XMM3 - #define REG_FLTARG_0 REG_XMM0 - #define REG_FLTARG_1 REG_XMM1 - #define REG_FLTARG_2 REG_XMM2 - #define REG_FLTARG_3 REG_XMM3 - - #define RBM_FLTARG_0 RBM_XMM0 - #define RBM_FLTARG_1 RBM_XMM1 - #define RBM_FLTARG_2 RBM_XMM2 - #define RBM_FLTARG_3 RBM_XMM3 - - #define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3) - - #define RBM_ALLFLOAT (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM3 | RBM_XMM4 | RBM_XMM5 | RBM_XMM6 | RBM_XMM7) - #define RBM_ALLDOUBLE RBM_ALLFLOAT - - #define RBM_ALLMASK_INIT (0) - #define RBM_ALLMASK_EVEX (RBM_K1 | RBM_K2 | RBM_K3 | RBM_K4 | RBM_K5 | RBM_K6 | RBM_K7) - #define RBM_ALLMASK get_RBM_ALLMASK() - - #define CNT_HIGHFLOAT 0 - - // TODO-CQ: Currently we are following the x86 ABI for SSE2 registers. - // This should be reconsidered. - #define RBM_FLT_CALLEE_SAVED RBM_NONE - #define RBM_FLT_CALLEE_TRASH RBM_ALLFLOAT - #define REG_VAR_ORDER_FLT REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7 - #define REG_VAR_ORDER_MSK REG_K1,REG_K2,REG_K3,REG_K4,REG_K5,REG_K6,REG_K7 - - #define REG_FLT_CALLEE_SAVED_FIRST REG_XMM6 - #define REG_FLT_CALLEE_SAVED_LAST REG_XMM7 +#define USER_ARGS_COME_LAST 0 +#define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this + // target +#define ETW_EBP_FRAMED 1 // if 1 we cannot use EBP as a scratch register and must create EBP based + // frames for most methods + +#define CSE_CONSTS 1 // Enable if we want to CSE constants +#define LOWER_DECOMPOSE_LONGS 1 // Decompose TYP_LONG operations into (typically two) TYP_INT ones +#define EMIT_TRACK_STACK_DEPTH 1 +#define EMIT_GENERATE_GCINFO 1 // Track GC ref liveness in codegen and emit and generate GCInfo based on that + +// The following defines are useful for iterating a regNumber +#define REG_FIRST REG_EAX +#define REG_INT_FIRST REG_EAX +#define REG_INT_LAST REG_EDI +#define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) +#define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) +#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) + +#define REG_FP_FIRST REG_XMM0 +#define REG_FP_LAST REG_XMM7 + +#define REG_MASK_FIRST REG_K0 +#define REG_MASK_LAST REG_K7 +#define CNT_MASK_REGS 8 + +#define FIRST_FP_ARGREG REG_XMM0 +#define LAST_FP_ARGREG REG_XMM3 +#define REG_FLTARG_0 REG_XMM0 +#define REG_FLTARG_1 REG_XMM1 +#define REG_FLTARG_2 REG_XMM2 +#define REG_FLTARG_3 REG_XMM3 + +#define RBM_FLTARG_0 RBM_XMM0 +#define RBM_FLTARG_1 RBM_XMM1 +#define RBM_FLTARG_2 RBM_XMM2 +#define RBM_FLTARG_3 RBM_XMM3 + +#define RBM_FLTARG_REGS (RBM_FLTARG_0|RBM_FLTARG_1|RBM_FLTARG_2|RBM_FLTARG_3) + +#define RBM_ALLFLOAT (RBM_XMM0 | RBM_XMM1 | RBM_XMM2 | RBM_XMM3 | RBM_XMM4 | RBM_XMM5 | RBM_XMM6 | RBM_XMM7) +#define RBM_ALLDOUBLE RBM_ALLFLOAT + +#define RBM_ALLMASK_INIT (0) +#define RBM_ALLMASK_EVEX (RBM_K1 | RBM_K2 | RBM_K3 | RBM_K4 | RBM_K5 | RBM_K6 | RBM_K7) +#define RBM_ALLMASK get_RBM_ALLMASK() + +#define CNT_HIGHFLOAT 0 + +// TODO-CQ: Currently we are following the x86 ABI for SSE2 registers. +// This should be reconsidered. +#define RBM_FLT_CALLEE_SAVED RBM_NONE +#define RBM_FLT_CALLEE_TRASH RBM_ALLFLOAT +#define REG_VAR_ORDER_FLT REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7 +#define REG_VAR_ORDER_MSK REG_K1,REG_K2,REG_K3,REG_K4,REG_K5,REG_K6,REG_K7 + +#define REG_FLT_CALLEE_SAVED_FIRST REG_XMM6 +#define REG_FLT_CALLEE_SAVED_LAST REG_XMM7 /* NOTE: Sync with variable name defined in compiler.h */ - #define RBM_MSK_CALLEE_TRASH_INIT (0) - #define RBM_MSK_CALLEE_TRASH_EVEX RBM_ALLMASK_EVEX +#define RBM_MSK_CALLEE_TRASH_INIT (0) +#define RBM_MSK_CALLEE_TRASH_EVEX RBM_ALLMASK_EVEX - #define RBM_MSK_CALLEE_SAVED (0) - #define RBM_MSK_CALLEE_TRASH get_RBM_MSK_CALLEE_TRASH() +#define RBM_MSK_CALLEE_SAVED (0) +#define RBM_MSK_CALLEE_TRASH get_RBM_MSK_CALLEE_TRASH() - #define XMM_REGSIZE_BYTES 16 // XMM register size in bytes - #define YMM_REGSIZE_BYTES 32 // YMM register size in bytes - #define ZMM_REGSIZE_BYTES 64 // ZMM register size in bytes +#define XMM_REGSIZE_BYTES 16 // XMM register size in bytes +#define YMM_REGSIZE_BYTES 32 // YMM register size in bytes +#define ZMM_REGSIZE_BYTES 64 // ZMM register size in bytes - #define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set - #define REGNUM_BITS 6 // number of bits in a REG_* - #define REGSIZE_BYTES 4 // number of bytes in one register - #define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. +#define HAS_FIXED_REGISTER_SET 1 // Has a fixed register set +#define REGNUM_BITS 6 // number of bits in a REG_* +#define REGSIZE_BYTES 4 // number of bytes in one register +#define MIN_ARG_AREA_FOR_CALL 0 // Minimum required outgoing argument space for a call. - #define CODE_ALIGN 1 // code alignment requirement +#define CODE_ALIGN 1 // code alignment requirement #if !defined(UNIX_X86_ABI) - #define STACK_ALIGN 4 // stack alignment requirement - #define STACK_ALIGN_SHIFT 2 // Shift-right amount to convert size in bytes to size in STACK_ALIGN units == log2(STACK_ALIGN) +#define STACK_ALIGN 4 // stack alignment requirement +#define STACK_ALIGN_SHIFT 2 // Shift-right amount to convert size in bytes to size in STACK_ALIGN units == log2(STACK_ALIGN) #else - #define STACK_ALIGN 16 // stack alignment requirement - #define STACK_ALIGN_SHIFT 4 // Shift-right amount to convert size in bytes to size in STACK_ALIGN units == log2(STACK_ALIGN) +#define STACK_ALIGN 16 // stack alignment requirement +#define STACK_ALIGN_SHIFT 4 // Shift-right amount to convert size in bytes to size in STACK_ALIGN units == log2(STACK_ALIGN) #endif // !UNIX_X86_ABI - #define RBM_INT_CALLEE_SAVED (RBM_EBX|RBM_ESI|RBM_EDI) - #define RBM_INT_CALLEE_TRASH (RBM_EAX|RBM_ECX|RBM_EDX) +#define RBM_INT_CALLEE_SAVED (RBM_EBX|RBM_ESI|RBM_EDI) +#define RBM_INT_CALLEE_TRASH (RBM_EAX|RBM_ECX|RBM_EDX) - #define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED | RBM_MSK_CALLEE_SAVED) - #define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH | RBM_MSK_CALLEE_TRASH) +#define RBM_CALLEE_SAVED (RBM_INT_CALLEE_SAVED | RBM_FLT_CALLEE_SAVED | RBM_MSK_CALLEE_SAVED) +#define RBM_CALLEE_TRASH (RBM_INT_CALLEE_TRASH | RBM_FLT_CALLEE_TRASH | RBM_MSK_CALLEE_TRASH) - #define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) +#define RBM_ALLINT (RBM_INT_CALLEE_SAVED | RBM_INT_CALLEE_TRASH) - #define REG_VAR_ORDER REG_EAX,REG_EDX,REG_ECX,REG_ESI,REG_EDI,REG_EBX - #define MAX_VAR_ORDER_SIZE 6 +#define REG_VAR_ORDER REG_EAX,REG_EDX,REG_ECX,REG_ESI,REG_EDI,REG_EBX +#define MAX_VAR_ORDER_SIZE 6 - #define CNT_CALLEE_SAVED (4) - #define CNT_CALLEE_TRASH (3) - #define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) +#define CNT_CALLEE_SAVED (4) +#define CNT_CALLEE_TRASH (3) +#define CNT_CALLEE_ENREG (CNT_CALLEE_SAVED-1) - #define CNT_CALLEE_SAVED_FLOAT (0) - #define CNT_CALLEE_TRASH_FLOAT (6) - #define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) +#define CNT_CALLEE_SAVED_FLOAT (0) +#define CNT_CALLEE_TRASH_FLOAT (6) +#define CNT_CALLEE_ENREG_FLOAT (CNT_CALLEE_SAVED_FLOAT) - #define CNT_CALLEE_SAVED_MASK (0) - #define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) +#define CNT_CALLEE_SAVED_MASK (0) +#define CNT_CALLEE_ENREG_MASK (CNT_CALLEE_SAVED_MASK) - #define CNT_CALLEE_TRASH_MASK_INIT (0) - #define CNT_CALLEE_TRASH_MASK_EVEX (7) - #define CNT_CALLEE_TRASH_MASK get_CNT_CALLEE_TRASH_MASK() +#define CNT_CALLEE_TRASH_MASK_INIT (0) +#define CNT_CALLEE_TRASH_MASK_EVEX (7) +#define CNT_CALLEE_TRASH_MASK get_CNT_CALLEE_TRASH_MASK() - #define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED*REGSIZE_BYTES) // EBX,ESI,EDI,EBP +#define CALLEE_SAVED_REG_MAXSZ (CNT_CALLEE_SAVED*REGSIZE_BYTES) // EBX,ESI,EDI,EBP - #define REG_LNGARG_LO REG_EAX - #define RBM_LNGARG_LO RBM_EAX - #define REG_LNGARG_HI REG_EDX - #define RBM_LNGARG_HI RBM_EDX - // register to hold shift amount - #define REG_SHIFT REG_ECX - #define RBM_SHIFT RBM_ECX +#define REG_LNGARG_LO REG_EAX +#define RBM_LNGARG_LO RBM_EAX +#define REG_LNGARG_HI REG_EDX +#define RBM_LNGARG_HI RBM_EDX +// register to hold shift amount +#define REG_SHIFT REG_ECX +#define RBM_SHIFT RBM_ECX - // register to hold shift amount when shifting 64-bit values - #define REG_SHIFT_LNG REG_ECX - #define RBM_SHIFT_LNG RBM_ECX +// register to hold shift amount when shifting 64-bit values +#define REG_SHIFT_LNG REG_ECX +#define RBM_SHIFT_LNG RBM_ECX - // This is a general scratch register that does not conflict with the argument registers - #define REG_SCRATCH REG_EAX +// This is a general scratch register that does not conflict with the argument registers +#define REG_SCRATCH REG_EAX - // Where is the exception object on entry to the handler block? - #define REG_EXCEPTION_OBJECT REG_EAX - #define RBM_EXCEPTION_OBJECT RBM_EAX +// Where is the exception object on entry to the handler block? +#define REG_EXCEPTION_OBJECT REG_EAX +#define RBM_EXCEPTION_OBJECT RBM_EAX - // Only used on ARM for GTF_CALL_M_VIRTSTUB_REL_INDIRECT - #define REG_JUMP_THUNK_PARAM REG_EAX - #define RBM_JUMP_THUNK_PARAM RBM_EAX +// Only used on ARM for GTF_CALL_M_VIRTSTUB_REL_INDIRECT +#define REG_JUMP_THUNK_PARAM REG_EAX +#define RBM_JUMP_THUNK_PARAM RBM_EAX - #define REG_R2R_INDIRECT_PARAM REG_EAX // Indirection cell for R2R fast tailcall, not currently used in x86. - #define RBM_R2R_INDIRECT_PARAM RBM_EAX +#define REG_R2R_INDIRECT_PARAM REG_EAX // Indirection cell for R2R fast tailcall, not currently used in x86. +#define RBM_R2R_INDIRECT_PARAM RBM_EAX - // x86 write barrier ABI (see vm\i386\jithelp.asm, vm\i386\jithelp.S): - // CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): - // On entry: - // edx: the destination address (object reference written here) - // For optimized write barriers, one of eax, ecx, ebx, esi, or edi contains the source (object to write). - // (There is a separate write barrier for each of these source options.) - // On exit: - // edx: trashed - // CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): - // On entry: - // esi: the source address (points to object reference to write) - // edi: the destination address (object reference written here) - // On exit: - // ecx: trashed - // edi: incremented by 8 - // esi: incremented by 8 - // +// x86 write barrier ABI (see vm\i386\jithelp.asm, vm\i386\jithelp.S): +// CORINFO_HELP_ASSIGN_REF (JIT_WriteBarrier), CORINFO_HELP_CHECKED_ASSIGN_REF (JIT_CheckedWriteBarrier): +// On entry: +// edx: the destination address (object reference written here) +// For optimized write barriers, one of eax, ecx, ebx, esi, or edi contains the source (object to write). +// (There is a separate write barrier for each of these source options.) +// On exit: +// edx: trashed +// CORINFO_HELP_ASSIGN_BYREF (JIT_ByRefWriteBarrier): +// On entry: +// esi: the source address (points to object reference to write) +// edi: the destination address (object reference written here) +// On exit: +// ecx: trashed +// edi: incremented by 8 +// esi: incremented by 8 +// - #define REG_WRITE_BARRIER_DST REG_ARG_0 - #define RBM_WRITE_BARRIER_DST RBM_ARG_0 +#define REG_WRITE_BARRIER_DST REG_ARG_0 +#define RBM_WRITE_BARRIER_DST RBM_ARG_0 - #define REG_WRITE_BARRIER_SRC REG_ARG_1 - #define RBM_WRITE_BARRIER_SRC RBM_ARG_1 +#define REG_WRITE_BARRIER_SRC REG_ARG_1 +#define RBM_WRITE_BARRIER_SRC RBM_ARG_1 #if NOGC_WRITE_BARRIERS - #define REG_OPTIMIZED_WRITE_BARRIER_DST REG_EDX - #define RBM_OPTIMIZED_WRITE_BARRIER_DST RBM_EDX +#define REG_OPTIMIZED_WRITE_BARRIER_DST REG_EDX +#define RBM_OPTIMIZED_WRITE_BARRIER_DST RBM_EDX - // We don't allow using ebp as a source register. Maybe we should only prevent this for ETW_EBP_FRAMED - // (but that is always set right now). - #define RBM_OPTIMIZED_WRITE_BARRIER_SRC (RBM_EAX|RBM_ECX|RBM_EBX|RBM_ESI|RBM_EDI) +// We don't allow using ebp as a source register. Maybe we should only prevent this for ETW_EBP_FRAMED +// (but that is always set right now). +#define RBM_OPTIMIZED_WRITE_BARRIER_SRC (RBM_EAX|RBM_ECX|RBM_EBX|RBM_ESI|RBM_EDI) #endif // NOGC_WRITE_BARRIERS - #define RBM_CALLEE_TRASH_NOGC RBM_EDX +#define RBM_CALLEE_TRASH_NOGC RBM_EDX - // Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - // Note that x86 normally emits an optimized (source-register-specific) write barrier, but can emit - // a call to a "general" write barrier. +// Registers killed by CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +// Note that x86 normally emits an optimized (source-register-specific) write barrier, but can emit +// a call to a "general" write barrier. #ifdef FEATURE_USE_ASM_GC_WRITE_BARRIERS - #define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) +#define RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) #else // !FEATURE_USE_ASM_GC_WRITE_BARRIERS - #define RBM_CALLEE_TRASH_WRITEBARRIER RBM_CALLEE_TRASH +#define RBM_CALLEE_TRASH_WRITEBARRIER RBM_CALLEE_TRASH #endif // !FEATURE_USE_ASM_GC_WRITE_BARRIERS - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_EDX - - // Registers killed by CORINFO_HELP_ASSIGN_BYREF. - #define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_ESI | RBM_EDI | RBM_ECX) - - // Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. - // Note that RDI and RSI are still valid byref pointers after this helper call, despite their value being changed. - #define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_ECX - - // GenericPInvokeCalliHelper unmanaged target parameter - #define REG_PINVOKE_TARGET_PARAM REG_EAX - #define RBM_PINVOKE_TARGET_PARAM RBM_EAX - - // GenericPInvokeCalliHelper cookie parameter - #define REG_PINVOKE_COOKIE_PARAM REG_EBX - - // IL stub's secret parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) - #define REG_SECRET_STUB_PARAM REG_EAX - #define RBM_SECRET_STUB_PARAM RBM_EAX - - // VSD target address register - #define REG_VIRTUAL_STUB_TARGET REG_EAX - #define RBM_VIRTUAL_STUB_TARGET RBM_EAX - - // Registers used by PInvoke frame setup - #define REG_PINVOKE_FRAME REG_EDI // EDI is p/invoke "Frame" pointer argument to CORINFO_HELP_INIT_PINVOKE_FRAME helper - #define RBM_PINVOKE_FRAME RBM_EDI - #define REG_PINVOKE_TCB REG_ESI // ESI is set to Thread Control Block (TCB) on return from - // CORINFO_HELP_INIT_PINVOKE_FRAME helper - #define RBM_PINVOKE_TCB RBM_ESI - #define REG_PINVOKE_SCRATCH REG_EAX // EAX is trashed by CORINFO_HELP_INIT_PINVOKE_FRAME helper - #define RBM_PINVOKE_SCRATCH RBM_EAX - - // The following defines are useful for iterating a regNumber - #define REG_FIRST REG_EAX - #define REG_INT_FIRST REG_EAX - #define REG_INT_LAST REG_EDI - #define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) - #define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) - #define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) - - // Which register are int and long values returned in ? - #define REG_INTRET REG_EAX - #define RBM_INTRET RBM_EAX - #define RBM_LNGRET (RBM_EDX|RBM_EAX) - #define REG_LNGRET_LO REG_EAX - #define RBM_LNGRET_LO RBM_EAX - #define REG_LNGRET_HI REG_EDX - #define RBM_LNGRET_HI RBM_EDX - - #define REG_FLOATRET REG_NA - #define RBM_FLOATRET RBM_NONE - #define RBM_DOUBLERET RBM_NONE - - // The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper - #define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH - - // The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. On x86, this helper has a custom calling - // convention that takes EDI as argument (but doesn't trash it), trashes EAX, and returns ESI. - #define RBM_INIT_PINVOKE_FRAME_TRASH (RBM_PINVOKE_SCRATCH | RBM_PINVOKE_TCB) - - #define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~RBM_ECX) - #define REG_VALIDATE_INDIRECT_CALL_ADDR REG_ECX - - #define REG_ASYNC_CONTINUATION_RET REG_ECX - #define RBM_ASYNC_CONTINUATION_RET RBM_ECX - - #define REG_FPBASE REG_EBP - #define RBM_FPBASE RBM_EBP - #define STR_FPBASE "ebp" - #define REG_SPBASE REG_ESP - #define RBM_SPBASE RBM_ESP - #define STR_SPBASE "esp" - - #define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved EBP and return address - - #define MAX_REG_ARG 2 - - #define MAX_FLOAT_REG_ARG 0 - #define REG_ARG_FIRST REG_ECX - #define REG_ARG_LAST REG_EDX - #define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots - - #define REG_ARG_0 REG_ECX - #define REG_ARG_1 REG_EDX +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_REF and CORINFO_HELP_CHECKED_ASSIGN_REF. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER RBM_EDX + +// Registers killed by CORINFO_HELP_ASSIGN_BYREF. +#define RBM_CALLEE_TRASH_WRITEBARRIER_BYREF (RBM_ESI | RBM_EDI | RBM_ECX) + +// Registers no longer containing GC pointers after CORINFO_HELP_ASSIGN_BYREF. +// Note that RDI and RSI are still valid byref pointers after this helper call, despite their value being changed. +#define RBM_CALLEE_GCTRASH_WRITEBARRIER_BYREF RBM_ECX + +// GenericPInvokeCalliHelper unmanaged target parameter +#define REG_PINVOKE_TARGET_PARAM REG_EAX +#define RBM_PINVOKE_TARGET_PARAM RBM_EAX + +// GenericPInvokeCalliHelper cookie parameter +#define REG_PINVOKE_COOKIE_PARAM REG_EBX + +// IL stub's secret parameter (JitFlags::JIT_FLAG_PUBLISH_SECRET_PARAM) +#define REG_SECRET_STUB_PARAM REG_EAX +#define RBM_SECRET_STUB_PARAM RBM_EAX + +// VSD target address register +#define REG_VIRTUAL_STUB_TARGET REG_EAX +#define RBM_VIRTUAL_STUB_TARGET RBM_EAX + +// Registers used by PInvoke frame setup +#define REG_PINVOKE_FRAME REG_EDI // EDI is p/invoke "Frame" pointer argument to CORINFO_HELP_INIT_PINVOKE_FRAME helper +#define RBM_PINVOKE_FRAME RBM_EDI +#define REG_PINVOKE_TCB REG_ESI // ESI is set to Thread Control Block (TCB) on return from + // CORINFO_HELP_INIT_PINVOKE_FRAME helper +#define RBM_PINVOKE_TCB RBM_ESI +#define REG_PINVOKE_SCRATCH REG_EAX // EAX is trashed by CORINFO_HELP_INIT_PINVOKE_FRAME helper +#define RBM_PINVOKE_SCRATCH RBM_EAX + +// The following defines are useful for iterating a regNumber +#define REG_FIRST REG_EAX +#define REG_INT_FIRST REG_EAX +#define REG_INT_LAST REG_EDI +#define REG_INT_COUNT (REG_INT_LAST - REG_INT_FIRST + 1) +#define REG_NEXT(reg) ((regNumber)((unsigned)(reg) + 1)) +#define REG_PREV(reg) ((regNumber)((unsigned)(reg) - 1)) + +// Which register are int and long values returned in ? +#define REG_INTRET REG_EAX +#define RBM_INTRET RBM_EAX +#define RBM_LNGRET (RBM_EDX|RBM_EAX) +#define REG_LNGRET_LO REG_EAX +#define RBM_LNGRET_LO RBM_EAX +#define REG_LNGRET_HI REG_EDX +#define RBM_LNGRET_HI RBM_EDX + +#define REG_FLOATRET REG_NA +#define RBM_FLOATRET RBM_NONE +#define RBM_DOUBLERET RBM_NONE + +// The registers trashed by the CORINFO_HELP_STOP_FOR_GC helper +#define RBM_STOP_FOR_GC_TRASH RBM_CALLEE_TRASH + +// The registers trashed by the CORINFO_HELP_INIT_PINVOKE_FRAME helper. On x86, this helper has a custom calling +// convention that takes EDI as argument (but doesn't trash it), trashes EAX, and returns ESI. +#define RBM_INIT_PINVOKE_FRAME_TRASH (RBM_PINVOKE_SCRATCH | RBM_PINVOKE_TCB) + +#define RBM_VALIDATE_INDIRECT_CALL_TRASH (RBM_INT_CALLEE_TRASH & ~RBM_ECX) +#define REG_VALIDATE_INDIRECT_CALL_ADDR REG_ECX + +#define REG_ASYNC_CONTINUATION_RET REG_ECX +#define RBM_ASYNC_CONTINUATION_RET RBM_ECX + +#define REG_FPBASE REG_EBP +#define RBM_FPBASE RBM_EBP +#define STR_FPBASE "ebp" +#define REG_SPBASE REG_ESP +#define RBM_SPBASE RBM_ESP +#define STR_SPBASE "esp" + +#define FIRST_ARG_STACK_OFFS (2*REGSIZE_BYTES) // Caller's saved EBP and return address + +#define MAX_REG_ARG 2 + +#define MAX_FLOAT_REG_ARG 0 +#define REG_ARG_FIRST REG_ECX +#define REG_ARG_LAST REG_EDX +#define INIT_ARG_STACK_SLOT 0 // No outgoing reserved stack slots + +#define REG_ARG_0 REG_ECX +#define REG_ARG_1 REG_EDX extern const regNumber intArgRegs [MAX_REG_ARG]; extern const regMaskTP intArgMasks[MAX_REG_ARG]; - #define RBM_ARG_0 RBM_ECX - #define RBM_ARG_1 RBM_EDX +#define RBM_ARG_0 RBM_ECX +#define RBM_ARG_1 RBM_EDX - #define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1) +#define RBM_ARG_REGS (RBM_ARG_0|RBM_ARG_1) - // The registers trashed by profiler enter/leave/tailcall hook - // See vm\i386\asmhelpers.asm for more details. - #define RBM_PROFILER_ENTER_TRASH RBM_NONE - #define RBM_PROFILER_LEAVE_TRASH RBM_NONE - #define RBM_PROFILER_TAILCALL_TRASH (RBM_CALLEE_TRASH & ~RBM_ARG_REGS) +// The registers trashed by profiler enter/leave/tailcall hook +// See vm\i386\asmhelpers.asm for more details. +#define RBM_PROFILER_ENTER_TRASH RBM_NONE +#define RBM_PROFILER_LEAVE_TRASH RBM_NONE +#define RBM_PROFILER_TAILCALL_TRASH (RBM_CALLEE_TRASH & ~RBM_ARG_REGS) - // Pointer-sized string move instructions - #define INS_movsp INS_movsd - #define INS_r_movsp INS_r_movsd - #define INS_stosp INS_stosd - #define INS_r_stosp INS_r_stosd +// Pointer-sized string move instructions +#define INS_movsp INS_movsd +#define INS_r_movsp INS_r_movsd +#define INS_stosp INS_stosd +#define INS_r_stosp INS_r_stosd - // Any stack pointer adjustments larger than this (in bytes) when setting up outgoing call arguments - // requires a stack probe. Set it large enough so all normal stack arguments don't get a probe. - #define ARG_STACK_PROBE_THRESHOLD_BYTES 1024 +// Any stack pointer adjustments larger than this (in bytes) when setting up outgoing call arguments +// requires a stack probe. Set it large enough so all normal stack arguments don't get a probe. +#define ARG_STACK_PROBE_THRESHOLD_BYTES 1024 - // The number of bytes from the end the last probed page that must also be probed, to allow for some - // small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word - // on the stack guard page, and must be touched before any further "SUB SP". - #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES ARG_STACK_PROBE_THRESHOLD_BYTES +// The number of bytes from the end the last probed page that must also be probed, to allow for some +// small SP adjustments without probes. If zero, then the stack pointer can point to the last byte/word +// on the stack guard page, and must be touched before any further "SUB SP". +#define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES ARG_STACK_PROBE_THRESHOLD_BYTES - #define REG_STACK_PROBE_HELPER_ARG REG_EAX - #define RBM_STACK_PROBE_HELPER_ARG RBM_EAX +#define REG_STACK_PROBE_HELPER_ARG REG_EAX +#define RBM_STACK_PROBE_HELPER_ARG RBM_EAX - #define RBM_STACK_PROBE_HELPER_TRASH RBM_NONE +#define RBM_STACK_PROBE_HELPER_TRASH RBM_NONE // clang-format on