softmmu_header.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Software MMU support
  3. *
  4. * Generate inline load/store functions for one MMU mode and data
  5. * size.
  6. *
  7. * Generate a store function as well as signed and unsigned loads. For
  8. * 32 and 64 bit cases, also generate floating point functions with
  9. * the same size.
  10. *
  11. * Not used directly but included from softmmu_exec.h and exec-all.h.
  12. *
  13. * Copyright (c) 2003 Fabrice Bellard
  14. *
  15. * This library is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU Lesser General Public
  17. * License as published by the Free Software Foundation; either
  18. * version 2 of the License, or (at your option) any later version.
  19. *
  20. * This library is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  23. * Lesser General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU Lesser General Public
  26. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  27. */
  28. #if DATA_SIZE == 8
  29. #define SUFFIX q
  30. #define USUFFIX q
  31. #define DATA_TYPE uint64_t
  32. #elif DATA_SIZE == 4
  33. #define SUFFIX l
  34. #define USUFFIX l
  35. #define DATA_TYPE uint32_t
  36. #elif DATA_SIZE == 2
  37. #define SUFFIX w
  38. #define USUFFIX uw
  39. #define DATA_TYPE uint16_t
  40. #define DATA_STYPE int16_t
  41. #elif DATA_SIZE == 1
  42. #define SUFFIX b
  43. #define USUFFIX ub
  44. #define DATA_TYPE uint8_t
  45. #define DATA_STYPE int8_t
  46. #else
  47. #error unsupported data size
  48. #endif
  49. #if ACCESS_TYPE < (NB_MMU_MODES)
  50. #define CPU_MMU_INDEX ACCESS_TYPE
  51. #define MMUSUFFIX _mmu
  52. #elif ACCESS_TYPE == (NB_MMU_MODES)
  53. #define CPU_MMU_INDEX (cpu_mmu_index(env))
  54. #define MMUSUFFIX _mmu
  55. #elif ACCESS_TYPE == (NB_MMU_MODES + 1)
  56. #define CPU_MMU_INDEX (cpu_mmu_index(env))
  57. #define MMUSUFFIX _cmmu
  58. #else
  59. #error invalid ACCESS_TYPE
  60. #endif
  61. #if DATA_SIZE == 8
  62. #define RES_TYPE uint64_t
  63. #else
  64. #define RES_TYPE uint32_t
  65. #endif
  66. #if ACCESS_TYPE == (NB_MMU_MODES + 1)
  67. #define ADDR_READ addr_code
  68. #else
  69. #define ADDR_READ addr_read
  70. #endif
  71. #ifndef CONFIG_TCG_PASS_AREG0
  72. #define ENV_PARAM
  73. #define ENV_VAR
  74. #define CPU_PREFIX
  75. #define HELPER_PREFIX __
  76. #else
  77. #define ENV_PARAM CPUArchState *env,
  78. #define ENV_VAR env,
  79. #define CPU_PREFIX cpu_
  80. #define HELPER_PREFIX helper_
  81. #endif
  82. /* generic load/store macros */
  83. static inline RES_TYPE
  84. glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
  85. target_ulong ptr)
  86. {
  87. int page_index;
  88. RES_TYPE res;
  89. target_ulong addr;
  90. int mmu_idx;
  91. addr = ptr;
  92. page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  93. mmu_idx = CPU_MMU_INDEX;
  94. if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
  95. (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
  96. res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR
  97. addr,
  98. mmu_idx);
  99. } else {
  100. uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  101. res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
  102. }
  103. return res;
  104. }
  105. #if DATA_SIZE <= 2
  106. static inline int
  107. glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
  108. target_ulong ptr)
  109. {
  110. int res, page_index;
  111. target_ulong addr;
  112. int mmu_idx;
  113. addr = ptr;
  114. page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  115. mmu_idx = CPU_MMU_INDEX;
  116. if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
  117. (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
  118. res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX),
  119. MMUSUFFIX)(ENV_VAR addr, mmu_idx);
  120. } else {
  121. uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  122. res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
  123. }
  124. return res;
  125. }
  126. #endif
  127. #if ACCESS_TYPE != (NB_MMU_MODES + 1)
  128. /* generic store macro */
  129. static inline void
  130. glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
  131. RES_TYPE v)
  132. {
  133. int page_index;
  134. target_ulong addr;
  135. int mmu_idx;
  136. addr = ptr;
  137. page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  138. mmu_idx = CPU_MMU_INDEX;
  139. if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
  140. (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
  141. glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v,
  142. mmu_idx);
  143. } else {
  144. uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
  145. glue(glue(st, SUFFIX), _raw)(hostaddr, v);
  146. }
  147. }
  148. #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
  149. #if ACCESS_TYPE != (NB_MMU_MODES + 1)
  150. #if DATA_SIZE == 8
  151. static inline float64 glue(glue(CPU_PREFIX, ldfq), MEMSUFFIX)(ENV_PARAM
  152. target_ulong ptr)
  153. {
  154. union {
  155. float64 d;
  156. uint64_t i;
  157. } u;
  158. u.i = glue(glue(CPU_PREFIX, ldq), MEMSUFFIX)(ENV_VAR ptr);
  159. return u.d;
  160. }
  161. static inline void glue(glue(CPU_PREFIX, stfq), MEMSUFFIX)(ENV_PARAM
  162. target_ulong ptr,
  163. float64 v)
  164. {
  165. union {
  166. float64 d;
  167. uint64_t i;
  168. } u;
  169. u.d = v;
  170. glue(glue(CPU_PREFIX, stq), MEMSUFFIX)(ENV_VAR ptr, u.i);
  171. }
  172. #endif /* DATA_SIZE == 8 */
  173. #if DATA_SIZE == 4
  174. static inline float32 glue(glue(CPU_PREFIX, ldfl), MEMSUFFIX)(ENV_PARAM
  175. target_ulong ptr)
  176. {
  177. union {
  178. float32 f;
  179. uint32_t i;
  180. } u;
  181. u.i = glue(glue(CPU_PREFIX, ldl), MEMSUFFIX)(ENV_VAR ptr);
  182. return u.f;
  183. }
  184. static inline void glue(glue(CPU_PREFIX, stfl), MEMSUFFIX)(ENV_PARAM
  185. target_ulong ptr,
  186. float32 v)
  187. {
  188. union {
  189. float32 f;
  190. uint32_t i;
  191. } u;
  192. u.f = v;
  193. glue(glue(CPU_PREFIX, stl), MEMSUFFIX)(ENV_VAR ptr, u.i);
  194. }
  195. #endif /* DATA_SIZE == 4 */
  196. #endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
  197. #undef RES_TYPE
  198. #undef DATA_TYPE
  199. #undef DATA_STYPE
  200. #undef SUFFIX
  201. #undef USUFFIX
  202. #undef DATA_SIZE
  203. #undef CPU_MMU_INDEX
  204. #undef MMUSUFFIX
  205. #undef ADDR_READ
  206. #undef ENV_PARAM
  207. #undef ENV_VAR
  208. #undef CPU_PREFIX
  209. #undef HELPER_PREFIX