From 64eaccc50929f10ff7e55446133b2613eaf04bc1 Mon Sep 17 00:00:00 2001 From: Eisen Montalvo Date: Tue, 8 Sep 2026 21:19:41 -0600 Subject: [PATCH] Ported Arches to macOS --- .gitignore | 10 ++++++- CMakeLists.txt | 4 +++ include/rtm/bvh.hpp | 25 +++++++++++++++- include/rtm/float.hpp | 14 ++++++++- include/rtm/ftb.hpp | 6 ++++ include/rtm/macros.hpp | 7 +++++ include/rtm/mesh.hpp | 2 +- include/rtm/qtb.hpp | 6 ++++ include/rtm/texture.hpp | 5 ++-- src/arches-v2/CMakeLists.txt | 10 ++++++- src/arches-v2/isa/registers.cpp | 19 ++++++++++++- src/arches-v2/isa/riscv.cpp | 14 +++++++++ src/arches-v2/main.cpp | 11 ++++---- src/arches-v2/shared-utils.hpp | 13 ++++++--- src/arches-v2/stdafx.hpp | 11 ++++++++ src/arches-v2/units/unit-memory-base.hpp | 2 +- src/arches-v2/util/alignment-allocator.hpp | 4 +++ src/arches-v2/util/bit-manipulation.hpp | 33 ++++++++++++++++++++-- 18 files changed, 176 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index d921c36d..a3e19990 100644 --- a/.gitignore +++ b/.gitignore @@ -422,4 +422,12 @@ out/ datasets/ -ext/ \ No newline at end of file +ext/ + +# macOS Ignores +.DS_Store + +# CLion Ignores +.idea +cmake-build* + diff --git a/CMakeLists.txt b/CMakeLists.txt index 19891871..a792dc30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,5 +7,9 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) set(CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +add_compile_definitions(FMT_CONSTEVAL=constexpr) + +set(CMAKE_POLICY_VERSION_MINIMUM 3.10) + add_subdirectory(external) add_subdirectory("src") diff --git a/include/rtm/bvh.hpp b/include/rtm/bvh.hpp index e18ecbd9..34150077 100644 --- a/include/rtm/bvh.hpp +++ b/include/rtm/bvh.hpp @@ -17,6 +17,19 @@ namespace rtm { +#if defined __aarch64__ +inline uint64_t _pdep_u64_sw(uint64_t data, uint64_t mask) +{ + uint64_t result = 0; + for (uint64_t bit = 1; mask; bit <<= 1) { + if (data & bit) + result |= mask & (-mask); + mask &= mask - 1; + } + return result; +} +#endif + union BVHPtr { struct @@ -241,10 +254,16 @@ class BVH rtm::vec3 centroid(build_object.aabb.centroid() - aabb.min); centroid = centroid * scale * max; - build_object.morton_code = + build_object.morton_code = +#if defined __aarch64__ + _pdep_u64_sw((uint32_t)centroid.x, 0b0001001001001001001001001001001001001001001001001001001001001001ull) | + _pdep_u64_sw((uint32_t)centroid.y, 0b0010010010010010010010010010010010010010010010010010010010010010ull) | + _pdep_u64_sw((uint32_t)centroid.z, 0b0100100100100100100100100100100100100100100100100100100100100100ull); +#else _pdep_u64((uint32_t)centroid.x, 0b0001001001001001001001001001001001001001001001001001001001001001ull) | _pdep_u64((uint32_t)centroid.y, 0b0010010010010010010010010010010010010010010010010010010010010010ull) | _pdep_u64((uint32_t)centroid.z, 0b0100100100100100100100100100100100100100100100100100100100100100ull); +#endif } } @@ -300,7 +319,11 @@ class BVH for(uint i = start; i < end; ++i) mask |= bld_objs[i].morton_code ^ bld_objs[start].morton_code; +#if defined __aarch64__ + uint64_t prefix = mask ? __builtin_clzll(mask) : 64; +#else uint64_t prefix = _lzcnt_u64(mask); +#endif if(prefix == 64) return (start + end) / 2; diff --git a/include/rtm/float.hpp b/include/rtm/float.hpp index b05785f7..9fedc50e 100644 --- a/include/rtm/float.hpp +++ b/include/rtm/float.hpp @@ -7,13 +7,15 @@ #include #if defined BUILD_PLATFORM_WINDOWS #include + #elif defined __aarch64__ + #include #elif defined BUILD_PLATFORM_LINUX #include #endif #include #endif -#ifdef BUILD_PLATFORM_LINUX +#if defined BUILD_PLATFORM_LINUX && !defined __aarch64__ // Declarations of intrinsics used that are defined but not declared in immintrin extern __m128 _mm_cos_ps(__m128 __A); extern __m128 _mm_sin_ps(__m128 __A); @@ -51,6 +53,8 @@ inline float sqrt(float input) float output; asm volatile ("fsqrt.s %0, %1\n\t" : "=f" (output) : "f" (input)); return output; + #elif defined __aarch64__ + return std::sqrt(input); #else return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ps1(input))); #endif @@ -62,6 +66,8 @@ inline float rsqrt(float input) float output; asm volatile ("frsqrt.s %0, %1\n\t" : "=f" (output) : "f" (input)); return output; + #elif defined __aarch64__ + return 1.0f / std::sqrt(input); #else return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ps1(input))); #endif @@ -73,6 +79,8 @@ inline float rcp(float input) float output; asm volatile ("frcp.s %0, %1\n\t" : "=f" (output) : "f" (input)); return output; + #elif defined __aarch64__ + return 1.0f / input; #else return _mm_cvtss_f32(_mm_rcp_ss(_mm_set_ps1(input))); #endif @@ -124,6 +132,8 @@ inline float cos(float input) { #ifdef __riscv return cos_32(input); + #elif defined __aarch64__ + return std::cos(input); #else return _mm_cvtss_f32(_mm_cos_ps(_mm_set_ps1(input))); #endif @@ -133,6 +143,8 @@ inline float sin(float input) { #ifdef __riscv return sin_32(input); + #elif defined __aarch64__ + return std::sin(input); #else return _mm_cvtss_f32(_mm_sin_ps(_mm_set_ps1(input))); #endif diff --git a/include/rtm/ftb.hpp b/include/rtm/ftb.hpp index 3e503691..eff85c02 100644 --- a/include/rtm/ftb.hpp +++ b/include/rtm/ftb.hpp @@ -66,9 +66,15 @@ inline bool compress(uint prim_idx, uint prim_cnt, const Mesh& mesh, FTB* block } uint max_pfx = 0; +#if defined __aarch64__ + uint px = min((uint)(mask_x ? __builtin_clz(mask_x) : 32), max_pfx); + uint py = min((uint)(mask_y ? __builtin_clz(mask_y) : 32), max_pfx); + uint pz = min((uint)(mask_z ? __builtin_clz(mask_z) : 32), max_pfx); +#else uint px = min(_lzcnt_u32(mask_x), max_pfx); uint py = min(_lzcnt_u32(mask_y), max_pfx); uint pz = min(_lzcnt_u32(mask_z), max_pfx); +#endif uint nx = 32 - px; uint ny = 32 - py; uint nz = 32 - pz; diff --git a/include/rtm/macros.hpp b/include/rtm/macros.hpp index 9844b512..a52bcde2 100644 --- a/include/rtm/macros.hpp +++ b/include/rtm/macros.hpp @@ -2,10 +2,14 @@ #if defined __x86_64__ || defined _M_X64 #define __x86 +#elif defined __aarch64__ || defined _M_ARM64 +#define __aarch64 #endif #if defined _WIN16 || defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __WIN32__ || defined __TOS_WIN__ || defined __WINDOWS__ #define BUILD_PLATFORM_WINDOWS +#elif defined __APPLE__ + #define BUILD_PLATFORM_MACOS #elif defined __linux__ #define BUILD_PLATFORM_LINUX #endif @@ -13,6 +17,9 @@ //To add breakpoints for debugging at runtime #if defined BUILD_PLATFORM_WINDOWS #define add_breakpoint() __debugbreak() +#elif defined BUILD_PLATFORM_MACOS + #include + #define add_breakpoint() raise(SIGTRAP) #elif defined BUILD_PLATFORM_LINUX #include #define add_breakpoint() raise(SIGINT) diff --git a/include/rtm/mesh.hpp b/include/rtm/mesh.hpp index a0d7416b..ff016116 100644 --- a/include/rtm/mesh.hpp +++ b/include/rtm/mesh.hpp @@ -303,7 +303,7 @@ class Mesh vertex_indices.emplace_back(0); tex_coord_indices.emplace_back(~0x0u); normal_indices.emplace_back(~0x0u); - material_indices.emplace_back(material_names.size() - 1u); + material_indices.emplace_back(material_names.empty() ? 0u : (uint)(material_names.size() - 1u)); read_face(line + data_start_index, vertex_indices.back(), tex_coord_indices.back(), normal_indices.back()); break; diff --git a/include/rtm/qtb.hpp b/include/rtm/qtb.hpp index e97b7c85..1778a860 100644 --- a/include/rtm/qtb.hpp +++ b/include/rtm/qtb.hpp @@ -62,9 +62,15 @@ inline bool compress(const uint* prim_ids, uint num_tris, const Mesh& mesh, QTB& } uint max_pfx = 24; +#if defined __aarch64__ + uint px = min((uint)((mask_x << 8) ? __builtin_clz(mask_x << 8) : 32), max_pfx); + uint py = min((uint)((mask_y << 8) ? __builtin_clz(mask_y << 8) : 32), max_pfx); + uint pz = min((uint)((mask_z << 8) ? __builtin_clz(mask_z << 8) : 32), max_pfx); +#else uint px = min(_lzcnt_u32(mask_x << 8), max_pfx); uint py = min(_lzcnt_u32(mask_y << 8), max_pfx); uint pz = min(_lzcnt_u32(mask_z << 8), max_pfx); +#endif uint nx = 24 - px; uint ny = 24 - py; uint nz = 24 - pz; diff --git a/include/rtm/texture.hpp b/include/rtm/texture.hpp index 1741f881..b388efbf 100644 --- a/include/rtm/texture.hpp +++ b/include/rtm/texture.hpp @@ -104,8 +104,9 @@ class Texture2D rtm::vec2 get_fract_uv(const rtm::vec2& uv) const { - rtm::vec2 fuv = uv * rtm::vec2(width, height); - return (fuv - rtm::vec2((int32_t)fuv[0], (int32_t)fuv[1])); + rtm::vec2 wrapped_uv(uv[0] - floorf(uv[0]), uv[1] - floorf(uv[1])); + rtm::vec2 fuv = wrapped_uv * rtm::vec2(width, height); + return rtm::vec2(fuv[0] - floorf(fuv[0]), fuv[1] - floorf(fuv[1])); } Texel* get_texel_addr(const rtm::uvec2& iuv) const diff --git a/src/arches-v2/CMakeLists.txt b/src/arches-v2/CMakeLists.txt index e2067c8b..b301402b 100644 --- a/src/arches-v2/CMakeLists.txt +++ b/src/arches-v2/CMakeLists.txt @@ -3,7 +3,7 @@ add_compile_definitions(UNICODE _UNICODE) set(PROJECT_NAME "arches-v2") -if(LINUX) +if(LINUX AND NOT APPLE) # enable intrinsics like _lzcnt_u64 add_compile_options(-march=native) endif() @@ -61,10 +61,18 @@ set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME}) if(WINDOWS) target_link_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/libraries/tbb) target_link_libraries(${PROJECT_NAME} PRIVATE tbb12.lib) +elseif(APPLE) + execute_process(COMMAND brew --prefix tbb OUTPUT_VARIABLE TBB_BREW_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) + target_include_directories(${PROJECT_NAME} PUBLIC ${TBB_BREW_PREFIX}/include) + target_link_directories(${PROJECT_NAME} PUBLIC ${TBB_BREW_PREFIX}/lib) + target_link_libraries(${PROJECT_NAME} PRIVATE tbb) elseif(LINUX) target_link_libraries(${PROJECT_NAME} PRIVATE tbb) endif() target_link_libraries(${PROJECT_NAME} PRIVATE Ramulator) +target_compile_definitions(${PROJECT_NAME} PRIVATE + ARCHES_SOURCE_DIR="${CMAKE_SOURCE_DIR}/" + ARCHES_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}/") #set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}) #set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER ${PROJECT_NAME}) diff --git a/src/arches-v2/isa/registers.cpp b/src/arches-v2/isa/registers.cpp index 649a7334..41817da2 100644 --- a/src/arches-v2/isa/registers.cpp +++ b/src/arches-v2/isa/registers.cpp @@ -1,5 +1,5 @@ #include "registers.hpp" - +#include namespace Arches { namespace ISA { namespace RISCV { @@ -19,6 +19,22 @@ FloatingPointRegisterFile::FloatingPointRegisterFile() { fcsr.data = 0u; //Make rounding mode match simulator rounding mode +#if defined BUILD_ARCH_aarch64 + switch (fegetround()) { + case FE_TONEAREST: + fcsr.frm = 0b000; + break; + case FE_DOWNWARD: + fcsr.frm = 0b010; + break; + case FE_UPWARD: + fcsr.frm = 0b011; + break; + case FE_TOWARDZERO: + fcsr.frm = 0b001; + break; + } +#else switch ((_mm_getcsr() >> 13) & 0b11) { case 0b00: //nearest (even) fcsr.frm = 0b000; @@ -33,6 +49,7 @@ FloatingPointRegisterFile::FloatingPointRegisterFile() fcsr.frm = 0b001; break; } +#endif for (int i = 0; i < sizeof(valid); ++i) valid[i] = true; } diff --git a/src/arches-v2/isa/riscv.cpp b/src/arches-v2/isa/riscv.cpp index 82e00fb3..999b4564 100644 --- a/src/arches-v2/isa/riscv.cpp +++ b/src/arches-v2/isa/riscv.cpp @@ -2,6 +2,8 @@ #if defined BUILD_PLATFORM_WINDOWS #include +#elif defined __aarch64__ + #include #elif defined BUILD_PLATFORM_LINUX #include #endif @@ -695,15 +697,27 @@ InstructionInfo const isa_OP_FP[32] = //r.funct5 InstructionInfo(0b010'10, IMPL_NONE), InstructionInfo(0b010'11, "fsqrt.s", InstrType::FSQRT, Encoding::R, RegFile::FLOAT, EXEC_DECL { +#if defined __aarch64__ + unit->float_regs->registers[instr.r.rd].f32 = std::sqrt(unit->float_regs->registers[instr.r.rs1].f32); +#else unit->float_regs->registers[instr.r.rd].f32 = _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ps1(unit->float_regs->registers[instr.r.rs1].f32))); +#endif }), InstructionInfo(0b011'00, "fisqrt.s", InstrType::FSQRT, Encoding::R, RegFile::FLOAT, EXEC_DECL { +#if defined __aarch64__ + unit->float_regs->registers[instr.r.rd].f32 = 1.0f / std::sqrt(unit->float_regs->registers[instr.r.rs1].f32); +#else unit->float_regs->registers[instr.r.rd].f32 = _mm_cvtss_f32(_mm_rsqrt_ps(_mm_set_ps1(unit->float_regs->registers[instr.r.rs1].f32))); +#endif }), InstructionInfo(0b011'01, "frcp.s", InstrType::FRCP, Encoding::R, RegFile::FLOAT, EXEC_DECL { +#if defined __aarch64__ + unit->float_regs->registers[instr.r.rd].f32 = 1.0f / unit->float_regs->registers[instr.r.rs1].f32; +#else unit->float_regs->registers[instr.r.rd].f32 = _mm_cvtss_f32(_mm_rcp_ss(_mm_set_ps1(unit->float_regs->registers[instr.r.rs1].f32))); +#endif }), InstructionInfo(0b011'10, IMPL_NONE), InstructionInfo(0b011'11, IMPL_NONE), diff --git a/src/arches-v2/main.cpp b/src/arches-v2/main.cpp index 6ee3e2a3..44dfd4f1 100644 --- a/src/arches-v2/main.cpp +++ b/src/arches-v2/main.cpp @@ -219,7 +219,7 @@ static TRaXKernelArgs initilize_buffers(Units::UnitMainMemoryBase** drams, const for(uint32_t i = 0; i < mesh.materials.size(); ++i) mesh.materials[i].albedo_texture.texels = nullptr; // to not free device memory textures - size_t temp = TRAX_KERNEL_ARGS_ADDRESS; + paddr_t temp = TRAX_KERNEL_ARGS_ADDRESS; write_array(drams, xbar, 256, (uint8_t*)&args, sizeof(TRaXKernelArgs), temp); return args; } @@ -227,6 +227,7 @@ static TRaXKernelArgs initilize_buffers(Units::UnitMainMemoryBase** drams, const static void run_sim_trax(SimulationConfig& sim_config) { std::string project_folder_path = get_project_folder_path(); + std::string project_binary_path = get_project_binary_path(); #if 0 //RTX 4090 ish //Compute @@ -244,7 +245,7 @@ static void run_sim_trax(SimulationConfig& sim_config) //DRAM UnitDRAM::Configuration dram_config; - dram_config.config_path = project_folder_path + "build\\src\\arches-v2\\config-files\\gddr6x_21000_config.yaml"; + dram_config.config_path = project_binary_path + "config-files/gddr6x_21000_config.yaml"; dram_config.size = 1ull << 30; //1GB per partition dram_config.clock_ratio = dram_clock / core_clock; dram_config.latency = 254; @@ -305,7 +306,7 @@ static void run_sim_trax(SimulationConfig& sim_config) //DRAM UnitDRAM::Configuration dram_config; - dram_config.config_path = project_folder_path + "build\\src\\arches-v2\\config-files\\gddr6_14000_config.yaml"; + dram_config.config_path = project_binary_path + "config-files/gddr6_14000_config.yaml"; dram_config.size = 1ull << 30; //1GB per partition dram_config.clock_ratio = dram_clock / core_clock; dram_config.latency = 254; @@ -375,7 +376,7 @@ static void run_sim_trax(SimulationConfig& sim_config) //DRAM UnitDRAM::Configuration dram_config; - dram_config.config_path = project_folder_path + "build/src/arches-v2/config-files/gddr6_14000_config.yaml"; + dram_config.config_path = project_binary_path + "config-files/gddr6_14000_config.yaml"; dram_config.size = 1ull << 30; //1GB dram_config.clock_ratio = dram_clock / core_clock; dram_config.latency = 92; @@ -433,7 +434,7 @@ static void run_sim_trax(SimulationConfig& sim_config) //DRAM UnitDRAM::Configuration dram_config; - dram_config.config_path = project_folder_path + "build\\src\\arches-v2\\config-files\\gddr6_pch_config.yaml"; + dram_config.config_path = project_binary_path + "config-files/gddr6_pch_config.yaml"; dram_config.size = 1ull << 30; //1GB dram_config.clock_ratio = dram_clock / core_clock; dram_config.latency = 1; diff --git a/src/arches-v2/shared-utils.hpp b/src/arches-v2/shared-utils.hpp index 87caeaf4..adf6b6b3 100644 --- a/src/arches-v2/shared-utils.hpp +++ b/src/arches-v2/shared-utils.hpp @@ -19,6 +19,9 @@ #if defined BUILD_PLATFORM_WINDOWS #include #define MAX_FILENAME_LENGTH MAX_PATH +#elif defined BUILD_PLATFORM_MACOS + #include + #define MAX_FILENAME_LENGTH PATH_MAX #elif defined BUILD_PLATFORM_LINUX #include #define MAX_FILENAME_LENGTH FILENAME_MAX @@ -33,10 +36,12 @@ void set_full_exe_name(const char *name) { std::string get_project_folder_path() { - // CHAR path[MAX_PATH]; - // GetModuleFileNameA(NULL, path, MAX_PATH); - std::string executable_path(full_exe_name); - return executable_path.substr(0, executable_path.rfind("build")); + return ARCHES_SOURCE_DIR; +} + +std::string get_project_binary_path() +{ + return ARCHES_BINARY_DIR; } template diff --git a/src/arches-v2/stdafx.hpp b/src/arches-v2/stdafx.hpp index 4e088650..c0a56da1 100644 --- a/src/arches-v2/stdafx.hpp +++ b/src/arches-v2/stdafx.hpp @@ -3,6 +3,8 @@ //Determine platform #if defined _WIN16 || defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __WIN32__ || defined __TOS_WIN__ || defined __WINDOWS__ #define BUILD_PLATFORM_WINDOWS +#elif defined __APPLE__ + #define BUILD_PLATFORM_MACOS #elif defined __linux__ #define BUILD_PLATFORM_LINUX #endif @@ -46,6 +48,10 @@ #define BUILD_ARCH_32 #define BUILD_ARCH_x86 #define BUILD_ARCH_ENDIAN_LITTLE +#elif defined __aarch64__ || defined _M_ARM64 + #define BUILD_ARCH_64 + #define BUILD_ARCH_aarch64 + #define BUILD_ARCH_ENDIAN_LITTLE #else #error "Define Endianness" #endif @@ -117,6 +123,9 @@ //To add breakpoints for debugging at runtime #if defined BUILD_PLATFORM_WINDOWS #define add_breakpoint() __debugbreak() +#elif defined BUILD_PLATFORM_MACOS + #include + #define add_breakpoint() raise(SIGTRAP) #elif defined BUILD_PLATFORM_LINUX #include #define add_breakpoint() raise(SIGINT) @@ -159,6 +168,8 @@ //Include platform intrinsics header #if defined BUILD_PLATFORM_WINDOWS #include +#elif defined BUILD_ARCH_aarch64 + #include #elif defined BUILD_PLATFORM_LINUX #include #endif diff --git a/src/arches-v2/units/unit-memory-base.hpp b/src/arches-v2/units/unit-memory-base.hpp index 65eeebda..40a61ccd 100644 --- a/src/arches-v2/units/unit-memory-base.hpp +++ b/src/arches-v2/units/unit-memory-base.hpp @@ -106,7 +106,7 @@ class MemoryMap if(unit == nullptr) return; - MemoryMapping mapping = {unit, port_id, num_ports, 0}; + MemoryMapping mapping = {unit, static_cast(port_id), static_cast(num_ports), 0}; uint j; for(j = 0; j < mappings.size(); ++j) diff --git a/src/arches-v2/util/alignment-allocator.hpp b/src/arches-v2/util/alignment-allocator.hpp index 44bcb7f1..4f0d29aa 100644 --- a/src/arches-v2/util/alignment-allocator.hpp +++ b/src/arches-v2/util/alignment-allocator.hpp @@ -37,6 +37,8 @@ class AlignmentAllocator { #if defined BUILD_PLATFORM_WINDOWS return (pointer)_aligned_malloc(n * sizeof(value_type), N); + #elif defined BUILD_PLATFORM_MACOS + return (pointer)aligned_alloc(N, n * sizeof(value_type)); #elif defined BUILD_PLATFORM_LINUX return (pointer)aligned_alloc(N, n * sizeof(value_type)); #endif @@ -46,6 +48,8 @@ class AlignmentAllocator { #if defined BUILD_PLATFORM_WINDOWS _aligned_free(p); + #elif defined BUILD_PLATFORM_MACOS + free(p); #elif defined BUILD_PLATFORM_LINUX free(p); #endif diff --git a/src/arches-v2/util/bit-manipulation.hpp b/src/arches-v2/util/bit-manipulation.hpp index a5da0c5d..5267476d 100644 --- a/src/arches-v2/util/bit-manipulation.hpp +++ b/src/arches-v2/util/bit-manipulation.hpp @@ -5,6 +5,9 @@ #if defined BUILD_PLATFORM_WINDOWS #define popcnt64(mask) __popcnt64(mask) #define rotr64(mask, n) _rotr64(mask, n) +#elif defined BUILD_ARCH_aarch64 + #define popcnt64(mask) __builtin_popcountll(mask) + #define rotr64(mask, n) (((mask) >> (n)) | ((mask) << (64 - (n)))) #elif defined BUILD_PLATFORM_LINUX #define popcnt64(mask) _popcnt64(mask) #define rotr64(mask, n) _lrotr(mask, n) @@ -30,14 +33,20 @@ inline Arches::paddr_t align_to(size_t alignment, Arches::paddr_t paddr) inline uint ctz(uint64_t mask) { - - +#if defined BUILD_ARCH_aarch64 + return __builtin_ctzll(mask); +#else return _tzcnt_u64(mask); +#endif } inline uint clz(uint64_t mask) { +#if defined BUILD_ARCH_aarch64 + return mask ? __builtin_clzll(mask) : 64; +#else return _lzcnt_u64(mask); +#endif } @@ -53,12 +62,32 @@ inline uint64_t rotr(uint64_t mask, uint n) inline uint64_t pdep(uint64_t data, uint64_t mask) { +#if defined BUILD_ARCH_aarch64 + uint64_t result = 0; + for (uint64_t bit = 1; mask; bit <<= 1) { + if (data & bit) + result |= mask & (-mask); + mask &= mask - 1; + } + return result; +#else return _pdep_u64(data, mask); +#endif } inline uint64_t pext(uint64_t data, uint64_t mask) { +#if defined BUILD_ARCH_aarch64 + uint64_t result = 0; + for (uint64_t bit = 1; mask; bit <<= 1) { + if (data & (mask & (-mask))) + result |= bit; + mask &= mask - 1; + } + return result; +#else return _pext_u64(data, mask); +#endif } struct BitStack27