home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / sim / ppc / cpu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-24  |  7.7 KB  |  383 lines

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