#ifndef EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_ #define EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_ #include #include // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define VA_ARGS \ uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, uint64_t overflow_arg_area, __m128 xmm0, \ __m128 xmm1, __m128 xmm2, __m128 xmm3, __m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ... // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define VA_CONTEXT(ctx) \ alignas(16) VaContext ctx; \ (ctx).reg_save_area.gp[0] = rdi; \ (ctx).reg_save_area.gp[1] = rsi; \ (ctx).reg_save_area.gp[2] = rdx; \ (ctx).reg_save_area.gp[3] = rcx; \ (ctx).reg_save_area.gp[4] = r8; \ (ctx).reg_save_area.gp[5] = r9; \ (ctx).reg_save_area.fp[0] = xmm0; \ (ctx).reg_save_area.fp[1] = xmm1; \ (ctx).reg_save_area.fp[2] = xmm2; \ (ctx).reg_save_area.fp[3] = xmm3; \ (ctx).reg_save_area.fp[4] = xmm4; \ (ctx).reg_save_area.fp[5] = xmm5; \ (ctx).reg_save_area.fp[6] = xmm6; \ (ctx).reg_save_area.fp[7] = xmm7; \ (ctx).va_list.reg_save_area = &(ctx).reg_save_area; \ (ctx).va_list.gp_offset = offsetof(VaRegSave, gp); \ (ctx).va_list.fp_offset = offsetof(VaRegSave, fp); \ (ctx).va_list.overflow_arg_area = &overflow_arg_area; namespace Kyty::Libs { #pragma pack(1) struct VaList { uint32_t gp_offset; uint32_t fp_offset; void* overflow_arg_area; void* reg_save_area; }; // typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16))); struct VaRegSave { uint64_t gp[6]; __m128 fp[8]; }; struct VaContext { VaRegSave reg_save_area; VaList va_list; }; struct VaCharX16 { char x[16]; }; struct VaShortX8 { short x[8]; // NOLINT(google-runtime-int) }; struct VaIntX4 { int x[4]; }; struct VaFloatX4 { float x[4]; }; #pragma pack() template T VaArg_overflow_arg_area(VaList* l) { auto ptr = ((reinterpret_cast(l->overflow_arg_area) + (Align - 1)) & ~(Align - 1)); auto* addr = reinterpret_cast(ptr); l->overflow_arg_area = reinterpret_cast(ptr + Size); return *addr; } template T VaArg_reg_save_area_gp(VaList* l) { auto* addr = reinterpret_cast(static_cast(l->reg_save_area) + l->gp_offset); l->gp_offset += Size; return *addr; } template T VaArg_reg_save_area_fp(VaList* l) { auto* addr = reinterpret_cast(static_cast(l->reg_save_area) + l->fp_offset); l->fp_offset += Size; return *addr; } template <> inline VaFloatX4 VaArg_reg_save_area_fp(VaList* l) { auto* addr = reinterpret_cast(static_cast(l->reg_save_area) + l->fp_offset); l->fp_offset += 32; VaFloatX4 ret = {{addr[0].x[0], addr[0].x[1], addr[1].x[0], addr[1].x[1]}}; return ret; } inline int VaArg_int(VaList* l) { if (l->gp_offset <= 40) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } inline double VaArg_double(VaList* l) { if (l->fp_offset <= 160) { return VaArg_reg_save_area_fp(l); } return VaArg_overflow_arg_area(l); } inline long double VaArg_long_double(VaList* l) { return VaArg_overflow_arg_area(l); } inline wint_t VaArg_wint_t(VaList* l) { if (l->gp_offset <= 40) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } inline VaCharX16 VaArg_char_x16(VaList* l) { if (l->gp_offset <= 32) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } inline long VaArg_long(VaList* l) // NOLINT(google-runtime-int) { if (l->gp_offset <= 40) { return VaArg_reg_save_area_gp(l); // NOLINT(google-runtime-int) } return VaArg_overflow_arg_area(l); // NOLINT(google-runtime-int) } inline intmax_t VaArg_intmax_t(VaList* l) { if (l->gp_offset <= 40) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } inline long long VaArg_long_long(VaList* l) // NOLINT(google-runtime-int) { if (l->gp_offset <= 40) { return VaArg_reg_save_area_gp(l); // NOLINT(google-runtime-int) } return VaArg_overflow_arg_area(l); // NOLINT(google-runtime-int) } inline ptrdiff_t VaArg_ptrdiff_t(VaList* l) { if (l->gp_offset <= 40) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } inline size_t VaArg_size_t(VaList* l) { if (l->gp_offset <= 40) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } inline VaShortX8 VaArg_ShortX8(VaList* l) { if (l->gp_offset <= 32) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } inline VaIntX4 VaArg_IntX4(VaList* l) { if (l->gp_offset <= 32) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } inline VaFloatX4 VaArg_FloatX4(VaList* l) { if (l->fp_offset <= 144) { return VaArg_reg_save_area_fp(l); } return VaArg_overflow_arg_area(l); } template T* VaArg_ptr(VaList* l) { if (l->gp_offset <= 40) { return VaArg_reg_save_area_gp(l); } return VaArg_overflow_arg_area(l); } } // namespace Kyty::Libs #endif /* EMULATOR_INCLUDE_EMULATOR_LIBS_VACONTEXT_H_ */