int32_helper.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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.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 do_interrupt(CPUSPARCState *env)
  58. {
  59. int cwp, intno = env->exception_index;
  60. #ifdef DEBUG_PCALL
  61. if (qemu_loglevel_mask(CPU_LOG_INT)) {
  62. static int count;
  63. const char *name;
  64. if (intno < 0 || intno >= 0x100) {
  65. name = "Unknown";
  66. } else if (intno >= 0x80) {
  67. name = "Trap Instruction";
  68. } else {
  69. name = excp_names[intno];
  70. if (!name) {
  71. name = "Unknown";
  72. }
  73. }
  74. qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
  75. count, name, intno,
  76. env->pc,
  77. env->npc, env->regwptr[6]);
  78. log_cpu_state(env, 0);
  79. #if 0
  80. {
  81. int i;
  82. uint8_t *ptr;
  83. qemu_log(" code=");
  84. ptr = (uint8_t *)env->pc;
  85. for (i = 0; i < 16; i++) {
  86. qemu_log(" %02x", ldub(ptr + i));
  87. }
  88. qemu_log("\n");
  89. }
  90. #endif
  91. count++;
  92. }
  93. #endif
  94. #if !defined(CONFIG_USER_ONLY)
  95. if (env->psret == 0) {
  96. if (env->exception_index == 0x80 &&
  97. env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
  98. qemu_system_shutdown_request();
  99. } else {
  100. cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
  101. env->exception_index);
  102. }
  103. return;
  104. }
  105. #endif
  106. env->psret = 0;
  107. cwp = cpu_cwp_dec(env, env->cwp - 1);
  108. cpu_set_cwp(env, cwp);
  109. env->regwptr[9] = env->pc;
  110. env->regwptr[10] = env->npc;
  111. env->psrps = env->psrs;
  112. env->psrs = 1;
  113. env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
  114. env->pc = env->tbr;
  115. env->npc = env->pc + 4;
  116. env->exception_index = -1;
  117. #if !defined(CONFIG_USER_ONLY)
  118. /* IRQ acknowledgment */
  119. if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
  120. env->qemu_irq_ack(env, env->irq_manager, intno);
  121. }
  122. #endif
  123. }
  124. #if !defined(CONFIG_USER_ONLY)
  125. static void leon3_cache_control_int(CPUSPARCState *env)
  126. {
  127. uint32_t state = 0;
  128. if (env->cache_control & CACHE_CTRL_IF) {
  129. /* Instruction cache state */
  130. state = env->cache_control & CACHE_STATE_MASK;
  131. if (state == CACHE_ENABLED) {
  132. state = CACHE_FROZEN;
  133. trace_int_helper_icache_freeze();
  134. }
  135. env->cache_control &= ~CACHE_STATE_MASK;
  136. env->cache_control |= state;
  137. }
  138. if (env->cache_control & CACHE_CTRL_DF) {
  139. /* Data cache state */
  140. state = (env->cache_control >> 2) & CACHE_STATE_MASK;
  141. if (state == CACHE_ENABLED) {
  142. state = CACHE_FROZEN;
  143. trace_int_helper_dcache_freeze();
  144. }
  145. env->cache_control &= ~(CACHE_STATE_MASK << 2);
  146. env->cache_control |= (state << 2);
  147. }
  148. }
  149. void leon3_irq_manager(CPUSPARCState *env, void *irq_manager, int intno)
  150. {
  151. leon3_irq_ack(irq_manager, intno);
  152. leon3_cache_control_int(env);
  153. }
  154. #endif