cpu.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /* This file is part of the program psim.
  2. Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #ifndef _CPU_C_
  15. #define _CPU_C_
  16. #include <setjmp.h>
  17. #include "cpu.h"
  18. #include "idecode.h"
  19. #ifdef HAVE_STRING_H
  20. #include <string.h>
  21. #else
  22. #ifdef HAVE_STRINGS_H
  23. #include <strings.h>
  24. #endif
  25. #endif
  26. struct _cpu {
  27. /* the registers */
  28. registers regs;
  29. /* current instruction address */
  30. unsigned_word program_counter;
  31. /* the memory maps */
  32. core *physical; /* all of memory */
  33. vm *virtual;
  34. vm_instruction_map *instruction_map; /* instructions */
  35. vm_data_map *data_map; /* data */
  36. /* the system this processor is contained within */
  37. cpu_mon *monitor;
  38. os_emul *os_emulation;
  39. psim *system;
  40. event_queue *events;
  41. int cpu_nr;
  42. /* Current CPU model information */
  43. model_data *model_ptr;
  44. #if WITH_IDECODE_CACHE_SIZE
  45. /* a cache to store cracked instructions */
  46. idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
  47. #endif
  48. /* any interrupt state */
  49. interrupts ints;
  50. /* address reservation: keep the physical address and the contents
  51. of memory at that address */
  52. memory_reservation reservation;
  53. /* offset from event time to this cpu's idea of the local time */
  54. signed64 time_base_local_time;
  55. signed64 decrementer_local_time;
  56. event_entry_tag decrementer_event;
  57. };
  58. INLINE_CPU\
  59. (cpu *)
  60. cpu_create(psim *system,
  61. core *memory,
  62. cpu_mon *monitor,
  63. os_emul *os_emulation,
  64. int cpu_nr)
  65. {
  66. cpu *processor = ZALLOC(cpu);
  67. /* create the virtual memory map from the core */
  68. processor->physical = memory;
  69. processor->virtual = vm_create(memory);
  70. processor->instruction_map = vm_create_instruction_map(processor->virtual);
  71. processor->data_map = vm_create_data_map(processor->virtual);
  72. if (CURRENT_MODEL_ISSUE > 0)
  73. processor->model_ptr = model_create (processor);
  74. /* link back to core system */
  75. processor->system = system;
  76. processor->events = psim_event_queue(system);
  77. processor->cpu_nr = cpu_nr;
  78. processor->monitor = monitor;
  79. processor->os_emulation = os_emulation;
  80. return processor;
  81. }
  82. INLINE_CPU\
  83. (void)
  84. cpu_init(cpu *processor)
  85. {
  86. memset(&processor->regs, 0, sizeof(processor->regs));
  87. /* vm init is delayed until after the device tree has been init as
  88. the devices may further init the cpu */
  89. if (CURRENT_MODEL_ISSUE > 0)
  90. model_init (processor->model_ptr);
  91. }
  92. /* find ones way home */
  93. INLINE_CPU\
  94. (psim *)
  95. cpu_system(cpu *processor)
  96. {
  97. return processor->system;
  98. }
  99. INLINE_CPU\
  100. (int)
  101. cpu_nr(cpu *processor)
  102. {
  103. return processor->cpu_nr;
  104. }
  105. INLINE_CPU\
  106. (cpu_mon *)
  107. cpu_monitor(cpu *processor)
  108. {
  109. return processor->monitor;
  110. }
  111. INLINE_CPU\
  112. (os_emul *)
  113. cpu_os_emulation(cpu *processor)
  114. {
  115. return processor->os_emulation;
  116. }
  117. INLINE_CPU\
  118. (model_data *)
  119. cpu_model(cpu *processor)
  120. {
  121. return processor->model_ptr;
  122. }
  123. /* program counter manipulation */
  124. INLINE_CPU\
  125. (void)
  126. cpu_set_program_counter(cpu *processor,
  127. unsigned_word new_program_counter)
  128. {
  129. processor->program_counter = new_program_counter;
  130. }
  131. INLINE_CPU\
  132. (unsigned_word)
  133. cpu_get_program_counter(cpu *processor)
  134. {
  135. return processor->program_counter;
  136. }
  137. INLINE_CPU\
  138. (void)
  139. cpu_restart(cpu *processor,
  140. unsigned_word nia)
  141. {
  142. ASSERT(processor != NULL);
  143. cpu_set_program_counter(processor, nia);
  144. psim_restart(processor->system, processor->cpu_nr);
  145. }
  146. INLINE_CPU\
  147. (void)
  148. cpu_halt(cpu *processor,
  149. unsigned_word nia,
  150. stop_reason reason,
  151. int signal)
  152. {
  153. ASSERT(processor != NULL);
  154. if (CURRENT_MODEL_ISSUE > 0)
  155. model_halt(processor->model_ptr);
  156. cpu_set_program_counter(processor, nia);
  157. psim_halt(processor->system, processor->cpu_nr, reason, signal);
  158. }
  159. EXTERN_CPU\
  160. (void)
  161. cpu_error(cpu *processor,
  162. unsigned_word cia,
  163. const char *fmt,
  164. ...)
  165. {
  166. char message[1024];
  167. va_list ap;
  168. /* format the message */
  169. va_start(ap, fmt);
  170. vsprintf(message, fmt, ap);
  171. va_end(ap);
  172. /* sanity check */
  173. if (strlen(message) >= sizeof(message))
  174. error("cpu_error: buffer overflow");
  175. if (processor != NULL) {
  176. printf_filtered("cpu %d, cia 0x%lx: %s\n",
  177. processor->cpu_nr + 1, (unsigned long)cia, message);
  178. cpu_halt(processor, cia, was_signalled, -1);
  179. }
  180. else {
  181. error("cpu: %s", message);
  182. }
  183. }
  184. /* The processors local concept of time */
  185. INLINE_CPU\
  186. (signed64)
  187. cpu_get_time_base(cpu *processor)
  188. {
  189. return (event_queue_time(processor->events)
  190. - processor->time_base_local_time);
  191. }
  192. INLINE_CPU\
  193. (void)
  194. cpu_set_time_base(cpu *processor,
  195. signed64 time_base)
  196. {
  197. processor->time_base_local_time = (event_queue_time(processor->events)
  198. - time_base);
  199. }
  200. INLINE_CPU\
  201. (signed32)
  202. cpu_get_decrementer(cpu *processor)
  203. {
  204. return (processor->decrementer_local_time
  205. - event_queue_time(processor->events));
  206. }
  207. STATIC_INLINE_CPU\
  208. (void)
  209. cpu_decrement_event(void *data)
  210. {
  211. cpu *processor = (cpu*)data;
  212. processor->decrementer_event = NULL;
  213. decrementer_interrupt(processor);
  214. }
  215. INLINE_CPU\
  216. (void)
  217. cpu_set_decrementer(cpu *processor,
  218. signed32 decrementer)
  219. {
  220. signed64 old_decrementer = cpu_get_decrementer(processor);
  221. event_queue_deschedule(processor->events, processor->decrementer_event);
  222. processor->decrementer_event = NULL;
  223. processor->decrementer_local_time = (event_queue_time(processor->events)
  224. + decrementer);
  225. if (decrementer < 0 && old_decrementer >= 0)
  226. /* A decrementer interrupt occures if the sign of the decrement
  227. register is changed from positive to negative by the load
  228. instruction */
  229. decrementer_interrupt(processor);
  230. else if (decrementer >= 0)
  231. processor->decrementer_event = event_queue_schedule(processor->events,
  232. decrementer,
  233. cpu_decrement_event,
  234. processor);
  235. }
  236. #if WITH_IDECODE_CACHE_SIZE
  237. /* allow access to the cpu's instruction cache */
  238. INLINE_CPU\
  239. (idecode_cache *)
  240. cpu_icache_entry(cpu *processor,
  241. unsigned_word cia)
  242. {
  243. return &processor->icache[cia / 4 % WITH_IDECODE_CACHE_SIZE];
  244. }
  245. INLINE_CPU\
  246. (void)
  247. cpu_flush_icache(cpu *processor)
  248. {
  249. int i;
  250. /* force all addresses to 0xff... so that they never hit */
  251. for (i = 0; i < WITH_IDECODE_CACHE_SIZE; i++)
  252. processor->icache[i].address = MASK(0, 63);
  253. }
  254. #endif
  255. /* address map revelation */
  256. INLINE_CPU\
  257. (vm_instruction_map *)
  258. cpu_instruction_map(cpu *processor)
  259. {
  260. return processor->instruction_map;
  261. }
  262. INLINE_CPU\
  263. (vm_data_map *)
  264. cpu_data_map(cpu *processor)
  265. {
  266. return processor->data_map;
  267. }
  268. INLINE_CPU\
  269. (void)
  270. cpu_page_tlb_invalidate_entry(cpu *processor,
  271. unsigned_word ea)
  272. {
  273. vm_page_tlb_invalidate_entry(processor->virtual, ea);
  274. }
  275. INLINE_CPU\
  276. (void)
  277. cpu_page_tlb_invalidate_all(cpu *processor)
  278. {
  279. vm_page_tlb_invalidate_all(processor->virtual);
  280. }
  281. /* interrupt access */
  282. INLINE_CPU\
  283. (interrupts *)
  284. cpu_interrupts(cpu *processor)
  285. {
  286. return &processor->ints;
  287. }
  288. /* reservation access */
  289. INLINE_CPU\
  290. (memory_reservation *)
  291. cpu_reservation(cpu *processor)
  292. {
  293. return &processor->reservation;
  294. }
  295. /* register access */
  296. INLINE_CPU\
  297. (registers *)
  298. cpu_registers(cpu *processor)
  299. {
  300. return &processor->regs;
  301. }
  302. INLINE_CPU\
  303. (void)
  304. cpu_synchronize_context(cpu *processor,
  305. unsigned_word cia)
  306. {
  307. #if (WITH_IDECODE_CACHE_SIZE)
  308. /* kill of the cache */
  309. cpu_flush_icache(processor);
  310. #endif
  311. /* update virtual memory */
  312. vm_synchronize_context(processor->virtual,
  313. processor->regs.spr,
  314. processor->regs.sr,
  315. processor->regs.msr,
  316. processor, cia);
  317. }
  318. /* might again be useful one day */
  319. INLINE_CPU\
  320. (void)
  321. cpu_print_info(cpu *processor, int verbose)
  322. {
  323. }
  324. #endif /* _CPU_C_ */