helper.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * LatticeMico32 helper routines.
  3. *
  4. * Copyright (c) 2010 Michael Walle <michael@walle.cc>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <assert.h>
  22. #include "config.h"
  23. #include "cpu.h"
  24. #include "host-utils.h"
  25. int cpu_lm32_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
  26. int mmu_idx)
  27. {
  28. int prot;
  29. address &= TARGET_PAGE_MASK;
  30. prot = PAGE_BITS;
  31. if (env->flags & LM32_FLAG_IGNORE_MSB) {
  32. tlb_set_page(env, address, address & 0x7fffffff, prot, mmu_idx,
  33. TARGET_PAGE_SIZE);
  34. } else {
  35. tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
  36. }
  37. return 0;
  38. }
  39. target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
  40. {
  41. return addr & TARGET_PAGE_MASK;
  42. }
  43. void do_interrupt(CPUState *env)
  44. {
  45. qemu_log_mask(CPU_LOG_INT,
  46. "exception at pc=%x type=%x\n", env->pc, env->exception_index);
  47. switch (env->exception_index) {
  48. case EXCP_INSN_BUS_ERROR:
  49. case EXCP_DATA_BUS_ERROR:
  50. case EXCP_DIVIDE_BY_ZERO:
  51. case EXCP_IRQ:
  52. case EXCP_SYSTEMCALL:
  53. /* non-debug exceptions */
  54. env->regs[R_EA] = env->pc;
  55. env->ie |= (env->ie & IE_IE) ? IE_EIE : 0;
  56. env->ie &= ~IE_IE;
  57. if (env->dc & DC_RE) {
  58. env->pc = env->deba + (env->exception_index * 32);
  59. } else {
  60. env->pc = env->eba + (env->exception_index * 32);
  61. }
  62. log_cpu_state_mask(CPU_LOG_INT, env, 0);
  63. break;
  64. case EXCP_BREAKPOINT:
  65. case EXCP_WATCHPOINT:
  66. /* debug exceptions */
  67. env->regs[R_BA] = env->pc;
  68. env->ie |= (env->ie & IE_IE) ? IE_BIE : 0;
  69. env->ie &= ~IE_IE;
  70. env->pc = env->deba + (env->exception_index * 32);
  71. log_cpu_state_mask(CPU_LOG_INT, env, 0);
  72. break;
  73. default:
  74. cpu_abort(env, "unhandled exception type=%d\n",
  75. env->exception_index);
  76. break;
  77. }
  78. }
  79. typedef struct {
  80. const char *name;
  81. uint32_t revision;
  82. uint8_t num_interrupts;
  83. uint8_t num_breakpoints;
  84. uint8_t num_watchpoints;
  85. uint32_t features;
  86. } LM32Def;
  87. static const LM32Def lm32_defs[] = {
  88. {
  89. .name = "lm32-basic",
  90. .revision = 3,
  91. .num_interrupts = 32,
  92. .num_breakpoints = 4,
  93. .num_watchpoints = 4,
  94. .features = (LM32_FEATURE_SHIFT
  95. | LM32_FEATURE_SIGN_EXTEND
  96. | LM32_FEATURE_CYCLE_COUNT),
  97. },
  98. {
  99. .name = "lm32-standard",
  100. .revision = 3,
  101. .num_interrupts = 32,
  102. .num_breakpoints = 4,
  103. .num_watchpoints = 4,
  104. .features = (LM32_FEATURE_MULTIPLY
  105. | LM32_FEATURE_DIVIDE
  106. | LM32_FEATURE_SHIFT
  107. | LM32_FEATURE_SIGN_EXTEND
  108. | LM32_FEATURE_I_CACHE
  109. | LM32_FEATURE_CYCLE_COUNT),
  110. },
  111. {
  112. .name = "lm32-full",
  113. .revision = 3,
  114. .num_interrupts = 32,
  115. .num_breakpoints = 4,
  116. .num_watchpoints = 4,
  117. .features = (LM32_FEATURE_MULTIPLY
  118. | LM32_FEATURE_DIVIDE
  119. | LM32_FEATURE_SHIFT
  120. | LM32_FEATURE_SIGN_EXTEND
  121. | LM32_FEATURE_I_CACHE
  122. | LM32_FEATURE_D_CACHE
  123. | LM32_FEATURE_CYCLE_COUNT),
  124. }
  125. };
  126. void cpu_lm32_list(FILE *f, fprintf_function cpu_fprintf)
  127. {
  128. int i;
  129. cpu_fprintf(f, "Available CPUs:\n");
  130. for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
  131. cpu_fprintf(f, " %s\n", lm32_defs[i].name);
  132. }
  133. }
  134. static const LM32Def *cpu_lm32_find_by_name(const char *name)
  135. {
  136. int i;
  137. for (i = 0; i < ARRAY_SIZE(lm32_defs); i++) {
  138. if (strcasecmp(name, lm32_defs[i].name) == 0) {
  139. return &lm32_defs[i];
  140. }
  141. }
  142. return NULL;
  143. }
  144. static uint32_t cfg_by_def(const LM32Def *def)
  145. {
  146. uint32_t cfg = 0;
  147. if (def->features & LM32_FEATURE_MULTIPLY) {
  148. cfg |= CFG_M;
  149. }
  150. if (def->features & LM32_FEATURE_DIVIDE) {
  151. cfg |= CFG_D;
  152. }
  153. if (def->features & LM32_FEATURE_SHIFT) {
  154. cfg |= CFG_S;
  155. }
  156. if (def->features & LM32_FEATURE_SIGN_EXTEND) {
  157. cfg |= CFG_X;
  158. }
  159. if (def->features & LM32_FEATURE_I_CACHE) {
  160. cfg |= CFG_IC;
  161. }
  162. if (def->features & LM32_FEATURE_D_CACHE) {
  163. cfg |= CFG_DC;
  164. }
  165. if (def->features & LM32_FEATURE_CYCLE_COUNT) {
  166. cfg |= CFG_CC;
  167. }
  168. cfg |= (def->num_interrupts << CFG_INT_SHIFT);
  169. cfg |= (def->num_breakpoints << CFG_BP_SHIFT);
  170. cfg |= (def->num_watchpoints << CFG_WP_SHIFT);
  171. cfg |= (def->revision << CFG_REV_SHIFT);
  172. return cfg;
  173. }
  174. CPUState *cpu_lm32_init(const char *cpu_model)
  175. {
  176. CPUState *env;
  177. const LM32Def *def;
  178. static int tcg_initialized;
  179. def = cpu_lm32_find_by_name(cpu_model);
  180. if (!def) {
  181. return NULL;
  182. }
  183. env = g_malloc0(sizeof(CPUState));
  184. env->features = def->features;
  185. env->num_bps = def->num_breakpoints;
  186. env->num_wps = def->num_watchpoints;
  187. env->cfg = cfg_by_def(def);
  188. env->flags = 0;
  189. cpu_exec_init(env);
  190. cpu_reset(env);
  191. qemu_init_vcpu(env);
  192. if (!tcg_initialized) {
  193. tcg_initialized = 1;
  194. lm32_translate_init();
  195. }
  196. return env;
  197. }
  198. /* Some soc ignores the MSB on the address bus. Thus creating a shadow memory
  199. * area. As a general rule, 0x00000000-0x7fffffff is cached, whereas
  200. * 0x80000000-0xffffffff is not cached and used to access IO devices. */
  201. void cpu_lm32_set_phys_msb_ignore(CPUState *env, int value)
  202. {
  203. if (value) {
  204. env->flags |= LM32_FLAG_IGNORE_MSB;
  205. } else {
  206. env->flags &= ~LM32_FLAG_IGNORE_MSB;
  207. }
  208. }
  209. void cpu_reset(CPUState *env)
  210. {
  211. if (qemu_loglevel_mask(CPU_LOG_RESET)) {
  212. qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
  213. log_cpu_state(env, 0);
  214. }
  215. tlb_flush(env, 1);
  216. /* reset cpu state */
  217. memset(env, 0, offsetof(CPULM32State, breakpoints));
  218. }