diff --git a/lib86cpu/core/memory_management.cpp b/lib86cpu/core/memory_management.cpp index 8d06c37..485e916 100644 --- a/lib86cpu/core/memory_management.cpp +++ b/lib86cpu/core/memory_management.cpp @@ -576,8 +576,7 @@ T mem_read_helper(cpu_ctx_t *cpu_ctx, addr_t addr, uint32_t eip, uint8_t is_priv default: // because all other region types are cached, this should only happen with the unmapped region - LOG(log_level::warn, "Memory read to unmapped memory at address %#010x with size %d", addr, sizeof(T)); - return std::numeric_limits::max(); + return log_unhandled_read(addr); } } } @@ -659,7 +658,7 @@ void mem_write_helper(cpu_ctx_t *cpu_ctx, addr_t addr, T val, uint32_t eip, uint default: // because all other region types are cached, this should only happen with the unmapped region - LOG(log_level::warn, "Memory write to unmapped memory at address %#010x with size %d", addr, sizeof(T)); + log_unhandled_write(addr, val); return; } } diff --git a/lib86cpu/core/memory_management.h b/lib86cpu/core/memory_management.h index b029cdb..c9848df 100644 --- a/lib86cpu/core/memory_management.h +++ b/lib86cpu/core/memory_management.h @@ -106,8 +106,7 @@ T as_memory_dispatch_read(cpu_t *cpu, addr_t addr, const memory_region_t break; case mem_type::unmapped: - LOG(log_level::warn, "Memory read to unmapped memory at address %#010x with size %d", addr, sizeof(T)); - return std::numeric_limits::max(); + return log_unhandled_read(addr); default: LIB86CPU_ABORT(); @@ -152,7 +151,7 @@ void as_memory_dispatch_write(cpu_t *cpu, addr_t addr, T value, const memory_reg break; case mem_type::unmapped: - LOG(log_level::warn, "Memory write to unmapped memory at address %#010x with size %d", addr, sizeof(T)); + log_unhandled_write(addr, value); break; default: @@ -180,8 +179,7 @@ T as_io_dispatch_read(cpu_t *cpu, port_t port, const memory_region_t *re } case mem_type::unmapped: - LOG(log_level::warn, "Io read to unmapped memory at port %#06x with size %d", port, sizeof(T)); - return std::numeric_limits::max(); + return log_unhandled_read(port); default: LIB86CPU_ABORT(); @@ -209,7 +207,7 @@ void as_io_dispatch_write(cpu_t *cpu, port_t port, T value, const memory_region_ break; case mem_type::unmapped: - LOG(log_level::warn, "Io write to unmapped memory at port %#06x with size %d", port, sizeof(T)); + log_unhandled_write(port, value); return; default: diff --git a/lib86cpu/interface.cpp b/lib86cpu/interface.cpp index a0193e6..11bbcf9 100644 --- a/lib86cpu/interface.cpp +++ b/lib86cpu/interface.cpp @@ -17,92 +17,85 @@ static uint8_t default_mmio_read_handler8(addr_t addr, void *opaque) { - LOG(log_level::warn, "Unhandled MMIO read at address %#010x with size 1", addr); - return std::numeric_limits::max(); + return log_unhandled_read(addr); } static uint16_t default_mmio_read_handler16(addr_t addr, void *opaque) { - LOG(log_level::warn, "Unhandled MMIO read at address %#010x with size 2", addr); - return std::numeric_limits::max(); + return log_unhandled_read(addr); } static uint32_t default_mmio_read_handler32(addr_t addr, void *opaque) { - LOG(log_level::warn, "Unhandled MMIO read at address %#010x with size 4", addr); - return std::numeric_limits::max(); + return log_unhandled_read(addr); } static uint64_t default_mmio_read_handler64(addr_t addr, void *opaque) { - LOG(log_level::warn, "Unhandled MMIO read at address %#010x with size 8", addr); - return std::numeric_limits::max(); + return log_unhandled_read(addr); } static void default_mmio_write_handler8(addr_t addr, const uint8_t value, void *opaque) { - LOG(log_level::warn, "Unhandled MMIO write at address %#010x with size 1", addr); + log_unhandled_write(addr, value); } static void default_mmio_write_handler16(addr_t addr, const uint16_t value, void *opaque) { - LOG(log_level::warn, "Unhandled MMIO write at address %#010x with size 2", addr); + log_unhandled_write(addr, value); } static void default_mmio_write_handler32(addr_t addr, const uint32_t value, void *opaque) { - LOG(log_level::warn, "Unhandled MMIO write at address %#010x with size 4", addr); + log_unhandled_write(addr, value); } static void default_mmio_write_handler64(addr_t addr, const uint64_t value, void *opaque) { - LOG(log_level::warn, "Unhandled MMIO write at address %#010x with size 8", addr); + log_unhandled_write(addr, value); } static uint8_t default_pmio_read_handler8(addr_t addr, void *opaque) { - LOG(log_level::warn, "Unhandled PMIO read at port %#06x with size 1", addr); - return std::numeric_limits::max(); + return log_unhandled_read(addr); } static uint16_t default_pmio_read_handler16(addr_t addr, void *opaque) { - LOG(log_level::warn, "Unhandled PMIO read at port %#06x with size 2", addr); - return std::numeric_limits::max(); + return log_unhandled_read(addr); } static uint32_t default_pmio_read_handler32(addr_t addr, void *opaque) { - LOG(log_level::warn, "Unhandled PMIO read at port %#06x with size 4", addr); - return std::numeric_limits::max(); + return log_unhandled_read(addr); } static void default_pmio_write_handler8(addr_t addr, const uint8_t value, void *opaque) { - LOG(log_level::warn, "Unhandled PMIO write at port %#06x with size 1", addr); + log_unhandled_write(addr, value); } static void default_pmio_write_handler16(addr_t addr, const uint16_t value, void *opaque) { - LOG(log_level::warn, "Unhandled PMIO write at port %#06x with size 2", addr); + log_unhandled_write(addr, value); } static void default_pmio_write_handler32(addr_t addr, const uint32_t value, void *opaque) { - LOG(log_level::warn, "Unhandled PMIO write at port %#06x with size 4", addr); + log_unhandled_write(addr, value); } // NOTE: lib86cpu runs entirely on the single thread that calls cpu_run, so calling the below functions from other threads is not safe. Only call them diff --git a/lib86cpu/support.h b/lib86cpu/support.h index 77fec48..d3d0f51 100644 --- a/lib86cpu/support.h +++ b/lib86cpu/support.h @@ -67,3 +67,84 @@ to_u64(auto val) inline logfn_t logfn = &discard_log; inline std::string last_error = "The operation completed successfully"; + +template +consteval const char *get_prix_prefix() +{ + if constexpr (sizeof(T) == 1) { + return PRIX8; + } + else if constexpr (sizeof(T) == 2) { + return PRIX16; + } + else if constexpr (sizeof(T) == 4) { + return PRIX32; + } + else if constexpr (sizeof(T) == 8) { + return PRIX64; + } + else { + return ""; + } +} + +template +void log_unhandled_write(addr_t addr, T value) +{ + if constexpr ((sizeof(T) == 10) || (sizeof(T) == 16)) { + constexpr size_t val_high_digits = sizeof(T) == 10 ? 4 : 16; + using type_high_digits = std::conditional_t; + if constexpr (type == mem_type::unmapped) { + LOG(log_level::warn, ("Memory write of value high=0x%0" + std::to_string(val_high_digits) + get_prix_prefix() + " and low=0x%016" PRIX64 " to \ +unmapped memory at address 0x%08" PRIX32 " with size %" PRId32).c_str(), + value.high, value.low, addr, sizeof(T)); + } + else { + LOG(log_level::warn, ("Unhandled mmio write of value high=0x%0" + std::to_string(val_high_digits) + get_prix_prefix() + " and low=0x%016" PRIX64 " at \ +address 0x%08" PRIX32 " with size %" PRId32).c_str(), + value.high, value.low, addr, sizeof(T)); + } + } + else { + constexpr size_t val_digits = sizeof(T) * 2; + if constexpr (type == mem_type::unmapped) { + LOG(log_level::warn, ("Memory write of value 0x%0" + std::to_string(val_digits) + get_prix_prefix() + " to unmapped memory at address 0x%08" PRIX32 " with size %" PRId32).c_str(), + value, addr, sizeof(T)); + } + else if constexpr (type == mem_type::mmio) { + LOG(log_level::warn, ("Unhandled mmio write of value 0x%0" + std::to_string(val_digits) + get_prix_prefix() + " at address 0x%08" PRIX32 " with size %" PRId32).c_str(), + value, addr, sizeof(T)); + } + else { + LOG(log_level::warn, ("Unhandled pmio write of value 0x%0" + std::to_string(val_digits) + get_prix_prefix() + " at port 0x%04" PRIX16 " with size %" PRId32).c_str(), + value, addr, sizeof(T)); + } + } +} + +template +T log_unhandled_read(addr_t addr) +{ + if constexpr ((sizeof(T) == 10) || (sizeof(T) == 16)) { + if constexpr (type == mem_type::unmapped) { + LOG(log_level::warn, "Memory read to unmapped memory at address 0x%08" PRIX32 " with size %" PRId32, addr, sizeof(T)); + } + else { + LOG(log_level::warn, "Unhandled mmio read at address 0x%08" PRIX32 " with size %" PRId32, addr, sizeof(T)); + } + return T(); + } + else { + constexpr size_t val_digits = sizeof(T) * 2 + 2; + if constexpr (type == mem_type::unmapped) { + LOG(log_level::warn, "Memory read to unmapped memory at address 0x%08" PRIX32 " with size %" PRId32, addr, sizeof(T)); + } + else if constexpr (type == mem_type::mmio) { + LOG(log_level::warn, "Unhandled mmio read at address 0x%08" PRIX32 " with size %" PRId32, addr, sizeof(T)); + } + else { + LOG(log_level::warn, "Unhandled pmio read at port 0x%04" PRIX16 " with size %" PRId32, addr, sizeof(T)); + } + return 0; + } +}