register_set.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. // Copyright 2014 Tony Wasserka
  6. // All rights reserved.
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are met:
  10. //
  11. // * Redistributions of source code must retain the above copyright
  12. // notice, this list of conditions and the following disclaimer.
  13. // * Redistributions in binary form must reproduce the above copyright
  14. // notice, this list of conditions and the following disclaimer in the
  15. // documentation and/or other materials provided with the distribution.
  16. // * Neither the name of the owner nor the names of its contributors may
  17. // be used to endorse or promote products derived from this software
  18. // without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. /*
  32. * Standardized way to define a group of registers and corresponding data structures. To define
  33. * a new register set, first define struct containing an enumeration called "Id" containing
  34. * all register IDs and a template union called "Struct". Specialize the Struct union for any
  35. * register ID which needs to be accessed in a specialized way. You can then declare the object
  36. * containing all register values using the RegisterSet<BaseType, DefiningStruct> type, where
  37. * BaseType is the underlying type of each register (e.g. u32).
  38. * Of course, you'll usually want to implement the Struct template such that they are of the same
  39. * size as BaseType. However, it's also possible to make it larger, e.g. when you want to describe
  40. * multiple registers with the same structure.
  41. *
  42. * Example:
  43. *
  44. * struct Regs {
  45. * enum Id : u32 {
  46. * Value1 = 0,
  47. * Value2 = 1,
  48. * Value3 = 2,
  49. * NumIds = 3
  50. * };
  51. *
  52. * // declare register definition structures
  53. * template<Id id>
  54. * union Struct;
  55. * };
  56. *
  57. * // Define register set object
  58. * RegisterSet<u32, CommandIds> registers;
  59. *
  60. * // define register definition structures
  61. * template<>
  62. * union Regs::Struct<Regs::Value1> {
  63. * BitField<0, 4, u32> some_field;
  64. * BitField<4, 3, u32> some_other_field;
  65. * };
  66. *
  67. * Usage in external code (within SomeNamespace scope):
  68. *
  69. * For a register which maps to a single index:
  70. * registers.Get<Regs::Value1>().some_field = some_value;
  71. *
  72. * For a register which maps to different indices, e.g. a group of similar registers
  73. * registers.Get<Regs::Value1>(index).some_field = some_value;
  74. *
  75. *
  76. * @tparam BaseType Base type used for storing individual registers, e.g. u32
  77. * @tparam RegDefinition Class defining an enumeration called "Id" and a template<Id id> union, as described above.
  78. * @note RegDefinition::Id needs to have an enum value called NumIds defining the number of registers to be allocated.
  79. */
  80. template<typename BaseType, typename RegDefinition>
  81. struct RegisterSet {
  82. // Register IDs
  83. using Id = typename RegDefinition::Id;
  84. // type used for *this
  85. using ThisType = RegisterSet<BaseType, RegDefinition>;
  86. // Register definition structs, defined in RegDefinition
  87. template<Id id>
  88. using Struct = typename RegDefinition::template Struct<id>;
  89. /*
  90. * Lookup register with the given id and return it as the corresponding structure type.
  91. * @note This just forwards the arguments to Get(Id).
  92. */
  93. template<Id id>
  94. const Struct<id>& Get() const {
  95. return Get<id>(id);
  96. }
  97. /*
  98. * Lookup register with the given id and return it as the corresponding structure type.
  99. * @note This just forwards the arguments to Get(Id).
  100. */
  101. template<Id id>
  102. Struct<id>& Get() {
  103. return Get<id>(id);
  104. }
  105. /*
  106. * Lookup register with the given index and return it as the corresponding structure type.
  107. * @todo Is this portable with regards to structures larger than BaseType?
  108. * @note if index==id, you don't need to specify the function parameter.
  109. */
  110. template<Id id>
  111. const Struct<id>& Get(const Id& index) const {
  112. const int idx = static_cast<size_t>(index);
  113. return *reinterpret_cast<const Struct<id>*>(&raw[idx]);
  114. }
  115. /*
  116. * Lookup register with the given index and return it as the corresponding structure type.
  117. * @note This just forwards the arguments to the const version of Get(Id).
  118. * @note if index==id, you don't need to specify the function parameter.
  119. */
  120. template<Id id>
  121. Struct<id>& Get(const Id& index) {
  122. return const_cast<Struct<id>&>(GetThis().Get<id>(index));
  123. }
  124. /*
  125. * Plain array access.
  126. * @note If you want to have this casted to a register defininition struct, use Get() instead.
  127. */
  128. const BaseType& operator[] (const Id& id) const {
  129. return raw[static_cast<size_t>(id)];
  130. }
  131. /*
  132. * Plain array access.
  133. * @note If you want to have this casted to a register defininition struct, use Get() instead.
  134. * @note This operator just forwards its argument to the const version.
  135. */
  136. BaseType& operator[] (const Id& id) {
  137. return const_cast<BaseType&>(GetThis()[id]);
  138. }
  139. private:
  140. /*
  141. * Returns a const reference to "this".
  142. */
  143. const ThisType& GetThis() const {
  144. return static_cast<const ThisType&>(*this);
  145. }
  146. BaseType raw[Id::NumIds];
  147. };