diff options
| author | Tony Wasserka <NeoBrainX@gmail.com> | 2014-07-12 14:35:47 +0200 |
|---|---|---|
| committer | Tony Wasserka <NeoBrainX@gmail.com> | 2014-07-27 19:23:19 +0200 |
| commit | 38c8a4efb245aec4bfd34c28e00c73b140c08489 (patch) | |
| tree | af3c9d232b29060736c6177c6f8f5facfc2597d8 /Source/Core | |
| parent | 96cfbd1bb0e03cfdd58c6c9ffa96a5bd17f850f4 (diff) | |
MMIO: Cleanup Mapping class by using templates instead of macros.
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Core/HW/MMIO.cpp | 15 | ||||
| -rw-r--r-- | Source/Core/Core/HW/MMIO.h | 161 | ||||
| -rw-r--r-- | Source/Core/Core/HW/MemmapFunctions.cpp | 2 | ||||
| -rw-r--r-- | Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp | 6 |
4 files changed, 109 insertions, 75 deletions
diff --git a/Source/Core/Core/HW/MMIO.cpp b/Source/Core/Core/HW/MMIO.cpp index d1b37e5c54..e1cd422f57 100644 --- a/Source/Core/Core/HW/MMIO.cpp +++ b/Source/Core/Core/HW/MMIO.cpp @@ -224,10 +224,8 @@ ReadHandlingMethod<T>* ReadToSmaller(Mapping* mmio, u32 high_part_addr, u32 low_ { typedef typename SmallerAccessSize<T>::value ST; - ReadHandler<ST>* high_part; - ReadHandler<ST>* low_part; - mmio->GetHandlerForRead(high_part_addr, &high_part); - mmio->GetHandlerForRead(low_part_addr, &low_part); + ReadHandler<ST>* high_part = &mmio->GetHandlerForRead<ST>(high_part_addr); + ReadHandler<ST>* low_part = &mmio->GetHandlerForRead<ST>(low_part_addr); // TODO(delroth): optimize return ComplexRead<T>([=](u32 addr) { @@ -241,10 +239,8 @@ WriteHandlingMethod<T>* WriteToSmaller(Mapping* mmio, u32 high_part_addr, u32 lo { typedef typename SmallerAccessSize<T>::value ST; - WriteHandler<ST>* high_part; - WriteHandler<ST>* low_part; - mmio->GetHandlerForWrite(high_part_addr, &high_part); - mmio->GetHandlerForWrite(low_part_addr, &low_part); + WriteHandler<ST>* high_part = &mmio->GetHandlerForWrite<ST>(high_part_addr); + WriteHandler<ST>* low_part = &mmio->GetHandlerForWrite<ST>(low_part_addr); // TODO(delroth): optimize return ComplexWrite<T>([=](u32 addr, T val) { @@ -258,8 +254,7 @@ ReadHandlingMethod<T>* ReadToLarger(Mapping* mmio, u32 larger_addr, u32 shift) { typedef typename LargerAccessSize<T>::value LT; - ReadHandler<LT>* large; - mmio->GetHandlerForRead(larger_addr, &large); + ReadHandler<LT>* large = &mmio->GetHandlerForRead<LT>(larger_addr); // TODO(delroth): optimize return ComplexRead<T>([large, shift](u32 addr) { diff --git a/Source/Core/Core/HW/MMIO.h b/Source/Core/Core/HW/MMIO.h index 721689fb54..79577aafe9 100644 --- a/Source/Core/Core/HW/MMIO.h +++ b/Source/Core/Core/HW/MMIO.h @@ -75,25 +75,24 @@ public: // // Example usages can be found in just about any HW/ module in Dolphin's // codebase. -#define REGISTER_FUNCS(Size) \ - void RegisterRead(u32 addr, ReadHandlingMethod<u##Size>* read) \ - { \ - u32 id = UniqueID(addr) / sizeof (u##Size); \ - m_Read##Size##Handlers[id].ResetMethod(read); \ - } \ - void RegisterWrite(u32 addr, WriteHandlingMethod<u##Size>* write) \ - { \ - u32 id = UniqueID(addr) / sizeof (u##Size); \ - m_Write##Size##Handlers[id].ResetMethod(write); \ - } \ - void Register(u32 addr, ReadHandlingMethod<u##Size>* read, \ - WriteHandlingMethod<u##Size>* write) \ - { \ - RegisterRead(addr, read); \ - RegisterWrite(addr, write); \ + template<typename Unit> + void RegisterRead(u32 addr, ReadHandlingMethod<Unit>* read) + { + GetHandlerForRead<Unit>(addr).ResetMethod(read); + } + + template<typename Unit> + void RegisterWrite(u32 addr, WriteHandlingMethod<Unit>* write) + { + GetHandlerForWrite<Unit>(addr).ResetMethod(write); + } + + template<typename Unit> + void Register(u32 addr, ReadHandlingMethod<Unit>* read, WriteHandlingMethod<Unit>* write) + { + RegisterRead(addr, read); + RegisterWrite(addr, write); } - REGISTER_FUNCS(8) REGISTER_FUNCS(16) REGISTER_FUNCS(32) -#undef REGISTER_FUNCS // Direct read/write interface. // @@ -101,54 +100,34 @@ public: // address. They are used by the Memory:: access functions, which are // called in interpreter mode, from Dolphin's own code, or from JIT'd code // where the access address could not be predicted. - // - // Note that for reads we cannot simply return the read value because C++ - // allows overloading only with parameter types, not return types. -#define READ_FUNC(Size) \ - void Read(u32 addr, u##Size* val) \ - { \ - u32 id = UniqueID(addr) / sizeof (u##Size); \ - *val = m_Read##Size##Handlers[id].Read(addr); \ + template<typename Unit> + Unit Read(u32 addr) + { + return GetHandlerForRead<Unit>(addr).Read(addr); } - READ_FUNC(8) READ_FUNC(16) READ_FUNC(32) -#undef READ_FUNC - -#define WRITE_FUNC(Size) \ - void Write(u32 addr, u##Size val) \ - { \ - u32 id = UniqueID(addr) / sizeof (u##Size); \ - m_Write##Size##Handlers[id].Write(addr, val); \ + + template<typename Unit> + void Write(u32 addr, Unit val) + { + GetHandlerForWrite<Unit>(addr).Write(addr, val); } - WRITE_FUNC(8) WRITE_FUNC(16) WRITE_FUNC(32) -#undef WRITE_FUNC // Handlers access interface. // // Use when you care more about how to access the MMIO register for an // address than the current value of that register. For example, this is // what could be used to implement fast MMIO accesses in Dolphin's JIT. - // - // Two variants of each GetHandler function are provided: one that returns - // the handler directly and one that has a pointer parameter to return the - // value. This second variant is needed because C++ doesn't do overloads - // based on return type but only based on argument types. -#define GET_HANDLERS_FUNC(Type, Size) \ - Type##Handler<u##Size>& GetHandlerFor##Type##Size(u32 addr) \ - { \ - return m_##Type##Size##Handlers[UniqueID(addr) / sizeof (u##Size)]; \ - } \ - void GetHandlerFor##Type(u32 addr, Type##Handler<u##Size>** h) \ - { \ - *h = &GetHandlerFor##Type##Size(addr); \ + template<typename Unit> + ReadHandler<Unit>& GetHandlerForRead(u32 addr) + { + return GetReadHandler<Unit>(UniqueID(addr) / sizeof(Unit)); } - GET_HANDLERS_FUNC(Read, 8) GET_HANDLERS_FUNC(Read, 16) GET_HANDLERS_FUNC(Read, 32) - GET_HANDLERS_FUNC(Write, 8) GET_HANDLERS_FUNC(Write, 16) GET_HANDLERS_FUNC(Write, 32) -#undef GET_HANDLERS_FUNC - // Dummy 64 bits variants of these functions. While 64 bits MMIO access is - // not supported, we need these in order to make the code compile. - void Read(u32 addr, u64* val) { _dbg_assert_(MEMMAP, 0); } - void Write(u32 addr, u64 val) { _dbg_assert_(MEMMAP, 0); } + template<typename Unit> + WriteHandler<Unit>& GetHandlerForWrite(u32 addr) + { + return GetWriteHandler<Unit>(UniqueID(addr) / sizeof(Unit)); + } private: // These arrays contain the handlers for each MMIO access type: read/write @@ -159,11 +138,71 @@ private: // Each array contains NUM_MMIOS / sizeof (AccessType) because larger // access types mean less possible adresses (assuming aligned only // accesses). -#define HANDLERS(Size) \ - std::array<ReadHandler<u##Size>, NUM_MMIOS / sizeof (u##Size)> m_Read##Size##Handlers; \ - std::array<WriteHandler<u##Size>, NUM_MMIOS / sizeof (u##Size)> m_Write##Size##Handlers; - HANDLERS(8) HANDLERS(16) HANDLERS(32) -#undef HANDLERS + template<typename Unit> + struct HandlerArray + { + using Read = std::array<ReadHandler<Unit>, NUM_MMIOS / sizeof(Unit)>; + using Write = std::array<WriteHandler<Unit>, NUM_MMIOS / sizeof(Unit)>; + }; + + HandlerArray<u8>::Read m_read_handlers8; + HandlerArray<u16>::Read m_read_handlers16; + HandlerArray<u32>::Read m_read_handlers32; + + HandlerArray<u8>::Write m_write_handlers8; + HandlerArray<u16>::Write m_write_handlers16; + HandlerArray<u32>::Write m_write_handlers32; + + // Getter functions for the handler arrays. + // + // TODO: + // It would be desirable to clean these methods up using tuples, i.e. doing something like + // + // auto handlers = std::tie(m_read_handlers8, m_read_handlers16, m_read_handlers32); + // return std::get<Unit>(handlers)[index]; + // + // However, we cannot use this currently because of a compiler bug in clang, presumably related + // to http://llvm.org/bugs/show_bug.cgi?id=18345, due to which the above code makes the compiler + // exceed the template recursion depth. + // As a workaround, we cast all handlers to the requested one's type. This cast will + // compile to a NOP for the returned member variable, but it's necessary to get this + // code to compile at all. + template<typename Unit> + ReadHandler<Unit>& GetReadHandler(size_t index) + { + static_assert(std::is_same<Unit, u8>::value || std::is_same<Unit, u16>::value || std::is_same<Unit, u32>::value, "Invalid unit used"); + using ArrayType = typename HandlerArray<Unit>::Read; + ArrayType& handler = *(std::is_same<Unit,u8>::value ? (ArrayType*)&m_read_handlers8 + : std::is_same<Unit,u16>::value ? (ArrayType*)&m_read_handlers16 + : (ArrayType*)&m_read_handlers32); + return handler[index]; + } + + template<typename Unit> + WriteHandler<Unit>& GetWriteHandler(size_t index) + { + static_assert(std::is_same<Unit, u8>::value || std::is_same<Unit, u16>::value || std::is_same<Unit, u32>::value, "Invalid unit used"); + using ArrayType = typename HandlerArray<Unit>::Write; + ArrayType& handler = *(std::is_same<Unit,u8>::value ? (ArrayType*)&m_write_handlers8 + : std::is_same<Unit,u16>::value ? (ArrayType*)&m_write_handlers16 + : (ArrayType*)&m_write_handlers32); + return handler[index]; + } }; +// Dummy 64 bits variants of these functions. While 64 bits MMIO access is +// not supported, we need these in order to make the code compile. +template<> +inline u64 Mapping::Read<u64>(u32 addr) +{ + _dbg_assert_(MEMMAP, 0); + return 0; +} + +template<> +inline void Mapping::Write(u32 addr, u64 val) +{ + _dbg_assert_(MEMMAP, 0); +} + } diff --git a/Source/Core/Core/HW/MemmapFunctions.cpp b/Source/Core/Core/HW/MemmapFunctions.cpp index 1a7c86a6d6..c06a8cb9cb 100644 --- a/Source/Core/Core/HW/MemmapFunctions.cpp +++ b/Source/Core/Core/HW/MemmapFunctions.cpp @@ -92,7 +92,7 @@ inline void ReadFromHardware(T &_var, const u32 em_address, const u32 effective_ if (em_address < 0xcc000000) _var = EFB_Read(em_address); else - mmio_mapping->Read(em_address, &_var); + _var = mmio_mapping->Read<T>(em_address); } else if (((em_address & 0xF0000000) == 0x80000000) || ((em_address & 0xF0000000) == 0xC0000000) || diff --git a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp index 3c8eababe1..18710d06d2 100644 --- a/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/Jit_Util.cpp @@ -253,21 +253,21 @@ void EmuCodeBlock::MMIOLoadToReg(MMIO::Mapping* mmio, Gen::X64Reg reg_value, { MMIOReadCodeGenerator<u8> gen(this, registers_in_use, reg_value, address, sign_extend); - mmio->GetHandlerForRead8(address).Visit(gen); + mmio->GetHandlerForRead<u8>(address).Visit(gen); break; } case 16: { MMIOReadCodeGenerator<u16> gen(this, registers_in_use, reg_value, address, sign_extend); - mmio->GetHandlerForRead16(address).Visit(gen); + mmio->GetHandlerForRead<u16>(address).Visit(gen); break; } case 32: { MMIOReadCodeGenerator<u32> gen(this, registers_in_use, reg_value, address, sign_extend); - mmio->GetHandlerForRead32(address).Visit(gen); + mmio->GetHandlerForRead<u32>(address).Visit(gen); break; } } |
