int64_helper.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Sparc64 interrupt helpers
  3. *
  4. * Copyright (c) 2003-2005 Fabrice Bellard
  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 "cpu.h"
  20. #include "helper.h"
  21. #include "trace.h"
  22. //#define DEBUG_PCALL
  23. #ifdef DEBUG_PCALL
  24. static const char * const excp_names[0x80] = {
  25. [TT_TFAULT] = "Instruction Access Fault",
  26. [TT_TMISS] = "Instruction Access MMU Miss",
  27. [TT_CODE_ACCESS] = "Instruction Access Error",
  28. [TT_ILL_INSN] = "Illegal Instruction",
  29. [TT_PRIV_INSN] = "Privileged Instruction",
  30. [TT_NFPU_INSN] = "FPU Disabled",
  31. [TT_FP_EXCP] = "FPU Exception",
  32. [TT_TOVF] = "Tag Overflow",
  33. [TT_CLRWIN] = "Clean Windows",
  34. [TT_DIV_ZERO] = "Division By Zero",
  35. [TT_DFAULT] = "Data Access Fault",
  36. [TT_DMISS] = "Data Access MMU Miss",
  37. [TT_DATA_ACCESS] = "Data Access Error",
  38. [TT_DPROT] = "Data Protection Error",
  39. [TT_UNALIGNED] = "Unaligned Memory Access",
  40. [TT_PRIV_ACT] = "Privileged Action",
  41. [TT_EXTINT | 0x1] = "External Interrupt 1",
  42. [TT_EXTINT | 0x2] = "External Interrupt 2",
  43. [TT_EXTINT | 0x3] = "External Interrupt 3",
  44. [TT_EXTINT | 0x4] = "External Interrupt 4",
  45. [TT_EXTINT | 0x5] = "External Interrupt 5",
  46. [TT_EXTINT | 0x6] = "External Interrupt 6",
  47. [TT_EXTINT | 0x7] = "External Interrupt 7",
  48. [TT_EXTINT | 0x8] = "External Interrupt 8",
  49. [TT_EXTINT | 0x9] = "External Interrupt 9",
  50. [TT_EXTINT | 0xa] = "External Interrupt 10",
  51. [TT_EXTINT | 0xb] = "External Interrupt 11",
  52. [TT_EXTINT | 0xc] = "External Interrupt 12",
  53. [TT_EXTINT | 0xd] = "External Interrupt 13",
  54. [TT_EXTINT | 0xe] = "External Interrupt 14",
  55. [TT_EXTINT | 0xf] = "External Interrupt 15",
  56. };
  57. #endif
  58. void do_interrupt(CPUSPARCState *env)
  59. {
  60. int intno = env->exception_index;
  61. trap_state *tsptr;
  62. #ifdef DEBUG_PCALL
  63. if (qemu_loglevel_mask(CPU_LOG_INT)) {
  64. static int count;
  65. const char *name;
  66. if (intno < 0 || intno >= 0x180) {
  67. name = "Unknown";
  68. } else if (intno >= 0x100) {
  69. name = "Trap Instruction";
  70. } else if (intno >= 0xc0) {
  71. name = "Window Fill";
  72. } else if (intno >= 0x80) {
  73. name = "Window Spill";
  74. } else {
  75. name = excp_names[intno];
  76. if (!name) {
  77. name = "Unknown";
  78. }
  79. }
  80. qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
  81. " SP=%016" PRIx64 "\n",
  82. count, name, intno,
  83. env->pc,
  84. env->npc, env->regwptr[6]);
  85. log_cpu_state(env, 0);
  86. #if 0
  87. {
  88. int i;
  89. uint8_t *ptr;
  90. qemu_log(" code=");
  91. ptr = (uint8_t *)env->pc;
  92. for (i = 0; i < 16; i++) {
  93. qemu_log(" %02x", ldub(ptr + i));
  94. }
  95. qemu_log("\n");
  96. }
  97. #endif
  98. count++;
  99. }
  100. #endif
  101. #if !defined(CONFIG_USER_ONLY)
  102. if (env->tl >= env->maxtl) {
  103. cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
  104. " Error state", env->exception_index, env->tl, env->maxtl);
  105. return;
  106. }
  107. #endif
  108. if (env->tl < env->maxtl - 1) {
  109. env->tl++;
  110. } else {
  111. env->pstate |= PS_RED;
  112. if (env->tl < env->maxtl) {
  113. env->tl++;
  114. }
  115. }
  116. tsptr = cpu_tsptr(env);
  117. tsptr->tstate = (cpu_get_ccr(env) << 32) |
  118. ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
  119. cpu_get_cwp64(env);
  120. tsptr->tpc = env->pc;
  121. tsptr->tnpc = env->npc;
  122. tsptr->tt = intno;
  123. switch (intno) {
  124. case TT_IVEC:
  125. cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
  126. break;
  127. case TT_TFAULT:
  128. case TT_DFAULT:
  129. case TT_TMISS ... TT_TMISS + 3:
  130. case TT_DMISS ... TT_DMISS + 3:
  131. case TT_DPROT ... TT_DPROT + 3:
  132. cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
  133. break;
  134. default:
  135. cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
  136. break;
  137. }
  138. if (intno == TT_CLRWIN) {
  139. cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
  140. } else if ((intno & 0x1c0) == TT_SPILL) {
  141. cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
  142. } else if ((intno & 0x1c0) == TT_FILL) {
  143. cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
  144. }
  145. env->tbr &= ~0x7fffULL;
  146. env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
  147. env->pc = env->tbr;
  148. env->npc = env->pc + 4;
  149. env->exception_index = -1;
  150. }
  151. trap_state *cpu_tsptr(CPUSPARCState* env)
  152. {
  153. return &env->ts[env->tl & MAXTL_MASK];
  154. }
  155. static bool do_modify_softint(CPUSPARCState *env, uint32_t value)
  156. {
  157. if (env->softint != value) {
  158. env->softint = value;
  159. #if !defined(CONFIG_USER_ONLY)
  160. if (cpu_interrupts_enabled(env)) {
  161. cpu_check_irqs(env);
  162. }
  163. #endif
  164. return true;
  165. }
  166. return false;
  167. }
  168. void helper_set_softint(CPUSPARCState *env, uint64_t value)
  169. {
  170. if (do_modify_softint(env, env->softint | (uint32_t)value)) {
  171. trace_int_helper_set_softint(env->softint);
  172. }
  173. }
  174. void helper_clear_softint(CPUSPARCState *env, uint64_t value)
  175. {
  176. if (do_modify_softint(env, env->softint & (uint32_t)~value)) {
  177. trace_int_helper_clear_softint(env->softint);
  178. }
  179. }
  180. void helper_write_softint(CPUSPARCState *env, uint64_t value)
  181. {
  182. if (do_modify_softint(env, (uint32_t)value)) {
  183. trace_int_helper_write_softint(env->softint);
  184. }
  185. }