int32_helper.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Sparc32 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 "trace.h"
  21. #include "sysemu/sysemu.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_ILL_INSN] = "Illegal Instruction",
  27. [TT_PRIV_INSN] = "Privileged Instruction",
  28. [TT_NFPU_INSN] = "FPU Disabled",
  29. [TT_WIN_OVF] = "Window Overflow",
  30. [TT_WIN_UNF] = "Window Underflow",
  31. [TT_UNALIGNED] = "Unaligned Memory Access",
  32. [TT_FP_EXCP] = "FPU Exception",
  33. [TT_DFAULT] = "Data Access Fault",
  34. [TT_TOVF] = "Tag Overflow",
  35. [TT_EXTINT | 0x1] = "External Interrupt 1",
  36. [TT_EXTINT | 0x2] = "External Interrupt 2",
  37. [TT_EXTINT | 0x3] = "External Interrupt 3",
  38. [TT_EXTINT | 0x4] = "External Interrupt 4",
  39. [TT_EXTINT | 0x5] = "External Interrupt 5",
  40. [TT_EXTINT | 0x6] = "External Interrupt 6",
  41. [TT_EXTINT | 0x7] = "External Interrupt 7",
  42. [TT_EXTINT | 0x8] = "External Interrupt 8",
  43. [TT_EXTINT | 0x9] = "External Interrupt 9",
  44. [TT_EXTINT | 0xa] = "External Interrupt 10",
  45. [TT_EXTINT | 0xb] = "External Interrupt 11",
  46. [TT_EXTINT | 0xc] = "External Interrupt 12",
  47. [TT_EXTINT | 0xd] = "External Interrupt 13",
  48. [TT_EXTINT | 0xe] = "External Interrupt 14",
  49. [TT_EXTINT | 0xf] = "External Interrupt 15",
  50. [TT_TOVF] = "Tag Overflow",
  51. [TT_CODE_ACCESS] = "Instruction Access Error",
  52. [TT_DATA_ACCESS] = "Data Access Error",
  53. [TT_DIV_ZERO] = "Division By Zero",
  54. [TT_NCP_INSN] = "Coprocessor Disabled",
  55. };
  56. #endif
  57. void sparc_cpu_do_interrupt(CPUState *cs)
  58. {
  59. SPARCCPU *cpu = SPARC_CPU(cs);
  60. CPUSPARCState *env = &cpu->env;
  61. int cwp, intno = cs->exception_index;
  62. /* Compute PSR before exposing state. */
  63. if (env->cc_op != CC_OP_FLAGS) {
  64. cpu_get_psr(env);
  65. }
  66. #ifdef DEBUG_PCALL
  67. if (qemu_loglevel_mask(CPU_LOG_INT)) {
  68. static int count;
  69. const char *name;
  70. if (intno < 0 || intno >= 0x100) {
  71. name = "Unknown";
  72. } else if (intno >= 0x80) {
  73. name = "Trap Instruction";
  74. } else {
  75. name = excp_names[intno];
  76. if (!name) {
  77. name = "Unknown";
  78. }
  79. }
  80. qemu_log("%6d: %s (v=%02x)\n", count, name, intno);
  81. log_cpu_state(cs, 0);
  82. #if 0
  83. {
  84. int i;
  85. uint8_t *ptr;
  86. qemu_log(" code=");
  87. ptr = (uint8_t *)env->pc;
  88. for (i = 0; i < 16; i++) {
  89. qemu_log(" %02x", ldub(ptr + i));
  90. }
  91. qemu_log("\n");
  92. }
  93. #endif
  94. count++;
  95. }
  96. #endif
  97. #if !defined(CONFIG_USER_ONLY)
  98. if (env->psret == 0) {
  99. if (cs->exception_index == 0x80 &&
  100. env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
  101. qemu_system_shutdown_request();
  102. } else {
  103. cpu_abort(cs, "Trap 0x%02x while interrupts disabled, Error state",
  104. cs->exception_index);
  105. }
  106. return;
  107. }
  108. #endif
  109. env->psret = 0;
  110. cwp = cpu_cwp_dec(env, env->cwp - 1);
  111. cpu_set_cwp(env, cwp);
  112. env->regwptr[9] = env->pc;
  113. env->regwptr[10] = env->npc;
  114. env->psrps = env->psrs;
  115. env->psrs = 1;
  116. env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
  117. env->pc = env->tbr;
  118. env->npc = env->pc + 4;
  119. cs->exception_index = -1;
  120. #if !defined(CONFIG_USER_ONLY)
  121. /* IRQ acknowledgment */
  122. if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
  123. env->qemu_irq_ack(env, env->irq_manager, intno);
  124. }
  125. #endif
  126. }
  127. #if !defined(CONFIG_USER_ONLY)
  128. static void leon3_cache_control_int(CPUSPARCState *env)
  129. {
  130. uint32_t state = 0;
  131. if (env->cache_control & CACHE_CTRL_IF) {
  132. /* Instruction cache state */
  133. state = env->cache_control & CACHE_STATE_MASK;
  134. if (state == CACHE_ENABLED) {
  135. state = CACHE_FROZEN;
  136. trace_int_helper_icache_freeze();
  137. }
  138. env->cache_control &= ~CACHE_STATE_MASK;
  139. env->cache_control |= state;
  140. }
  141. if (env->cache_control & CACHE_CTRL_DF) {
  142. /* Data cache state */
  143. state = (env->cache_control >> 2) & CACHE_STATE_MASK;
  144. if (state == CACHE_ENABLED) {
  145. state = CACHE_FROZEN;
  146. trace_int_helper_dcache_freeze();
  147. }
  148. env->cache_control &= ~(CACHE_STATE_MASK << 2);
  149. env->cache_control |= (state << 2);
  150. }
  151. }
  152. void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno)
  153. {
  154. leon3_irq_ack(irq_manager, intno);
  155. leon3_cache_control_int(env);
  156. }
  157. #endif